// However, it is a hard error when not using method call syntax.
Foo::trait_method::<'static, 'static, 'static>(Foo, &(), &());
Foo::trait_function::<'static, 'static, 'static>(&(), &());
Foo::inherent_function::<'static, 'static, 'static>(&(), &());
free_function::<'static, 'static, 'static>(&(), &());
```
Even when specifying enough lifetime arguments for both the late and early bound lifetime parameter, these arguments are not actually used to annotate the lifetime provided to late bound parameters. We can demonstrate this by turbofishing `'static` to a function while providing a non-static borrow:
```rust
struct Foo;
impl Foo {
fn inherent_method<'a: 'a, 'b>(self, _: &'a (), _: &'b String ) {}
}
Foo.inherent_method::<'static, 'static>(&(), &String::new());
```
This compiles even though the `&String::new()` function argument does not have a `'static` lifetime, this is because "extra" lifetime arguments are discarded rather than taken into account for late bound parameters when actually calling the function.
### Liveness of types with late bound parameters
When checking type outlives bounds involving function item types we take into account early bound parameters. For example:
```rust
fn foo<T>(_: T) {}
fn requires_static<T: 'static>(_: T) {}
fn bar<T>() {
let f /* : FooFnItem<T> */ = foo::<T>;
requires_static(f);
}
```
As the type parameter `T` is early bound, the desugaring of the function item type for `foo` would look something like `struct FooFnItem<T>`. Then in order for `FooFnItem<T>: 'static` to hold we must also require `T: 'static` to hold as otherwise we would wind up with soundness bugs.
Unfortunately, due to bugs in the compiler, we do not take into account early bound *lifetimes*, which is the cause of the open soundness bug [#84366](https://github.com/rust-lang/rust/issues/84366). This means that it's impossible to demonstrate a "difference" between early/late bound parameters for liveness/type outlives bounds as the only kind of generic parameters that are able to be late bound are lifetimes which are handled incorrectly.
Regardless, in theory the code example below *should* demonstrate such a difference once [#84366](https://github.com/rust-lang/rust/issues/84366) is fixed:
```rust
fn early_bound<'a: 'a>(_: &'a String) {}
fn late_bound<'a>(_: &'a String) {}
fn requires_static<T: 'static>(_: T) {}
fn bar<'b>() {
let e = early_bound::<'b>;
// this *should* error but does not
requires_static(e);
let l = late_bound;
// this correctly does not error
requires_static(l);
}
```
## Requirements for a parameter to be late bound
### Must be a lifetime parameter
Type and Const parameters are not able to be late bound as we do not have a way to support types such as `dyn for<T> Fn(Box<T>)` or `for<T> fn(Box<T>)`. Calling such types requires being able to monomorphize the underlying function which is not possible with indirection through dynamic dispatch.
### Must not be used in a where clause
Currently when a generic parameter is used in a where clause it must be early bound. For example:
```rust
# trait Trait<'a> {}
fn foo<'a, T: Trait<'a>>(_: &'a String, _: T) {}
```
In this example the lifetime parameter `'a` is considered to be early bound as it appears in the where clause `T: Trait<'a>`. This is true even for "trivial" where clauses such as `'a: 'a` or those implied by wellformedness of function arguments, for example:
```rust