I need another hand to fully understand lifetime notation, and its proper specification.
Quick summary: I'm building a potentially elaborate nested directed graph of hook instances. Each hook will execute some atomic transformation of the workpiece. In this example the workpiece is a string, but my problem is with lifetime notation of a factory helper function.
since the references are chained, and Rust hates
null
references, we have an Option
.
since the references are among self-referential types, we have the reference in a
Box
— I'm guessing ultimately this will be a dyn Box
, but I'm not there yet.
I can assemble an arbitrary-length hook chain explicitly, no problem there.
My problem is, when I create a function to automate appending a hook on the end of the hook chain, Rust complains about lifetimes. I have tried putting the lifetime notation in ALL possible positions, using all the confections my noob skill knows, and I can't get this to compile. This fails on line 24 — shown here without any failed lifetime-tic notation attempts, so someone can please steer me right.
Also note, the error message also says,
expected 'potato' \n found 'potato'
. Is that a known compiler bug, or is this legit because of potentially several problems that lie beyond this lifetime notation blocker?
Thank you for your patience with me
// Experimenting with hooks in Rust
use std::option::Option;
#[derive(Debug, Clone)]
pub struct Hook<'a> {
pub hook: Option<Box<&'a Hook<'a>>>,
}
pub trait Hooking {
type Thing;
fn sethook<'a>(&self, t: &'a mut Self) -> &'a mut Self;
}
impl Hooking for Hook<'_> {
type Thing = String;
fn sethook<'a>(&self, hook_passed: &'a mut Self) -> &'a mut Self {
match &self.hook {
Some(h) => {
h.sethook(hook_passed);
}
None => {
self.hook = Some(Box::new(hook_passed));
}
}
hook_passed
}
}
fn main() {
let mut h1 = Hook {
hook: None,
};
let h2 = Hook {
hook: None,
};
h1.sethook(&mut h2);
}
Errors:
Compiling playground v0.0.1 (/playground)
error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
--> src/main.rs:24:34
|
24 | self.hook = Some(Box::new(hook_passed));
| ^^^^^^^^^^^^^^^^^^^^^
|
note: first, the lifetime cannot outlive the lifetime `'a` as defined on the method body at 18:16...
--> src/main.rs:18:16
|
18 | fn sethook<'a>(&self, hook_passed: &'a mut Self) -> &'a mut Self {
| ^^
note: ...so that reference does not outlive borrowed content
--> src/main.rs:24:43
|
24 | self.hook = Some(Box::new(hook_passed));
| ^^^^^^^^^^^
note: but, the lifetime must be valid for the lifetime `'_` as defined on the impl at 15:23...
--> src/main.rs:15:23
|
15 | impl Hooking for Hook<'_> {
| ^^
note: ...so that the expression is assignable
--> src/main.rs:24:29
|
24 | self.hook = Some(Box::new(hook_passed));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: expected `std::option::Option<std::boxed::Box<&Hook<'_>>>`
found `std::option::Option<std::boxed::Box<&Hook<'_>>>`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0495`.
error: could not compile `playground`.
To learn more, run the command again with --verbose.