I've run into a problem with lifetimes I can't seem to get past. So far I've just put in lifetimes when the compiler yelled at me, but now I've run into a compiler error that doesn't give me a clear idea of how to proceed. (Sorry for the somewhat long example here; it's simplified a fair amount from the original source, but I didn't want to risk simplifying it too much and being unable to translate a solution back to the original code.)
trait MyTrait<T> {
fn get(&self) -> &T;
}
struct Slice<'a, T> {
slice: &'a mut [T],
}
impl<'a, T> MyTrait<T> for Slice<'a, T> {
fn get(&self) -> &T {
&self.slice[0]
}
}
struct Component<'a> {
name: &'a str,
}
struct Metadata<'a, Storage: MyTrait<Component<'a>>> {
components: Storage,
_phantom: std::marker::PhantomData<Component<'a>>,
}
impl<'a, Storage> Metadata<'a, Storage>
where
Storage: MyTrait<Component<'a>>,
{
fn do_mut_stuff(&mut self) {
todo!();
}
}
enum ValidationResult<'a> {
Revoked(&'a Component<'a>),
}
fn validate<'a, MetadataStorage>(
metadata: &'a Metadata<'a, MetadataStorage>,
) -> ValidationResult<'a>
where
MetadataStorage: MyTrait<Component<'a>>,
{
ValidationResult::Revoked(&metadata.components.get())
}
pub fn does_not_compile() {
let mut metadata_storage = Vec::new();
let metadata_storage = Slice {
slice: &mut metadata_storage,
};
let mut metadata = Metadata {
components: metadata_storage,
_phantom: Default::default(),
};
validate(&metadata);
metadata.do_mut_stuff();
}
Errors:
error[E0502]: cannot borrow `metadata` as mutable because it is also borrowed as immutable
--> src/lib.rs:59:5
|
57 | validate(&metadata);
| --------- immutable borrow occurs here
58 |
59 | metadata.do_mut_stuff();
| ^^^^^^^^^------------^^
| | |
| | immutable borrow later used by call
| mutable borrow occurs here
In my mental model, the call to validate
borrows metadata
, and then it returns a struct that references the data in metadata
. Since the return value isn't used, that struct would be immediately dropped and then metadata
would no longer be borrowed. Then the do_mut_stuff
call should succeed since metadata
isn't borrowed anymore. Clearly the compiler sees things differently
Would appreciate any help understanding the error better, and how to solve it. I'd also be interested to know what resources I should be looking at to figure this out myself. Or, coming at it from a different angle, is there any way to get more useful info from the compiler here about why the immutable borrow keeps living?