Reputation: 22193
I would like to be able to obtain references (both immutable and mutable) to the usize
wrapped in Bar
in the Foo
enum:
use Foo::*;
#[derive(Debug, PartialEq, Clone)]
pub enum Foo {
Bar(usize)
}
impl Foo {
/* this works */
fn get_bar_ref(&self) -> &usize {
match *self {
Bar(ref n) => &n
}
}
/* this doesn't */
fn get_bar_ref_mut(&mut self) -> &mut usize {
match *self {
Bar(ref mut n) => &mut n
}
}
}
But I can't obtain the mutable reference because:
n
does not live long enough
I was able to provide both variants of similar functions accessing other contents of Foo
that are Box
ed - why does the mutable borrow (and why only it) fail with an unboxed primitive?
Upvotes: 9
Views: 1033
Reputation: 3861
You need to replace Bar(ref mut n) => &mut n
with Bar(ref mut n) => n
.
When you use ref mut n
in Bar(ref mut n)
, it creates a mutable
reference to the data in Bar
, so the type of n
is &mut usize
.
Then you try to return &mut n
of &mut &mut u32
type.
This part is most likely incorrect.
Now deref coercion kicks in and converts
&mut n
into&mut *n
, creating a temporary value*n
of typeusize
, which doesn't live long enough.
Upvotes: 8
Reputation: 784
These examples show the sample problem:
fn implicit_reborrow<T>(x: &mut T) -> &mut T {
x
}
fn explicit_reborrow<T>(x: &mut T) -> &mut T {
&mut *x
}
fn implicit_reborrow_bad<T>(x: &mut T) -> &mut T {
&mut x
}
fn explicit_reborrow_bad<T>(x: &mut T) -> &mut T {
&mut **&mut x
}
The explicit_
versions show what the compiler deduces through deref coercions.
The _bad
versions both error in the exact same way, while the other two compile.
This is either a bug, or a limitation in how lifetimes are currently implemented in the compiler. The invariance of &mut T
over T
might have something to do with it, because it results in &mut &'a mut T
being invariant over 'a
and thus more restrictive during inference than the shared reference (&&'a T
) case, even though in this situation the strictness is unnecessary.
Upvotes: 7