This code doesn’t compiles, and I don’t understand why. Any help is welcome. I tried to give more context, but I don’t think it will make things clearer.
struct Referenced;
struct HasReference<'a> {
referenced: &'a Referenced,
}
struct Output<'a> {
referenced: &'a Referenced,
}
trait T {
fn foo(&self) -> Output;
}
impl<'a> T for HasReference<'a> {
fn foo(&self) -> Output {
Output {
referenced: self.referenced,
}
}
}
impl <'a, Collection> T for &'a Collection
where
&'a Collection: IntoIterator,
<&'a Collection as IntoIterator>::Item: T,
{
fn foo(&self) -> Output {
self.into_iter()
// in reality, there is some filtering
.map(|t| t.foo())
.last()
.unwrap() // in reality foo returns Option<Output>
}
}
Compiling playground v0.0.1 (/playground)
error[E0515]: cannot return value referencing function parameter `t`
--> src/lib.rs:30:22
|
30 | .map(|t| t.foo())
| -^^^^^^
| |
| returns a value referencing data owned by the current function
| `t` is borrowed here
error: aborting due to previous error
For more information about this error, try `rustc --explain E0515`.
error: could not compile `playground`
To learn more, run the command again with --verbose.
I realized that I had to add a lifetime parameter to the trait T to make it work.
In case someone is still interested, here was the context. I’m following the ray tracing in one week-end in Rust.
Referenced are my materials. There are created in main() and can be shared between multiple Objects.
HasReference are the implementation of the trait Object. For example a sphere or a cube. One of properties of the objects is its material. Multiple Objects can share the same Material. The list of all the object of the world is stored in a Vec<Sphere> since I only have sphere currently, but it may become a Vec<Box<dyn Object> in the future.
T is the Object trait. The main function of that trait is to provide a hit() function.
Output is the type returned by the hit() function. That struct contain a copy of the reference to a material referenced in the object.
For example when implementing Object for Sphere, then hit(&self: Sphere<'material>) -> Output<'material>.
I also implemented the Object trait for any collection that contains value implement Object themselves (for example Vec<Sphere> implements Object). In order to abstract over any collection, I’m using IntoIterator<Item: Object>). In that case, what I want is hit(&self: impl IntoIterator<Item: Object<'material>>) -> Output<'material>