11// Well-formedness of nested opaque types, i.e. `impl Sized` in
2- // `type Outer = impl Trait<Assoc = impl Sized>`.
3- // See the comments below.
4- //
5- //@ revisions: pass pass_sound fail
6- //@ [pass] check-fail
7- //@ [pass_sound] check-fail
8- //@ [fail] check-fail
9-
2+ // `type Outer = impl Trait<Assoc = impl Sized>`. We check that
3+ // the nested type is well-formed, even though this would also
4+ // be implied by the item bounds of the opaque being
5+ // well-formed. See the comments below.
106#![ feature( type_alias_impl_trait) ]
117
128struct IsStatic < T : ' static > ( T ) ;
@@ -23,46 +19,26 @@ impl<T> Trait<&'static T> for () {
2319 type Out = IsStatic < T > ;
2420}
2521
26- // The hidden type for `impl Sized` is `IsStatic<T>`, which requires `T: 'static`.
27- // We know it is well-formed because it can *only* be referenced as a projection:
28- // <OuterOpaque<T> as Trait<&'static T>>::Out`.
29- // So any instantiation of the type already requires proving `T: 'static`.
30- #[ cfg( pass) ]
31- mod pass {
32- use super :: * ;
33- type OuterOpaque < T > = impl Trait < & ' static T , Out = impl Sized > ;
34- fn define < T > ( ) -> OuterOpaque < T > { }
35- //[pass]~^ ERROR `T` may not live long enough
36-
37- fn define_rpit < T > ( ) -> impl Trait < & ' static T , Out = impl Sized > { }
38- //[pass]~^ ERROR the parameter type `T` may not live long enough
39- }
40-
41- // Test the soundness of `pass` - We should require `T: 'static` at the use site.
42- #[ cfg( pass_sound) ]
43- mod pass_sound {
44- use super :: * ;
45- type OuterOpaque < T > = impl Trait < & ' static T , Out = impl Sized > ;
46- fn define < T > ( ) -> OuterOpaque < T > { }
47- //[pass_sound]~^ ERROR `T` may not live long enough
4822
49- fn test < T > ( ) {
50- let outer = define :: < T > ( ) ;
51- let _ = outer. get ( ) ;
52- //[pass_sound]~^ ERROR `T` may not live long enough
53- //[pass_sound]~| ERROR `T` may not live long enough
54- }
55- }
56-
57- // Similar to `pass` but here `impl Sized` can be referenced directly as
58- // InnerOpaque<T>, so we require an explicit bound `T: 'static`.
59- #[ cfg( fail) ]
60- mod fail {
61- use super :: * ;
62- type InnerOpaque < T > = impl Sized ;
63- type OuterOpaque < T > = impl Trait < & ' static T , Out = InnerOpaque < T > > ;
64- fn define < T > ( ) -> OuterOpaque < T > { }
65- //[fail]~^ ERROR the parameter type `T` may not live long enough
66- }
23+ // We could theoretically allow this (and previously did), as even
24+ // though the nested opaque is not well-formed, it can only be
25+ // used by normalizing the projection
26+ // <OuterOpaque1<T> as Trait<&'static T>>::Out
27+ // Assuming that we check that this projection is well-formed, the wf
28+ // of the nested opaque is implied.
29+ type OuterOpaque1 < T > = impl Trait < & ' static T , Out = impl Sized > ;
30+ fn define < T > ( ) -> OuterOpaque1 < T > { }
31+ //~^ ERROR `T` may not live long enough
32+
33+ fn define_rpit < T > ( ) -> impl Trait < & ' static T , Out = impl Sized > { }
34+ //~^ ERROR the parameter type `T` may not live long enough
35+
36+ // Similar to `define` but here `impl Sized` can be referenced directly as
37+ // InnerOpaque<T>, so the `'static` bound is definitely required for
38+ // soundness.
39+ type InnerOpaque < T > = impl Sized ;
40+ type OuterOpaque2 < T > = impl Trait < & ' static T , Out = InnerOpaque < T > > ;
41+ fn define_nested_rpit < T > ( ) -> OuterOpaque2 < T > { }
42+ //~^ ERROR the parameter type `T` may not live long enough
6743
6844fn main ( ) { }
0 commit comments