What happen when move &mut T


#1

I had written the bad code(I think) like this:

  struct Type<T> {
        x: T,
    }

    let mut a = Type{x: 5};
    let b = &mut a;
    {
        let c = b;
    }
    // println!("{:?}", a); it can't work

It can compile, but I can’t access a after out of inner scope , because a is borrowed as mutable. Then I try it by b, as we can see, b has been moved, and also can’t by c, it end out of inner scope.So I can’t use a any longer, Resource Type{x:5} has been cleared or still there?
And I change mutable to immutable as follow, it can access resource.

#[derive(Debug)]
    struct Type<T> {
        x: T,
    }

    let a = Type{x: 5};
    let b = &a;
    {
        let c = b;
    }
    println!("{:?}", a);

#2

I am not really sure if the below writeup is correct so please do correct me if I am wrong.

#[derive(Debug)]
struct Type<T> {
    x: T,
}

let mut a = Type{x: 5};
// a is now owned

let b = &mut a;
// a is now mutably borrowed and stored as a reference in b
{
    let c = b;
    // b is now moved to c and therefore the variable b is "cleared" of content
}
// the lifetime of c is over therefore the borrow of a should end and a should be accessible again

Is this some sort of compiler bug or did I misunderstand lifetimes and borrows?


#3

Thanks, I also think borrow of a end and it can be accessed again, but when I try, complier don’t allow. I 'am not sure a is cleared or it still there ?


#4

a is definitely not cleared, a is borrowed from.


#5

Lifetimes in Rust are currently tied to lexical scopes. When you borrow a reference and assign it to a variable, the borrow must have a lifetime at least as long as the variable’s scope. There’s no way (yet) to end a borrow “early” by dropping or moving it.

{
    let mut a = Type{x: 5};
    let b = &mut a; // <-+- borrow starts here
    {               //   |
        let c = b;  //   |
    }               //   |
}                   // <-+- and ends here, no matter what happens in between

This problem is explained in detail, along with some proposed future solutions, in @nikomatsakis’s recent articles on non-lexical lifetimes.


#6

That means the original example would need to be written as the following?

#[derive(Debug)]
struct Type<T> {
    x: T,
}

let mut a = Type{x: 5};
{
    let b = &mut a;
    {
        let c = b;
    }
}

#7

Yes, you can shorten the borrow of a by limiting the scope of b.