Lifetimes bounds & trait methods

Hi all,

I have a problem with my lifetime bound here:

pub trait FromNetworkOrder {
    // copy from a network-order buffer to a structure
    fn from_network_order<'a>(&mut self, buffer: &mut Cursor<&'a [u8]>) -> Result<()>;
}

pub struct DomainName<'a> {
    // a domain name is a list of labels as defined in the RFC1035
    pub labels: Vec<&'a str>,
}

impl<'a> FromNetworkOrder for DomainName<'a> {
    fn from_network_order<'b: 'a>(&'a mut self, buffer: &mut Cursor<&'b [u8]>) -> Result<()> {
       // ....
    }
}

Compiler complains with:

17 |     fn from_network_order<'b: 'a>(&mut self, buffer: &mut Cursor<&'b [u8]>) -> Result<()> {
    |                          ^^^^^^^^ lifetimes do not match method in trait

I understand, after reading error E0195, that trait methods should have exactly the same lifetimes & bounds. But then, how to express the fact that the Cursor lifetime 'b must outlive the Domain lifetime 'a ?

Any help appreciated !

The way your trait is written, you cannot. Either you change the code of the impl so that this is not needed, or you need to modify the trait to add this bound.

1 Like

The trait itself must express this relationship between the lifetimes.

Usage of these methods through the trait must have the same requirements, you can't add additional restrictions in the implementation.

1 Like

Here is one possible redefinition of the trait:

use std::io::{Cursor, Result};

pub trait FromNetworkOrder<'a> {
    // copy from a network-order buffer to a structure
    fn from_network_order(&mut self, buffer: &mut Cursor<&'a [u8]>) -> Result<()>;
}

pub struct DomainName<'a> {
    // a domain name is a list of labels as defined in the RFC1035
    pub labels: Vec<&'a str>,
}

impl<'a> FromNetworkOrder<'a> for DomainName<'a> {
    fn from_network_order(&mut self, buffer: &mut Cursor<&'a [u8]>) -> Result<()> {
       todo!()
    }
}

Compare this to e.g. serde::Deserialize, which similarly has a lifetime that is "the lifetime of the borrowed input data".

2 Likes

Actually, I found this solution which compiles:

pub trait FromNetworkOrder<'a> {
    // copy from a network-order buffer to a structure
    fn from_network_order<'b: 'a>(&'a mut self, buffer: &mut Cursor<&'b [u8]>) -> Result<()>;
}

pub struct DomainName<'a> {
    // a domain name is a list of labels as defined in the RFC1035
    pub labels: Vec<&'a str>,
}

impl<'a> FromNetworkOrder<'a> for DomainName<'a> {
    fn from_network_order<'b: 'a>(&'a mut self, buffer: &mut Cursor<&'b [u8]>) -> Result<()> {
       // ....
    }
}

It may compile, but this is going to bite:

impl<'a> ... for DomainName<'a> {
    fn ...(&'a mut self, 

You've asked for a &'a mut Self = &'a mut DomainName<'a> — you're specifying that the mutable reference to self lasts for 'a, but 'a also must outlive all instances of the Self type because Self contains it. These two constraints lead to the conclusion that the value will be mutably borrowed for the rest of its existence. You will discover that once you have called the method, you will no longer be able to do anything with the DomainName value.

5 Likes

Hi Sir

The it in the quoted statement refers to the lifetime 'a?

Thank you.

Yes.

Hi, yes it compiles but was indeed a lifetime nightmare :wink: