I'm implementing a stack-like structure, where the structure holds a mutable reference to a slice.
struct StackLike<'a, X> {
data: &'a mut [X],
}
I'd like to be able to pop the last element off this stack, something like:
impl<'a, X> StackLike<'a, X> {
pub fn pop(&mut self) -> Option<&'a X> {
if self.data.is_empty() {
return None;
}
let n = self.data.len();
let result = &self.data[n - 1];
self.data = &mut self.data[0..n - 1];
Some(result)
}
}
This fails:
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter in function call due to conflicting requirements
--> src/lib.rs:11:23
|
11 | let result = &self.data[n - 1];
| ^^^^^^^^^^^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 6:5...
--> src/lib.rs:6:5
|
6 | / pub fn pop(&mut self) -> Option<&'a X> {
7 | | if self.data.is_empty() {
8 | | return None;
9 | | }
... |
13 | | Some(result)
14 | | }
| |_____^
note: ...so that reference does not outlive borrowed content
--> src/lib.rs:11:23
|
11 | let result = &self.data[n - 1];
| ^^^^^^^^^
note: but, the lifetime must be valid for the lifetime `'a` as defined on the impl at 5:6...
--> src/lib.rs:5:6
|
5 | impl<'a, X> StackLike<'a, X> {
| ^^
note: ...so that the expression is assignable
--> src/lib.rs:13:9
|
13 | Some(result)
| ^^^^^^^^^^^^
= note: expected `std::option::Option<&'a X>`
found `std::option::Option<&X>`
Even a simplified version of pop
that doesn't return a value and only shrinks the slice doesn't work.
impl<'a, X> StackLike<'a, X> {
pub fn pop_no_return(&mut self) {
if self.data.is_empty() {
return;
}
let n = self.data.len();
self.data = &mut self.data[0..n - 1];
}
}
which gives
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter in function call due to conflicting requirements
--> src/lib.rs:11:26
|
11 | self.data = &mut self.data[0..n - 1];
| ^^^^^^^^^^^^^^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 6:5...
--> src/lib.rs:6:5
|
6 | / pub fn pop_no_return(&mut self) {
7 | | if self.data.is_empty() {
8 | | return;
9 | | }
10 | | let n = self.data.len();
11 | | self.data = &mut self.data[0..n - 1];
12 | | }
| |_____^
note: ...so that reference does not outlive borrowed content
--> src/lib.rs:11:26
|
11 | self.data = &mut self.data[0..n - 1];
| ^^^^^^^^^
note: but, the lifetime must be valid for the lifetime `'a` as defined on the impl at 5:6...
--> src/lib.rs:5:6
|
5 | impl<'a, X> StackLike<'a, X> {
| ^^
note: ...so that reference does not outlive borrowed content
--> src/lib.rs:11:21
|
11 | self.data = &mut self.data[0..n - 1];
| ^^^^^^^^^^^^^^^^^^^^^^^^
Is there a way to make this work, or do I need to track the bounds of the slice I'm interested in more explicitly?
self.data
starts out empty (because you lose the original slice whensplit_last_mut
returnsNone
). Practically, this probably isn't an issue, because all empty slices are more or less equivalent, but it could lead to surprises if you were doing something tricky with the address of the data. – Zeeba