Why impl<'a> Trait &'a str {} does mean the impl is not for all lifetimes

So here's the call with an error:

    let to_upper = ArgCallback::new(|a: &str| Value::String(a.to_uppercase()));

And here are the bounds in question:

    pub fn new<F, Arg>(f: F) -> ArgCallback
    where
        F: CallbackTrait<Arg>,
        Arg: for<'a> TryConvertValue<'a>,

Type parameters like F and Arg must resolve to a single, concrete type. And &str over all lifetimes or &str without a concrete lifetime isn't a concrete type -- it's a type constructor that takes a lifetime parameter. For the closure to be passed to new, it's going to be interpreted as or coerced to:

|a: &'x str| Value::String(a.to_uppercase())

where 'x is one single inferred lifetime. Then Arg == &'x str is possible.


Next we need to satisfy

&'x str: for<'a> TryConvertValue<'a>

But the implementation is

impl<'a> TryConvertValue<'a> for &'a str {

So &'long str doesn't implement TryConvertValue<'short> or TryConvertValue<'static> for example, it only implements TryConvertValue<'long>.

Hence the error.

The implementation could be made more generic:

impl<'b: 'a, 'a> TryConvertValue<'b> for &'a str {

And now &'long str does implement TryConvertValue<'static> ... but still not TryConvertValue<'short>. And being able to pass in arbitrarily short borrows of a Value is the functionality being required. So this doesn't actually help with the error at hand.


What you really need is for the closure to remain higher-ranked so that it can accept &str of any lifetime, and not some concrete 'x. That means you need to change the bounds so that Arg isn't a type parameter. I walk through that process in this post, which is also linked in that article.