How to return value from for loop

fn fun()-> i32 {
 for a in 0..2 {
        break a
    }
}

why the above code is giving me error when I'm clearly returning i32 type from for loop?

Since for is not statically known to be an infinite loop, and the iterator it is looping over might be empty, it is not guaranteed that either the control flow reaches the break unconditionally or it loops forever. You probably want a loop {} instead of for.

Additional context - the RFC that introduced break-with-value deliberately left for/while/while let out of scope, as there was not consencus on how to resolve the issue that @H2CO3 mentioned:

https://rust-lang.github.io/rfcs/1624-loop-break-value.html#extension-to-for-while-while-let

To add this functionality, there'd likely need to be another RFC.

2 Likes

You're mixing value- and type-level thinking here, which is what is tripping you up.

You, as a human, can look at the example and see in 0..2 which you know will execute at least once.

But that's not what the compiler does. The compiler is just looking at types, so that you could, for example, make the range into a function parameter later and have it still work.

And it's possible for a Range to be empty† -- imagine you'd used in 2..0 -- so the compiler's type-level thinking makes you account for that.

You can, of course, use your value-level knowledge to do something like

fn fun()-> i32 {
    for a in 0..2 {
        break a
    }
    unreachable!()
}

to make it happy if you really wanted to. But as H₂CO₃ said, using a different construct might express it better.

† As an aside, this isn't actually Range knowledge. The way iterators are encoded it's impossible for them to be known to be non-empty at the type level. So even if you're iterating something like a Repeat<_>, you'll still hit this.

2 Likes

You might also want to consider using functional combinators. To iterate through a bunch of values, stop when you've found what you wanted, calculate some value, and have that be the result, you might use find_map: