diff options
| author | Ariel Ben-Yehuda <ariel.byd@gmail.com> | 2016-04-22 02:31:04 +0300 |
|---|---|---|
| committer | Ariel Ben-Yehuda <ariel.byd@gmail.com> | 2016-05-03 18:30:10 +0300 |
| commit | 2f8f256cef42350af2f0376891fd020b6b1c37de (patch) | |
| tree | 2b0185237a64ee442e9a76994a0eb137cb597d3a | |
| parent | 0a6dfc51777eb388b6e795399bf1d3f8aac57db8 (diff) | |
| download | rust-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.rs | 12 | ||||
| -rw-r--r-- | src/librustc/ty/wf.rs | 19 | ||||
| -rw-r--r-- | src/test/compile-fail/bad-sized.rs | 1 | ||||
| -rw-r--r-- | src/test/compile-fail/issue-32963.rs | 21 | ||||
| -rw-r--r-- | src/test/compile-fail/kindck-copy.rs | 8 |
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>(); |
