# lazy norm funtime
https://github.com/rust-lang/trait-system-refactor-initiative/issues/61
```rust
trait Tr<'a> {
type Assoc;
}
fn outlives<'o, T: 'o>() {}
fn foo<'a, 'b, T: Tr<'a, Assoc = ()>>() {
outlives::<'b, T::Assoc>();
// fail to prove `<T as Tr<'a>>::Assoc: 'b` which is `(): 'b`
}
```
- https://github.com/rust-lang/trait-system-refactor-initiative/issues/63
```rust
trait Mirror {
type Assoc;
}
impl<T> Mirror for T {
type Assoc = T;
}
fn is_static<T: 'static>() {}
fn test<T>() where <T as Mirror>::Assoc: 'static {
is_static::<T>();
// fail to prove `T: 'static` even though there is a
// `<T as Mirror>::Assoc: 'static` where-bound
// (which normalizes to `T: 'static`).
}
```
- https://github.com/rust-lang/trait-system-refactor-initiative/issues/59
```rust
trait StaticTy {
type Item<'a>: 'static;
}
impl StaticTy for () {
type Item<'a> = &'a ();
// WF checking the impl proves `<() as StaticTy>::Item<'a>: 'static`
// which uses an item bounds to prove that the item bound holds
}
fn foo<T: StaticTy>() { }
fn main() {
foo::<()>();
// Have to prove `(): StaticTy`
//
// which requires using the impl
//
// which requires proving the impl is well-formed, i.e., trait requires are met, and this proof is done inductively (it cannot assume `(): StaticTy` holds), which would lead us to prove this...
//
// * `for<'a> <() as StaticTy>::Item<'a>: 'static`
//
// Three ways to prove that an alias `A` outlives a lifetime `'x`
//
// * all inputs outlive `'x`
// * prove `(): 'static` (true) and prove `for<'a> 'a: static` (false)
// * the trait definition specifies `A` must outlive `'x` **and the trait is implemented**
// * prove `(): StaticTy` (inductive cycle)
// * normalizing `A` to a type `T` and showing that `T` outlives `'x`
// * can normalize with impl to `&'a ()` but then must show that `for<'a> &'a (): 'static` (false)
//
// Question: but is it ok to skip proving `(): StaticTy` (and hence that impl is WF) in that final step? If not, we would get trivial cycles all the time, which seems bad.
//
// Seems like we require that...
// * Normalizing an assoc type does NOT require showing the trait is WF?
// * Or do we do "1-step normalizing"
//
// https://github.com/rust-lang/a-mir-formality/blob/13b4ad847d609142f92948656e32d5790d0bc28a/crates/formality-prove/src/prove/prove_wc.rs#L51-L62
//
// line 58: when proving the where-clauses on the impl hold, it can use the coinductive assumptions
//
// line 59: when proving the trait where-clauses hold (i.e., impl is well-formed), it does not
//
// (should extend a-mir-formality with this precise case)
}
```
longterm:
Using an impl requires proving all where bounds and item bounds of the trait inductive (everything which can be used as an alias bound, has to be proven)
- wf check - hopefully - also has to prove `WF(<() as StaticTy>::Item<'a>: 'static)`
- `WF(<() as StaticTy>::Item<'a>)`
- ... I would like us to prove `&'a (): 'static`. but why