Skip to content

Commit 1d2b20e

Browse files
committed
Check existential type contents against destination trait bounds.
1 parent 1ffcc6f commit 1d2b20e

File tree

1 file changed

+31
-25
lines changed

1 file changed

+31
-25
lines changed

src/librustc/middle/kind.rs

+31-25
Original file line numberDiff line numberDiff line change
@@ -291,7 +291,13 @@ pub fn check_expr(e: @expr, (cx, v): (Context, visit::vt<Context>)) {
291291
match e.node {
292292
expr_cast(source, _) => {
293293
check_cast_for_escaping_regions(cx, source, e);
294-
check_kind_bounds_of_cast(cx, source, e);
294+
match ty::get(ty::expr_ty(cx.tcx, e)).sty {
295+
ty::ty_trait(_, _, store, _, bounds) => {
296+
let source_ty = ty::expr_ty(cx.tcx, source);
297+
check_trait_cast_bounds(cx, e.span, source_ty, bounds, store)
298+
}
299+
_ => { }
300+
}
295301
}
296302
expr_copy(expr) => {
297303
// Note: This is the only place where we must check whether the
@@ -335,8 +341,9 @@ fn check_ty(aty: @Ty, (cx, v): (Context, visit::vt<Context>)) {
335341
visit::visit_ty(aty, (cx, v));
336342
}
337343

338-
pub fn check_builtin_bounds(cx: Context, ty: ty::t, bounds: ty::BuiltinBounds)
339-
-> ty::BuiltinBounds // returns the missing bounds
344+
// Calls "any_missing" if any bounds were missing.
345+
pub fn check_builtin_bounds(cx: Context, ty: ty::t, bounds: ty::BuiltinBounds,
346+
any_missing: &fn(ty::BuiltinBounds))
340347
{
341348
let kind = ty::type_contents(cx.tcx, ty);
342349
let mut missing = ty::EmptyBuiltinBounds();
@@ -345,7 +352,9 @@ pub fn check_builtin_bounds(cx: Context, ty: ty::t, bounds: ty::BuiltinBounds)
345352
missing.add(bound);
346353
}
347354
}
348-
missing
355+
if !missing.is_empty() {
356+
any_missing(missing);
357+
}
349358
}
350359

351360
pub fn check_typaram_bounds(cx: Context,
@@ -354,8 +363,7 @@ pub fn check_typaram_bounds(cx: Context,
354363
ty: ty::t,
355364
type_param_def: &ty::TypeParameterDef)
356365
{
357-
let missing = check_builtin_bounds(cx, ty, type_param_def.bounds.builtin_bounds);
358-
if !missing.is_empty() {
366+
do check_builtin_bounds(cx, ty, type_param_def.bounds.builtin_bounds) |missing| {
359367
cx.tcx.sess.span_err(
360368
sp,
361369
fmt!("instantiating a type parameter with an incompatible type \
@@ -368,8 +376,7 @@ pub fn check_typaram_bounds(cx: Context,
368376
pub fn check_freevar_bounds(cx: Context, sp: span, ty: ty::t,
369377
bounds: ty::BuiltinBounds)
370378
{
371-
let missing = check_builtin_bounds(cx, ty, bounds);
372-
if !missing.is_empty() {
379+
do check_builtin_bounds(cx, ty, bounds) |missing| {
373380
cx.tcx.sess.span_err(
374381
sp,
375382
fmt!("cannot capture variable of type `%s`, which does not fulfill \
@@ -382,6 +389,22 @@ pub fn check_freevar_bounds(cx: Context, sp: span, ty: ty::t,
382389
}
383390
}
384391

392+
pub fn check_trait_cast_bounds(cx: Context, sp: span, ty: ty::t,
393+
bounds: ty::BuiltinBounds, store: ty::TraitStore) {
394+
do check_builtin_bounds(cx, ty, bounds) |missing| {
395+
cx.tcx.sess.span_err(sp,
396+
fmt!("cannot pack type `%s`, which does not fulfill \
397+
`%s`, as a trait bounded by %s",
398+
ty_to_str(cx.tcx, ty), missing.user_string(cx.tcx),
399+
bounds.user_string(cx.tcx)));
400+
}
401+
// FIXME(#3569): Remove this check when the corresponding restriction
402+
// is made with type contents.
403+
if store == ty::UniqTraitStore && !ty::type_is_owned(cx.tcx, ty) {
404+
cx.tcx.sess.span_err(sp, "uniquely-owned trait objects must be sendable");
405+
}
406+
}
407+
385408
fn is_nullary_variant(cx: Context, ex: @expr) -> bool {
386409
match ex.node {
387410
expr_path(_) => {
@@ -564,20 +587,3 @@ pub fn check_cast_for_escaping_regions(
564587
cx.tcx.region_maps.is_subregion_of(r_sub, r_sup)
565588
}
566589
}
567-
568-
/// Ensures that values placed into a ~Trait are copyable and sendable.
569-
pub fn check_kind_bounds_of_cast(cx: Context, source: @expr, target: @expr) {
570-
let target_ty = ty::expr_ty(cx.tcx, target);
571-
match ty::get(target_ty).sty {
572-
// FIXME(#3569) kind check bounds here
573-
ty::ty_trait(_, _, ty::UniqTraitStore, _, _bounds) => {
574-
let source_ty = ty::expr_ty(cx.tcx, source);
575-
if !ty::type_is_owned(cx.tcx, source_ty) {
576-
cx.tcx.sess.span_err(
577-
target.span,
578-
"uniquely-owned trait objects must be sendable");
579-
}
580-
}
581-
_ => {} // Nothing to do.
582-
}
583-
}

0 commit comments

Comments
 (0)