0

I have a file format that is made up of containers of containers. I've memory-mapped the file and each child structure contains a reference to the bytes in that memory-map. I'm trying to implement a Filterable trait that allows me to parse the containers in succession and pull out a vector of child containers.

I've attempted to capture the behavior in the simplified version below. Everything references the same lifetime 'mmap, so I don't see why the compiler is insisting that I have an additional 'static lifetime.

use memmap::MmapOptions; // 0.7.0
use std::fs::File;

type Filtered<'mmap> = Box<dyn Filterable<'mmap>>;
type Collection<'mmap> = Vec<Filtered<'mmap>>;

struct Foo<'mmap> {
    body: &'mmap [u8],
}
struct Bar<'mmap> {
    body: &'mmap [u8],
}

trait Filterable<'mmap> {
    fn filtered(&'mmap self) -> Collection<'mmap>;
}

impl<'mmap> Filterable<'mmap> for Foo<'mmap> {
    fn filtered(&'mmap self) -> Collection<'mmap> {
        let bytes: &'mmap [u8] = self.body;
        vec![Box::new(Bar { body: self.body }) as Filtered<'mmap>]
    }
}

impl<'mmap> Filterable<'mmap> for Bar<'mmap> {
    fn filtered(&'mmap self) -> Collection<'mmap> {
        vec![]
    }
}

fn main() {
    let file = File::open("any_file_will_do").unwrap();
    let mmap = unsafe { MmapOptions::new().map(&file).unwrap() };

    let foo = Foo { body: &mmap };
    let bars = foo.filtered();
}
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'mmap` due to conflicting requirements
  --> src/main.rs:21:23
   |
21 |         vec![Box::new(Bar { body: self.body }) as Filtered<'mmap>]
   |                       ^^^
   |
note: first, the lifetime cannot outlive the lifetime `'mmap` as defined on the impl at 18:6...
  --> src/main.rs:18:6
   |
18 | impl<'mmap> Filterable<'mmap> for Foo<'mmap> {
   |      ^^^^^
note: ...so that reference does not outlive borrowed content
  --> src/main.rs:21:35
   |
21 |         vec![Box::new(Bar { body: self.body }) as Filtered<'mmap>]
   |                                   ^^^^^^^^^
   = note: but, the lifetime must be valid for the static lifetime...
note: ...so that the expression is assignable
  --> src/main.rs:21:14
   |
21 |         vec![Box::new(Bar { body: self.body }) as Filtered<'mmap>]
   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   = note: expected `Box<(dyn Filterable<'mmap> + 'static)>`
              found `Box<dyn Filterable<'mmap>>`
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
  • `type Filtered<'mmap> = Box + 'mmap>` – Shepmaster Jul 27 '21 at 20:43
  • Your question might be answered by the answers of [Why is adding a lifetime to a trait with the plus operator (Iterator + 'a) needed?](https://stackoverflow.com/q/42028470/155423); [Why is &'a Box treated as &'a Box and not &'a Box?](https://stackoverflow.com/q/53049213/155423). If not, please **[edit]** your question to explain the differences. Otherwise, we can mark this question as already answered. – Shepmaster Jul 27 '21 at 20:44
  • As you suggested this worked: `type Filtered<'mmap> = Box + 'mmap>` Thanks! – ahenshaw Jul 28 '21 at 01:24

0 Answers0