Jarod
Jarod

Reputation: 1702

Need help on lifetime issue

pub struct Decoder<'a> {
    reader: &'a mut io::Reader+'a,
}

impl<'a> Decoder<'a> {
    pub fn from_reader(r: &'a mut io::Reader) -> Decoder<'a> {
        Decoder {
            reader: r,
        }
    }
}

// shortcut method to accept bytes to decode
pub fn decode<'a, T: Decodable<Decoder<'a>, IoError>>(data: Vec<u8>) -> DecodeResult<T> {
    let mut r = MemReader::new(data);
    let mut decoder = Decoder::from_reader(&mut r); // error: `r` does not live long enough
    Decodable::decode(&mut decoder)
}

I have two question here.

  1. How do you read this declaration(what it means) reader: &'a mut io::Reader+'a. Which I was referencing the code from the std json encoder.
  2. I write a shortcut method to wrap Vec<u8> with MemReader, so that I can just interfacing io::Reader. But the compiler complains error:rdoes not live long. How to make it right.

Update: I upload the code to github.

Upvotes: 0

Views: 107

Answers (1)

Francis Gagn&#233;
Francis Gagn&#233;

Reputation: 65712

  1. The first 'a means that the Reader object itself has lifetime 'a. The second 'a means that the Reader object doesn't contain references that outlive 'a. Since Reader is a trait, it could be implemented by a struct that has lifetime parameters. This bound applies to those potential lifetime parameters.

  2. The problem is with the bound on T: Decodable<Decoder<'a>, IoError> references the lifetime parameter 'a. However, the Decoder you're creating references a local variable, whereas 'a refers to a lifetime that lives longer than the function call (because it's an input parameter specified implicitly at the call site).

    I think there's no way to make this function compile successfully without unsafe code for the moment. In fact, Encoder::buffer_encode seems to be having the same issue (#14302) and uses a similar workaround. transmute allows us to coerce the local lifetime to 'a.

    pub fn decode<'a, T: Decodable<Decoder<'a>, IoError>>(data: Vec<u8>) -> DecodeResult<T> {
        let mut r = MemReader::new(data);
        let mut decoder = unsafe { mem::transmute(Decoder::from_reader(&mut r)) };
        Decodable::decode(&mut decoder)
    }
    

Upvotes: 1

Related Questions