What does the lifetime 'a refer to in this strange code

fn greet<T>() -> impl Into<T> where T:for <'a> From<&'a str>{
"hello"
}
fn main(){
    
    print!("{}",greet::<String>().into());
}

I was messing around with rust when I wrote this code, it compiles but I don't understand what where T:for <'a> From<&'a str> means in this code. Does this mean T has to exist for as long as x of type &str exists where x is the thing which goes inside From
T::from(x) .

My other question is , are these types of questions allowed on this forum? Since it doesn't appear to have a practical benefit and is more like a puzzle.

The for here means "for all lifetimes". That is, it means that T implements the following infinite list of traits:

  • From<&'lifetime1 str>
  • From<&'lifetime2 str>
  • From<&'lifetime3 str>
  • ...
  • From<&'static str>

where the list goes through every possible lifetime.

In other words, it means that you can create a T from a &str no matter what the lifetime is.

5 Likes

It's called a higher-ranked trait bound (HRTB), and it means that T must implement From<&str> for all possible choices of the lifetime of the reference.

Documentation.

5 Likes

Yes.


Incidentally, the place you usually need HRTB is when you need to do something with a lifetime the caller can't name -- a lifetime that doesn't leave your function body. Like the borrow of a local variable.

Example:

// Works
fn greet<T>() -> impl Into<T> 
where 
    T: for <'a> From<&'a str>,
{
    let s = String::new();
    let _ = T::from(&*s);
    "hello"
}

// Fails
fn greet2<'a, T>() -> impl Into<T> 
where 
    T: From<&'a str>,
{
    let s = String::new();
    let _ = T::from(&*s);
    "hello"
}

In greet2, the caller chooses the lifetime -- it's a generic parameter on the function -- and the caller can only choose lifetimes longer than the function body.


You may have seen a HRTB before without realizing it. The Fn/FnMut/FnOnce traits have special sugar: Elided input lifetimes are actually higher-ranked.

Example:

// Works
fn example<F>(mut f: F)
where
    F: FnMut(&str),
{
    let s = String::new();
    let _ = f(&*s);
}

The bound is the same as F: for<'any> FnMut(&'any str).

4 Likes