The example code below is somewhat crafted but illustrates my major concern. The code compiles perfectly.
struct SliceWrapper<'a>(&'a mut[i32]);
impl<'a> SliceWrapper<'a> {
fn clear(&mut self) {
self.0 = &mut [];
}
}
fn main() {
let slice = &mut [1, 2, 3];
let mut wrapper = SliceWrapper(slice);
wrapper.clear();
}
The line self.0 = &mut [];
works but is very strange if we look at their lifetimes: a reference to a local variable is assigned to self.0
, which lives beyond the method call clear()
.
What makes it more confusing is that if I change that line to self.0 = &mut [0];
, then the compiler will throw me an error saying: creates a temporary which is freed while still in use.
So I guess the Rust compiler treats the lifetime of &mut []
differently. Is that true? What is the precise lifetime rule for &mut []
?
Empty array is indeed special-cased by the compiler.
This answer describes the similar yet different case with shared references to constexpr-values. For this case, there is an RFC to make this constexpt-values "promoted to static", i.e. allocated in static memory and not at stack, so that they will live outside the function they're defined in.
And, inside this RFC, we have the following statement:
the compiler already special cases a small subset of rvalue const expressions to have static lifetime - namely the empty array expression:
let x: &'static [u8] = &[];
As for the mutable - or, as will be more relevant here, exclusive, or unique, references, RFC states the following:
It would be possible to extend support to
&'static mut
references, as long as there is the additional constraint that the referenced type is zero sized.
...
The zero-sized restriction is there because aliasing mutable references are only safe for zero sized types (since you never dereference the pointer for them).
This part seems to be not implemented, since this code is invalid:
fn main() {
let _: &'static mut [()] = &mut [()]; // fail, reference to local
}
although [(); 1]
is ZST, as one can check with std::mem::size_of
.
The line
self.0 = &mut [];
works but is very strange if we look at their lifetimes: a reference to a local variable is assigned toself.0
, which lives beyond the method callclear()
.
This is because Rust has rvalue static promotion feature which is explained in another post which @Lukas Kalbertodt pointed in comment,
Please check : Why can I return a reference to a local literal but not a variable?
For the lifetime error in this code:
self.0 = &mut [0];
This is not supported by static promotion from the RFC :
It would be possible to extend support to
&'static mut
references, as long as there is the additional constraint that the referenced type is zero sized.
This is a constraint for static mutability in this feature. It is possible for immutable types.
The code below will work fine for immutable slices.
let _: &'static [u32] = &[1, 2, 3]; // Possible
let _: &'static mut [u32] = &mut [1, 2, 3]; //Not possible
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With