Quick question regarding de-sugars for..loop in Rust

For the std::iter,

let values = vec![1, 2, 3, 4, 5];

for x in values {
    println!("{}", x);
}

de-sugars to

let values = vec![1, 2, 3, 4, 5];
{
    let result = match IntoIterator::into_iter(values) {
        mut iter => loop {
            let next;
            match iter.next() {
                Some(val) => next = val,
                None => break,
            };
            let x = next;
            let () = { println!("{}", x); };  /* why?*/
        },
    };
    result
}

I'm not fully understand, let () = { println!("{}", x); }; try to assign let () = (). Any reason to code this way? Why not just println!("{}", x);
I feel I miss something here.

By hand? No, there's no need to do that.

I suspect, though, that it helps make the compiler give better errors if you do something like for x in values { x }, since it helps the type checker see exactly what the type is expected to be without a bunch of extra work. And it's inside a block so that all the normal "block stuff" happens from the desugar with no special effort.

1 Like

If they didn't do that, then you would not get an error if you return something from the body of the loop.

1 Like

They still would, as the body of a loop needs to be () too.

    let x = loop {
        4
    };

fails with

 --> src/main.rs:3:9
  |
3 |         4
  |         ^ expected `()`, found integer
  |
help: you might have meant to break the loop with this value
  |
3 |         break 4;
  |         +++++  +

But that also gives a potential reason for having the let -- that would clearly be a bad help for a for loop, and the let doesn't have that help.

(That said, the diagnostic could also be suppressed in the compiler based on DesugaringKind::ForLoop, so there might still be a different reason for it.)

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.