I meant, you have this method:
fn do_foo<'a, 'df>(&'df self, n: &'a i32) -> impl use<'a, Self> + Sized;
And elsewhere you want the return type to meet an outlives bound that corresponds to 'a in that signature:
fn use_do_foo<DF: DoFoo>(df: &DF, n: &'static i32) {
fn check_static<T: 'static>(t: &T) {}
check_static(&df.do_foo(n));
}
But consider this implementation:
struct DownStreamSomewhere<'a>(&'a str);
impl<'this> DoFoo for DownStreamSomewhere<'this> {
fn do_foo<'a, 'df>(&'df self, n: &'a i32) -> impl use<'a, 'this> + Sized {
Self(self.0)
}
}
The use<'a, ..> does not impose an 'this: 'a bound on 'this (nor vice-versa). So you can pass in a &'static i32 and get back an arbitrarily short DownStreamSomewhere<'this>.
Therefore this is a concrete example of something which satisfies DF: DoFoo but fails your 'static check. Since it's possible, and use_do_foo is required to work with any DF: DoFoo, putting your 'static check within use_do_foo results in the borrow check error.
I agree on this point. I hope the specification project improves matters eventually. 
In case it helps, let me outline how I think of -> impl Trait.
fn example<'a, 'b, T>() -> impl use<'a, T> + Trait + Send { ... }
Corresponds to
// vvvvv generics of `+ use<..>`
trait ExampleRet<'a, T> {
#[rustc_opaque] // <-- forbid knowing ("normalizing") the type everywhere...
#[rustc_leak_auto] // <-- ...except details about the auto traits
type Ty: Trait + Send;
// ^^^^^^^^^^^^ Bounds on return type (including outlives, if any)
}
struct HiddenType;
impl ExampleRet<'a, T> for HiddenType { ... }
fn example<'a, 'b, T> -> <HiddenType as ExampleRet<'a, T>>::Ty { ... }
And in a trait it would be more like
trait MethodHolder<'m, 'n, M> {
// You're forced to capture all trait parameters and `Self`
fn method<'a, 'b, T> -> impl use<'a, 'm, 'n, M, T, Self> + Trait + Send;
}
Becomes
trait MethodHolder<'m, 'n, M> {
// vvvvv Captured generics from the *method*
type Ty<'a, T>: Trait + Send; // <-- Bounds (including outlives, if any)
fn method<'a, 'b, T> -> <Self as MethodHolder<'m, 'n, M>>::Ty<'a, T>;
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// Note how all *trait parameters and `Self`* appear in this path
}
And the definition is based on each implementation. Note how when defining the associated type, it's possible for the implementor to name all the trait parameters and any generics that might be part of Self.
In terms of your OP and my DownStreamSomewhere example, that would be:
struct DownStreamSomewhere<'a>(&'a str);
impl<'this> DoFoo for DownStreamSomewhere<'this> {
type FooRet<'a> = DownStreamSomewhere<'this>;
fn do_foo<'a, 'df>(&'df self, n: &'a i32) -> Self::FooRet<'a> {
Self(self.0)
}
}
There's nothing preventing this implementation which defines a return type FooRet<'a> that doesn't have to outlive 'a... unless you add + 'a or similar.
trait DoFoo {
- type FooRet<'a>: Sized;
+ type FooRet<'a>: Sized + 'a;
fn do_foo<'a, 'df>(&'df self, n: &'a i32) -> Self::FooRet<'a>;
}
I.e.
trait DoFoo {
- fn do_foo<'a, 'df>(&'df self, n: &'a i32) -> impl use<'a, Self> + Sized;
+ fn do_foo<'a, 'df>(&'df self, n: &'a i32) -> impl use<'a, Self> + Sized + 'a;
}
If you understand how associated types work well enough -- for example, how "projection outlives" works from that RFC I linked -- I find this way of thinking about things to be quite useful when reasoning about -> impl Trait.
With all that context, I hope it's more clear that use<'a> is about lifetimes that can be mentioned in the definition of the hidden type of an opaque, but doesn't impose a bound on its own.
Similarly, if you have a lifetime parameter on a trait that has an associated type, an implementation can use that parameter in the definition of the associated type, but doesn't have to. And whether it does or doesn't, the mere presence of the lifetime doesn't impose an outlives bound on the associated type.