]> git.lizzy.rs Git - rust.git/blobdiff - src/librustc/traits/object_safety.rs
forbid all self-referencing predicates
[rust.git] / src / librustc / traits / object_safety.rs
index 0681be129b67e9cbd3983ad8202065c2365fa566..60808fbc741fb9898bde442a1f568641256b68d9 100644 (file)
@@ -21,7 +21,8 @@
 
 use hir::def_id::DefId;
 use traits;
-use ty::{self, ToPolyTraitRef, Ty, TyCtxt, TypeFoldable};
+use ty::{self, Ty, TyCtxt, TypeFoldable};
+use ty::subst::Substs;
 use syntax::ast;
 
 #[derive(Clone, Debug, PartialEq, Eq, Hash)]
@@ -80,8 +81,10 @@ pub fn astconv_object_safety_violations(self, trait_def_id: DefId)
     {
         let mut violations = vec![];
 
-        if self.supertraits_reference_self(trait_def_id) {
-            violations.push(ObjectSafetyViolation::SupertraitSelf);
+        for def_id in traits::supertrait_def_ids(self, trait_def_id) {
+            if self.predicates_reference_self(def_id, true) {
+                violations.push(ObjectSafetyViolation::SupertraitSelf);
+            }
         }
 
         debug!("astconv_object_safety_violations(trait_def_id={:?}) = {:?}",
@@ -114,7 +117,7 @@ fn object_safety_violations_for_trait(self, trait_def_id: DefId)
         if self.trait_has_sized_self(trait_def_id) {
             violations.push(ObjectSafetyViolation::SizedSelf);
         }
-        if self.supertraits_reference_self(trait_def_id) {
+        if self.predicates_reference_self(trait_def_id, false) {
             violations.push(ObjectSafetyViolation::SupertraitSelf);
         }
 
@@ -125,11 +128,20 @@ fn object_safety_violations_for_trait(self, trait_def_id: DefId)
         violations
     }
 
-    fn supertraits_reference_self(self, trait_def_id: DefId) -> bool {
-        let trait_def = self.lookup_trait_def(trait_def_id);
-        let trait_ref = trait_def.trait_ref.clone();
-        let trait_ref = trait_ref.to_poly_trait_ref();
-        let predicates = self.item_super_predicates(trait_def_id);
+    fn predicates_reference_self(
+        self,
+        trait_def_id: DefId,
+        supertraits_only: bool) -> bool
+    {
+        let trait_ref = ty::Binder(ty::TraitRef {
+            def_id: trait_def_id,
+            substs: Substs::identity_for_item(self, trait_def_id)
+        });
+        let predicates = if supertraits_only {
+            self.item_super_predicates(trait_def_id)
+        } else {
+            self.item_predicates(trait_def_id)
+        };
         predicates
             .predicates
             .into_iter()
@@ -239,12 +251,12 @@ fn virtual_call_violation_for_method(self,
         // The `Self` type is erased, so it should not appear in list of
         // arguments or return type apart from the receiver.
         let ref sig = self.item_type(method.def_id).fn_sig();
-        for &input_ty in &sig.0.inputs[1..] {
+        for input_ty in &sig.skip_binder().inputs()[1..] {
             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, sig.0.output) {
+        if self.contains_illegal_self_type_reference(trait_def_id, sig.output().skip_binder()) {
             return Some(MethodViolationCode::ReferencesSelf);
         }
 
@@ -317,8 +329,10 @@ fn contains_illegal_self_type_reference(self,
 
                     // Compute supertraits of current trait lazily.
                     if supertraits.is_none() {
-                        let trait_def = self.lookup_trait_def(trait_def_id);
-                        let trait_ref = ty::Binder(trait_def.trait_ref.clone());
+                        let trait_ref = ty::Binder(ty::TraitRef {
+                            def_id: trait_def_id,
+                            substs: Substs::identity_for_item(self, trait_def_id)
+                        });
                         supertraits = Some(traits::supertraits(self, trait_ref).collect());
                     }