diff --git a/src/librustc/middle/kind.rs b/src/librustc/middle/kind.rs index 2e69e5efd8dd..7f7a81fa974a 100644 --- a/src/librustc/middle/kind.rs +++ b/src/librustc/middle/kind.rs @@ -291,7 +291,13 @@ pub fn check_expr(e: @expr, (cx, v): (Context, visit::vt)) { match e.node { expr_cast(source, _) => { check_cast_for_escaping_regions(cx, source, e); - check_kind_bounds_of_cast(cx, source, e); + match ty::get(ty::expr_ty(cx.tcx, e)).sty { + ty::ty_trait(_, _, store, _, bounds) => { + let source_ty = ty::expr_ty(cx.tcx, source); + check_trait_cast_bounds(cx, e.span, source_ty, bounds, store) + } + _ => { } + } } expr_copy(expr) => { // 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)) { visit::visit_ty(aty, (cx, v)); } -pub fn check_builtin_bounds(cx: Context, ty: ty::t, bounds: ty::BuiltinBounds) - -> ty::BuiltinBounds // returns the missing bounds +// Calls "any_missing" if any bounds were missing. +pub fn check_builtin_bounds(cx: Context, ty: ty::t, bounds: ty::BuiltinBounds, + any_missing: &fn(ty::BuiltinBounds)) { let kind = ty::type_contents(cx.tcx, ty); let mut missing = ty::EmptyBuiltinBounds(); @@ -345,7 +352,9 @@ pub fn check_builtin_bounds(cx: Context, ty: ty::t, bounds: ty::BuiltinBounds) missing.add(bound); } } - missing + if !missing.is_empty() { + any_missing(missing); + } } pub fn check_typaram_bounds(cx: Context, @@ -354,8 +363,7 @@ pub fn check_typaram_bounds(cx: Context, ty: ty::t, type_param_def: &ty::TypeParameterDef) { - let missing = check_builtin_bounds(cx, ty, type_param_def.bounds.builtin_bounds); - if !missing.is_empty() { + do check_builtin_bounds(cx, ty, type_param_def.bounds.builtin_bounds) |missing| { cx.tcx.sess.span_err( sp, fmt!("instantiating a type parameter with an incompatible type \ @@ -368,8 +376,7 @@ pub fn check_typaram_bounds(cx: Context, pub fn check_freevar_bounds(cx: Context, sp: span, ty: ty::t, bounds: ty::BuiltinBounds) { - let missing = check_builtin_bounds(cx, ty, bounds); - if !missing.is_empty() { + do check_builtin_bounds(cx, ty, bounds) |missing| { cx.tcx.sess.span_err( sp, 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, } } +pub fn check_trait_cast_bounds(cx: Context, sp: span, ty: ty::t, + bounds: ty::BuiltinBounds, store: ty::TraitStore) { + do check_builtin_bounds(cx, ty, bounds) |missing| { + cx.tcx.sess.span_err(sp, + fmt!("cannot pack type `%s`, which does not fulfill \ + `%s`, as a trait bounded by %s", + 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 { match ex.node { expr_path(_) => { @@ -564,20 +587,3 @@ pub fn check_cast_for_escaping_regions( cx.tcx.region_maps.is_subregion_of(r_sub, r_sup) } } - -/// Ensures that values placed into a ~Trait are copyable and sendable. -pub fn check_kind_bounds_of_cast(cx: Context, source: @expr, target: @expr) { - let target_ty = ty::expr_ty(cx.tcx, target); - match ty::get(target_ty).sty { - // FIXME(#3569) kind check bounds here - ty::ty_trait(_, _, ty::UniqTraitStore, _, _bounds) => { - let source_ty = ty::expr_ty(cx.tcx, source); - if !ty::type_is_owned(cx.tcx, source_ty) { - cx.tcx.sess.span_err( - target.span, - "uniquely-owned trait objects must be sendable"); - } - } - _ => {} // Nothing to do. - } -}