What's the semantic of lifetime in an impl type?

In my understanding , lifetime annotation in a reference type means that

you can only borrow object which has longer lifetime than the lifetime specified in the reference type

for example

fn test<'a>() {
  let x=0;
  let y : &'a u8 = &x;
}

x has a shorter lifetime than 'a, so the code can't compile. In case of impl type , we can also specify a lifetime annotation , but I can't figure out the semantic of this kind of lifetime annotation. Please help.

trait Tr {}
fn test<'a>(x:impl Tr+'a) {  // what's the semantic of 'a ?
}

The code

trait Tr {}
fn test<'a>(x: impl Tr+'a) {
}

is equivalent to

trait Tr {}
fn test<'a, T>(x: T)
where 
    T: Tr + 'a,
{
}

or

trait Tr {}
fn test<'a, T>(x: T)
where 
    T: Tr, 
    T: 'a,
{
}

The bound T: 'a roughly means that the type T must be such that every reference contained in values of type T must live / be valid at least as long as 'a. For example of T is something like (&'b u32, RefMut<'c, String>) then T: 'a is only fulfilled if both 'b and 'c outlive 'a, i. e. 'b: 'a and 'c: 'a.

A type T "impls" 'a (written as T : 'a —and, in an anonymous fashion, impl 'a + …) if every instance of that type can soundly be used within the region 'a.

  • I personally call it the "lifetime/region of owned-usability", since, indeed, it represents a region within which we can use instances without any danger / problem whatsover.

In practice, this boils down to whether the type features generics lifetime parameters (e.g., Foo<'b, 'c>, or &'b U, etc.), and in that case, if each and every one of those lifetimes parameters is at least as big as 'a (e.g., 'b : 'a, 'c : 'a, etc.).

  • So another way to view it is T : 'a if all the borrows inside T last at least as long as 'a.

A typical example is to observe that String : 'static, that is, when you own a(n instance of a) String, you can keep it around for 'static, i.e., for as long as you want, even though in practice you'll almost always eventually drop that very String instance (which is why you won't be able to borrow it for a 'static duration (this is the "&'staticimpl 'static" distinction):

{
    let s = String::from("Hello, World!");
    assert_ty_is_static!(s); // OK
    let _: &'static String = &s; // Error! ----+
} // <- `s` is dropped here -------------------+

{
    let s = String::from("Hello, World!");
    let my_ref: &String = &s; // This can't be a `&'static String`
    // thus, the following fails
    assert_ty_is_static!(my_ref);
}

that is, even if you owned that my_ref variable, you wouldn't be able to use it beyond the lifetime of its borrow, and since such borrow can't be 'static (since s is eventually dropped), that means that the type of my_ref does not meet the : 'static bound.

Your example is cool , it takes me some time to find out the assert_ty_is_static :sweat_smile:

thank you , this is easily verified

fn main() {
  trait Tr {}
  impl Tr for (&u8,&u8) {}
  fn test(x:impl Tr+'static) {
  }
  let a=0;
  let x = (&a,&0);
  test(x);
}

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.