| // Ensure that we eagerly *expand* free alias types during variance computation. | |
| // | |
| // Since free alias types are always normalizable it's not unreasonable to expect that variance | |
| // information "propagates through" free aliases unlike projections for example which constrain | |
| // all of their generic arguments to be invariant[^1]. | |
| // | |
| // For context, we can't *normalize* types before trying to compute variances because we need | |
| // variances for normalization in the first place, more specifically type relating. | |
| // | |
| // [^1]: Parent args: Traits are invariant over their params. Own args: Projections can be rigid. | |
| // | |
| // issue: <https://github.com/rust-lang/rust/issues/114221> | |
| // | |
| //@ check-pass | |
| // FIXME(checked_type_aliases): Revisit this before stabilization (it's not blocking tho): | |
| // We might want to compute variances for free alias types again | |
| // with a special rule. See `variance-1.rs` for details. | |
| #![feature(checked_type_aliases)] | |
| // `Co` is covariant over `'a` since we expand `A` to `&'a ()`. | |
| struct Co<'a>(A<'a>); | |
| // `A` is *not* in a variance relation with its args since it's a type alias. | |
| type A<'a> = &'a (); | |
| fn co<'a>(x: Co<'static>) { | |
| let _: Co<'a> = x; // OK | |
| } | |
| // `Contra` is contravariant over `'a` since we expand `B` to `fn(&'a ())`. | |
| struct Contra<'a>(B<'a>); | |
| // (not in a variance relation) | |
| type B<'a> = fn(&'a ()); | |
| fn contra<'a>(x: Contra<'a>) { | |
| let _: Contra<'static> = x; // OK | |
| } | |
| // `CoContra` is covariant over `T` and contravariant over `U` since we expand `C`. | |
| struct CoContra<T, U>(C<T, U>); | |
| // (not in a variance relation) | |
| type C<T, U> = Option<(T, fn(U))>; | |
| fn co_contra<'a>(x: CoContra<&'static (), &'a ()>) -> CoContra<&'a (), &'static ()> { | |
| x // OK | |
| } | |
| // Check that we deeply expand: | |
| struct Co2<'a>(D0<'a>); | |
| type D0<'a> = D1<'a>; | |
| type D1<'a> = D2<'a>; | |
| type D2<'a> = D3<'a>; | |
| type D3<'a> = &'a (); | |
| fn co2<'a>(x: Co2<'static>) -> Co2<'a> { x } // OK | |
| fn main() {} |