The opposite of "outlives"?

Sorry to ask what feels like an elementary question, but I can't figure out a set of lifetime bounds to accomplish this situation below, although I don't think it violates any fundamental rules.

In this example, the idea is that the trait implementor only needs to implement slice and gets all the default implementations from the trait.

To make this compile, I need to be able to tell the compile that 'in_self "can't outlive" 'a, but I can't figure out how to do that.

struct MyStruct<'a> {
    ref_member : &'a Vec<u8>
}

trait MyTrait<'a> {
    
    fn slice(&self) -> &'a [u8];

    //This is fine if slice() returns &'a [u8], but fails if the lifetime is elided
    fn into_slice(self) -> &'a [u8] where Self: Sized {
        self.slice()
    }

    //This is the opposite
    //This is fine if slice() returns &[u8] (elided lifetime), but fails if 'a is specified
    fn iter<'in_self>(&'in_self self) -> Box<dyn Iterator<Item=&'in_self u8> + 'in_self> {
        Box::new(self.slice().iter().enumerate().map(move |(idx, _char)| &self.slice()[self.slice().len()-idx-1]))
    }
}

impl <'a>MyTrait<'a> for MyStruct<'a> {

    fn slice(&self) -> &'a [u8] {
        &self.ref_member[..]
    }
}

fn main() {

    let my_struct = MyStruct{ref_member : &[1, 2, 3].to_vec()};
    
    for char in my_struct.iter() {
        println!("{}", char);
    }
    
    for char in my_struct.into_slice().iter() {
        println!("{}", char);
    } 
}

Any insight is appreciated.

Thank you.

Are you looking for this?

fn iter<'in_self>(&'in_self self) -> Box<dyn Iterator<Item=&'in_self u8> + 'in_self>
where
    'a: 'in_self,
{
    Box::new(self.slice().iter().enumerate().map(move |(idx, _char)| &self.slice()[self.slice().len()-idx-1]))
}

There's also this option:

fn iter(&self) -> Box<dyn Iterator<Item=&'a u8> + 'a> {
    let slice = self.slice();
    Box::new(slice.iter().enumerate().map(move |(idx, _char)| &slice[slice.len()-idx-1]))
}
3 Likes

Are you looking for this?

YES!!

I just didn't have the syntax. I guess I mentally always thought of where as a more verbose form of bounds in the definition, but here was a place where bounds wouldn't cut it and where was the trick.

There's also this option:

This actually won't work. That's why I used a map() and borrowed the slice a second time again inside the closure. To illustrate where this approach would fail.

Thank you!

My second option does compile. Of course, it's possible that you have some other structs that override the method with something else where it wouldn't.

1 Like

Ahhh. You moved the borrow so the closure doesn't borrow self anymore.

Sorry I ever doubted you. :star_struck:

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.