Skip to content

Commit 4657ad1

Browse files
committed
Pre intern the Self parameter type
Use this to simplify the object safety code a bit.
1 parent 165e460 commit 4657ad1

File tree

2 files changed

+26
-34
lines changed

2 files changed

+26
-34
lines changed

src/librustc/traits/object_safety.rs

+20-33
Original file line numberDiff line numberDiff line change
@@ -92,9 +92,8 @@ impl<'tcx> TyCtxt<'tcx> {
9292
-> Vec<ObjectSafetyViolation>
9393
{
9494
debug_assert!(self.generics_of(trait_def_id).has_self);
95-
let self_ty = self.mk_self_type();
9695
let violations = traits::supertrait_def_ids(self, trait_def_id)
97-
.filter(|&def_id| self.predicates_reference_self(def_id, self_ty, true))
96+
.filter(|&def_id| self.predicates_reference_self(def_id, true))
9897
.map(|_| ObjectSafetyViolation::SupertraitSelf)
9998
.collect();
10099

@@ -109,11 +108,10 @@ impl<'tcx> TyCtxt<'tcx> {
109108
-> Vec<ObjectSafetyViolation>
110109
{
111110
debug_assert!(self.generics_of(trait_def_id).has_self);
112-
let self_ty = self.mk_self_type();
113111
debug!("object_safety_violations: {:?}", trait_def_id);
114112

115113
traits::supertrait_def_ids(self, trait_def_id)
116-
.flat_map(|def_id| self.object_safety_violations_for_trait(def_id, self_ty))
114+
.flat_map(|def_id| self.object_safety_violations_for_trait(def_id))
117115
.collect()
118116
}
119117

@@ -123,29 +121,24 @@ impl<'tcx> TyCtxt<'tcx> {
123121
/// otherwise ensure that they cannot be used when `Self=Trait`.
124122
pub fn is_vtable_safe_method(self, trait_def_id: DefId, method: &ty::AssocItem) -> bool {
125123
debug_assert!(self.generics_of(trait_def_id).has_self);
126-
let self_ty = self.mk_self_type();
127124
debug!("is_vtable_safe_method({:?}, {:?})", trait_def_id, method);
128125
// Any method that has a `Self : Sized` requisite can't be called.
129-
if self.generics_require_sized_self(method.def_id, self_ty) {
126+
if self.generics_require_sized_self(method.def_id) {
130127
return false;
131128
}
132129

133-
match self.virtual_call_violation_for_method(trait_def_id, self_ty, method) {
130+
match self.virtual_call_violation_for_method(trait_def_id, method) {
134131
None | Some(MethodViolationCode::WhereClauseReferencesSelf(_)) => true,
135132
Some(_) => false,
136133
}
137134
}
138135

139-
fn object_safety_violations_for_trait(
140-
self,
141-
trait_def_id: DefId,
142-
self_ty: Ty<'tcx>,
143-
) -> Vec<ObjectSafetyViolation> {
136+
fn object_safety_violations_for_trait(self, trait_def_id: DefId) -> Vec<ObjectSafetyViolation> {
144137
// Check methods for violations.
145138
let mut violations: Vec<_> = self.associated_items(trait_def_id)
146139
.filter(|item| item.kind == ty::AssocKind::Method)
147140
.filter_map(|item|
148-
self.object_safety_violation_for_method(trait_def_id, self_ty, &item)
141+
self.object_safety_violation_for_method(trait_def_id, &item)
149142
.map(|code| ObjectSafetyViolation::Method(item.ident.name, code))
150143
).filter(|violation| {
151144
if let ObjectSafetyViolation::Method(_,
@@ -167,10 +160,10 @@ impl<'tcx> TyCtxt<'tcx> {
167160
}).collect();
168161

169162
// Check the trait itself.
170-
if self.trait_has_sized_self(trait_def_id, self_ty) {
163+
if self.trait_has_sized_self(trait_def_id) {
171164
violations.push(ObjectSafetyViolation::SizedSelf);
172165
}
173-
if self.predicates_reference_self(trait_def_id, self_ty, false) {
166+
if self.predicates_reference_self(trait_def_id, false) {
174167
violations.push(ObjectSafetyViolation::SupertraitSelf);
175168
}
176169

@@ -188,7 +181,6 @@ impl<'tcx> TyCtxt<'tcx> {
188181
fn predicates_reference_self(
189182
self,
190183
trait_def_id: DefId,
191-
self_ty: Ty<'tcx>,
192184
supertraits_only: bool,
193185
) -> bool {
194186
let trait_ref = ty::Binder::dummy(ty::TraitRef::identity(self, trait_def_id));
@@ -197,6 +189,7 @@ impl<'tcx> TyCtxt<'tcx> {
197189
} else {
198190
self.predicates_of(trait_def_id)
199191
};
192+
let self_ty = self.mk_self_type();
200193
let has_self_ty = |t: Ty<'tcx>| t.walk().any(|t| t == self_ty);
201194
predicates
202195
.predicates
@@ -241,11 +234,11 @@ impl<'tcx> TyCtxt<'tcx> {
241234
})
242235
}
243236

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)
237+
fn trait_has_sized_self(self, trait_def_id: DefId) -> bool {
238+
self.generics_require_sized_self(trait_def_id)
246239
}
247240

248-
fn generics_require_sized_self(self, def_id: DefId, self_ty: Ty<'tcx>) -> bool {
241+
fn generics_require_sized_self(self, def_id: DefId) -> bool {
249242
let sized_def_id = match self.lang_items().sized_trait() {
250243
Some(def_id) => def_id,
251244
None => { return false; /* No Sized trait, can't require it! */ }
@@ -258,7 +251,7 @@ impl<'tcx> TyCtxt<'tcx> {
258251
.any(|predicate| match predicate {
259252
ty::Predicate::Trait(ref trait_pred) => {
260253
trait_pred.def_id() == sized_def_id
261-
&& trait_pred.skip_binder().self_ty() == self_ty
254+
&& trait_pred.skip_binder().self_ty().is_param(0)
262255
}
263256
ty::Predicate::Projection(..) |
264257
ty::Predicate::Subtype(..) |
@@ -278,17 +271,16 @@ impl<'tcx> TyCtxt<'tcx> {
278271
fn object_safety_violation_for_method(
279272
self,
280273
trait_def_id: DefId,
281-
self_ty: Ty<'tcx>,
282274
method: &ty::AssocItem,
283275
) -> Option<MethodViolationCode> {
284276
debug!("object_safety_violation_for_method({:?}, {:?})", trait_def_id, method);
285277
// Any method that has a `Self : Sized` requisite is otherwise
286278
// exempt from the regulations.
287-
if self.generics_require_sized_self(method.def_id, self_ty) {
279+
if self.generics_require_sized_self(method.def_id) {
288280
return None;
289281
}
290282

291-
self.virtual_call_violation_for_method(trait_def_id, self_ty, method)
283+
self.virtual_call_violation_for_method(trait_def_id, method)
292284
}
293285

294286
/// Returns `Some(_)` if this method cannot be called on a trait
@@ -298,7 +290,6 @@ impl<'tcx> TyCtxt<'tcx> {
298290
fn virtual_call_violation_for_method(
299291
self,
300292
trait_def_id: DefId,
301-
self_ty: Ty<'tcx>,
302293
method: &ty::AssocItem,
303294
) -> Option<MethodViolationCode> {
304295
// The method's first parameter must be named `self`
@@ -309,15 +300,11 @@ impl<'tcx> TyCtxt<'tcx> {
309300
let sig = self.fn_sig(method.def_id);
310301

311302
for input_ty in &sig.skip_binder().inputs()[1..] {
312-
if self.contains_illegal_self_type_reference(trait_def_id, self_ty, input_ty) {
303+
if self.contains_illegal_self_type_reference(trait_def_id, input_ty) {
313304
return Some(MethodViolationCode::ReferencesSelf);
314305
}
315306
}
316-
if self.contains_illegal_self_type_reference(
317-
trait_def_id,
318-
self_ty,
319-
sig.output().skip_binder(),
320-
) {
307+
if self.contains_illegal_self_type_reference(trait_def_id, sig.output().skip_binder()) {
321308
return Some(MethodViolationCode::ReferencesSelf);
322309
}
323310

@@ -336,7 +323,7 @@ impl<'tcx> TyCtxt<'tcx> {
336323
// Do a shallow visit so that `contains_illegal_self_type_reference`
337324
// may apply it's custom visiting.
338325
.visit_tys_shallow(|t| {
339-
self.contains_illegal_self_type_reference(trait_def_id, self_ty, t)
326+
self.contains_illegal_self_type_reference(trait_def_id, t)
340327
}) {
341328
let span = self.def_span(method.def_id);
342329
return Some(MethodViolationCode::WhereClauseReferencesSelf(span));
@@ -351,7 +338,7 @@ impl<'tcx> TyCtxt<'tcx> {
351338
// However, this is already considered object-safe. We allow it as a special case here.
352339
// FIXME(mikeyhew) get rid of this `if` statement once `receiver_is_dispatchable` allows
353340
// `Receiver: Unsize<Receiver[Self => dyn Trait]>`
354-
if receiver_ty != self_ty {
341+
if receiver_ty != self.mk_self_type() {
355342
if !self.receiver_is_dispatchable(method, receiver_ty) {
356343
return Some(MethodViolationCode::UndispatchableReceiver);
357344
} else {
@@ -628,7 +615,6 @@ impl<'tcx> TyCtxt<'tcx> {
628615
fn contains_illegal_self_type_reference(
629616
self,
630617
trait_def_id: DefId,
631-
self_ty: Ty<'tcx>,
632618
ty: Ty<'tcx>,
633619
) -> bool {
634620
// This is somewhat subtle. In general, we want to forbid
@@ -672,6 +658,7 @@ impl<'tcx> TyCtxt<'tcx> {
672658

673659
let mut supertraits: Option<Vec<ty::PolyTraitRef<'tcx>>> = None;
674660
let mut error = false;
661+
let self_ty = self.mk_self_type();
675662
ty.maybe_walk(|ty| {
676663
match ty.sty {
677664
ty::Param(_) => {

src/librustc/ty/context.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,7 @@ pub struct CommonTypes<'tcx> {
173173
pub f32: Ty<'tcx>,
174174
pub f64: Ty<'tcx>,
175175
pub never: Ty<'tcx>,
176+
self_param: Ty<'tcx>,
176177
pub err: Ty<'tcx>,
177178

178179
/// Dummy type used for the `Self` of a `TraitRef` created for converting
@@ -915,6 +916,10 @@ impl<'tcx> CommonTypes<'tcx> {
915916
u128: mk(Uint(ast::UintTy::U128)),
916917
f32: mk(Float(ast::FloatTy::F32)),
917918
f64: mk(Float(ast::FloatTy::F64)),
919+
self_param: mk(ty::Param(ty::ParamTy {
920+
index: 0,
921+
name: kw::SelfUpper.as_interned_str(),
922+
})),
918923

919924
trait_object_dummy_self: mk(Infer(ty::FreshTy(0))),
920925
}
@@ -2568,7 +2573,7 @@ impl<'tcx> TyCtxt<'tcx> {
25682573

25692574
#[inline]
25702575
pub fn mk_self_type(self) -> Ty<'tcx> {
2571-
self.mk_ty_param(0, kw::SelfUpper.as_interned_str())
2576+
self.types.self_param
25722577
}
25732578

25742579
pub fn mk_param_from_def(self, param: &ty::GenericParamDef) -> Kind<'tcx> {

0 commit comments

Comments
 (0)