I've recently come across a borrow checker message I've never seen before which I'm trying to understand. Here is the code to reproduce it (simplified, real-life example was more complex) - playground:
fn foo(v1: &mut Vec<u8>, v2: &mut Vec<u8>, which: bool) {
let dest = if which { &mut v1 } else { &mut v2 };
dest.push(1);
}
It fails to compile with the following error:
error[E0623]: lifetime mismatch
--> src/main.rs:2:44
|
1 | fn foo(v1: &mut Vec<u8>, v2: &mut Vec<u8>, which: bool) {
| ------------ ------------ these two types are declared with different lifetimes...
2 | let dest = if which { &mut v1 } else { &mut v2 };
| ^^^^^^^ ...but data from `v2` flows into `v1` here
...followed by another one about data flowing from v1 into v2.
My question is: what does this error mean? What is data flow and how does it occur between the two variables, given that the code is only pushing Copy data to one of them?
If I follow the compiler and force the lifetimes of v1 and v2 to match, the function compiles (playground):
fn foo<'a>(mut v1: &'a mut Vec<u8>, mut v2: &'a mut Vec<u8>, which: bool) {
let dest = if which { &mut v1 } else { &mut v2 };
dest.push(1);
}
However, on further inspection it turned out that the original code was needlessly complex, left over from when v1 and v2 were actual Vecs, and not references. A simpler and more natural variant is to set dest not to &mut v1 and &mut v2, but to the simpler v1 and v2, which are references to begin with. And that compiles too (playground):
fn foo(v1: &mut Vec<u8>, v2: &mut Vec<u8>, which: bool) {
let dest = if which { v1 } else { v2 };
dest.push(1);
}
In this seemingly equivalent formulation lifetimes of v1 and v2 matching are no longer a requirement.
The problem is that &'a mut T is invariant over T.
First, let's look at the working code:
fn foo(v1: &mut Vec<u8>, v2: &mut Vec<u8>, which: bool) {
let dest = if which { v1 } else { v2 };
dest.push(1);
}
The types of v1 and v2 have elided lifetime parameters. Let's make them explicit:
fn foo<'a, 'b>(v1: &'a mut Vec<u8>, v2: &'b mut Vec<u8>, which: bool) {
let dest = if which { v1 } else { v2 };
dest.push(1);
}
The compiler has to figure out the type of dest. The two branches of the if expression produce values of different types: &'a mut Vec<u8> and &'b mut Vec<u8>. Despite that, the compiler is able to figure out a type that is compatible with both types; let's call this type &'c mut Vec<u8>, where 'a: 'c, 'b: 'c. &'c mut Vec<u8> here is a common supertype of both &'a mut Vec<u8> and &'b mut Vec<u8>, because both 'a and 'b outlive 'c (i.e. 'c is a shorter/smaller lifetime than either 'a or 'b).
Now, let's examine the erroneous code:
fn foo<'a, 'b>(v1: &'a mut Vec<u8>, v2: &'b mut Vec<u8>, which: bool) {
let dest = if which { &mut v1 } else { &mut v2 };
dest.push(1);
}
Again, the compiler has to figure out the type of dest. The two branches of the if expression produce values of types: &'c mut &'a mut Vec<u8> and &'d mut &'b mut Vec<u8> respectively (where 'c and 'd are fresh lifetimes).
I said earlier that &'a mut T is invariant over T. What this means is that we can't change the T in &'a mut T such that we can produce a subtype or supertype of &'a mut T. Here, the T types are &'a mut Vec<u8> and &'b mut Vec<u8>. They are not the same type, so we must conclude that the types &'c mut &'a mut Vec<u8> and &'d mut &'b mut Vec<u8> are unrelated. Therefore, there is no valid type for dest.
What you have here is a variation of this erroneous program:
fn foo(x: &mut Vec<&u32>, y: &u32) {
x.push(y);
}
The error messages used to be a bit more vague but were changed with this pull request. This is a case of Variance, which you can read more about in the nomicon if you are interested. It is a complex subject but I will try my best to explain the quick and short of it.
Unless you specify the lifetimes, when you return &mut v1 or &mut v2 from your if statement, the types are determined by the compiler to have different lifetimes, thus returning a different type. Therefore the compiler can't determine the correct lifetime (or type) for dest. When you explicitly set all lifetimes to be the same, the compiler now understands that both branches of the if statement return the same lifetime and it can figure out the type of dest.
In the example above x has a different lifetime from y and thus a different type.
Related
Parameters can be passed to functions and modified:
fn set_42(int: &mut i32) {
*int += 42;
}
fn main() {
let mut int = 0;
set_42(&mut int);
println!("{:?}", int);
}
Output:
42
Changing the code to use a slice fails with a whole bunch of errors:
fn pop_front(slice: &mut [i32]) {
*slice = &{slice}[1..];
}
fn main() {
let mut slice = &[0, 1, 2, 3][..];
pop_front(&mut slice);
println!("{:?}", slice);
}
Output:
error[E0308]: mismatched types
--> src/main.rs:2:14
|
2 | *slice = &{ slice }[1..];
| ^^^^^^^^^^^^^^^
| |
| expected slice `[i32]`, found `&[i32]`
| help: consider removing the borrow: `{ slice }[1..]`
error[E0277]: the size for values of type `[i32]` cannot be known at compilation time
--> src/main.rs:2:5
|
2 | *slice = &{ slice }[1..];
| ^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `[i32]`
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
= note: the left-hand-side of an assignment must have a statically known size
If we try using a mutable slice (which isn't what I really want; I don't want to modify the values within the slice, I just want to modify the slice itself so it covers a smaller range of elements) and a mutable parameter, it has no effect on the original slice:
fn pop_front(mut slice: &mut [i32]) {
slice = &mut {slice}[1..];
}
fn main() {
let mut slice = &mut [0, 1, 2, 3][..];
pop_front(&mut slice);
println!("{:?}", slice);
}
Output:
[0, 1, 2, 3]
Is there a way to modify a slice that's a function parameter? I don't want to modify the elements within the slice; I just want to modify the range of the slice itself so it becomes a smaller "sub-slice".
As others have said, the core idea here is to take a &mut &... [T] (where ... is mut or empty) and read/write to the internal slice. The other answers demonstrate it is possible for &mut &[T] in safe code, and possible for &mut &mut [T] with unsafe code, but they don't explain why there's the difference... and &mut &mut [T] is possible with safe code too.
In explicit-lifetime terms, the nested reference is something like &'a mut &'b ... [T] for some lifetimes 'a and 'b, and the goal here is to get a &'b ... [T], slice it and write that into the &'a mut.
For &'a mut &'b [T], this is easy: &[T] is copy, so writing *slice = &slice[1..] will effectively copy the &'b [T] out of the &mut and then, later, overwrite the existing value with the shorter one. The copy means that one literally gets a &'b [T] to operate with, and so there's no direct connection between that and the &'a mut, and hence it is legal to mutate. It is effectively something like
fn pop_front<'a, 'b>(slice: &'a mut &'b[i32]) {
// *slice = &slice[1..] behaves like
let value: &'b [i32] = *slice;
*slice = &value[1..]
}
(I've labelled the lifetimes and annotated the type to tie into my explanation, but this is not required for the code to work.)
For &'a mut &'b mut [T] things are a little trickier: &mut [T] cannot be copied: dereferencing won't copy, it will reborrow to give a &'a mut [T] i.e. the slice has a lifetime that is connected to the outer &'a mut, not the inner &'b mut [T]. This means the sliced reference has a shorter lifetime than the type it is trying to overwrite, so it's invalid to store the slice into that position. In other words:
fn pop_front<'a, 'b>(slice: &'a mut &'b mut [i32]) {
let value: &'a mut [i32] = &mut **slice;
*slice = &mut value[1..] // error
}
The way to do this safely for &'a mut &'b mut [T] is to get the internal slice out of the reference with that 'b lifetime. This requires keeping track of the "one owner" rule, doing no borrowing, and the best function for this sort of ownership manipulation is mem::replace. It allows us to extract the inner &'b mut [T] by swapping it with some placeholder, which we can then overwrite with the short version. The best/only placeholder is an empty array: writing &mut [] can be a &'c mut [X] for any type X and any lifetime 'c, since there's no data to store and so nothing needs initialisation, and no data will ever become invalid. In particular, it can be a &'b mut [T]:
fn pop_front<'a, 'b>(slice: &'a mut &'b mut [i32]) {
let value: &'b mut [i32] = mem::replace(slice, &mut []);
*slice = &mut value[1..]
}
Since &mut[T] implements Default, we can also use mem::take:
fn pop_front<'a, 'b>(slice: &'a mut &'b mut [i32]) {
let value: &'b mut [i32] = mem::take(slice);
*slice = &mut value[1..]
}
(As above, I've made things more explicit than necessary.)
See also:
Why can't I assign one dereference of a reference of a reference to another when the outer lifetimes differ?
Why does linking lifetimes matter only with mutable references?
How can I swap in a new value for a field in a mutable reference to a structure?
If you need to modify an immutable slice, see Cornstalks's answer.
You cannot modify a mutable slice in safe Rust. When you take a subslice of a mutable slice, you effectively borrow from the original slice. This means that the subslice must not outlive the original slice.
You want something that looks like this:
fn pop_front(slice: &mut &mut [i32]) {
*slice = &mut slice[1..];
}
but the subslice slice[1..] is only valid until the end of the function, and which point the borrow will end and the original slice (the slice parameter) will be usable again.
We can use some unsafe code to construct manually the slice we want:
use std::slice;
fn pop_front(slice: &mut &mut [i32]) {
let ptr = slice.as_mut_ptr();
let len = slice.len();
*slice = unsafe { slice::from_raw_parts_mut(ptr.offset(1), len - 1) };
}
fn main() {
let mut slice = &mut [0, 1, 2, 3][..];
pop_front(&mut slice);
println!("{:?}", slice);
}
playground
This program outputs:
[1, 2, 3]
Using part of Francis Gagné's answer (I didn't think of trying &mut &), I was able to get it working without using unsafe code:
fn pop_front(mut slice: &mut &[i32]) {
*slice = &slice[1..];
}
fn main() {
let mut slice = &[0, 1, 2, 3][..];
pop_front(&mut slice);
println!("{:?}", slice);
}
Output:
[1, 2, 3]
I was implementing linked lists by following along too many linked lists. When trying to implement iter_mut(), I did it myself and made the following code:
type Link<T> = Option<Box<Node<T>>>;
pub struct List<T> {
head: Link<T>,
}
struct Node<T> {
elem: T,
next: Link<T>,
}
impl<T> List<T> {
pub fn iter_mut(&mut self) -> IterMut<T> {
IterMut::<T>(&mut self.head)
}
}
pub struct IterMut<'a, T>(&'a mut Link<T>);
impl<'a, T> Iterator for IterMut<'a, T> {
type Item = &'a mut T;
fn next<'b>(&'b mut self) -> Option<&'a mut T> {
self.0.as_mut().map(|node| {
self.0 = &mut (**node).next;
&mut (**node).elem
})
}
}
I am to avoiding coersions and elisions because being explicit lets me understand more.
Error:
error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements
--> src/third.rs:24:16
|
24 | self.0.as_mut().map(|node| {
| ^^^^^^
|
note: first, the lifetime cannot outlive the lifetime `'b` as defined on the method body at 23:13...
--> src/third.rs:23:13
|
23 | fn next<'b>(&'b mut self) -> Option<&'a mut T> {
| ^^
note: ...so that reference does not outlive borrowed content
--> src/third.rs:24:9
|
24 | self.0.as_mut().map(|node| {
| ^^^^^^
note: but, the lifetime must be valid for the lifetime `'a` as defined on the impl at 20:6...
--> src/third.rs:20:6
|
20 | impl<'a, T> Iterator for IterMut<'a, T> {
| ^^
note: ...so that reference does not outlive borrowed content
--> src/third.rs:25:22
|
25 | self.0 = &mut (**node).next;
| ^^^^^^^^^^^^^^^^^^
error: aborting due to previous error
For more information about this error, try `rustc --explain E0495`.
I have looked at Cannot infer an appropriate lifetime for autoref due to conflicting requirements.
I understand a bit but not much. The problem that I am facing here is that if I try to change anything, an error pops saying that can't match the trait definition.
My thought was that basically I need to state somehow that lifetime 'b outlives 'a i.e <'b : 'a> but I can't figure out how to do it. Also, I have similar functions to implement iter() which works fine. It confuses me why iter_mut() produces such errors.
Iter
type Link<T> = Option<Box<Node<T>>>;
pub struct Iter<'a, T>(&'a Link<T>);
impl<'a, T> Iterator for Iter<'a, T> {
type Item = &'a T;
fn next(&mut self) -> Option<Self::Item> {
self.0.as_ref().map(|node| {
self.0 = &((**node).next);
&((**node).elem)
})
}
}
impl<T> List<T> {
pub fn iter(&self) -> Iter<T> {
Iter::<T>(&self.head)
}
}
☝️This works.
The key thing is that you need to be able to somehow extract an Option<&'a mut T> from a &'b mut IterMut<'a, T>.
To understand why IterMut<'a, T> := &'a mut Link<T> can't work, you need to understand what exactly you can do with a mutable reference. The answer, of course, is almost everything. You can copy data out of it, change its value, and lots of other things. The one thing you can't do is invalidate it. If you want to move the data under the mutable reference out, it has to be replaced with something of the same type (including lifetimes).
Inside the body of next, self is (essentially) &'b mut &'a mut Link<T>. Unless we know something about T (and we can't in this context), there's simply no way to produce something of type &'a mut Link<T> from this. For example, if this were possible in general, we'd be able to do
fn bad<'a, 'b, T>(_x: &'b mut &'a mut T) -> &'a mut T {
todo!()
}
fn do_stuff<'a>(x: &'a mut i32, y: &'a mut i32) {
// lots of stuff that only works if x and y don't alias
*x = 13;
*y = 42;
}
fn main() {
let mut x: &mut i32 = &mut 0;
let y: &mut i32 = {
let z: &mut &mut i32 = &mut x;
bad(z)
};
// `x` and `y` are aliasing mutable references
// and we can use both at once!
do_stuff(x, y);
}
(playground link)
The point is that if we were able to borrow something for a short (generic) lifetime 'b and return something that allowed modification during the longer lifetime 'a, we'd be able to use multiple short lifetimes (shorter than 'a and non-overlapping) to get multiple mutable references with the same lifetime 'a.
This also explains why the immutable version works. With immutable references, it's trivial to go from &'b &'a T to &'a T: just deference and copy the immutable reference. By contrast, mutable references don't implement Copy.
So if we can't produce a &'a mut Link<T> from a &'b mut &'a mut Link<T>, we certainly can't get an Option<&'a mut T out of it either (other than None). (Note that we can produce a &'b mut Link<T> and hence an Option<'b mut T>. That's what your code does right now.)
So what does work? Remember our goal is to be able to produce an Option<&'a mut T> from a &'b mut IterMut<'a, T>.
If we were able to produce a IterMut<'a, T> unconditionally, we'd be able to (temporarily) replace self with it and hence be able to directly access the IterMut<'a, T> associated to our list.
// This actually type-checks!
fn next<'b>(&'b mut self) -> Option<&'a mut T> {
let mut temp: IterMut<'a, T> = todo!(); // obviously this won't work
std::mem::swap(&mut self.0, &mut temp.0);
temp.0.as_mut().map(|node| {
self.0 = &mut node.next;
&mut node.elem
})
}
(playground link)
The easiest way to set things up so that this all works is by transposing IterMut<'a, T> a bit. Rather than having the mutable reference outside the option, make it inside! Now you'll always be able to produce an IterMut<'a, T> with None!
struct IterMut<'a, T>(Option<&mut Box<Node<T>>>);
Translating next, we get
fn next<'b>(&'b mut self) -> Option<&'a mut T> {
let mut temp: IterMut<'a, T> = IterMut(None);
std::mem::swap(&mut self.0, &mut temp.0);
temp.0.map(|node| {
self.0 = node.next.as_mut();
&mut node.elem
})
}
More idiomatically, we can use Option::take rather than std::mem::swap (This is mentioned earlier in Too Many Linked Lists).
fn next<'b>(&'b mut self) -> Option<&'a mut T> {
self.0.take().map(|node| {
self.0 = node.next.as_mut();
&mut node.elem
})
}
(playground link)
This actually ends up being slightly different than the implementation in Too Many Linked Lists. That implementation removes the double indirection of &mut Box<Node<T>> and replaces it with simply &mut Node<T>. However, I'm not sure how much you gain since that implementation still has a double deref in List::iter_mut and Iterator::next.
Rust is trying to say that you have a dangling reference.
self.0.as_mut() // value borrowed
self.0 = <> // underlying value changed here.
The problem is the following definition:
pub struct IterMut<'a, T>(&'a mut Link<T>)
This can't encapsulate that you will have a "empty" node meaning reached the end of the node.
Use the structure as mentioned in the book like:
pub struct IterMut<'a, T>(Option<&'a mut Node<T>>);
This ensures that you can leave None in its place when you run end of list and use take to modify the IterMut content behind the scenes.
I want to write the following function:
fn foo<'a, 'b, 'c>(rr1: &'a mut &'c mut u32, rr2: &'b mut &'c mut u32) {
*rr1 = *rr2;
}
But the compiler complains:
error[E0623]: lifetime mismatch
--> src/lib.rs:2:12
|
1 | fn foo<'a, 'b, 'c>(rr1: &'a mut &'c mut u32, rr2: &'b mut &'c mut u32) {
| ----------- ------------------- these two types are declared with different lifetimes...
2 | *rr1 = *rr2;
| ^^^^ ...but data from `rr2` flows into `rr1` here
My mental model of Rust's lifetimes does not agree that the code is wrong. I read the type of rr2 as "A reference with lifetime 'b to a reference with lifetime 'c to an u32". Thus when I dereference rr2, I get a reference with lifetime 'c to an u32. This should be safe to store in *rr1, which has the same type.
If I require that 'b outlives 'c, it works:
fn foo<'a, 'b: 'c, 'c>(rr1: &'a mut &'c mut u32, rr2: &'b mut &'c mut u32) {
*rr1 = *rr2;
}
This makes me think that the type &'b mut &'c mut u32 means the u32 at the end of the reference chain is only available during the intersection of 'b and 'c.
What is the right explanation for Rust's behavior here? And why do references of references behave this way instead of the way I thought they do?
You cannot dereference a &'b mut &'c mut u32 and get a &'c mut u32 because:
&mut references are not trivially copiable, so you can't copy the &'c mut u32; and
You cannot move out of a reference, so you also can't move the &'c mut u32 (which would leave the outer reference dangling).
Instead, the compiler reborrows the u32 with the outer lifetime, 'b. This is why you get an error message that data from rr2 flows into rr1.
If foo were allowed to compile, you could use it to get two &mut references to the same u32, which is forbidden by the rules of references:
let (mut x, mut y) = (10, 20);
let mut rx = &mut x;
let mut ry = &mut y;
foo(&mut rx, &mut ry); // rx and ry now both refer to y
std::mem::swap(rx, ry); // undefined behavior!
If I require that 'b outlives 'c, it works
Because 'c must already outlive 'b¹, if you require that 'b also outlives 'c, it follows that 'c = 'b. The updated signature is equivalent to this:
fn foo<'a, 'b>(rr1: &'a mut &'b mut u32, rr2: &'b mut &'b mut u32)
That is, you have unified 'c and 'b, and now there's no problem borrowing a &'b mut u32 from rr2 because the inner and outer lifetimes both live for 'b. However, the compiler now won't let you write the broken code in the example I gave earlier, since ry is already borrowed for its entire lifetime.
Interestingly, if you make the inner reference non-mut, it also works:
fn foo<'a, 'b, 'c>(rr1: &'a mut &'c u32, rr2: &'b mut &'c u32) {
*rr1 = *rr2;
}
This is because & references are Copy, so *rr2 is not a reborrow, but actually just a copy of the inner value.
For more information, read:
Why does linking lifetimes matter only with mutable references?
How can I modify a slice that is a function parameter?
¹ It might not be obvious why 'c outlives 'b when there is no explicit 'c: 'b bound. The reason is because the compiler assumes that the type &'b mut &'c mut u32 is well-formed. Well-formedness can become complex (see RFC 1214) but in this case it just means you can't have a reference that's valid for longer ('b) than the thing it references ('c).
The following code fails to compile because MutRef is not Copy. It can not be made copy because &'a mut i32 is not Copy. Is there any way give MutRef similar semantics to &'a mut i32?
The motivation for this is being able to package up a large set of function parameters into a struct so that they can be passed as a group instead of needing to be passed individually.
struct MutRef<'a> {
v: &'a mut i32
}
fn wrapper_use(s: MutRef) {
}
fn raw_use(s: &mut i32) {
}
fn raw_ref() {
let mut s: i32 = 9;
let q = &mut s;
raw_use(q);
raw_use(q);
}
fn wrapper() {
let mut s: i32 = 9;
let q = MutRef{ v: &mut s };
wrapper_use(q);
wrapper_use(q);
}
No.
The name for this feature is "implicit reborrowing" and it happens when you pass a &mut reference where the compiler expects a &mut reference of a possibly different lifetime. The compiler only implicitly reborrows when the actual type and the expected type are both &mut references. It does not work with generic arguments or structs that contain &mut references. There is no way in current Rust to make a custom type that can be implicitly reborrowed. There is an open issue about this limitation dating from 2015, but so far nobody has proposed any way to lift it.
You can always implement your own method to explicitly reborrow:
impl<'a> MutRef<'a> {
// equivalent to fn reborrow(&mut self) -> MutRef<'_>
fn reborrow<'b>(&'b mut self) -> MutRef<'b> {
MutRef {v: self.v}
}
}
fn wrapper() {
let mut s: i32 = 9;
let mut q = MutRef{ v: &mut s };
wrapper_use(q.reborrow()); // does not move q
wrapper_use(q); // moves q
}
See also
Why is the mutable reference not moved here?
Type inference and borrowing vs ownership transfer
Parameters can be passed to functions and modified:
fn set_42(int: &mut i32) {
*int += 42;
}
fn main() {
let mut int = 0;
set_42(&mut int);
println!("{:?}", int);
}
Output:
42
Changing the code to use a slice fails with a whole bunch of errors:
fn pop_front(slice: &mut [i32]) {
*slice = &{slice}[1..];
}
fn main() {
let mut slice = &[0, 1, 2, 3][..];
pop_front(&mut slice);
println!("{:?}", slice);
}
Output:
error[E0308]: mismatched types
--> src/main.rs:2:14
|
2 | *slice = &{ slice }[1..];
| ^^^^^^^^^^^^^^^
| |
| expected slice `[i32]`, found `&[i32]`
| help: consider removing the borrow: `{ slice }[1..]`
error[E0277]: the size for values of type `[i32]` cannot be known at compilation time
--> src/main.rs:2:5
|
2 | *slice = &{ slice }[1..];
| ^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `[i32]`
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
= note: the left-hand-side of an assignment must have a statically known size
If we try using a mutable slice (which isn't what I really want; I don't want to modify the values within the slice, I just want to modify the slice itself so it covers a smaller range of elements) and a mutable parameter, it has no effect on the original slice:
fn pop_front(mut slice: &mut [i32]) {
slice = &mut {slice}[1..];
}
fn main() {
let mut slice = &mut [0, 1, 2, 3][..];
pop_front(&mut slice);
println!("{:?}", slice);
}
Output:
[0, 1, 2, 3]
Is there a way to modify a slice that's a function parameter? I don't want to modify the elements within the slice; I just want to modify the range of the slice itself so it becomes a smaller "sub-slice".
As others have said, the core idea here is to take a &mut &... [T] (where ... is mut or empty) and read/write to the internal slice. The other answers demonstrate it is possible for &mut &[T] in safe code, and possible for &mut &mut [T] with unsafe code, but they don't explain why there's the difference... and &mut &mut [T] is possible with safe code too.
In explicit-lifetime terms, the nested reference is something like &'a mut &'b ... [T] for some lifetimes 'a and 'b, and the goal here is to get a &'b ... [T], slice it and write that into the &'a mut.
For &'a mut &'b [T], this is easy: &[T] is copy, so writing *slice = &slice[1..] will effectively copy the &'b [T] out of the &mut and then, later, overwrite the existing value with the shorter one. The copy means that one literally gets a &'b [T] to operate with, and so there's no direct connection between that and the &'a mut, and hence it is legal to mutate. It is effectively something like
fn pop_front<'a, 'b>(slice: &'a mut &'b[i32]) {
// *slice = &slice[1..] behaves like
let value: &'b [i32] = *slice;
*slice = &value[1..]
}
(I've labelled the lifetimes and annotated the type to tie into my explanation, but this is not required for the code to work.)
For &'a mut &'b mut [T] things are a little trickier: &mut [T] cannot be copied: dereferencing won't copy, it will reborrow to give a &'a mut [T] i.e. the slice has a lifetime that is connected to the outer &'a mut, not the inner &'b mut [T]. This means the sliced reference has a shorter lifetime than the type it is trying to overwrite, so it's invalid to store the slice into that position. In other words:
fn pop_front<'a, 'b>(slice: &'a mut &'b mut [i32]) {
let value: &'a mut [i32] = &mut **slice;
*slice = &mut value[1..] // error
}
The way to do this safely for &'a mut &'b mut [T] is to get the internal slice out of the reference with that 'b lifetime. This requires keeping track of the "one owner" rule, doing no borrowing, and the best function for this sort of ownership manipulation is mem::replace. It allows us to extract the inner &'b mut [T] by swapping it with some placeholder, which we can then overwrite with the short version. The best/only placeholder is an empty array: writing &mut [] can be a &'c mut [X] for any type X and any lifetime 'c, since there's no data to store and so nothing needs initialisation, and no data will ever become invalid. In particular, it can be a &'b mut [T]:
fn pop_front<'a, 'b>(slice: &'a mut &'b mut [i32]) {
let value: &'b mut [i32] = mem::replace(slice, &mut []);
*slice = &mut value[1..]
}
Since &mut[T] implements Default, we can also use mem::take:
fn pop_front<'a, 'b>(slice: &'a mut &'b mut [i32]) {
let value: &'b mut [i32] = mem::take(slice);
*slice = &mut value[1..]
}
(As above, I've made things more explicit than necessary.)
See also:
Why can't I assign one dereference of a reference of a reference to another when the outer lifetimes differ?
Why does linking lifetimes matter only with mutable references?
How can I swap in a new value for a field in a mutable reference to a structure?
If you need to modify an immutable slice, see Cornstalks's answer.
You cannot modify a mutable slice in safe Rust. When you take a subslice of a mutable slice, you effectively borrow from the original slice. This means that the subslice must not outlive the original slice.
You want something that looks like this:
fn pop_front(slice: &mut &mut [i32]) {
*slice = &mut slice[1..];
}
but the subslice slice[1..] is only valid until the end of the function, and which point the borrow will end and the original slice (the slice parameter) will be usable again.
We can use some unsafe code to construct manually the slice we want:
use std::slice;
fn pop_front(slice: &mut &mut [i32]) {
let ptr = slice.as_mut_ptr();
let len = slice.len();
*slice = unsafe { slice::from_raw_parts_mut(ptr.offset(1), len - 1) };
}
fn main() {
let mut slice = &mut [0, 1, 2, 3][..];
pop_front(&mut slice);
println!("{:?}", slice);
}
playground
This program outputs:
[1, 2, 3]
Using part of Francis Gagné's answer (I didn't think of trying &mut &), I was able to get it working without using unsafe code:
fn pop_front(mut slice: &mut &[i32]) {
*slice = &slice[1..];
}
fn main() {
let mut slice = &[0, 1, 2, 3][..];
pop_front(&mut slice);
println!("{:?}", slice);
}
Output:
[1, 2, 3]