Move into for loop

This code cannot be compiled

fn main()
{
    let r1 = 0..10;
    for x in r1
    {
        println!("{}", x);
    }
    println!("{}", r1.len());
}

ok, r1 is moved into another reference owned by the for loop...but has this to happen? Why cannot the for loop refers to the original reference?

Thx.

You could call it a design flaw with the current Range implementation: Derive Copy for std::ops::Range and RangeFrom by SimonSapin · Pull Request #27186 · rust-lang/rust · GitHub

I don't know if this can ever be fixed. For now, you have to explicitly clone the range (which is cheap):

fn main() {
    let r1 = 0..10;
    for x in r1.clone() {
        println!("{}", x);
    }
    println!("{}", r1.len());
}
1 Like

This happens because the for loop calls into_iter on r1, which takes ownership of it. There are no references here, only moves.

What you are suggesting wouldn't work with shared references, because iterators must be mutable to update their state when next() is called. Thus you need to write this if you want to use your original range:

fn main() {
    let mut r1 = 0..10;
    for x in &mut r1 {
        println!("{}", x);
    }
    println!("{}", r1.len());
}

You can never iterate over an immutable iterator, so you either need to use a mut reference, or pass ownership.

Ah, good point. Depending on what you want to happen with your iterator, the piece of code that skysch posted and the piece of code that I posted do not do the same.

skysch's prints "0" as the length of the range after the loop and mine prints "10". So which of these variants you should use depends on what you want to achieve.

Ah, so "into_iter" is responsible of ownership... ok, coming from other languages it sounds quiet interesting

thx

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.