rustc: Implement "@Foo as @Bar" for boxed traits
This commit is contained in:
@@ -929,6 +929,8 @@ fn decode_side_tables(xcx: extended_decode_ctxt,
|
|||||||
|
|
||||||
if tag == (c::tag_table_mutbl as uint) {
|
if tag == (c::tag_table_mutbl as uint) {
|
||||||
dcx.maps.mutbl_map.insert(id, ());
|
dcx.maps.mutbl_map.insert(id, ());
|
||||||
|
} else if tag == (c::tag_table_legacy_boxed_trait as uint) {
|
||||||
|
dcx.tcx.legacy_boxed_traits.insert(id, ());
|
||||||
} else {
|
} else {
|
||||||
let val_doc = entry_doc[c::tag_table_val as uint];
|
let val_doc = entry_doc[c::tag_table_val as uint];
|
||||||
let val_dsr = ebml::ebml_deserializer(val_doc);
|
let val_dsr = ebml::ebml_deserializer(val_doc);
|
||||||
@@ -969,8 +971,6 @@ fn decode_side_tables(xcx: extended_decode_ctxt,
|
|||||||
} else if tag == (c::tag_table_adjustments as uint) {
|
} else if tag == (c::tag_table_adjustments as uint) {
|
||||||
let adj = @ty::deserialize_AutoAdjustment(val_dsr).tr(xcx);
|
let adj = @ty::deserialize_AutoAdjustment(val_dsr).tr(xcx);
|
||||||
dcx.tcx.adjustments.insert(id, adj);
|
dcx.tcx.adjustments.insert(id, adj);
|
||||||
} else if tag == (c::tag_table_legacy_boxed_trait as uint) {
|
|
||||||
dcx.tcx.legacy_boxed_traits.insert(id, ());
|
|
||||||
} else {
|
} else {
|
||||||
xcx.dcx.tcx.sess.bug(
|
xcx.dcx.tcx.sess.bug(
|
||||||
fmt!("unknown tag found in side tables: %x", tag));
|
fmt!("unknown tag found in side tables: %x", tag));
|
||||||
|
|||||||
@@ -536,6 +536,7 @@ fn trans_trait_cast(bcx: block,
|
|||||||
dest: expr::Dest)
|
dest: expr::Dest)
|
||||||
-> block
|
-> block
|
||||||
{
|
{
|
||||||
|
let mut bcx = bcx;
|
||||||
let _icx = bcx.insn_ctxt("impl::trans_cast");
|
let _icx = bcx.insn_ctxt("impl::trans_cast");
|
||||||
|
|
||||||
let lldest = match dest {
|
let lldest = match dest {
|
||||||
@@ -548,16 +549,24 @@ fn trans_trait_cast(bcx: block,
|
|||||||
let ccx = bcx.ccx();
|
let ccx = bcx.ccx();
|
||||||
let v_ty = expr_ty(bcx, val);
|
let v_ty = expr_ty(bcx, val);
|
||||||
|
|
||||||
|
let mut llboxdest = GEPi(bcx, lldest, [0u, 1u]);
|
||||||
|
llboxdest = PointerCast(bcx, llboxdest,
|
||||||
|
T_ptr(type_of::type_of(bcx.ccx(), v_ty)));
|
||||||
|
|
||||||
|
if bcx.tcx().legacy_boxed_traits.contains_key(id) {
|
||||||
// Allocate an @ box and store the value into it
|
// Allocate an @ box and store the value into it
|
||||||
let {bcx: bcx, box: llbox, body: body} = malloc_boxed(bcx, v_ty);
|
let {bcx: new_bcx, box: llbox, body: body} = malloc_boxed(bcx, v_ty);
|
||||||
|
bcx = new_bcx;
|
||||||
add_clean_free(bcx, llbox, heap_shared);
|
add_clean_free(bcx, llbox, heap_shared);
|
||||||
let bcx = expr::trans_into(bcx, val, SaveIn(body));
|
bcx = expr::trans_into(bcx, val, SaveIn(body));
|
||||||
revoke_clean(bcx, llbox);
|
revoke_clean(bcx, llbox);
|
||||||
|
|
||||||
// Store the @ box into the pair
|
// Store the @ box into the pair
|
||||||
Store(bcx, llbox, PointerCast(bcx,
|
Store(bcx, llbox, llboxdest);
|
||||||
GEPi(bcx, lldest, [0u, 1u]),
|
} else {
|
||||||
T_ptr(val_ty(llbox))));
|
// Just store the @ box into the pair.
|
||||||
|
bcx = expr::trans_into(bcx, val, SaveIn(llboxdest));
|
||||||
|
}
|
||||||
|
|
||||||
// Store the vtable into the pair
|
// Store the vtable into the pair
|
||||||
let orig = ccx.maps.vtable_map.get(id)[0];
|
let orig = ccx.maps.vtable_map.get(id)[0];
|
||||||
|
|||||||
@@ -51,8 +51,18 @@ fn lookup_vtables(fcx: @fn_ctxt,
|
|||||||
match *bound {
|
match *bound {
|
||||||
ty::bound_trait(i_ty) => {
|
ty::bound_trait(i_ty) => {
|
||||||
let i_ty = ty::subst(tcx, substs, i_ty);
|
let i_ty = ty::subst(tcx, substs, i_ty);
|
||||||
result.push(lookup_vtable(fcx, expr, *ty, i_ty,
|
match lookup_vtable(fcx, expr, *ty, i_ty, allow_unsafe,
|
||||||
allow_unsafe, is_early));
|
is_early) {
|
||||||
|
Some(vtable) => result.push(vtable),
|
||||||
|
None => {
|
||||||
|
fcx.tcx().sess.span_fatal(
|
||||||
|
expr.span,
|
||||||
|
fmt!("failed to find an implementation of trait \
|
||||||
|
%s for %s",
|
||||||
|
ty_to_str(fcx.tcx(), i_ty),
|
||||||
|
ty_to_str(fcx.tcx(), *ty)));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
_ => ()
|
_ => ()
|
||||||
}
|
}
|
||||||
@@ -91,7 +101,7 @@ fn lookup_vtable(fcx: @fn_ctxt,
|
|||||||
trait_ty: ty::t,
|
trait_ty: ty::t,
|
||||||
allow_unsafe: bool,
|
allow_unsafe: bool,
|
||||||
is_early: bool)
|
is_early: bool)
|
||||||
-> vtable_origin
|
-> Option<vtable_origin>
|
||||||
{
|
{
|
||||||
|
|
||||||
debug!("lookup_vtable(ty=%s, trait_ty=%s)",
|
debug!("lookup_vtable(ty=%s, trait_ty=%s)",
|
||||||
@@ -113,7 +123,7 @@ fn lookup_vtable(fcx: @fn_ctxt,
|
|||||||
// The type has unconstrained type variables in it, so we can't
|
// The type has unconstrained type variables in it, so we can't
|
||||||
// do early resolution on it. Return some completely bogus vtable
|
// do early resolution on it. Return some completely bogus vtable
|
||||||
// information: we aren't storing it anyways.
|
// information: we aren't storing it anyways.
|
||||||
return vtable_param(0, 0);
|
return Some(vtable_param(0, 0));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -135,7 +145,7 @@ fn lookup_vtable(fcx: @fn_ctxt,
|
|||||||
idid);
|
idid);
|
||||||
relate_trait_tys(fcx, expr,
|
relate_trait_tys(fcx, expr,
|
||||||
trait_ty, ity);
|
trait_ty, ity);
|
||||||
return vtable_param(n, n_bound);
|
return Some(vtable_param(n, n_bound));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => tcx.sess.impossible_case(
|
_ => tcx.sess.impossible_case(
|
||||||
@@ -170,7 +180,7 @@ fn lookup_vtable(fcx: @fn_ctxt,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return vtable_trait(did, substs.tps);
|
return Some(vtable_trait(did, substs.tps));
|
||||||
}
|
}
|
||||||
|
|
||||||
_ => {
|
_ => {
|
||||||
@@ -303,7 +313,7 @@ fn lookup_vtable(fcx: @fn_ctxt,
|
|||||||
None => {
|
None => {
|
||||||
assert is_early;
|
assert is_early;
|
||||||
// Bail out with a bogus answer
|
// Bail out with a bogus answer
|
||||||
return vtable_param(0, 0);
|
return Some(vtable_param(0, 0));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -341,23 +351,20 @@ fn lookup_vtable(fcx: @fn_ctxt,
|
|||||||
|
|
||||||
match found.len() {
|
match found.len() {
|
||||||
0 => { /* fallthrough */ }
|
0 => { /* fallthrough */ }
|
||||||
1 => { return found[0]; }
|
1 => { return Some(found[0]); }
|
||||||
_ => {
|
_ => {
|
||||||
if !is_early {
|
if !is_early {
|
||||||
fcx.ccx.tcx.sess.span_err(
|
fcx.ccx.tcx.sess.span_err(
|
||||||
expr.span,
|
expr.span,
|
||||||
~"multiple applicable methods in scope");
|
~"multiple applicable methods in scope");
|
||||||
}
|
}
|
||||||
return found[0];
|
return Some(found[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tcx.sess.span_fatal(
|
return None;
|
||||||
expr.span,
|
|
||||||
fmt!("failed to find an implementation of trait %s for %s",
|
|
||||||
ty_to_str(tcx, trait_ty), ty_to_str(tcx, ty)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fixup_ty(fcx: @fn_ctxt,
|
fn fixup_ty(fcx: @fn_ctxt,
|
||||||
@@ -459,13 +466,55 @@ fn early_resolve_expr(ex: @ast::expr, &&fcx: @fn_ctxt, is_early: bool) {
|
|||||||
Look up vtables for the type we're casting to,
|
Look up vtables for the type we're casting to,
|
||||||
passing in the source and target type
|
passing in the source and target type
|
||||||
*/
|
*/
|
||||||
let vtable = lookup_vtable(fcx, ex, fcx.expr_ty(src),
|
let ty = fcx.expr_ty(src);
|
||||||
target_ty, true, is_early);
|
let vtable_opt = lookup_vtable(fcx, ex, ty, target_ty, true,
|
||||||
|
is_early);
|
||||||
|
match vtable_opt {
|
||||||
|
None => {
|
||||||
|
// Try the new-style boxed trait; "@int as @Trait".
|
||||||
|
let mut err = false;
|
||||||
|
let ty = structurally_resolved_type(fcx, ex.span, ty);
|
||||||
|
match ty::get(ty).sty {
|
||||||
|
ty::ty_box(boxed_ty) => {
|
||||||
|
let vtable_opt = lookup_vtable(fcx, ex,
|
||||||
|
boxed_ty.ty,
|
||||||
|
target_ty, true,
|
||||||
|
is_early);
|
||||||
|
match vtable_opt {
|
||||||
|
Some(vtable) => {
|
||||||
|
/*
|
||||||
|
Map this expression to that vtable (that
|
||||||
|
is: "ex has vtable <vtable>")
|
||||||
|
*/
|
||||||
|
if !is_early {
|
||||||
|
cx.vtable_map.insert(ex.id,
|
||||||
|
@~[vtable]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => err = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => err = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if err {
|
||||||
|
fcx.tcx().sess.span_fatal(
|
||||||
|
ex.span,
|
||||||
|
fmt!("failed to find an implementation of trait \
|
||||||
|
%s for %s",
|
||||||
|
ty_to_str(fcx.tcx(), target_ty),
|
||||||
|
ty_to_str(fcx.tcx(), ty)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Some(vtable) => {
|
||||||
/*
|
/*
|
||||||
Map this expression to that vtable (that is: "ex has
|
Map this expression to that vtable (that is: "ex has
|
||||||
vtable <vtable>")
|
vtable <vtable>")
|
||||||
*/
|
*/
|
||||||
if !is_early { cx.vtable_map.insert(ex.id, @~[vtable]); }
|
if !is_early { cx.vtable_map.insert(ex.id, @~[vtable]); }
|
||||||
|
fcx.tcx().legacy_boxed_traits.insert(ex.id, ());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
_ => ()
|
_ => ()
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user