Is borrow checker allowing use of moved value because of reinitialisation?

Consider the code:

fn process_partition(v: Vec<String>) {
    println!("{:?}", v);
}

pub fn main() {
    let data = vec![
        "Hello".to_string(),
        "World".to_string(),
        "-".to_string(),
        "Public".to_string(),
        "Park".to_string(),
    ];
    
    let mut partition = vec![];
    for d in data {
        if d == "-" {
            process_partition(partition); // Value moved here
            partition = vec![]; // Reinitialised
        } else {
            partition.push(d);
        }
    }
    
    process_partition(partition);
}

I was surprised that this compiles and works. Specifically, the moving of value inside the for-loop and then subsequent access being allowed by the borrow checker:

        if d == "-" {
            process_partition(partition); // Value moved here
            partition = vec![]; // Reinitialised
        } else {
            partition.push(d);
        }

My hunch was that the borrow checker is able to detect the re-initialisation and therefore is allowing the same. Went ahead and commented out the re-initialisation part and the borrow checker flagged the violation of rules.

        if d == "-" {
            process_partition(partition); // Value moved here
           // Commented out and fails borrow checker tests
           // partition = vec![]; 
        } 

Is it indeed because of re-initialisation or are there some other rules at play?

The compiler is supposed to allow all valid programs, what you do here is perfectly fine. The compiler isn't perfect so there are cases where a valid program gets rejected but it shouldn't surprise you that a valid one compiles =)

I couldn't find an example in the book nor rust-by-example, I'm going to search a bit more and open an issue if I can't find anything.

1 Like

Thanks! But just to be sure, it is indeed the re-initialisation that is making the program valid from the borrow checker point of view?

Yes, I'd even say it's the re-initialization that makes your program valid. And the compiler understands it. If you make the same program in a language with the same rules as Rust but without this check in place, you could read freed memory and your program would be void.

I might be reading too much into it, if this is the case sorry.

1 Like

No, not at all. Thanks!