Skip to content

Commit

Permalink
require the existential bounds of an object type to be object-safe
Browse files Browse the repository at this point in the history
This is required, as Copy and Sized are object-unsafe.

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

Fixes #32963
  • Loading branch information
arielb1 committed May 3, 2016
1 parent 0a6dfc5 commit 2f8f256
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 11 deletions.
12 changes: 9 additions & 3 deletions src/librustc/traits/select.rs
Expand Up @@ -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,
Expand Down
19 changes: 15 additions & 4 deletions src/librustc/ty/wf.rs
Expand Up @@ -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 {
Expand Down Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions src/test/compile-fail/bad-sized.rs
Expand Up @@ -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
}
21 changes: 21 additions & 0 deletions 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
}
8 changes: 4 additions & 4 deletions src/test/compile-fail/kindck-copy.rs
Expand Up @@ -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>();
Expand Down

0 comments on commit 2f8f256

Please sign in to comment.