about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc/infer/error_reporting/mod.rs4
-rw-r--r--src/librustc/traits/object_safety.rs144
-rw-r--r--src/librustc/ty/error.rs8
-rw-r--r--src/librustc/ty/flags.rs8
-rw-r--r--src/librustc/ty/fold.rs3
-rw-r--r--src/librustc/ty/instance.rs5
-rw-r--r--src/librustc/ty/layout.rs3
-rw-r--r--src/librustc/ty/mod.rs22
-rw-r--r--src/librustc/ty/sty.rs15
-rw-r--r--src/librustc_mir/shim.rs2
-rw-r--r--src/librustc_typeck/astconv.rs5
-rw-r--r--src/librustc_typeck/outlives/implicit_infer.rs30
-rw-r--r--src/librustdoc/clean/simplify.rs4
-rw-r--r--src/test/ui/structs/struct-path-self.rs6
-rw-r--r--src/test/ui/structs/struct-path-self.stderr6
-rw-r--r--src/test/ui/type/type-params-in-different-spaces-1.rs2
-rw-r--r--src/test/ui/type/type-params-in-different-spaces-1.stderr2
-rw-r--r--src/test/ui/type/type-params-in-different-spaces-3.stderr2
18 files changed, 128 insertions, 143 deletions
diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs
index 2ffcd2c4ace..84687b8cab5 100644
--- a/src/librustc/infer/error_reporting/mod.rs
+++ b/src/librustc/infer/error_reporting/mod.rs
@@ -1329,7 +1329,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
                     let generics = self.tcx.generics_of(did);
                     // Account for the case where `did` corresponds to `Self`, which doesn't have
                     // the expected type argument.
-                    if !param.is_self() {
+                    if !(generics.has_self && param.index == 0) {
                         let type_param = generics.type_param(param, self.tcx);
                         let hir = &self.tcx.hir();
                         hir.as_local_hir_id(type_param.def_id).map(|id| {
@@ -1337,7 +1337,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
                             // We do this to avoid suggesting code that ends up as `T: 'a'b`,
                             // instead we suggest `T: 'a + 'b` in that case.
                             let mut has_bounds = false;
-                            if let Node::GenericParam(ref param) = hir.get(id) {
+                            if let Node::GenericParam(param) = hir.get(id) {
                                 has_bounds = !param.bounds.is_empty();
                             }
                             let sp = hir.span(id);
diff --git a/src/librustc/traits/object_safety.rs b/src/librustc/traits/object_safety.rs
index 37eff852abd..98603edd806 100644
--- a/src/librustc/traits/object_safety.rs
+++ b/src/librustc/traits/object_safety.rs
@@ -91,8 +91,10 @@ impl<'tcx> TyCtxt<'tcx> {
     pub fn astconv_object_safety_violations(self, trait_def_id: DefId)
                                             -> 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, true))
+            .filter(|&def_id| self.predicates_reference_self(def_id, self_ty, true))
             .map(|_| ObjectSafetyViolation::SupertraitSelf)
             .collect();
 
@@ -106,21 +108,44 @@ impl<'tcx> TyCtxt<'tcx> {
     pub fn object_safety_violations(self, trait_def_id: DefId)
                                     -> 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))
+            .flat_map(|def_id| self.object_safety_violations_for_trait(def_id, self_ty))
             .collect()
     }
 
-    fn object_safety_violations_for_trait(self, trait_def_id: DefId)
-                                          -> Vec<ObjectSafetyViolation>
-    {
+    /// We say a method is *vtable safe* if it can be invoked on a trait
+    /// object.  Note that object-safe traits can have some
+    /// non-vtable-safe methods, so long as they require `Self:Sized` or
+    /// 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) {
+            return false;
+        }
+
+        match self.virtual_call_violation_for_method(trait_def_id, self_ty, 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> {
         // 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, &item)
+                self.object_safety_violation_for_method(trait_def_id, self_ty, &item)
                     .map(|code| ObjectSafetyViolation::Method(item.ident.name, code))
             ).filter(|violation| {
                 if let ObjectSafetyViolation::Method(_,
@@ -142,10 +167,10 @@ impl<'tcx> TyCtxt<'tcx> {
             }).collect();
 
         // Check the trait itself.
-        if self.trait_has_sized_self(trait_def_id) {
+        if self.trait_has_sized_self(trait_def_id, self_ty) {
             violations.push(ObjectSafetyViolation::SizedSelf);
         }
-        if self.predicates_reference_self(trait_def_id, false) {
+        if self.predicates_reference_self(trait_def_id, self_ty, false) {
             violations.push(ObjectSafetyViolation::SupertraitSelf);
         }
 
@@ -163,14 +188,16 @@ impl<'tcx> TyCtxt<'tcx> {
     fn predicates_reference_self(
         self,
         trait_def_id: DefId,
-        supertraits_only: bool) -> bool
-    {
+        self_ty: Ty<'tcx>,
+        supertraits_only: bool,
+    ) -> bool {
         let trait_ref = ty::Binder::dummy(ty::TraitRef::identity(self, trait_def_id));
         let predicates = if supertraits_only {
             self.super_predicates_of(trait_def_id)
         } else {
             self.predicates_of(trait_def_id)
         };
+        let has_self_ty = |t: Ty<'tcx>| t.walk().any(|t| t == self_ty);
         predicates
             .predicates
             .iter()
@@ -179,7 +206,7 @@ impl<'tcx> TyCtxt<'tcx> {
                 match predicate {
                     ty::Predicate::Trait(ref data) => {
                         // In the case of a trait predicate, we can skip the "self" type.
-                        data.skip_binder().input_types().skip(1).any(|t| t.has_self_ty())
+                        data.skip_binder().input_types().skip(1).any(has_self_ty)
                     }
                     ty::Predicate::Projection(ref data) => {
                         // And similarly for projections. This should be redundant with
@@ -199,7 +226,7 @@ impl<'tcx> TyCtxt<'tcx> {
                             .trait_ref(self)
                             .input_types()
                             .skip(1)
-                            .any(|t| t.has_self_ty())
+                            .any(has_self_ty)
                     }
                     ty::Predicate::WellFormed(..) |
                     ty::Predicate::ObjectSafe(..) |
@@ -214,11 +241,11 @@ impl<'tcx> TyCtxt<'tcx> {
             })
     }
 
-    fn trait_has_sized_self(self, trait_def_id: DefId) -> bool {
-        self.generics_require_sized_self(trait_def_id)
+    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 generics_require_sized_self(self, def_id: DefId) -> bool {
+    fn generics_require_sized_self(self, def_id: DefId, self_ty: Ty<'tcx>) -> 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! */ }
@@ -229,11 +256,11 @@ impl<'tcx> TyCtxt<'tcx> {
         let predicates = predicates.instantiate_identity(self).predicates;
         elaborate_predicates(self, predicates)
             .any(|predicate| match predicate {
-                ty::Predicate::Trait(ref trait_pred) if trait_pred.def_id() == sized_def_id => {
-                    trait_pred.skip_binder().self_ty().is_self()
+                ty::Predicate::Trait(ref trait_pred) => {
+                    trait_pred.def_id() == sized_def_id
+                        && trait_pred.skip_binder().self_ty() == self_ty
                 }
                 ty::Predicate::Projection(..) |
-                ty::Predicate::Trait(..) |
                 ty::Predicate::Subtype(..) |
                 ty::Predicate::RegionOutlives(..) |
                 ty::Predicate::WellFormed(..) |
@@ -248,51 +275,32 @@ impl<'tcx> TyCtxt<'tcx> {
     }
 
     /// Returns `Some(_)` if this method makes the containing trait not object safe.
-    fn object_safety_violation_for_method(self,
-                                          trait_def_id: DefId,
-                                          method: &ty::AssocItem)
-                                          -> Option<MethodViolationCode>
-    {
+    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) {
+        if self.generics_require_sized_self(method.def_id, self_ty) {
             return None;
         }
 
-        self.virtual_call_violation_for_method(trait_def_id, method)
-    }
-
-    /// We say a method is *vtable safe* if it can be invoked on a trait
-    /// object.  Note that object-safe traits can have some
-    /// non-vtable-safe methods, so long as they require `Self:Sized` or
-    /// 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!("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) {
-            return false;
-        }
-
-        match self.virtual_call_violation_for_method(trait_def_id, method) {
-            None | Some(MethodViolationCode::WhereClauseReferencesSelf(_)) => true,
-            Some(_) => false,
-        }
+        self.virtual_call_violation_for_method(trait_def_id, self_ty, method)
     }
 
     /// Returns `Some(_)` if this method cannot be called on a trait
     /// object; this does not necessarily imply that the enclosing trait
     /// is not object safe, because the method might have a where clause
     /// `Self:Sized`.
-    fn virtual_call_violation_for_method(self,
-                                         trait_def_id: DefId,
-                                         method: &ty::AssocItem)
-                                         -> Option<MethodViolationCode>
-    {
+    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`
         if !method.method_has_self_argument {
             return Some(MethodViolationCode::StaticMethod);
@@ -301,11 +309,15 @@ 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, input_ty) {
+            if self.contains_illegal_self_type_reference(trait_def_id, self_ty, input_ty) {
                 return Some(MethodViolationCode::ReferencesSelf);
             }
         }
-        if self.contains_illegal_self_type_reference(trait_def_id, sig.output().skip_binder()) {
+        if self.contains_illegal_self_type_reference(
+            trait_def_id,
+            self_ty,
+            sig.output().skip_binder(),
+        ) {
             return Some(MethodViolationCode::ReferencesSelf);
         }
 
@@ -323,7 +335,9 @@ impl<'tcx> TyCtxt<'tcx> {
                 .collect::<Vec<_>>()
                 // 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, t)) {
+                .visit_tys_shallow(|t| {
+                    self.contains_illegal_self_type_reference(trait_def_id, self_ty, t)
+                }) {
             let span = self.def_span(method.def_id);
             return Some(MethodViolationCode::WhereClauseReferencesSelf(span));
         }
@@ -337,7 +351,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.mk_self_type() {
+        if receiver_ty != self_ty {
             if !self.receiver_is_dispatchable(method, receiver_ty) {
                 return Some(MethodViolationCode::UndispatchableReceiver);
             } else {
@@ -404,7 +418,10 @@ impl<'tcx> TyCtxt<'tcx> {
     /// Performs a type substitution to produce the version of receiver_ty when `Self = self_ty`
     /// e.g., for receiver_ty = `Rc<Self>` and self_ty = `Foo`, returns `Rc<Foo>`.
     fn receiver_for_self_ty(
-        self, receiver_ty: Ty<'tcx>, self_ty: Ty<'tcx>, method_def_id: DefId
+        self,
+        receiver_ty: Ty<'tcx>,
+        self_ty: Ty<'tcx>,
+        method_def_id: DefId,
     ) -> Ty<'tcx> {
         debug!("receiver_for_self_ty({:?}, {:?}, {:?})", receiver_ty, self_ty, method_def_id);
         let substs = InternalSubsts::for_item(self, method_def_id, |param, _| {
@@ -608,11 +625,12 @@ impl<'tcx> TyCtxt<'tcx> {
         })
     }
 
-    fn contains_illegal_self_type_reference(self,
-                                            trait_def_id: DefId,
-                                            ty: Ty<'tcx>)
-                                            -> bool
-    {
+    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
         // references to `Self` in the argument and return types,
         // since the value of `Self` is erased. However, there is one
@@ -656,8 +674,8 @@ impl<'tcx> TyCtxt<'tcx> {
         let mut error = false;
         ty.maybe_walk(|ty| {
             match ty.sty {
-                ty::Param(ref param_ty) => {
-                    if param_ty.is_self() {
+                ty::Param(_) => {
+                    if ty == self_ty {
                         error = true;
                     }
 
diff --git a/src/librustc/ty/error.rs b/src/librustc/ty/error.rs
index 4a72794b61a..d6d17a67e01 100644
--- a/src/librustc/ty/error.rs
+++ b/src/librustc/ty/error.rs
@@ -239,13 +239,7 @@ impl<'tcx> ty::TyS<'tcx> {
             ty::Infer(ty::FreshFloatTy(_)) => "fresh floating-point type".into(),
             ty::Projection(_) => "associated type".into(),
             ty::UnnormalizedProjection(_) => "non-normalized associated type".into(),
-            ty::Param(ref p) => {
-                if p.is_self() {
-                    "Self".into()
-                } else {
-                    "type parameter".into()
-                }
-            }
+            ty::Param(_) => "type parameter".into(),
             ty::Opaque(..) => "opaque type".into(),
             ty::Error => "type error".into(),
         }
diff --git a/src/librustc/ty/flags.rs b/src/librustc/ty/flags.rs
index 411b18e043a..3944a2d9d03 100644
--- a/src/librustc/ty/flags.rs
+++ b/src/librustc/ty/flags.rs
@@ -86,13 +86,9 @@ impl FlagComputation {
                 self.add_flags(TypeFlags::HAS_TY_ERR)
             }
 
-            &ty::Param(ref p) => {
+            &ty::Param(_) => {
                 self.add_flags(TypeFlags::HAS_FREE_LOCAL_NAMES);
-                if p.is_self() {
-                    self.add_flags(TypeFlags::HAS_SELF);
-                } else {
-                    self.add_flags(TypeFlags::HAS_PARAMS);
-                }
+                self.add_flags(TypeFlags::HAS_PARAMS);
             }
 
             &ty::Generator(_, ref substs, _) => {
diff --git a/src/librustc/ty/fold.rs b/src/librustc/ty/fold.rs
index ab7df8e4e84..4b30412b419 100644
--- a/src/librustc/ty/fold.rs
+++ b/src/librustc/ty/fold.rs
@@ -85,9 +85,6 @@ pub trait TypeFoldable<'tcx>: fmt::Debug + Clone {
     fn has_param_types(&self) -> bool {
         self.has_type_flags(TypeFlags::HAS_PARAMS)
     }
-    fn has_self_ty(&self) -> bool {
-        self.has_type_flags(TypeFlags::HAS_SELF)
-    }
     fn has_infer_types(&self) -> bool {
         self.has_type_flags(TypeFlags::HAS_TY_INFER)
     }
diff --git a/src/librustc/ty/instance.rs b/src/librustc/ty/instance.rs
index 457d018f017..c71e1ea4e58 100644
--- a/src/librustc/ty/instance.rs
+++ b/src/librustc/ty/instance.rs
@@ -298,8 +298,9 @@ impl<'tcx> Instance<'tcx> {
     ) -> Option<Instance<'tcx>> {
         debug!("resolve(def_id={:?}, substs={:?})", def_id, substs);
         let fn_sig = tcx.fn_sig(def_id);
-        let is_vtable_shim =
-            fn_sig.inputs().skip_binder().len() > 0 && fn_sig.input(0).skip_binder().is_self();
+        let is_vtable_shim = fn_sig.inputs().skip_binder().len() > 0
+            && fn_sig.input(0).skip_binder().is_param(0)
+            && tcx.generics_of(def_id).has_self;
         if is_vtable_shim {
             debug!(" => associated item with unsizeable self: Self");
             Some(Instance {
diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs
index a9d1fd1fffc..2475fc86bb7 100644
--- a/src/librustc/ty/layout.rs
+++ b/src/librustc/ty/layout.rs
@@ -1601,7 +1601,6 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
         // resulting from the final codegen session.
         if
             layout.ty.has_param_types() ||
-            layout.ty.has_self_ty() ||
             !self.param_env.caller_bounds.is_empty()
         {
             return;
@@ -1767,7 +1766,7 @@ impl<'tcx> SizeSkeleton<'tcx> {
                 let tail = tcx.struct_tail_erasing_lifetimes(pointee, param_env);
                 match tail.sty {
                     ty::Param(_) | ty::Projection(_) => {
-                        debug_assert!(tail.has_param_types() || tail.has_self_ty());
+                        debug_assert!(tail.has_param_types());
                         Ok(SizeSkeleton::Pointer {
                             non_zero,
                             tail: tcx.erase_regions(&tail)
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index a10578b0a43..77237bf9b39 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -414,31 +414,30 @@ pub struct CReaderCacheKey {
 bitflags! {
     pub struct TypeFlags: u32 {
         const HAS_PARAMS         = 1 << 0;
-        const HAS_SELF           = 1 << 1;
-        const HAS_TY_INFER       = 1 << 2;
-        const HAS_RE_INFER       = 1 << 3;
-        const HAS_RE_PLACEHOLDER = 1 << 4;
+        const HAS_TY_INFER       = 1 << 1;
+        const HAS_RE_INFER       = 1 << 2;
+        const HAS_RE_PLACEHOLDER = 1 << 3;
 
         /// Does this have any `ReEarlyBound` regions? Used to
         /// determine whether substitition is required, since those
         /// represent regions that are bound in a `ty::Generics` and
         /// hence may be substituted.
-        const HAS_RE_EARLY_BOUND = 1 << 5;
+        const HAS_RE_EARLY_BOUND = 1 << 4;
 
         /// Does this have any region that "appears free" in the type?
         /// Basically anything but `ReLateBound` and `ReErased`.
-        const HAS_FREE_REGIONS   = 1 << 6;
+        const HAS_FREE_REGIONS   = 1 << 5;
 
         /// Is an error type reachable?
-        const HAS_TY_ERR         = 1 << 7;
-        const HAS_PROJECTION     = 1 << 8;
+        const HAS_TY_ERR         = 1 << 6;
+        const HAS_PROJECTION     = 1 << 7;
 
         // FIXME: Rename this to the actual property since it's used for generators too
-        const HAS_TY_CLOSURE     = 1 << 9;
+        const HAS_TY_CLOSURE     = 1 << 8;
 
         /// `true` if there are "names" of types and regions and so forth
         /// that are local to a particular fn
-        const HAS_FREE_LOCAL_NAMES    = 1 << 10;
+        const HAS_FREE_LOCAL_NAMES    = 1 << 9;
 
         /// Present if the type belongs in a local type context.
         /// Only set for Infer other than Fresh.
@@ -458,14 +457,12 @@ bitflags! {
         const HAS_CT_PLACEHOLDER = 1 << 16;
 
         const NEEDS_SUBST        = TypeFlags::HAS_PARAMS.bits |
-                                   TypeFlags::HAS_SELF.bits |
                                    TypeFlags::HAS_RE_EARLY_BOUND.bits;
 
         /// Flags representing the nominal content of a type,
         /// computed by FlagsComputation. If you add a new nominal
         /// flag, it should be added here too.
         const NOMINAL_FLAGS     = TypeFlags::HAS_PARAMS.bits |
-                                  TypeFlags::HAS_SELF.bits |
                                   TypeFlags::HAS_TY_INFER.bits |
                                   TypeFlags::HAS_RE_INFER.bits |
                                   TypeFlags::HAS_CT_INFER.bits |
@@ -1734,7 +1731,6 @@ impl<'tcx> ParamEnv<'tcx> {
                 if value.has_placeholders()
                     || value.needs_infer()
                     || value.has_param_types()
-                    || value.has_self_ty()
                 {
                     ParamEnvAnd {
                         param_env: self,
diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs
index 064c374de2b..1dd8108cb4b 100644
--- a/src/librustc/ty/sty.rs
+++ b/src/librustc/ty/sty.rs
@@ -1140,13 +1140,6 @@ impl<'tcx> ParamTy {
     pub fn to_ty(self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
         tcx.mk_ty_param(self.index, self.name)
     }
-
-    pub fn is_self(&self) -> bool {
-        // FIXME(#50125): Ignoring `Self` with `index != 0` might lead to weird behavior elsewhere,
-        // but this should only be possible when using `-Z continue-parse-after-error` like
-        // `compile-fail/issue-36638.rs`.
-        self.name.as_symbol() == kw::SelfUpper && self.index == 0
-    }
 }
 
 #[derive(Copy, Clone, Hash, RustcEncodable, RustcDecodable,
@@ -1789,14 +1782,6 @@ impl<'tcx> TyS<'tcx> {
     }
 
     #[inline]
-    pub fn is_self(&self) -> bool {
-        match self.sty {
-            Param(ref p) => p.is_self(),
-            _ => false,
-        }
-    }
-
-    #[inline]
     pub fn is_slice(&self) -> bool {
         match self.sty {
             RawPtr(TypeAndMut { ty, .. }) | Ref(_, ty, _) => match ty.sty {
diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs
index 42945c79ddf..39deb0fe5d3 100644
--- a/src/librustc_mir/shim.rs
+++ b/src/librustc_mir/shim.rs
@@ -710,7 +710,7 @@ fn build_call_shim<'tcx>(
         Adjustment::DerefMove => {
             // fn(Self, ...) -> fn(*mut Self, ...)
             let arg_ty = local_decls[rcvr_arg].ty;
-            assert!(arg_ty.is_self());
+            debug_assert!(tcx.generics_of(def_id).has_self && arg_ty == tcx.mk_self_type());
             local_decls[rcvr_arg].ty = tcx.mk_mut_ptr(arg_ty);
 
             Operand::Move(rcvr_l.deref())
diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs
index 922afbae2a4..e29e412858f 100644
--- a/src/librustc_typeck/astconv.rs
+++ b/src/librustc_typeck/astconv.rs
@@ -635,8 +635,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         });
         let default_needs_object_self = |param: &ty::GenericParamDef| {
             if let GenericParamDefKind::Type { has_default, .. } = param.kind {
-                if is_object && has_default {
-                    if tcx.at(span).type_of(param.def_id).has_self_ty() {
+                if is_object && has_default && has_self {
+                    let self_param = tcx.mk_self_type();
+                    if tcx.at(span).type_of(param.def_id).walk().any(|ty| ty == self_param) {
                         // There is no suitable inference default for a type parameter
                         // that references self, in an object type.
                         return true;
diff --git a/src/librustc_typeck/outlives/implicit_infer.rs b/src/librustc_typeck/outlives/implicit_infer.rs
index 6b288347ad0..a70aff1dee6 100644
--- a/src/librustc_typeck/outlives/implicit_infer.rs
+++ b/src/librustc_typeck/outlives/implicit_infer.rs
@@ -3,7 +3,6 @@ use rustc::hir::def_id::DefId;
 use rustc::hir::itemlikevisit::ItemLikeVisitor;
 use rustc::ty::subst::{Kind, Subst, UnpackedKind};
 use rustc::ty::{self, Ty, TyCtxt};
-use rustc::ty::fold::TypeFoldable;
 use rustc::util::nodemap::FxHashMap;
 
 use super::explicit::ExplicitPredicatesMap;
@@ -178,11 +177,11 @@ fn insert_required_predicates_to_be_wf<'tcx>(
                 // let _: () = substs.region_at(0);
                 check_explicit_predicates(
                     tcx,
-                    &def.did,
+                    def.did,
                     substs,
                     required_predicates,
                     explicit_map,
-                    IgnoreSelfTy(false),
+                    None,
                 );
             }
 
@@ -208,11 +207,11 @@ fn insert_required_predicates_to_be_wf<'tcx>(
                         .substs;
                     check_explicit_predicates(
                         tcx,
-                        &ex_trait_ref.skip_binder().def_id,
+                        ex_trait_ref.skip_binder().def_id,
                         substs,
                         required_predicates,
                         explicit_map,
-                        IgnoreSelfTy(true),
+                        Some(tcx.mk_self_type()),
                     );
                 }
             }
@@ -223,11 +222,11 @@ fn insert_required_predicates_to_be_wf<'tcx>(
                 debug!("Projection");
                 check_explicit_predicates(
                     tcx,
-                    &tcx.associated_item(obj.item_def_id).container.id(),
+                    tcx.associated_item(obj.item_def_id).container.id(),
                     obj.substs,
                     required_predicates,
                     explicit_map,
-                    IgnoreSelfTy(false),
+                    None,
                 );
             }
 
@@ -236,9 +235,6 @@ fn insert_required_predicates_to_be_wf<'tcx>(
     }
 }
 
-#[derive(Debug)]
-pub struct IgnoreSelfTy(bool);
-
 /// We also have to check the explicit predicates
 /// declared on the type.
 ///
@@ -256,25 +252,25 @@ pub struct IgnoreSelfTy(bool);
 /// applying the substitution as above.
 pub fn check_explicit_predicates<'tcx>(
     tcx: TyCtxt<'tcx>,
-    def_id: &DefId,
+    def_id: DefId,
     substs: &[Kind<'tcx>],
     required_predicates: &mut RequiredPredicates<'tcx>,
     explicit_map: &mut ExplicitPredicatesMap<'tcx>,
-    ignore_self_ty: IgnoreSelfTy,
+    ignored_self_ty: Option<Ty<'tcx>>,
 ) {
     debug!(
         "check_explicit_predicates(def_id={:?}, \
          substs={:?}, \
          explicit_map={:?}, \
          required_predicates={:?}, \
-         ignore_self_ty={:?})",
+         ignored_self_ty={:?})",
         def_id,
         substs,
         explicit_map,
         required_predicates,
-        ignore_self_ty,
+        ignored_self_ty,
     );
-    let explicit_predicates = explicit_map.explicit_predicates_of(tcx, *def_id);
+    let explicit_predicates = explicit_map.explicit_predicates_of(tcx, def_id);
 
     for outlives_predicate in explicit_predicates.iter() {
         debug!("outlives_predicate = {:?}", &outlives_predicate);
@@ -313,9 +309,9 @@ pub fn check_explicit_predicates<'tcx>(
         // = X` binding from the object type (there must be such a
         // binding) and thus infer an outlives requirement that `X:
         // 'b`.
-        if ignore_self_ty.0 {
+        if let Some(self_ty) = ignored_self_ty {
             if let UnpackedKind::Type(ty) = outlives_predicate.0.unpack() {
-                if ty.has_self_ty() {
+                if ty.walk().any(|ty| ty == self_ty) {
                     debug!("skipping self ty = {:?}", &ty);
                     continue;
                 }
diff --git a/src/librustdoc/clean/simplify.rs b/src/librustdoc/clean/simplify.rs
index e4fba73b820..4075d2af667 100644
--- a/src/librustdoc/clean/simplify.rs
+++ b/src/librustdoc/clean/simplify.rs
@@ -149,9 +149,11 @@ fn trait_is_same_or_supertrait(cx: &DocContext<'_>, child: DefId,
         return true
     }
     let predicates = cx.tcx.super_predicates_of(child);
+    debug_assert!(cx.tcx.generics_of(child).has_self);
+    let self_ty = cx.tcx.mk_self_type();
     predicates.predicates.iter().filter_map(|(pred, _)| {
         if let ty::Predicate::Trait(ref pred) = *pred {
-            if pred.skip_binder().trait_ref.self_ty().is_self() {
+            if pred.skip_binder().trait_ref.self_ty() == self_ty {
                 Some(pred.def_id())
             } else {
                 None
diff --git a/src/test/ui/structs/struct-path-self.rs b/src/test/ui/structs/struct-path-self.rs
index 77880bfca40..c938ce8dad9 100644
--- a/src/test/ui/structs/struct-path-self.rs
+++ b/src/test/ui/structs/struct-path-self.rs
@@ -3,13 +3,13 @@ struct S;
 trait Tr {
     fn f() {
         let s = Self {};
-        //~^ ERROR expected struct, variant or union type, found Self
+        //~^ ERROR expected struct, variant or union type, found type parameter
         let z = Self::<u8> {};
-        //~^ ERROR expected struct, variant or union type, found Self
+        //~^ ERROR expected struct, variant or union type, found type parameter
         //~| ERROR type arguments are not allowed for this type
         match s {
             Self { .. } => {}
-            //~^ ERROR expected struct, variant or union type, found Self
+            //~^ ERROR expected struct, variant or union type, found type parameter
         }
     }
 }
diff --git a/src/test/ui/structs/struct-path-self.stderr b/src/test/ui/structs/struct-path-self.stderr
index 9eaa1f95bd0..8c88cacc69e 100644
--- a/src/test/ui/structs/struct-path-self.stderr
+++ b/src/test/ui/structs/struct-path-self.stderr
@@ -1,4 +1,4 @@
-error[E0071]: expected struct, variant or union type, found Self
+error[E0071]: expected struct, variant or union type, found type parameter
   --> $DIR/struct-path-self.rs:5:17
    |
 LL |         let s = Self {};
@@ -10,13 +10,13 @@ error[E0109]: type arguments are not allowed for this type
 LL |         let z = Self::<u8> {};
    |                        ^^ type argument not allowed
 
-error[E0071]: expected struct, variant or union type, found Self
+error[E0071]: expected struct, variant or union type, found type parameter
   --> $DIR/struct-path-self.rs:7:17
    |
 LL |         let z = Self::<u8> {};
    |                 ^^^^^^^^^^ not a struct
 
-error[E0071]: expected struct, variant or union type, found Self
+error[E0071]: expected struct, variant or union type, found type parameter
   --> $DIR/struct-path-self.rs:11:13
    |
 LL |             Self { .. } => {}
diff --git a/src/test/ui/type/type-params-in-different-spaces-1.rs b/src/test/ui/type/type-params-in-different-spaces-1.rs
index 449a26e901d..71fb7f380ae 100644
--- a/src/test/ui/type/type-params-in-different-spaces-1.rs
+++ b/src/test/ui/type/type-params-in-different-spaces-1.rs
@@ -5,7 +5,7 @@ trait BrokenAdd: Copy + Add<Output=Self> {
         *self + rhs //~  ERROR mismatched types
                     //~| expected type `Self`
                     //~| found type `T`
-                    //~| expected Self, found type parameter
+                    //~| expected type parameter, found a different type parameter
     }
 }
 
diff --git a/src/test/ui/type/type-params-in-different-spaces-1.stderr b/src/test/ui/type/type-params-in-different-spaces-1.stderr
index b3b78424fd9..0448a28ea8e 100644
--- a/src/test/ui/type/type-params-in-different-spaces-1.stderr
+++ b/src/test/ui/type/type-params-in-different-spaces-1.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
   --> $DIR/type-params-in-different-spaces-1.rs:5:17
    |
 LL |         *self + rhs
-   |                 ^^^ expected Self, found type parameter
+   |                 ^^^ expected type parameter, found a different type parameter
    |
    = note: expected type `Self`
               found type `T`
diff --git a/src/test/ui/type/type-params-in-different-spaces-3.stderr b/src/test/ui/type/type-params-in-different-spaces-3.stderr
index 4e8134da2dd..e25f79947c7 100644
--- a/src/test/ui/type/type-params-in-different-spaces-3.stderr
+++ b/src/test/ui/type/type-params-in-different-spaces-3.stderr
@@ -4,7 +4,7 @@ error[E0308]: mismatched types
 LL |     fn test<X>(u: X) -> Self {
    |                         ---- expected `Self` because of return type
 LL |         u
-   |         ^ expected Self, found type parameter
+   |         ^ expected type parameter, found a different type parameter
    |
    = note: expected type `Self`
               found type `X`