Looser restrictions on what can be captured in unbounded traits.

This commit is contained in:
Ben Blum 2013-06-19 22:06:50 -04:00
parent 7b968783d7
commit 108739f533
3 changed files with 35 additions and 23 deletions

View file

@ -423,7 +423,7 @@ type MonitorMsg = (TestDesc, TestResult);
fn run_tests(opts: &TestOpts,
tests: ~[TestDescAndFn],
callback: @fn(e: TestEvent)) {
callback: &fn(e: TestEvent)) {
let filtered_tests = filter_tests(opts, tests);
let filtered_descs = filtered_tests.map(|t| copy t.desc);

View file

@ -293,9 +293,9 @@ pub fn check_expr(e: @expr, (cx, v): (Context, visit::vt<Context>)) {
expr_cast(source, _) => {
check_cast_for_escaping_regions(cx, source, e);
match ty::get(ty::expr_ty(cx.tcx, e)).sty {
ty::ty_trait(_, _, store, _, bounds) => {
ty::ty_trait(_, _, _, _, bounds) => {
let source_ty = ty::expr_ty(cx.tcx, source);
check_trait_cast_bounds(cx, e.span, source_ty, bounds, store)
check_trait_cast_bounds(cx, e.span, source_ty, bounds)
}
_ => { }
}
@ -391,7 +391,7 @@ pub fn check_freevar_bounds(cx: Context, sp: span, ty: ty::t,
}
pub fn check_trait_cast_bounds(cx: Context, sp: span, ty: ty::t,
bounds: ty::BuiltinBounds, store: ty::TraitStore) {
bounds: ty::BuiltinBounds) {
do check_builtin_bounds(cx, ty, bounds) |missing| {
cx.tcx.sess.span_err(sp,
fmt!("cannot pack type `%s`, which does not fulfill \
@ -399,11 +399,6 @@ pub fn check_trait_cast_bounds(cx: Context, sp: span, ty: ty::t,
ty_to_str(cx.tcx, ty), missing.user_string(cx.tcx),
bounds.user_string(cx.tcx)));
}
// FIXME(#3569): Remove this check when the corresponding restriction
// is made with type contents.
if store == ty::UniqTraitStore && !ty::type_is_owned(cx.tcx, ty) {
cx.tcx.sess.span_err(sp, "uniquely-owned trait objects must be sendable");
}
}
fn is_nullary_variant(cx: Context, ex: @expr) -> bool {

View file

@ -2063,20 +2063,8 @@ pub fn type_contents(cx: ctxt, ty: t) -> TypeContents {
TC_MANAGED + statically_sized(nonowned(tc_mt(cx, mt, cache)))
}
ty_trait(_, _, UniqTraitStore, _, _bounds) => {
// FIXME(#3569): Make this conditional on the trait's bounds.
TC_NONCOPY_TRAIT + TC_OWNED_POINTER
}
ty_trait(_, _, BoxTraitStore, mutbl, _bounds) => {
match mutbl {
ast::m_mutbl => TC_MANAGED + TC_MUTABLE,
_ => TC_MANAGED
}
}
ty_trait(_, _, RegionTraitStore(r), mutbl, _bounds) => {
borrowed_contents(r, mutbl)
ty_trait(_, _, store, mutbl, bounds) => {
trait_contents(store, mutbl, bounds)
}
ty_rptr(r, mt) => {
@ -2278,6 +2266,35 @@ pub fn type_contents(cx: ctxt, ty: t) -> TypeContents {
st + rt + ot
}
fn trait_contents(store: TraitStore, mutbl: ast::mutability,
bounds: BuiltinBounds) -> TypeContents {
let st = match store {
UniqTraitStore => TC_OWNED_POINTER,
BoxTraitStore => TC_MANAGED,
RegionTraitStore(r) => borrowed_contents(r, mutbl),
};
let mt = match mutbl { ast::m_mutbl => TC_MUTABLE, _ => TC_NONE };
// We get additional "special type contents" for each bound that *isn't*
// on the trait. So iterate over the inverse of the bounds that are set.
// This is like with typarams below, but less "pessimistic" and also
// dependent on the trait store.
let mut bt = TC_NONE;
for (AllBuiltinBounds() - bounds).each |bound| {
bt = bt + match bound {
BoundCopy if store == UniqTraitStore
=> TC_NONCOPY_TRAIT,
BoundCopy => TC_NONE, // @Trait/&Trait are copyable either way
BoundStatic if bounds.contains_elem(BoundOwned)
=> TC_NONE, // Owned bound implies static bound.
BoundStatic => TC_BORROWED_POINTER, // Useful for "@Trait:'static"
BoundOwned => TC_NON_OWNED,
BoundConst => TC_MUTABLE,
BoundSized => TC_NONE, // don't care if interior is sized
};
}
st + mt + bt
}
fn type_param_def_to_contents(cx: ctxt,
type_param_def: &TypeParameterDef) -> TypeContents
{