0

This is a follow up to this question

I have another enum:

enum InfoP<'a, 'b> {
    Imut(&'a Info<'b>),
    Mut(&'a mut Info<'b>),
}

So I tried the solution:

impl<'a, 'b> InfoP<'a, 'b> {
    fn reborrow(self: &mut InfoP<'a, 'b>) -> InfoP<'a, 'b> {
        match *self {
            InfoP::Imut(info) => InfoP::Imut(info),
            InfoP::Mut(ref mut info) => InfoP::Mut(*info),
        }
    }
}

Hoever this doesn't work

lifetime may not live long enough

associated function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'1` 

How can I fix this?

playground

2 Answers2

2

When you reborrow (rather than moving) a mutable reference, the resulting lifetime is always shorter. The problem here is that your function signature does not reflect this. You have:

fn reborrow(self: &mut InfoP<'a, 'b>) -> InfoP<'a, 'b> {
//                                             ^^
//                                             too long

You need instead:

fn reborrow<'s>(self: &'s mut InfoP<'a, 'b>) -> InfoP<'s, 'b> {
//                                                    ^^

That is, the lifetime of the reference that will be returned inside InfoP is (no longer than) the lifetime 's of the incoming self borrow, not the &'a mut it contains.

Playground

Kevin Reid
  • 37,492
  • 13
  • 80
  • 108
0

Assuming you want to keep ownership of the Info struct while using the enum, to achieve this is to ensure that the owner of the Info struct outlives the 'a lifetime parameter of the enum. This means that the owner of the Info struct should exist for as long as any references to it exist in the enum variants.

struct Info<'a> {
    data: &'a str,
}
enum InfoP<'a, 'b> {
    Imut(&'a Info<'b>),
    Mut(&'a mut Info<'b>),
}
fn main() {
    let data = "example";
    let mut info = Info { data };
    let mut info_p = get_info_p(&mut info);
    match info_p {
        InfoP::Imut(ref i) => println!("Imut: {}", i.data),
        InfoP::Mut(ref mut i) => {
            i.data = "modified";
            println!("Mut: {}", i.data);
        }
    }
}
fn get_info_p<'a, 'b>(info: &'a Info<'b>) -> InfoP<'a, 'b> {
    // Return the enum variant with an immutable reference
    InfoP::Imut(info)
}

The Info struct is created in the main function and passed to the "get_info_p" function, which returns an "InfoP" enum with an immutable reference to the "Info" struct. The "'a" lifetime parameter of the enum is tied to the lifetime of the "info" parameter, which means that the owner of the "Info" struct (in this case, the main function) must exist for as long as the "info_p" variable exists.

Rayeez
  • 1
  • 2