Skip to content

Commit

Permalink
Pre intern the Self parameter type
Browse files Browse the repository at this point in the history
Use this to simplify the object safety code a bit.
  • Loading branch information
matthewjasper committed Aug 12, 2019
1 parent 165e460 commit 4657ad1
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 34 deletions.
53 changes: 20 additions & 33 deletions src/librustc/traits/object_safety.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,9 +92,8 @@ impl<'tcx> TyCtxt<'tcx> {
-> Vec<ObjectSafetyViolation>
{
debug_assert!(self.generics_of(trait_def_id).has_self);
let self_ty = self.mk_self_type();
let violations = traits::supertrait_def_ids(self, trait_def_id)
.filter(|&def_id| self.predicates_reference_self(def_id, self_ty, true))
.filter(|&def_id| self.predicates_reference_self(def_id, true))
.map(|_| ObjectSafetyViolation::SupertraitSelf)
.collect();

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

traits::supertrait_def_ids(self, trait_def_id)
.flat_map(|def_id| self.object_safety_violations_for_trait(def_id, self_ty))
.flat_map(|def_id| self.object_safety_violations_for_trait(def_id))
.collect()
}

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

match self.virtual_call_violation_for_method(trait_def_id, self_ty, method) {
match self.virtual_call_violation_for_method(trait_def_id, method) {
None | Some(MethodViolationCode::WhereClauseReferencesSelf(_)) => true,
Some(_) => false,
}
}

fn object_safety_violations_for_trait(
self,
trait_def_id: DefId,
self_ty: Ty<'tcx>,
) -> Vec<ObjectSafetyViolation> {
fn object_safety_violations_for_trait(self, trait_def_id: DefId) -> Vec<ObjectSafetyViolation> {
// Check methods for violations.
let mut violations: Vec<_> = self.associated_items(trait_def_id)
.filter(|item| item.kind == ty::AssocKind::Method)
.filter_map(|item|
self.object_safety_violation_for_method(trait_def_id, self_ty, &item)
self.object_safety_violation_for_method(trait_def_id, &item)
.map(|code| ObjectSafetyViolation::Method(item.ident.name, code))
).filter(|violation| {
if let ObjectSafetyViolation::Method(_,
Expand All @@ -167,10 +160,10 @@ impl<'tcx> TyCtxt<'tcx> {
}).collect();

// Check the trait itself.
if self.trait_has_sized_self(trait_def_id, self_ty) {
if self.trait_has_sized_self(trait_def_id) {
violations.push(ObjectSafetyViolation::SizedSelf);
}
if self.predicates_reference_self(trait_def_id, self_ty, false) {
if self.predicates_reference_self(trait_def_id, false) {
violations.push(ObjectSafetyViolation::SupertraitSelf);
}

Expand All @@ -188,7 +181,6 @@ impl<'tcx> TyCtxt<'tcx> {
fn predicates_reference_self(
self,
trait_def_id: DefId,
self_ty: Ty<'tcx>,
supertraits_only: bool,
) -> bool {
let trait_ref = ty::Binder::dummy(ty::TraitRef::identity(self, trait_def_id));
Expand All @@ -197,6 +189,7 @@ impl<'tcx> TyCtxt<'tcx> {
} else {
self.predicates_of(trait_def_id)
};
let self_ty = self.mk_self_type();
let has_self_ty = |t: Ty<'tcx>| t.walk().any(|t| t == self_ty);
predicates
.predicates
Expand Down Expand Up @@ -241,11 +234,11 @@ impl<'tcx> TyCtxt<'tcx> {
})
}

fn trait_has_sized_self(self, trait_def_id: DefId, self_ty: Ty<'tcx>) -> bool {
self.generics_require_sized_self(trait_def_id, self_ty)
fn trait_has_sized_self(self, trait_def_id: DefId) -> bool {
self.generics_require_sized_self(trait_def_id)
}

fn generics_require_sized_self(self, def_id: DefId, self_ty: Ty<'tcx>) -> bool {
fn generics_require_sized_self(self, def_id: DefId) -> bool {
let sized_def_id = match self.lang_items().sized_trait() {
Some(def_id) => def_id,
None => { return false; /* No Sized trait, can't require it! */ }
Expand All @@ -258,7 +251,7 @@ impl<'tcx> TyCtxt<'tcx> {
.any(|predicate| match predicate {
ty::Predicate::Trait(ref trait_pred) => {
trait_pred.def_id() == sized_def_id
&& trait_pred.skip_binder().self_ty() == self_ty
&& trait_pred.skip_binder().self_ty().is_param(0)
}
ty::Predicate::Projection(..) |
ty::Predicate::Subtype(..) |
Expand All @@ -278,17 +271,16 @@ impl<'tcx> TyCtxt<'tcx> {
fn object_safety_violation_for_method(
self,
trait_def_id: DefId,
self_ty: Ty<'tcx>,
method: &ty::AssocItem,
) -> Option<MethodViolationCode> {
debug!("object_safety_violation_for_method({:?}, {:?})", trait_def_id, method);
// Any method that has a `Self : Sized` requisite is otherwise
// exempt from the regulations.
if self.generics_require_sized_self(method.def_id, self_ty) {
if self.generics_require_sized_self(method.def_id) {
return None;
}

self.virtual_call_violation_for_method(trait_def_id, self_ty, method)
self.virtual_call_violation_for_method(trait_def_id, method)
}

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

for input_ty in &sig.skip_binder().inputs()[1..] {
if self.contains_illegal_self_type_reference(trait_def_id, self_ty, input_ty) {
if self.contains_illegal_self_type_reference(trait_def_id, input_ty) {
return Some(MethodViolationCode::ReferencesSelf);
}
}
if self.contains_illegal_self_type_reference(
trait_def_id,
self_ty,
sig.output().skip_binder(),
) {
if self.contains_illegal_self_type_reference(trait_def_id, sig.output().skip_binder()) {
return Some(MethodViolationCode::ReferencesSelf);
}

Expand All @@ -336,7 +323,7 @@ impl<'tcx> TyCtxt<'tcx> {
// Do a shallow visit so that `contains_illegal_self_type_reference`
// may apply it's custom visiting.
.visit_tys_shallow(|t| {
self.contains_illegal_self_type_reference(trait_def_id, self_ty, t)
self.contains_illegal_self_type_reference(trait_def_id, t)
}) {
let span = self.def_span(method.def_id);
return Some(MethodViolationCode::WhereClauseReferencesSelf(span));
Expand All @@ -351,7 +338,7 @@ impl<'tcx> TyCtxt<'tcx> {
// However, this is already considered object-safe. We allow it as a special case here.
// FIXME(mikeyhew) get rid of this `if` statement once `receiver_is_dispatchable` allows
// `Receiver: Unsize<Receiver[Self => dyn Trait]>`
if receiver_ty != self_ty {
if receiver_ty != self.mk_self_type() {
if !self.receiver_is_dispatchable(method, receiver_ty) {
return Some(MethodViolationCode::UndispatchableReceiver);
} else {
Expand Down Expand Up @@ -628,7 +615,6 @@ impl<'tcx> TyCtxt<'tcx> {
fn contains_illegal_self_type_reference(
self,
trait_def_id: DefId,
self_ty: Ty<'tcx>,
ty: Ty<'tcx>,
) -> bool {
// This is somewhat subtle. In general, we want to forbid
Expand Down Expand Up @@ -672,6 +658,7 @@ impl<'tcx> TyCtxt<'tcx> {

let mut supertraits: Option<Vec<ty::PolyTraitRef<'tcx>>> = None;
let mut error = false;
let self_ty = self.mk_self_type();
ty.maybe_walk(|ty| {
match ty.sty {
ty::Param(_) => {
Expand Down
7 changes: 6 additions & 1 deletion src/librustc/ty/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ pub struct CommonTypes<'tcx> {
pub f32: Ty<'tcx>,
pub f64: Ty<'tcx>,
pub never: Ty<'tcx>,
self_param: Ty<'tcx>,
pub err: Ty<'tcx>,

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

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

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

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

0 comments on commit 4657ad1

Please sign in to comment.