about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2017-01-20 04:55:01 +0000
committerbors <bors@rust-lang.org>2017-01-20 04:55:01 +0000
commitb53d37479079d820290e21c424f0a6f9af112afe (patch)
tree024664de02e9a09764a050f46409be5a6e4e5d2a
parentf0b42075981d9914c39e848377a3e12f0adf37d7 (diff)
parentc85fb1933f0924401f89f935f8f0b436bf177b14 (diff)
Auto merge of #38603 - arielb1:supertrait-self-3, r=nikomatsakis
traits with self-containing supertraits are not object safe

This should be the last time I fix this function.

Fixes #38404.
-rw-r--r--src/librustc/traits/object_safety.rs20
-rw-r--r--src/test/compile-fail/issue-38404.rs16
-rw-r--r--src/test/compile-fail/issue-38604.rs26
3 files changed, 57 insertions, 5 deletions
diff --git a/src/librustc/traits/object_safety.rs b/src/librustc/traits/object_safety.rs
index 0d5c9b98941..60808fbc741 100644
--- a/src/librustc/traits/object_safety.rs
+++ b/src/librustc/traits/object_safety.rs
@@ -81,8 +81,10 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
     {
         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={:?}) = {:?}",
@@ -115,7 +117,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
         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);
         }
 
@@ -126,12 +128,20 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
         violations
     }
 
-    fn supertraits_reference_self(self, trait_def_id: DefId) -> bool {
+    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 = self.item_super_predicates(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()
diff --git a/src/test/compile-fail/issue-38404.rs b/src/test/compile-fail/issue-38404.rs
new file mode 100644
index 00000000000..a2b0d0a60c0
--- /dev/null
+++ b/src/test/compile-fail/issue-38404.rs
@@ -0,0 +1,16 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+trait A<T>: std::ops::Add<Self> + Sized {}
+trait B<T>: A<T> {}
+trait C<T>: A<B<T, Output=usize>> {}
+//~^ ERROR the trait `B` cannot be made into an object
+
+fn main() {}
diff --git a/src/test/compile-fail/issue-38604.rs b/src/test/compile-fail/issue-38604.rs
new file mode 100644
index 00000000000..c1939a7707f
--- /dev/null
+++ b/src/test/compile-fail/issue-38604.rs
@@ -0,0 +1,26 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+trait Q<T:?Sized> {}
+trait Foo where u32: Q<Self> {
+    fn foo(&self);
+}
+
+impl Q<()> for u32 {}
+impl Foo for () {
+    fn foo(&self) {
+        println!("foo!");
+    }
+}
+
+fn main() {
+    let _f: Box<Foo> = //~ ERROR `Foo` cannot be made into an object
+        Box::new(()); //~ ERROR `Foo` cannot be made into an object
+}