Search code examples
rustmove-semanticsmutability

Why does mutating a passed Option inside a function not propagate to the Option outside?


I've illustrated it thus:

fn main() {

    let mut opt1 = Some(1);
    // compiler complains that opt2 doesn't have to be mutable
    let mut opt2 = Some(1);

    fn take_inner(mut opt: Option<u8>) {
        opt.take();
    };

    opt1.take();
    take_inner(opt2);

    println!("opt1 {:?}", opt1); // prints "opt1 None"
    println!("opt2 {:?}", opt2); // prints "opt2 Some(1)"

}

Rust Playground link

Why does calling opt.take() within a function have a different effect than calling it outside (relative to the main function's scope)?


Solution

  • Since u8 is a copy type, and Option has

    impl<T> Copy for Option<T>
    where
        T: Copy,
    

    take_inner takes a copy of opt2

    You can fix that by taking a mutable reference:

    fn main() {
        let mut opt1 = Some(1);
        // compiler complains that opt2 doesn't have to be mutable
        let mut opt2 = Some(1);
    
        fn take_inner(opt: &mut Option<u8>) {
            opt.take();
        };
    
        opt1.take();
        take_inner(&mut opt2);
    
        println!("opt1 {:?}", opt1);
        println!("opt2 {:?}", opt2);
    }
    

    Playground link