I have to admit that I generally avoid messing about with lifetimes if I can help it. Which is probably why it is an area of weakness for me.... So now i am trying to convert the following usecase to use references...
I have a manager which looks something like this:
type Mgr = HashMap<String, Box<Material>>;
Material is a trait...
I have a struct which stores a reference to the boxed material.
pub struct Sphere<'a> {
...
pub material: &'a Box<Material + 'a>
}
Sphere implements a Shape trait which has a method, hit, that takes a mutable reference to a HitRecord.
fn hit(&self, &mut HitRecord);
The HitRecord also stores a reference to an Option wrapped reference to a Boxed Material
pub struct HitRecord<'b> {
...
material: Option<&'b Box<Material + 'b>
}
The material gets created first, and stored in a Mgr instance.
The sphere gets created next, with a reference to a material in the Mgr.
in an inner scope, I create a mutable HitRecord. I then call sphere.hit(&mut HitRecord).
the hit method attempts to set the HitRecord's material field to the sphere's material record
hit_record.material = Some(self.material)
And this is where things go tragically wrong. I really don't quite know how to express the lifetimes. I a have two objects that hold on to a reference to a third object which outlives them. I get something like:
hit_record.material = Some(self.material);
| ^^^^^^^^^^^^^^^^^^^
|
note: first, the lifetime cannot outlive the lifetime 'a as defined on the impl at 17:1...
--> src/sphere.rs:17:1
|
17 | impl<'a> Shape for Sphere<'a> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...so that the typestd::boxed::Box<traits::Material + 'a>
is not borrowed for too long
--> src/sphere.rs:23:36
|
23 | hit_record.material = Some(self.material);
| ^^^^^^^^^^^^^
note: but, the lifetime must be valid for the anonymous lifetime #3 defined on the method body at 22:5...
--> src/sphere.rs:22:5
|
22 | / fn hit(&self, hit_record: &mut HitRecord) {
23 | | hit_record.material = Some(self.material);
24 | | }
| |_____^
= note: ...so that the expression is assignable:
expected std::option::Option<&std::boxed::Boxtraits::Material>
found std::option::Option<&std::boxed::Boxtraits::Material>
here is a github repo if you are curious:
renderer-scratch repo