5

I have written a macro that implements Scala-like for comprehensions in Rust. It will turn this:

map_for!{
    x <- 0..4;
    y = 2*x;
    z <- 0..1;
    => y+z
}

into this:

((0..4).map (move |x| { let y = 2 * x; (x, y) }))
    .flat_map (move |params| {
        let (x, y) = params;
        (0..1).map (move |z| { y + z })
    })

This works, but the compiler emits an "unused variable" warning because x is not used inside the flat_map. I can disable the warning by adding #[allow(unused_variables)] before the let statements in the macro, but then it removes all unused variable warnings so this:

map_for!{
    x <- 0..4;
    y = 2;
    z <- 0..1;
    => y+z
}

will expand into:

((0..4).map (move |x| { let y = 2; (x, y) }))
    .flat_map (move |params| {
        #[allow(unused_variables)]
        let (x, y) = params;
        (0..1).map (move |z| { y + z })
    })

and will not generate a warning either even though x really is not used.

Is there a way to make it so that the first example will not generate a warning, but the second one will?

The full code of the macro with warnings is available, as is the full code with warnings suppressed.

Jmb
  • 18,893
  • 2
  • 28
  • 55

1 Answers1

2

The simplest way I can think of is to ensure x is being used, by using some inert operation. For example, you can use drop(&x); or perhaps {let _ = &x;}. Neither of these should have any effect on the surrounding code, since they both create, and then immediately relinquish, a borrow.

DK.
  • 55,277
  • 5
  • 189
  • 162
  • 1
    Or even the extremely opaque but concise `{&x}` – Shepmaster Jun 23 '17 at 13:42
  • 1
    Wouldn't doing this hide the non-use of `x` in the second example though? If I understand the OP correctly, they would like a warning generated there. – Shepmaster Jun 23 '17 at 13:55
  • @Shepmaster: Either a variable is going to be "always used" and an inert use can be added to the expansion, or it isn't. If the author doesn't know which is which, then no one does and there is no solution. – DK. Jun 24 '17 at 08:40
  • @DK As the macro author, I can't know if the macro user uses the variable or not without a full rust parser.But from the standpoint of the macro user, it looks like `x` is used in the first example and not in the second. – Jmb Jun 26 '17 at 07:05
  • @Jmb: Well, then this sounds infeasible. *Someone* has to know whether a variable that is genuinely not being used from the compiler's perspective is supposed to be treated as "used". If that's not you, and it's not the end-user, then there's no one left. – DK. Jun 26 '17 at 07:11
  • I was wondering if there was a way to tell the compiler that "these two variables are linked" and so if one is used then you can assume that the other is "used" too. – Jmb Jun 26 '17 at 07:14