Why is the mutable reference not moved here?

后端 未结 2 1760
说谎
说谎 2020-12-01 18:37

I was under the impression that mutable references (i.e. &mut T) are always moved. That makes perfect sense, since they allow exclusive mutable access. In t

相关标签:
2条回答
  • 2020-12-01 19:06

    I asked something along those lines here.

    It seems that in some (many?) cases, instead of a move, a re-borrow takes place. Memory safety is not violated, only the "moved" value is still around. I could not find any docs on that behavior either.

    @Levans opened a github issue here, although I'm not entirely convinced this is just a doc issue: dependably moving out of a &mut reference seems central to Rust's approach of ownership.

    0 讨论(0)
  • 2020-12-01 19:24

    There might actually be a good reason for this.

    &mut T isn't actually a type: all borrows are parametrized by some (potentially inexpressible) lifetime.

    When one writes

    fn move_try(val: &mut ()) {
        { let new = val; }
        *val
    }
    
    fn main() {
        move_try(&mut ());
    }
    

    the type inference engine infers typeof new == typeof val, so they share the original lifetime. This means the borrow from new does not end until the borrow from val does.

    This means it's equivalent to

    fn move_try<'a>(val: &'a mut ()) {
        { let new: &'a mut _ = val; }
        *val
    }
    
    fn main() {
        move_try(&mut ());
    }
    

    However, when you write

    fn move_try(val: &mut ()) {
        { let new: &mut _ = val; }
        *val
    }
    
    fn main() {
        move_try(&mut ());
    }
    

    a cast happens - the same kind of thing that lets you cast away pointer mutability. This means that the lifetime is some (seemingly unspecifiable) 'b < 'a. This involves a cast, and thus a reborrow, and so the reborrow is able to fall out of scope.

    An always-reborrow rule would probably be nicer, but explicit declaration isn't too problematic.

    0 讨论(0)
提交回复
热议问题