about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAriel Ben-Yehuda <ariel.byd@gmail.com>2016-04-22 02:31:04 +0300
committerAriel Ben-Yehuda <ariel.byd@gmail.com>2016-05-03 18:30:10 +0300
commit2f8f256cef42350af2f0376891fd020b6b1c37de (patch)
tree2b0185237a64ee442e9a76994a0eb137cb597d3a
parent0a6dfc51777eb388b6e795399bf1d3f8aac57db8 (diff)
downloadrust-2f8f256cef42350af2f0376891fd020b6b1c37de.tar.gz
rust-2f8f256cef42350af2f0376891fd020b6b1c37de.zip
require the existential bounds of an object type to be object-safe
This is required, as Copy and Sized are object-unsafe.

As a soundness fix, this is a [breaking-change]

Fixes #32963
-rw-r--r--src/librustc/traits/select.rs12
-rw-r--r--src/librustc/ty/wf.rs19
-rw-r--r--src/test/compile-fail/bad-sized.rs1
-rw-r--r--src/test/compile-fail/issue-32963.rs21
-rw-r--r--src/test/compile-fail/kindck-copy.rs8
5 files changed, 50 insertions, 11 deletions
diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs
index 08a996c142d..738ed85ae6d 100644
--- a/src/librustc/traits/select.rs
+++ b/src/librustc/traits/select.rs
@@ -2408,9 +2408,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
 
             // T -> Trait.
             (_, &ty::TyTrait(ref data)) => {
-                let object_did = data.principal_def_id();
-                if !object_safety::is_object_safe(tcx, object_did) {
-                    return Err(TraitNotObjectSafe(object_did));
+                let mut object_dids =
+                    data.bounds.builtin_bounds.iter().flat_map(|bound| {
+                        tcx.lang_items.from_builtin_kind(bound).ok()
+                    })
+                    .chain(Some(data.principal_def_id()));
+                if let Some(did) = object_dids.find(|did| {
+                    !object_safety::is_object_safe(tcx, *did)
+                }) {
+                    return Err(TraitNotObjectSafe(did))
                 }
 
                 let cause = ObligationCause::new(obligation.cause.span,
diff --git a/src/librustc/ty/wf.rs b/src/librustc/ty/wf.rs
index 2dda63802e0..316a81e8f62 100644
--- a/src/librustc/ty/wf.rs
+++ b/src/librustc/ty/wf.rs
@@ -301,6 +301,7 @@ impl<'a,'tcx> WfPredicates<'a,'tcx> {
     /// is WF. Returns false if `ty0` is an unresolved type variable,
     /// in which case we are not able to simplify at all.
     fn compute(&mut self, ty0: Ty<'tcx>) -> bool {
+        let tcx = self.infcx.tcx;
         let mut subtys = ty0.walk();
         while let Some(ty) = subtys.next() {
             match ty.sty {
@@ -385,10 +386,20 @@ impl<'a,'tcx> WfPredicates<'a,'tcx> {
                     // checking those
 
                     let cause = self.cause(traits::MiscObligation);
-                    self.out.push(
-                        traits::Obligation::new(
-                            cause,
-                            ty::Predicate::ObjectSafe(data.principal_def_id())));
+
+                    let component_traits =
+                        data.bounds.builtin_bounds.iter().flat_map(|bound| {
+                            tcx.lang_items.from_builtin_kind(bound).ok()
+                        })
+                        .chain(Some(data.principal_def_id()));
+                    self.out.extend(
+                        component_traits.map(|did| {
+                            traits::Obligation::new(
+                                cause.clone(),
+                                ty::Predicate::ObjectSafe(did)
+                            )
+                        })
+                    );
                 }
 
                 // Inference variables are the complicated case, since we don't
diff --git a/src/test/compile-fail/bad-sized.rs b/src/test/compile-fail/bad-sized.rs
index f62404e60e6..ba0a6f19f07 100644
--- a/src/test/compile-fail/bad-sized.rs
+++ b/src/test/compile-fail/bad-sized.rs
@@ -15,4 +15,5 @@ pub fn main() {
     //~^ ERROR `Trait + Sized: std::marker::Sized` is not satisfied
     //~| ERROR `Trait + Sized: std::marker::Sized` is not satisfied
     //~| ERROR `Trait + Sized: std::marker::Sized` is not satisfied
+    //~| ERROR `std::marker::Sized` cannot be made into an object
 }
diff --git a/src/test/compile-fail/issue-32963.rs b/src/test/compile-fail/issue-32963.rs
new file mode 100644
index 00000000000..d0434384cd0
--- /dev/null
+++ b/src/test/compile-fail/issue-32963.rs
@@ -0,0 +1,21 @@
+// 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.
+
+use std::mem;
+
+trait Misc {}
+
+fn size_of_copy<T: Copy+?Sized>() -> usize { mem::size_of::<T>() }
+
+fn main() {
+    size_of_copy::<Misc+Copy>();
+    //~^ ERROR `std::marker::Copy` cannot be made into an object
+    //~| ERROR `Misc + Copy: std::marker::Copy` is not satisfied
+}
diff --git a/src/test/compile-fail/kindck-copy.rs b/src/test/compile-fail/kindck-copy.rs
index 08b4e1a45f3..747fe2d2046 100644
--- a/src/test/compile-fail/kindck-copy.rs
+++ b/src/test/compile-fail/kindck-copy.rs
@@ -45,15 +45,15 @@ fn test<'a,T,U:Copy>(_: &'a isize) {
 
     // borrowed object types are generally ok
     assert_copy::<&'a Dummy>();
-    assert_copy::<&'a (Dummy+Copy)>();
-    assert_copy::<&'static (Dummy+Copy)>();
+    assert_copy::<&'a (Dummy+Send)>();
+    assert_copy::<&'static (Dummy+Send)>();
 
     // owned object types are not ok
     assert_copy::<Box<Dummy>>(); //~ ERROR : std::marker::Copy` is not satisfied
-    assert_copy::<Box<Dummy+Copy>>(); //~ ERROR : std::marker::Copy` is not satisfied
+    assert_copy::<Box<Dummy+Send>>(); //~ ERROR : std::marker::Copy` is not satisfied
 
     // mutable object types are not ok
-    assert_copy::<&'a mut (Dummy+Copy)>();  //~ ERROR : std::marker::Copy` is not satisfied
+    assert_copy::<&'a mut (Dummy+Send)>();  //~ ERROR : std::marker::Copy` is not satisfied
 
     // unsafe ptrs are ok
     assert_copy::<*const isize>();