@@ -91,8 +91,10 @@ impl<'tcx> TyCtxt<'tcx> {
9191 pub fn astconv_object_safety_violations ( self , trait_def_id : DefId )
9292 -> Vec < ObjectSafetyViolation >
9393 {
94+ debug_assert ! ( self . generics_of( trait_def_id) . has_self) ;
95+ let self_ty = self . mk_self_type ( ) ;
9496 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 ) )
9698 . map ( |_| ObjectSafetyViolation :: SupertraitSelf )
9799 . collect ( ) ;
98100
@@ -106,21 +108,44 @@ impl<'tcx> TyCtxt<'tcx> {
106108 pub fn object_safety_violations ( self , trait_def_id : DefId )
107109 -> Vec < ObjectSafetyViolation >
108110 {
111+ debug_assert ! ( self . generics_of( trait_def_id) . has_self) ;
112+ let self_ty = self . mk_self_type ( ) ;
109113 debug ! ( "object_safety_violations: {:?}" , trait_def_id) ;
110114
111115 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 ) )
113117 . collect ( )
114118 }
115119
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 > {
119144 // Check methods for violations.
120145 let mut violations: Vec < _ > = self . associated_items ( trait_def_id)
121146 . filter ( |item| item. kind == ty:: AssocKind :: Method )
122147 . 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)
124149 . map ( |code| ObjectSafetyViolation :: Method ( item. ident . name , code) )
125150 ) . filter ( |violation| {
126151 if let ObjectSafetyViolation :: Method ( _,
@@ -142,10 +167,10 @@ impl<'tcx> TyCtxt<'tcx> {
142167 } ) . collect ( ) ;
143168
144169 // 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 ) {
146171 violations. push ( ObjectSafetyViolation :: SizedSelf ) ;
147172 }
148- if self . predicates_reference_self ( trait_def_id, false ) {
173+ if self . predicates_reference_self ( trait_def_id, self_ty , false ) {
149174 violations. push ( ObjectSafetyViolation :: SupertraitSelf ) ;
150175 }
151176
@@ -163,14 +188,16 @@ impl<'tcx> TyCtxt<'tcx> {
163188 fn predicates_reference_self (
164189 self ,
165190 trait_def_id : DefId ,
166- supertraits_only : bool ) -> bool
167- {
191+ self_ty : Ty < ' tcx > ,
192+ supertraits_only : bool ,
193+ ) -> bool {
168194 let trait_ref = ty:: Binder :: dummy ( ty:: TraitRef :: identity ( self , trait_def_id) ) ;
169195 let predicates = if supertraits_only {
170196 self . super_predicates_of ( trait_def_id)
171197 } else {
172198 self . predicates_of ( trait_def_id)
173199 } ;
200+ let has_self_ty = |t : Ty < ' tcx > | t. walk ( ) . any ( |t| t == self_ty) ;
174201 predicates
175202 . predicates
176203 . iter ( )
@@ -179,7 +206,7 @@ impl<'tcx> TyCtxt<'tcx> {
179206 match predicate {
180207 ty:: Predicate :: Trait ( ref data) => {
181208 // 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)
183210 }
184211 ty:: Predicate :: Projection ( ref data) => {
185212 // And similarly for projections. This should be redundant with
@@ -199,7 +226,7 @@ impl<'tcx> TyCtxt<'tcx> {
199226 . trait_ref ( self )
200227 . input_types ( )
201228 . skip ( 1 )
202- . any ( |t| t . has_self_ty ( ) )
229+ . any ( has_self_ty)
203230 }
204231 ty:: Predicate :: WellFormed ( ..) |
205232 ty:: Predicate :: ObjectSafe ( ..) |
@@ -214,11 +241,11 @@ impl<'tcx> TyCtxt<'tcx> {
214241 } )
215242 }
216243
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 )
219246 }
220247
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 {
222249 let sized_def_id = match self . lang_items ( ) . sized_trait ( ) {
223250 Some ( def_id) => def_id,
224251 None => { return false ; /* No Sized trait, can't require it! */ }
@@ -229,11 +256,11 @@ impl<'tcx> TyCtxt<'tcx> {
229256 let predicates = predicates. instantiate_identity ( self ) . predicates ;
230257 elaborate_predicates ( self , predicates)
231258 . 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
234262 }
235263 ty:: Predicate :: Projection ( ..) |
236- ty:: Predicate :: Trait ( ..) |
237264 ty:: Predicate :: Subtype ( ..) |
238265 ty:: Predicate :: RegionOutlives ( ..) |
239266 ty:: Predicate :: WellFormed ( ..) |
@@ -248,51 +275,32 @@ impl<'tcx> TyCtxt<'tcx> {
248275 }
249276
250277 /// 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 > {
256284 debug ! ( "object_safety_violation_for_method({:?}, {:?})" , trait_def_id, method) ;
257285 // Any method that has a `Self : Sized` requisite is otherwise
258286 // 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 ) {
260288 return None ;
261289 }
262290
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)
285292 }
286293
287294 /// Returns `Some(_)` if this method cannot be called on a trait
288295 /// object; this does not necessarily imply that the enclosing trait
289296 /// is not object safe, because the method might have a where clause
290297 /// `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 > {
296304 // The method's first parameter must be named `self`
297305 if !method. method_has_self_argument {
298306 return Some ( MethodViolationCode :: StaticMethod ) ;
@@ -301,11 +309,15 @@ impl<'tcx> TyCtxt<'tcx> {
301309 let sig = self . fn_sig ( method. def_id ) ;
302310
303311 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) {
305313 return Some ( MethodViolationCode :: ReferencesSelf ) ;
306314 }
307315 }
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+ ) {
309321 return Some ( MethodViolationCode :: ReferencesSelf ) ;
310322 }
311323
@@ -323,7 +335,9 @@ impl<'tcx> TyCtxt<'tcx> {
323335 . collect :: < Vec < _ > > ( )
324336 // Do a shallow visit so that `contains_illegal_self_type_reference`
325337 // 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+ } ) {
327341 let span = self . def_span ( method. def_id ) ;
328342 return Some ( MethodViolationCode :: WhereClauseReferencesSelf ( span) ) ;
329343 }
@@ -337,7 +351,7 @@ impl<'tcx> TyCtxt<'tcx> {
337351 // However, this is already considered object-safe. We allow it as a special case here.
338352 // FIXME(mikeyhew) get rid of this `if` statement once `receiver_is_dispatchable` allows
339353 // `Receiver: Unsize<Receiver[Self => dyn Trait]>`
340- if receiver_ty != self . mk_self_type ( ) {
354+ if receiver_ty != self_ty {
341355 if !self . receiver_is_dispatchable ( method, receiver_ty) {
342356 return Some ( MethodViolationCode :: UndispatchableReceiver ) ;
343357 } else {
@@ -404,7 +418,10 @@ impl<'tcx> TyCtxt<'tcx> {
404418 /// Performs a type substitution to produce the version of receiver_ty when `Self = self_ty`
405419 /// e.g., for receiver_ty = `Rc<Self>` and self_ty = `Foo`, returns `Rc<Foo>`.
406420 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 ,
408425 ) -> Ty < ' tcx > {
409426 debug ! ( "receiver_for_self_ty({:?}, {:?}, {:?})" , receiver_ty, self_ty, method_def_id) ;
410427 let substs = InternalSubsts :: for_item ( self , method_def_id, |param, _| {
@@ -608,11 +625,12 @@ impl<'tcx> TyCtxt<'tcx> {
608625 } )
609626 }
610627
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 {
616634 // This is somewhat subtle. In general, we want to forbid
617635 // references to `Self` in the argument and return types,
618636 // since the value of `Self` is erased. However, there is one
@@ -656,8 +674,8 @@ impl<'tcx> TyCtxt<'tcx> {
656674 let mut error = false ;
657675 ty. maybe_walk ( |ty| {
658676 match ty. sty {
659- ty:: Param ( ref param_ty ) => {
660- if param_ty . is_self ( ) {
677+ ty:: Param ( _ ) => {
678+ if ty == self_ty {
661679 error = true ;
662680 }
663681
0 commit comments