Context
Playground, This works:
fn get_owned_box_working<'a>(b: Box<&'a i32>) -> Box<&'static i32> {
Box::new(&42)
}
but this doesn’t:
fn get_owned_box_broken<'a>(b: Box<&'a i32>) -> Box<&'static i32> {
*b = &42;
b
}
error[E0308]: mismatched types
--> src/lib.rs:3:5
|
3 | b
| ^ lifetime mismatch
|
= note: expected struct `Box<&'static i32>`
found struct `Box<&'a i32>`
note: the lifetime `'a` as defined here...
--> src/lib.rs:1:25
|
1 | fn get_owned_box_broken<'a>(b: Box<&'a i32>) -> Box<&'static i32> {
| ^^
= note: ...does not necessarily outlive the static lifetime
Question
- How come the compiler can’t update the lifetime of the existing box from
'a
->'static
when I mutate it? - Is there some way to get this to work without the extra allocation from creating a new box?
>Solution :
How come the compiler can’t update the lifetime of the existing box from
'a
->'static
when I mutate it?
From the compiler point of view, you cannot "update" the value from using 'a
to using 'static
. You are assigning to it, but the type stays the same. Then later you’re trying to convert from Box<&'a i32>
to Box<&'static i32>
, and it rightfully bails.
Is there some way to get this to work without the extra allocation from creating a new box?
Yes, but only using unsafe
: Playground
fn get_owned_box_broken<'a>(s: Box<&'a i32>) -> Box<&'static i32> {
unsafe {
let s = Box::into_raw(s);
let s = s.cast::<&'static i32>();
s.write(&42);
Box::from_raw(s)
}
}
However, think carefully if you need that: it is likely you can afford an allocation.