@@ -91,8 +91,10 @@ impl<'tcx> TyCtxt<'tcx> {
91
91
pub fn astconv_object_safety_violations ( self , trait_def_id : DefId )
92
92
-> Vec < ObjectSafetyViolation >
93
93
{
94
+ debug_assert ! ( self . generics_of( trait_def_id) . has_self) ;
95
+ let self_ty = self . mk_self_type ( ) ;
94
96
let violations = traits:: supertrait_def_ids ( self , trait_def_id)
95
- . filter ( |& def_id| self . predicates_reference_self ( def_id, true ) )
97
+ . filter ( |& def_id| self . predicates_reference_self ( def_id, self_ty , true ) )
96
98
. map ( |_| ObjectSafetyViolation :: SupertraitSelf )
97
99
. collect ( ) ;
98
100
@@ -106,21 +108,44 @@ impl<'tcx> TyCtxt<'tcx> {
106
108
pub fn object_safety_violations ( self , trait_def_id : DefId )
107
109
-> Vec < ObjectSafetyViolation >
108
110
{
111
+ debug_assert ! ( self . generics_of( trait_def_id) . has_self) ;
112
+ let self_ty = self . mk_self_type ( ) ;
109
113
debug ! ( "object_safety_violations: {:?}" , trait_def_id) ;
110
114
111
115
traits:: supertrait_def_ids ( self , trait_def_id)
112
- . flat_map ( |def_id| self . object_safety_violations_for_trait ( def_id) )
116
+ . flat_map ( |def_id| self . object_safety_violations_for_trait ( def_id, self_ty ) )
113
117
. collect ( )
114
118
}
115
119
116
- fn object_safety_violations_for_trait ( self , trait_def_id : DefId )
117
- -> Vec < ObjectSafetyViolation >
118
- {
120
+ /// We say a method is *vtable safe* if it can be invoked on a trait
121
+ /// object. Note that object-safe traits can have some
122
+ /// non-vtable-safe methods, so long as they require `Self:Sized` or
123
+ /// otherwise ensure that they cannot be used when `Self=Trait`.
124
+ pub fn is_vtable_safe_method ( self , trait_def_id : DefId , method : & ty:: AssocItem ) -> bool {
125
+ debug_assert ! ( self . generics_of( trait_def_id) . has_self) ;
126
+ let self_ty = self . mk_self_type ( ) ;
127
+ debug ! ( "is_vtable_safe_method({:?}, {:?})" , trait_def_id, method) ;
128
+ // Any method that has a `Self : Sized` requisite can't be called.
129
+ if self . generics_require_sized_self ( method. def_id , self_ty) {
130
+ return false ;
131
+ }
132
+
133
+ match self . virtual_call_violation_for_method ( trait_def_id, self_ty, method) {
134
+ None | Some ( MethodViolationCode :: WhereClauseReferencesSelf ( _) ) => true ,
135
+ Some ( _) => false ,
136
+ }
137
+ }
138
+
139
+ fn object_safety_violations_for_trait (
140
+ self ,
141
+ trait_def_id : DefId ,
142
+ self_ty : Ty < ' tcx > ,
143
+ ) -> Vec < ObjectSafetyViolation > {
119
144
// Check methods for violations.
120
145
let mut violations: Vec < _ > = self . associated_items ( trait_def_id)
121
146
. filter ( |item| item. kind == ty:: AssocKind :: Method )
122
147
. filter_map ( |item|
123
- self . object_safety_violation_for_method ( trait_def_id, & item)
148
+ self . object_safety_violation_for_method ( trait_def_id, self_ty , & item)
124
149
. map ( |code| ObjectSafetyViolation :: Method ( item. ident . name , code) )
125
150
) . filter ( |violation| {
126
151
if let ObjectSafetyViolation :: Method ( _,
@@ -142,10 +167,10 @@ impl<'tcx> TyCtxt<'tcx> {
142
167
} ) . collect ( ) ;
143
168
144
169
// Check the trait itself.
145
- if self . trait_has_sized_self ( trait_def_id) {
170
+ if self . trait_has_sized_self ( trait_def_id, self_ty ) {
146
171
violations. push ( ObjectSafetyViolation :: SizedSelf ) ;
147
172
}
148
- if self . predicates_reference_self ( trait_def_id, false ) {
173
+ if self . predicates_reference_self ( trait_def_id, self_ty , false ) {
149
174
violations. push ( ObjectSafetyViolation :: SupertraitSelf ) ;
150
175
}
151
176
@@ -163,14 +188,16 @@ impl<'tcx> TyCtxt<'tcx> {
163
188
fn predicates_reference_self (
164
189
self ,
165
190
trait_def_id : DefId ,
166
- supertraits_only : bool ) -> bool
167
- {
191
+ self_ty : Ty < ' tcx > ,
192
+ supertraits_only : bool ,
193
+ ) -> bool {
168
194
let trait_ref = ty:: Binder :: dummy ( ty:: TraitRef :: identity ( self , trait_def_id) ) ;
169
195
let predicates = if supertraits_only {
170
196
self . super_predicates_of ( trait_def_id)
171
197
} else {
172
198
self . predicates_of ( trait_def_id)
173
199
} ;
200
+ let has_self_ty = |t : Ty < ' tcx > | t. walk ( ) . any ( |t| t == self_ty) ;
174
201
predicates
175
202
. predicates
176
203
. iter ( )
@@ -179,7 +206,7 @@ impl<'tcx> TyCtxt<'tcx> {
179
206
match predicate {
180
207
ty:: Predicate :: Trait ( ref data) => {
181
208
// In the case of a trait predicate, we can skip the "self" type.
182
- data. skip_binder ( ) . input_types ( ) . skip ( 1 ) . any ( |t| t . has_self_ty ( ) )
209
+ data. skip_binder ( ) . input_types ( ) . skip ( 1 ) . any ( has_self_ty)
183
210
}
184
211
ty:: Predicate :: Projection ( ref data) => {
185
212
// And similarly for projections. This should be redundant with
@@ -199,7 +226,7 @@ impl<'tcx> TyCtxt<'tcx> {
199
226
. trait_ref ( self )
200
227
. input_types ( )
201
228
. skip ( 1 )
202
- . any ( |t| t . has_self_ty ( ) )
229
+ . any ( has_self_ty)
203
230
}
204
231
ty:: Predicate :: WellFormed ( ..) |
205
232
ty:: Predicate :: ObjectSafe ( ..) |
@@ -214,11 +241,11 @@ impl<'tcx> TyCtxt<'tcx> {
214
241
} )
215
242
}
216
243
217
- fn trait_has_sized_self ( self , trait_def_id : DefId ) -> bool {
218
- self . generics_require_sized_self ( trait_def_id)
244
+ fn trait_has_sized_self ( self , trait_def_id : DefId , self_ty : Ty < ' tcx > ) -> bool {
245
+ self . generics_require_sized_self ( trait_def_id, self_ty )
219
246
}
220
247
221
- fn generics_require_sized_self ( self , def_id : DefId ) -> bool {
248
+ fn generics_require_sized_self ( self , def_id : DefId , self_ty : Ty < ' tcx > ) -> bool {
222
249
let sized_def_id = match self . lang_items ( ) . sized_trait ( ) {
223
250
Some ( def_id) => def_id,
224
251
None => { return false ; /* No Sized trait, can't require it! */ }
@@ -229,11 +256,11 @@ impl<'tcx> TyCtxt<'tcx> {
229
256
let predicates = predicates. instantiate_identity ( self ) . predicates ;
230
257
elaborate_predicates ( self , predicates)
231
258
. any ( |predicate| match predicate {
232
- ty:: Predicate :: Trait ( ref trait_pred) if trait_pred. def_id ( ) == sized_def_id => {
233
- trait_pred. skip_binder ( ) . self_ty ( ) . is_self ( )
259
+ ty:: Predicate :: Trait ( ref trait_pred) => {
260
+ trait_pred. def_id ( ) == sized_def_id
261
+ && trait_pred. skip_binder ( ) . self_ty ( ) == self_ty
234
262
}
235
263
ty:: Predicate :: Projection ( ..) |
236
- ty:: Predicate :: Trait ( ..) |
237
264
ty:: Predicate :: Subtype ( ..) |
238
265
ty:: Predicate :: RegionOutlives ( ..) |
239
266
ty:: Predicate :: WellFormed ( ..) |
@@ -248,51 +275,32 @@ impl<'tcx> TyCtxt<'tcx> {
248
275
}
249
276
250
277
/// Returns `Some(_)` if this method makes the containing trait not object safe.
251
- fn object_safety_violation_for_method ( self ,
252
- trait_def_id : DefId ,
253
- method : & ty:: AssocItem )
254
- -> Option < MethodViolationCode >
255
- {
278
+ fn object_safety_violation_for_method (
279
+ self ,
280
+ trait_def_id : DefId ,
281
+ self_ty : Ty < ' tcx > ,
282
+ method : & ty:: AssocItem ,
283
+ ) -> Option < MethodViolationCode > {
256
284
debug ! ( "object_safety_violation_for_method({:?}, {:?})" , trait_def_id, method) ;
257
285
// Any method that has a `Self : Sized` requisite is otherwise
258
286
// exempt from the regulations.
259
- if self . generics_require_sized_self ( method. def_id ) {
287
+ if self . generics_require_sized_self ( method. def_id , self_ty ) {
260
288
return None ;
261
289
}
262
290
263
- self . virtual_call_violation_for_method ( trait_def_id, method)
264
- }
265
-
266
- /// We say a method is *vtable safe* if it can be invoked on a trait
267
- /// object. Note that object-safe traits can have some
268
- /// non-vtable-safe methods, so long as they require `Self:Sized` or
269
- /// otherwise ensure that they cannot be used when `Self=Trait`.
270
- pub fn is_vtable_safe_method ( self ,
271
- trait_def_id : DefId ,
272
- method : & ty:: AssocItem )
273
- -> bool
274
- {
275
- debug ! ( "is_vtable_safe_method({:?}, {:?})" , trait_def_id, method) ;
276
- // Any method that has a `Self : Sized` requisite can't be called.
277
- if self . generics_require_sized_self ( method. def_id ) {
278
- return false ;
279
- }
280
-
281
- match self . virtual_call_violation_for_method ( trait_def_id, method) {
282
- None | Some ( MethodViolationCode :: WhereClauseReferencesSelf ( _) ) => true ,
283
- Some ( _) => false ,
284
- }
291
+ self . virtual_call_violation_for_method ( trait_def_id, self_ty, method)
285
292
}
286
293
287
294
/// Returns `Some(_)` if this method cannot be called on a trait
288
295
/// object; this does not necessarily imply that the enclosing trait
289
296
/// is not object safe, because the method might have a where clause
290
297
/// `Self:Sized`.
291
- fn virtual_call_violation_for_method ( self ,
292
- trait_def_id : DefId ,
293
- method : & ty:: AssocItem )
294
- -> Option < MethodViolationCode >
295
- {
298
+ fn virtual_call_violation_for_method (
299
+ self ,
300
+ trait_def_id : DefId ,
301
+ self_ty : Ty < ' tcx > ,
302
+ method : & ty:: AssocItem ,
303
+ ) -> Option < MethodViolationCode > {
296
304
// The method's first parameter must be named `self`
297
305
if !method. method_has_self_argument {
298
306
return Some ( MethodViolationCode :: StaticMethod ) ;
@@ -301,11 +309,15 @@ impl<'tcx> TyCtxt<'tcx> {
301
309
let sig = self . fn_sig ( method. def_id ) ;
302
310
303
311
for input_ty in & sig. skip_binder ( ) . inputs ( ) [ 1 ..] {
304
- if self . contains_illegal_self_type_reference ( trait_def_id, input_ty) {
312
+ if self . contains_illegal_self_type_reference ( trait_def_id, self_ty , input_ty) {
305
313
return Some ( MethodViolationCode :: ReferencesSelf ) ;
306
314
}
307
315
}
308
- if self . contains_illegal_self_type_reference ( trait_def_id, sig. output ( ) . skip_binder ( ) ) {
316
+ if self . contains_illegal_self_type_reference (
317
+ trait_def_id,
318
+ self_ty,
319
+ sig. output ( ) . skip_binder ( ) ,
320
+ ) {
309
321
return Some ( MethodViolationCode :: ReferencesSelf ) ;
310
322
}
311
323
@@ -323,7 +335,9 @@ impl<'tcx> TyCtxt<'tcx> {
323
335
. collect :: < Vec < _ > > ( )
324
336
// Do a shallow visit so that `contains_illegal_self_type_reference`
325
337
// may apply it's custom visiting.
326
- . visit_tys_shallow ( |t| self . contains_illegal_self_type_reference ( trait_def_id, t) ) {
338
+ . visit_tys_shallow ( |t| {
339
+ self . contains_illegal_self_type_reference ( trait_def_id, self_ty, t)
340
+ } ) {
327
341
let span = self . def_span ( method. def_id ) ;
328
342
return Some ( MethodViolationCode :: WhereClauseReferencesSelf ( span) ) ;
329
343
}
@@ -337,7 +351,7 @@ impl<'tcx> TyCtxt<'tcx> {
337
351
// However, this is already considered object-safe. We allow it as a special case here.
338
352
// FIXME(mikeyhew) get rid of this `if` statement once `receiver_is_dispatchable` allows
339
353
// `Receiver: Unsize<Receiver[Self => dyn Trait]>`
340
- if receiver_ty != self . mk_self_type ( ) {
354
+ if receiver_ty != self_ty {
341
355
if !self . receiver_is_dispatchable ( method, receiver_ty) {
342
356
return Some ( MethodViolationCode :: UndispatchableReceiver ) ;
343
357
} else {
@@ -404,7 +418,10 @@ impl<'tcx> TyCtxt<'tcx> {
404
418
/// Performs a type substitution to produce the version of receiver_ty when `Self = self_ty`
405
419
/// e.g., for receiver_ty = `Rc<Self>` and self_ty = `Foo`, returns `Rc<Foo>`.
406
420
fn receiver_for_self_ty (
407
- self , receiver_ty : Ty < ' tcx > , self_ty : Ty < ' tcx > , method_def_id : DefId
421
+ self ,
422
+ receiver_ty : Ty < ' tcx > ,
423
+ self_ty : Ty < ' tcx > ,
424
+ method_def_id : DefId ,
408
425
) -> Ty < ' tcx > {
409
426
debug ! ( "receiver_for_self_ty({:?}, {:?}, {:?})" , receiver_ty, self_ty, method_def_id) ;
410
427
let substs = InternalSubsts :: for_item ( self , method_def_id, |param, _| {
@@ -608,11 +625,12 @@ impl<'tcx> TyCtxt<'tcx> {
608
625
} )
609
626
}
610
627
611
- fn contains_illegal_self_type_reference ( self ,
612
- trait_def_id : DefId ,
613
- ty : Ty < ' tcx > )
614
- -> bool
615
- {
628
+ fn contains_illegal_self_type_reference (
629
+ self ,
630
+ trait_def_id : DefId ,
631
+ self_ty : Ty < ' tcx > ,
632
+ ty : Ty < ' tcx > ,
633
+ ) -> bool {
616
634
// This is somewhat subtle. In general, we want to forbid
617
635
// references to `Self` in the argument and return types,
618
636
// since the value of `Self` is erased. However, there is one
@@ -656,8 +674,8 @@ impl<'tcx> TyCtxt<'tcx> {
656
674
let mut error = false ;
657
675
ty. maybe_walk ( |ty| {
658
676
match ty. sty {
659
- ty:: Param ( ref param_ty ) => {
660
- if param_ty . is_self ( ) {
677
+ ty:: Param ( _ ) => {
678
+ if ty == self_ty {
661
679
error = true ;
662
680
}
663
681
0 commit comments