1
1
// 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.
10
6
#![ feature( type_alias_impl_trait) ]
11
7
12
8
struct IsStatic < T : ' static > ( T ) ;
@@ -23,46 +19,26 @@ impl<T> Trait<&'static T> for () {
23
19
type Out = IsStatic < T > ;
24
20
}
25
21
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
48
22
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
67
43
68
44
fn main ( ) { }
0 commit comments