@@ -91,6 +91,7 @@ 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) ;
94
95
let violations = traits:: supertrait_def_ids ( self , trait_def_id)
95
96
. filter ( |& def_id| self . predicates_reference_self ( def_id, true ) )
96
97
. map ( |_| ObjectSafetyViolation :: SupertraitSelf )
@@ -106,16 +107,33 @@ impl<'tcx> TyCtxt<'tcx> {
106
107
pub fn object_safety_violations ( self , trait_def_id : DefId )
107
108
-> Vec < ObjectSafetyViolation >
108
109
{
110
+ debug_assert ! ( self . generics_of( trait_def_id) . has_self) ;
109
111
debug ! ( "object_safety_violations: {:?}" , trait_def_id) ;
110
112
111
113
traits:: supertrait_def_ids ( self , trait_def_id)
112
114
. flat_map ( |def_id| self . object_safety_violations_for_trait ( def_id) )
113
115
. collect ( )
114
116
}
115
117
116
- fn object_safety_violations_for_trait ( self , trait_def_id : DefId )
117
- -> Vec < ObjectSafetyViolation >
118
- {
118
+ /// We say a method is *vtable safe* if it can be invoked on a trait
119
+ /// object. Note that object-safe traits can have some
120
+ /// non-vtable-safe methods, so long as they require `Self:Sized` or
121
+ /// otherwise ensure that they cannot be used when `Self=Trait`.
122
+ pub fn is_vtable_safe_method ( self , trait_def_id : DefId , method : & ty:: AssocItem ) -> bool {
123
+ debug_assert ! ( self . generics_of( trait_def_id) . has_self) ;
124
+ debug ! ( "is_vtable_safe_method({:?}, {:?})" , trait_def_id, method) ;
125
+ // Any method that has a `Self : Sized` requisite can't be called.
126
+ if self . generics_require_sized_self ( method. def_id ) {
127
+ return false ;
128
+ }
129
+
130
+ match self . virtual_call_violation_for_method ( trait_def_id, method) {
131
+ None | Some ( MethodViolationCode :: WhereClauseReferencesSelf ( _) ) => true ,
132
+ Some ( _) => false ,
133
+ }
134
+ }
135
+
136
+ fn object_safety_violations_for_trait ( self , trait_def_id : DefId ) -> Vec < ObjectSafetyViolation > {
119
137
// Check methods for violations.
120
138
let mut violations: Vec < _ > = self . associated_items ( trait_def_id)
121
139
. filter ( |item| item. kind == ty:: AssocKind :: Method )
@@ -163,14 +181,16 @@ impl<'tcx> TyCtxt<'tcx> {
163
181
fn predicates_reference_self (
164
182
self ,
165
183
trait_def_id : DefId ,
166
- supertraits_only : bool ) -> bool
167
- {
184
+ supertraits_only : bool ,
185
+ ) -> bool {
168
186
let trait_ref = ty:: Binder :: dummy ( ty:: TraitRef :: identity ( self , trait_def_id) ) ;
169
187
let predicates = if supertraits_only {
170
188
self . super_predicates_of ( trait_def_id)
171
189
} else {
172
190
self . predicates_of ( trait_def_id)
173
191
} ;
192
+ let self_ty = self . types . self_param ;
193
+ let has_self_ty = |t : Ty < ' tcx > | t. walk ( ) . any ( |t| t == self_ty) ;
174
194
predicates
175
195
. predicates
176
196
. iter ( )
@@ -179,7 +199,7 @@ impl<'tcx> TyCtxt<'tcx> {
179
199
match predicate {
180
200
ty:: Predicate :: Trait ( ref data) => {
181
201
// 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 ( ) )
202
+ data. skip_binder ( ) . input_types ( ) . skip ( 1 ) . any ( has_self_ty)
183
203
}
184
204
ty:: Predicate :: Projection ( ref data) => {
185
205
// And similarly for projections. This should be redundant with
@@ -199,7 +219,7 @@ impl<'tcx> TyCtxt<'tcx> {
199
219
. trait_ref ( self )
200
220
. input_types ( )
201
221
. skip ( 1 )
202
- . any ( |t| t . has_self_ty ( ) )
222
+ . any ( has_self_ty)
203
223
}
204
224
ty:: Predicate :: WellFormed ( ..) |
205
225
ty:: Predicate :: ObjectSafe ( ..) |
@@ -229,11 +249,11 @@ impl<'tcx> TyCtxt<'tcx> {
229
249
let predicates = predicates. instantiate_identity ( self ) . predicates ;
230
250
elaborate_predicates ( self , predicates)
231
251
. 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 ( )
252
+ ty:: Predicate :: Trait ( ref trait_pred) => {
253
+ trait_pred. def_id ( ) == sized_def_id
254
+ && trait_pred. skip_binder ( ) . self_ty ( ) . is_param ( 0 )
234
255
}
235
256
ty:: Predicate :: Projection ( ..) |
236
- ty:: Predicate :: Trait ( ..) |
237
257
ty:: Predicate :: Subtype ( ..) |
238
258
ty:: Predicate :: RegionOutlives ( ..) |
239
259
ty:: Predicate :: WellFormed ( ..) |
@@ -248,11 +268,11 @@ impl<'tcx> TyCtxt<'tcx> {
248
268
}
249
269
250
270
/// 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
- {
271
+ fn object_safety_violation_for_method (
272
+ self ,
273
+ trait_def_id : DefId ,
274
+ method : & ty :: AssocItem ,
275
+ ) -> Option < MethodViolationCode > {
256
276
debug ! ( "object_safety_violation_for_method({:?}, {:?})" , trait_def_id, method) ;
257
277
// Any method that has a `Self : Sized` requisite is otherwise
258
278
// exempt from the regulations.
@@ -263,36 +283,15 @@ impl<'tcx> TyCtxt<'tcx> {
263
283
self . virtual_call_violation_for_method ( trait_def_id, method)
264
284
}
265
285
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
- }
285
- }
286
-
287
286
/// Returns `Some(_)` if this method cannot be called on a trait
288
287
/// object; this does not necessarily imply that the enclosing trait
289
288
/// is not object safe, because the method might have a where clause
290
289
/// `Self:Sized`.
291
- fn virtual_call_violation_for_method ( self ,
292
- trait_def_id : DefId ,
293
- method : & ty :: AssocItem )
294
- -> Option < MethodViolationCode >
295
- {
290
+ fn virtual_call_violation_for_method (
291
+ self ,
292
+ trait_def_id : DefId ,
293
+ method : & ty :: AssocItem ,
294
+ ) -> Option < MethodViolationCode > {
296
295
// The method's first parameter must be named `self`
297
296
if !method. method_has_self_argument {
298
297
return Some ( MethodViolationCode :: StaticMethod ) ;
@@ -323,7 +322,9 @@ impl<'tcx> TyCtxt<'tcx> {
323
322
. collect :: < Vec < _ > > ( )
324
323
// Do a shallow visit so that `contains_illegal_self_type_reference`
325
324
// may apply it's custom visiting.
326
- . visit_tys_shallow ( |t| self . contains_illegal_self_type_reference ( trait_def_id, t) ) {
325
+ . visit_tys_shallow ( |t| {
326
+ self . contains_illegal_self_type_reference ( trait_def_id, t)
327
+ } ) {
327
328
let span = self . def_span ( method. def_id ) ;
328
329
return Some ( MethodViolationCode :: WhereClauseReferencesSelf ( span) ) ;
329
330
}
@@ -337,7 +338,7 @@ impl<'tcx> TyCtxt<'tcx> {
337
338
// However, this is already considered object-safe. We allow it as a special case here.
338
339
// FIXME(mikeyhew) get rid of this `if` statement once `receiver_is_dispatchable` allows
339
340
// `Receiver: Unsize<Receiver[Self => dyn Trait]>`
340
- if receiver_ty != self . mk_self_type ( ) {
341
+ if receiver_ty != self . types . self_param {
341
342
if !self . receiver_is_dispatchable ( method, receiver_ty) {
342
343
return Some ( MethodViolationCode :: UndispatchableReceiver ) ;
343
344
} else {
@@ -404,7 +405,10 @@ impl<'tcx> TyCtxt<'tcx> {
404
405
/// Performs a type substitution to produce the version of receiver_ty when `Self = self_ty`
405
406
/// e.g., for receiver_ty = `Rc<Self>` and self_ty = `Foo`, returns `Rc<Foo>`.
406
407
fn receiver_for_self_ty (
407
- self , receiver_ty : Ty < ' tcx > , self_ty : Ty < ' tcx > , method_def_id : DefId
408
+ self ,
409
+ receiver_ty : Ty < ' tcx > ,
410
+ self_ty : Ty < ' tcx > ,
411
+ method_def_id : DefId ,
408
412
) -> Ty < ' tcx > {
409
413
debug ! ( "receiver_for_self_ty({:?}, {:?}, {:?})" , receiver_ty, self_ty, method_def_id) ;
410
414
let substs = InternalSubsts :: for_item ( self , method_def_id, |param, _| {
@@ -555,7 +559,7 @@ impl<'tcx> TyCtxt<'tcx> {
555
559
// Self: Unsize<U>
556
560
let unsize_predicate = ty:: TraitRef {
557
561
def_id : unsize_did,
558
- substs : self . mk_substs_trait ( self . mk_self_type ( ) , & [ unsized_self_ty. into ( ) ] ) ,
562
+ substs : self . mk_substs_trait ( self . types . self_param , & [ unsized_self_ty. into ( ) ] ) ,
559
563
} . to_predicate ( ) ;
560
564
561
565
// U: Trait<Arg1, ..., ArgN>
@@ -608,11 +612,11 @@ impl<'tcx> TyCtxt<'tcx> {
608
612
} )
609
613
}
610
614
611
- fn contains_illegal_self_type_reference ( self ,
612
- trait_def_id : DefId ,
613
- ty : Ty < ' tcx > )
614
- -> bool
615
- {
615
+ fn contains_illegal_self_type_reference (
616
+ self ,
617
+ trait_def_id : DefId ,
618
+ ty : Ty < ' tcx > ,
619
+ ) -> bool {
616
620
// This is somewhat subtle. In general, we want to forbid
617
621
// references to `Self` in the argument and return types,
618
622
// since the value of `Self` is erased. However, there is one
@@ -654,10 +658,11 @@ impl<'tcx> TyCtxt<'tcx> {
654
658
655
659
let mut supertraits: Option < Vec < ty:: PolyTraitRef < ' tcx > > > = None ;
656
660
let mut error = false ;
661
+ let self_ty = self . types . self_param ;
657
662
ty. maybe_walk ( |ty| {
658
663
match ty. sty {
659
- ty:: Param ( ref param_ty ) => {
660
- if param_ty . is_self ( ) {
664
+ ty:: Param ( _ ) => {
665
+ if ty == self_ty {
661
666
error = true ;
662
667
}
663
668
0 commit comments