@@ -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