20
20
use super :: supertraits;
21
21
use super :: elaborate_predicates;
22
22
23
- use middle:: subst:: { self , SelfSpace } ;
23
+ use middle:: subst:: { self , SelfSpace , TypeSpace } ;
24
24
use middle:: traits;
25
25
use middle:: ty:: { self , Ty } ;
26
26
use std:: rc:: Rc ;
@@ -31,6 +31,10 @@ pub enum ObjectSafetyViolation<'tcx> {
31
31
/// Self : Sized declared on the trait
32
32
SizedSelf ,
33
33
34
+ /// Supertrait reference references `Self` an in illegal location
35
+ /// (e.g. `trait Foo : Bar<Self>`)
36
+ SupertraitSelf ,
37
+
34
38
/// Method has something illegal
35
39
Method ( Rc < ty:: Method < ' tcx > > , MethodViolationCode ) ,
36
40
}
@@ -110,6 +114,9 @@ fn object_safety_violations_for_trait<'tcx>(tcx: &ty::ctxt<'tcx>,
110
114
if trait_has_sized_self ( tcx, trait_def_id) {
111
115
violations. push ( ObjectSafetyViolation :: SizedSelf ) ;
112
116
}
117
+ if supertraits_reference_self ( tcx, trait_def_id) {
118
+ violations. push ( ObjectSafetyViolation :: SupertraitSelf ) ;
119
+ }
113
120
114
121
debug ! ( "object_safety_violations_for_trait(trait_def_id={}) = {}" ,
115
122
trait_def_id. repr( tcx) ,
@@ -118,6 +125,34 @@ fn object_safety_violations_for_trait<'tcx>(tcx: &ty::ctxt<'tcx>,
118
125
violations
119
126
}
120
127
128
+ fn supertraits_reference_self < ' tcx > ( tcx : & ty:: ctxt < ' tcx > ,
129
+ trait_def_id : ast:: DefId )
130
+ -> bool
131
+ {
132
+ let trait_def = ty:: lookup_trait_def ( tcx, trait_def_id) ;
133
+ let trait_ref = trait_def. trait_ref . clone ( ) ;
134
+ let predicates = ty:: predicates_for_trait_ref ( tcx, & ty:: Binder ( trait_ref) ) ;
135
+ predicates
136
+ . into_iter ( )
137
+ . any ( |predicate| {
138
+ match predicate {
139
+ ty:: Predicate :: Trait ( ref data) => {
140
+ // In the case of a trait predicate, we can skip the "self" type.
141
+ data. 0 . trait_ref . substs . types . get_slice ( TypeSpace )
142
+ . iter ( )
143
+ . cloned ( )
144
+ . any ( is_self)
145
+ }
146
+ ty:: Predicate :: Projection ( ..) |
147
+ ty:: Predicate :: TypeOutlives ( ..) |
148
+ ty:: Predicate :: RegionOutlives ( ..) |
149
+ ty:: Predicate :: Equate ( ..) => {
150
+ false
151
+ }
152
+ }
153
+ } )
154
+ }
155
+
121
156
fn trait_has_sized_self < ' tcx > ( tcx : & ty:: ctxt < ' tcx > ,
122
157
trait_def_id : ast:: DefId )
123
158
-> bool
@@ -138,11 +173,7 @@ fn trait_has_sized_self<'tcx>(tcx: &ty::ctxt<'tcx>,
138
173
. any ( |predicate| {
139
174
match predicate {
140
175
ty:: Predicate :: Trait ( ref trait_pred) if trait_pred. def_id ( ) == sized_def_id => {
141
- let self_ty = trait_pred. 0 . self_ty ( ) ;
142
- match self_ty. sty {
143
- ty:: ty_param( ref data) => data. space == subst:: SelfSpace ,
144
- _ => false ,
145
- }
176
+ is_self ( trait_pred. 0 . self_ty ( ) )
146
177
}
147
178
ty:: Predicate :: Projection ( ..) |
148
179
ty:: Predicate :: Trait ( ..) |
@@ -295,8 +326,17 @@ impl<'tcx> Repr<'tcx> for ObjectSafetyViolation<'tcx> {
295
326
match * self {
296
327
ObjectSafetyViolation :: SizedSelf =>
297
328
format ! ( "SizedSelf" ) ,
329
+ ObjectSafetyViolation :: SupertraitSelf =>
330
+ format ! ( "SupertraitSelf" ) ,
298
331
ObjectSafetyViolation :: Method ( ref m, code) =>
299
332
format ! ( "Method({},{:?})" , m. repr( tcx) , code) ,
300
333
}
301
334
}
302
335
}
336
+
337
+ fn is_self < ' tcx > ( ty : Ty < ' tcx > ) -> bool {
338
+ match ty. sty {
339
+ ty:: ty_param( ref data) => data. space == subst:: SelfSpace ,
340
+ _ => false ,
341
+ }
342
+ }
0 commit comments