Understanding "if-let chain" scope and move semantics

⚓ Rust    📅 2025-06-30    👤 surdeus    👁️ 6      

surdeus

Warning

This post was published 38 days ago. The information described in this article may have changed.

Hi, so I've encountered an interesting case when working with "if-let chains", and I am not sure I fully understand what actually happens.

playground link

    let flag = true;
    let owned = Some(String::from("asd"));
    if let Some(s) = owned && flag {
        println!("{s}");
    } else {
        println!("flag could be false but move 'occured': {owned:?}")
        // borrow of partially moved value: `owned`
    }

So, everything makes sense. The move occurs inside if statement: if *move* {...} else {}, therefore we can't use owned in else block.

But if I change the order of statements, everything works fine:

    let flag = true;
    let owned2 = Some(String::from("asd"));
    if flag && let Some(s) = owned2 {
        println!("{s}");
    } else {
        println!("flag could be false but move 'occured': {owned2:?}")
    }

Does it mean that there is some rule saying "if let expression is the last in the chain, then the value is not considered "moved" for the else block"? Maybe there is some broader rule that results in this behaviour?

8 posts - 4 participants

Read full topic

🏷️ rust_feed