Join GitHub today
GitHub is home to over 31 million developers working together to host and review code, manage projects, and build software together.
Sign upInconsistent life time behavior between BorrowMut::borrow_mut() and AsMut::as_mut() #38624
Comments
This comment has been minimized.
This comment has been minimized.
|
There is some discussion of this issue at https://users.rust-lang.org/t/trait-objects-and-borrowmut/8520 |
This comment has been minimized.
This comment has been minimized.
|
Likewise, there is a related Stack Overflow question. The code there boiled down to: use std::borrow::BorrowMut;
trait Foo {}
fn repro(mut foo: Box<Foo>) {
let borrowed: &mut Foo = foo.borrow_mut();
}
fn main() {}
This isn't related to the |
This comment has been minimized.
This comment has been minimized.
|
@rust-lang/compiler Any insight? This looks pretty baffling to me. |
This comment has been minimized.
This comment has been minimized.
|
The change from stable to nightly feels like potentially a regression. I'm not sure of the cause. I'm also not 100% sure of the cause of the original error, although I agree that trait object lifetime defaults is likely part of it. (I'll note that |
This comment has been minimized.
This comment has been minimized.
|
Nominating for prioritization, in case we don't get to it before. |
This comment has been minimized.
This comment has been minimized.
In code, this is: fn repro<'a>(mut foo: Box<Foo + 'a>) {
let borrowed: &mut (Foo + 'a) = foo.borrow_mut();
}
fn repro2(mut foo: Box<Foo>) {
let borrowed: &mut (Foo + 'static) = foo.borrow_mut();
} |
This comment has been minimized.
This comment has been minimized.
|
To be clear, I'm mostly concerned about the change in nightly behavior. |
This comment has been minimized.
This comment has been minimized.
|
(Yes, so, per some conversation with @eddyb, and in line with the earlier comments on the thread, I think the reason an error is reported in the first place is that |
This comment has been minimized.
This comment has been minimized.
|
I believe there should be a coercion but it's not triggering for some reason. |
This comment has been minimized.
This comment has been minimized.
|
Ought it not be |
This comment has been minimized.
This comment has been minimized.
|
|
This comment has been minimized.
This comment has been minimized.
|
@nikomatsakis your analysis was very enlightening, thank you! Could I trouble you to add why let borrowed: &mut Foo = &mut *foo; |
This comment has been minimized.
This comment has been minimized.
No, because the trait appears underneath the
We do have a coercion for
This is because of the coercion that @eddyb mentioned. So, to elaborate, to try and ameliorate this problem, we added a special rule that says if you have a value of type On a related note, one of the changes that I (and others) have been contemplating is to rejigger how the type-checker works to try and have coercions trigger more often (e.g., to allow them to work also in generic cases where the types aren't known up front). But just how effective we can get it is something of an open question. |
eddyb
referenced this issue
Jan 25, 2017
Merged
Perform lifetime elision (more) syntactically, before type-checking. #39305
brson
added
the
T-compiler
label
Jan 26, 2017
nikomatsakis
self-assigned this
Jan 26, 2017
This comment has been minimized.
This comment has been minimized.
|
triage: P-high |
rust-highfive
added
P-high
and removed
I-nominated
labels
Jan 26, 2017
pnkfelix
self-assigned this
Jan 26, 2017
alexcrichton
added a commit
to alexcrichton/rust
that referenced
this issue
Jan 27, 2017
bors
added a commit
that referenced
this issue
Jan 28, 2017
This comment has been minimized.
This comment has been minimized.
|
Minified: pub trait BorrowMut<Borrowed> where Borrowed: ?Sized {
fn borrow_mut(&mut self) -> &mut Borrowed;
}
impl<T> BorrowMut<T> for Box<T> where T: ?Sized {
fn borrow_mut(&mut self) -> &mut T { panic!() }
}
#[cfg(not(works))]
impl<T> BorrowMut<T> for T where T: ?Sized {
fn borrow_mut(&mut self) -> &mut T { panic!() }
}
trait T {}
impl T for u8 {}
fn main() {
// D (BorrowMut and Trait Object):
let mut r: Box<T> = Box::new(23u8);
let _: &mut T = BorrowMut::borrow_mut(&mut r);
} |
brson
added
regression-from-stable-to-beta
and removed
regression-from-stable-to-nightly
labels
Feb 9, 2017
This comment has been minimized.
This comment has been minimized.
|
Anyone want to bisect? @TimNN :) |
This comment has been minimized.
This comment has been minimized.
|
@brson: Sure thing :) |
This comment has been minimized.
This comment has been minimized.
|
The problem is that this code: use std::borrow::BorrowMut;
trait T {}
impl T for u8 {}
fn main() {
let mut r: Box<T> = Box::new(23u8);
let _: &mut T = r.borrow_mut();
}compiles on nightly but not on stable |
This comment has been minimized.
This comment has been minimized.
|
I believe it is due to this PR: #39066 In this case, the change is expected. |
This comment has been minimized.
This comment has been minimized.
|
I confirmed this by checking nightlies; it has the new behavior in 2017-02-02, the closest nightly I could find after the PR landed, but not in 2017-01-26 (before the PR). |
This comment has been minimized.
This comment has been minimized.
|
So essentially this issue -- while confusing -- is working as intended. Shall we close? |
This comment has been minimized.
This comment has been minimized.
|
#39066 does fall into the range of nightlies I bisected this to: Live Edit: Well, @nikomatsakis was a bit faster than me ;) |
This comment has been minimized.
This comment has been minimized.
|
My main concern was, that
I'm still a bit surprised how that difference could even occur in 1.15. Is one of those traits special-cased in the compiler? Isn't the signature the only relevant thing for the borrow checker? |
This comment has been minimized.
This comment has been minimized.
|
@troplin neither is special to the compiler that I know of; I don't know why |
This comment has been minimized.
This comment has been minimized.
|
@troplin ah well also I think @eddyb landed a PR that adjusts how the defaulting works around |
This comment has been minimized.
This comment has been minimized.
|
Yeah, I did mention (on IRC?) that change being a fix to the strictness identified in #38624 (comment). |
This comment has been minimized.
This comment has been minimized.
|
Since both changes here seem to be intentional, closing. |
FabianEmmes commentedDec 26, 2016
The following code shows inconsistent behavior in lifetime checking:
Using the stable compiler 1.14.0, case B and D yield a lifetime error:
A nightly rustc from last week shows only an error in case D.
This is strange, as
BorrowMut::borrow_mut()andAsMut::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.