简体   繁体   中英

When variables move in rust does it do variable shadowing under the hood?

I wanted to know if rust is doing variable shadowing under the hood when variables move from one scope to another.

Since when I move a variable to another function the other function's signature can be changed to make the variable mutable and but when the variable is moved/returned back from other function to main it's not immutable anymore.

I am just curious to what's happening here.

fn main() {
    let vec0 = Vec::new(); // immutable by default
    let mut vec1 = foreign_func(vec0); // vec0 has now moved
    // Is foreign_func returning a mutable vector? Because without `mut` keyword vec1 is immutable by default.
    vec1.push(10);
}

fn foreign_func(mut vec: Vec<i32>) -> Vec<i32> { 
    // argument passed for vec is now mutable in this scope.
    // Is this like variable shadowing?
    // let test = 10;
    // let mut test = 20;
    vec.push(20);
    vec
}

There's no such thing as an immutable Vec , it's only a variable or a borrow that can be immutable (actually unique/exclusive, but in case of Vec that's the same thing).

What happens in your example is a move : the Vec first moves from main 's vec0 into foreign_func 's vec , and then back to main , this time to vec1 . Some of these bindings are mut and some are not, but that has no bearing on the moved value. In fact, transferring a Vec from an immutable to a mutable variable can be as simple as let mut vec1 = vec0 , which compiles just fine.

As pointed out by Peter Hall, shadowing is a different concept: introducing a new variable which intentionally shares the name of an existing one. Since the two variables have the same name, only the most recent one is accessible in its scope. Note that the shadowed variable and the one that shadowed it don't have to have the same type, and that a move may or may not occur when shadowing:

fn shadow1(v: Option<Vec<u32>>) {
    // here shadowing moves the old value
    let v = v.unwrap_or_else(Vec::new);
}

fn shadow2(v: Vec<u32>) {
    // here shadowing not accompanied by move
    let v = v.as_slice();
}

When there is no move, it is possible that the shadowed value will again become useful after an operation ends. In that case the shadowing variable may be introduced in a separate scope, so that the old value resurfaces after the inner scope finishes:

fn shadow3(v: Vec<u32>) {
    {
        let v = v.as_slice();
        // temporarily working with a &[u32] slice, Vec is inaccessible
    }
    // here we have the Vec again
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM