Help: indicate the anonymous lifetimes

I have a method to parse HTTP request via httparse crate.

async fn parse_request<IO>(&self, stream: &mut IO) -> Result<httparse::Request, Error>
        where IO: AsyncRead + AsyncWrite + Unpin
{
    // ....
    let mut req = httparse::Request::new(&mut headers);
    
    // .....

    
    Ok(req)
}

This method returns a httparse::Request on success. but that causes compliation error.

    |
111 |     async fn parse_request<IO>(&self, stream: &mut IO) -> Result<httparse::Request, Error>
    |                                                                  ^^^^^^^^^^^^^^^^^- help: indicate the anonymous lifetimes: `<'_, '_>`

I try to solve this error but no success.

async fn parse_request<IO, 'a>(&self, stream: &mut IO) -> Result<'a httparse::Request, Error>

How can I solve this error :slight_smile: ?

Thank you

Lifetimes are for showing where the data came from. They always connect two or more things together. If you just add 'a to the result, and nothing else, it doesn't say anything. Where's the source of that data?

httparse has these lifetimes to indicate that this object doesn't contain all information about the request. Instead, it references data given to parse() and still needs this data to be alive in the same place where it was before for as long as Request exists.

If all the data given to parse came from &self, then &'a self & Request<'a, 'a> would say so (Request has two lifetimes, because it tracks source of headers separately).

But most likely, the data to parse comes from a local variable inside the function. In that case it's not a problem of lifetime syntax, but that returning Request in this would crash the program. Rust is saving you from memory corruption and use-after-free bugs here. That's because the variable will be destroyed before Request is returned (all local variables are always destroyed at the end of their scope, and lifetime annotations can't change that fact), but the Request will continue referencing ex-variable's memory.

So the httparse::Request type seems to be designed to be used only temporarily while on stack, and can't be returned from a function. It may sound silly that Rust can't return a type from a function, but that's not a Rust thing, that's always the case with referencing on-stack data in all languages.

I suggest using data from httparse::Request to build http::Request, which owns its data and can be passed around freely.

3 Likes