Help with lifetime

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>
    }
}

(Playground)

Errors:

   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.

what exactly are you trying to do here can you please explain in plain English so it might be easier to understand and help

solved!

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>

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.