Skip to content

Inconsistent life time behavior between BorrowMut::borrow_mut() and AsMut::as_mut() #38624

Closed
@FabianEmmes

Description

@FabianEmmes

The following code shows inconsistent behavior in lifetime checking:

use std::convert::AsMut;
use std::borrow::BorrowMut;

trait T {}

impl T for u8 {}

fn main() {
    // A (AsMut and Primitive Type):
    {
        let mut r: Box<u8> = Box::new(23u8);
        let _: &mut u8 = r.as_mut();
    }

    // B (AsMut and Trait Objects):
    {
        let mut r: Box<T> = Box::new(23u8);
        let _: &mut T = r.as_mut();
    }

    // C (BorrowMut and Primitive Type):
    {
        let mut r: Box<u8> = Box::new(23u8);
        let _: &mut u8 = r.borrow_mut();
    }

    // D (BorrowMut and Trait Object):
    {
        let mut r: Box<T> = Box::new(23u8);
        let _: &mut T = r.borrow_mut();
    }
}

Using the stable compiler 1.14.0, case B and D yield a lifetime error:

$ rustc --version
rustc 1.14.0 (e8a012324 2016-12-16)

$ rustc test.rs 
error: `r` does not live long enough
  --> test.rs:19:5
   |
18 |         let _: &mut T = r.as_mut();
   |                         - borrow occurs here
19 |     }
   |     ^ `r` dropped here while still borrowed
   |
   = note: values in a scope are dropped in the opposite order they are created

error: `r` does not live long enough
  --> test.rs:31:5
   |
30 |         let _: &mut T = r.borrow_mut();
   |                         - borrow occurs here
31 |     }
   |     ^ `r` dropped here while still borrowed
   |
   = note: values in a scope are dropped in the opposite order they are created

error: aborting due to 2 previous errors

return code: 101

A nightly rustc from last week shows only an error in case D.

$ rustc --version
rustc 1.15.0-nightly (71c06a56a 2016-12-18)

$ rustc test.rs 
error: `r` does not live long enough
  --> test.rs:31:5
   |
30 |         let _: &mut T = r.borrow_mut();
   |                         - borrow occurs here
31 |     }
   |     ^ `r` dropped here while still borrowed
   |
   = note: values in a scope are dropped in the opposite order they are created

error: aborting due to previous error

return code: 101

This is strange, as BorrowMut::borrow_mut() and AsMut::as_mut() have the same type signature. So cases B and D should give the same result.

Furthermore, I am not sure why case A and B (or, for that matter, case C and D) behave differently. The only difference is that they use trait objects instead of primitive types, and as far as I understand, this should have no influence on the lifetime behavior.

Metadata

Metadata

Labels

A-type-systemArea: Type systemP-highHigh priorityT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.regression-from-stable-to-betaPerformance or correctness regression from stable to beta.

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions