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
This commit is contained in:
Ariel Ben-Yehuda 2016-04-22 02:31:04 +03:00
parent 0a6dfc5177
commit 2f8f256cef
5 changed files with 50 additions and 11 deletions

View File

@ -2408,9 +2408,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
// T -> Trait. // T -> Trait.
(_, &ty::TyTrait(ref data)) => { (_, &ty::TyTrait(ref data)) => {
let object_did = data.principal_def_id(); let mut object_dids =
if !object_safety::is_object_safe(tcx, object_did) { data.bounds.builtin_bounds.iter().flat_map(|bound| {
return Err(TraitNotObjectSafe(object_did)); 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, let cause = ObligationCause::new(obligation.cause.span,

View File

@ -301,6 +301,7 @@ impl<'a,'tcx> WfPredicates<'a,'tcx> {
/// is WF. Returns false if `ty0` is an unresolved type variable, /// is WF. Returns false if `ty0` is an unresolved type variable,
/// in which case we are not able to simplify at all. /// in which case we are not able to simplify at all.
fn compute(&mut self, ty0: Ty<'tcx>) -> bool { fn compute(&mut self, ty0: Ty<'tcx>) -> bool {
let tcx = self.infcx.tcx;
let mut subtys = ty0.walk(); let mut subtys = ty0.walk();
while let Some(ty) = subtys.next() { while let Some(ty) = subtys.next() {
match ty.sty { match ty.sty {
@ -385,10 +386,20 @@ impl<'a,'tcx> WfPredicates<'a,'tcx> {
// checking those // checking those
let cause = self.cause(traits::MiscObligation); let cause = self.cause(traits::MiscObligation);
self.out.push(
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( traits::Obligation::new(
cause, cause.clone(),
ty::Predicate::ObjectSafe(data.principal_def_id()))); ty::Predicate::ObjectSafe(did)
)
})
);
} }
// Inference variables are the complicated case, since we don't // Inference variables are the complicated case, since we don't

View File

@ -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 `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
} }

View File

@ -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
}

View File

@ -45,15 +45,15 @@ fn test<'a,T,U:Copy>(_: &'a isize) {
// borrowed object types are generally ok // borrowed object types are generally ok
assert_copy::<&'a Dummy>(); assert_copy::<&'a Dummy>();
assert_copy::<&'a (Dummy+Copy)>(); assert_copy::<&'a (Dummy+Send)>();
assert_copy::<&'static (Dummy+Copy)>(); assert_copy::<&'static (Dummy+Send)>();
// owned object types are not ok // owned object types are not ok
assert_copy::<Box<Dummy>>(); //~ ERROR : std::marker::Copy` is not satisfied 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 // 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 // unsafe ptrs are ok
assert_copy::<*const isize>(); assert_copy::<*const isize>();