Skip to content

Commit b34327b

Browse files
committed
rustc: Implement "@foo as @bar" for boxed traits
1 parent d936773 commit b34327b

File tree

3 files changed

+89
-31
lines changed

3 files changed

+89
-31
lines changed

src/rustc/middle/astencode.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -929,6 +929,8 @@ fn decode_side_tables(xcx: extended_decode_ctxt,
929929

930930
if tag == (c::tag_table_mutbl as uint) {
931931
dcx.maps.mutbl_map.insert(id, ());
932+
} else if tag == (c::tag_table_legacy_boxed_trait as uint) {
933+
dcx.tcx.legacy_boxed_traits.insert(id, ());
932934
} else {
933935
let val_doc = entry_doc[c::tag_table_val as uint];
934936
let val_dsr = ebml::ebml_deserializer(val_doc);
@@ -969,8 +971,6 @@ fn decode_side_tables(xcx: extended_decode_ctxt,
969971
} else if tag == (c::tag_table_adjustments as uint) {
970972
let adj = @ty::deserialize_AutoAdjustment(val_dsr).tr(xcx);
971973
dcx.tcx.adjustments.insert(id, adj);
972-
} else if tag == (c::tag_table_legacy_boxed_trait as uint) {
973-
dcx.tcx.legacy_boxed_traits.insert(id, ());
974974
} else {
975975
xcx.dcx.tcx.sess.bug(
976976
fmt!("unknown tag found in side tables: %x", tag));

src/rustc/middle/trans/meth.rs

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -536,6 +536,7 @@ fn trans_trait_cast(bcx: block,
536536
dest: expr::Dest)
537537
-> block
538538
{
539+
let mut bcx = bcx;
539540
let _icx = bcx.insn_ctxt("impl::trans_cast");
540541

541542
let lldest = match dest {
@@ -548,16 +549,24 @@ fn trans_trait_cast(bcx: block,
548549
let ccx = bcx.ccx();
549550
let v_ty = expr_ty(bcx, val);
550551

551-
// Allocate an @ box and store the value into it
552-
let {bcx: bcx, box: llbox, body: body} = malloc_boxed(bcx, v_ty);
553-
add_clean_free(bcx, llbox, heap_shared);
554-
let bcx = expr::trans_into(bcx, val, SaveIn(body));
555-
revoke_clean(bcx, llbox);
552+
let mut llboxdest = GEPi(bcx, lldest, [0u, 1u]);
553+
llboxdest = PointerCast(bcx, llboxdest,
554+
T_ptr(type_of::type_of(bcx.ccx(), v_ty)));
555+
556+
if bcx.tcx().legacy_boxed_traits.contains_key(id) {
557+
// Allocate an @ box and store the value into it
558+
let {bcx: new_bcx, box: llbox, body: body} = malloc_boxed(bcx, v_ty);
559+
bcx = new_bcx;
560+
add_clean_free(bcx, llbox, heap_shared);
561+
bcx = expr::trans_into(bcx, val, SaveIn(body));
562+
revoke_clean(bcx, llbox);
556563

557-
// Store the @ box into the pair
558-
Store(bcx, llbox, PointerCast(bcx,
559-
GEPi(bcx, lldest, [0u, 1u]),
560-
T_ptr(val_ty(llbox))));
564+
// Store the @ box into the pair
565+
Store(bcx, llbox, llboxdest);
566+
} else {
567+
// Just store the @ box into the pair.
568+
bcx = expr::trans_into(bcx, val, SaveIn(llboxdest));
569+
}
561570

562571
// Store the vtable into the pair
563572
let orig = ccx.maps.vtable_map.get(id)[0];

src/rustc/middle/typeck/check/vtable.rs

Lines changed: 69 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,18 @@ fn lookup_vtables(fcx: @fn_ctxt,
5151
match *bound {
5252
ty::bound_trait(i_ty) => {
5353
let i_ty = ty::subst(tcx, substs, i_ty);
54-
result.push(lookup_vtable(fcx, expr, *ty, i_ty,
55-
allow_unsafe, is_early));
54+
match lookup_vtable(fcx, expr, *ty, i_ty, allow_unsafe,
55+
is_early) {
56+
Some(vtable) => result.push(vtable),
57+
None => {
58+
fcx.tcx().sess.span_fatal(
59+
expr.span,
60+
fmt!("failed to find an implementation of trait \
61+
%s for %s",
62+
ty_to_str(fcx.tcx(), i_ty),
63+
ty_to_str(fcx.tcx(), *ty)));
64+
}
65+
}
5666
}
5767
_ => ()
5868
}
@@ -91,7 +101,7 @@ fn lookup_vtable(fcx: @fn_ctxt,
91101
trait_ty: ty::t,
92102
allow_unsafe: bool,
93103
is_early: bool)
94-
-> vtable_origin
104+
-> Option<vtable_origin>
95105
{
96106

97107
debug!("lookup_vtable(ty=%s, trait_ty=%s)",
@@ -113,7 +123,7 @@ fn lookup_vtable(fcx: @fn_ctxt,
113123
// The type has unconstrained type variables in it, so we can't
114124
// do early resolution on it. Return some completely bogus vtable
115125
// information: we aren't storing it anyways.
116-
return vtable_param(0, 0);
126+
return Some(vtable_param(0, 0));
117127
}
118128
};
119129

@@ -135,7 +145,7 @@ fn lookup_vtable(fcx: @fn_ctxt,
135145
idid);
136146
relate_trait_tys(fcx, expr,
137147
trait_ty, ity);
138-
return vtable_param(n, n_bound);
148+
return Some(vtable_param(n, n_bound));
139149
}
140150
}
141151
_ => tcx.sess.impossible_case(
@@ -170,7 +180,7 @@ fn lookup_vtable(fcx: @fn_ctxt,
170180
}
171181
}
172182
}
173-
return vtable_trait(did, substs.tps);
183+
return Some(vtable_trait(did, substs.tps));
174184
}
175185

176186
_ => {
@@ -303,7 +313,7 @@ fn lookup_vtable(fcx: @fn_ctxt,
303313
None => {
304314
assert is_early;
305315
// Bail out with a bogus answer
306-
return vtable_param(0, 0);
316+
return Some(vtable_param(0, 0));
307317
}
308318
};
309319

@@ -341,23 +351,20 @@ fn lookup_vtable(fcx: @fn_ctxt,
341351

342352
match found.len() {
343353
0 => { /* fallthrough */ }
344-
1 => { return found[0]; }
354+
1 => { return Some(found[0]); }
345355
_ => {
346356
if !is_early {
347357
fcx.ccx.tcx.sess.span_err(
348358
expr.span,
349359
~"multiple applicable methods in scope");
350360
}
351-
return found[0];
361+
return Some(found[0]);
352362
}
353363
}
354364
}
355365
}
356366

357-
tcx.sess.span_fatal(
358-
expr.span,
359-
fmt!("failed to find an implementation of trait %s for %s",
360-
ty_to_str(tcx, trait_ty), ty_to_str(tcx, ty)));
367+
return None;
361368
}
362369

363370
fn fixup_ty(fcx: @fn_ctxt,
@@ -459,13 +466,55 @@ fn early_resolve_expr(ex: @ast::expr, &&fcx: @fn_ctxt, is_early: bool) {
459466
Look up vtables for the type we're casting to,
460467
passing in the source and target type
461468
*/
462-
let vtable = lookup_vtable(fcx, ex, fcx.expr_ty(src),
463-
target_ty, true, is_early);
464-
/*
465-
Map this expression to that vtable (that is: "ex has
466-
vtable <vtable>")
467-
*/
468-
if !is_early { cx.vtable_map.insert(ex.id, @~[vtable]); }
469+
let ty = fcx.expr_ty(src);
470+
let vtable_opt = lookup_vtable(fcx, ex, ty, target_ty, true,
471+
is_early);
472+
match vtable_opt {
473+
None => {
474+
// Try the new-style boxed trait; "@int as @Trait".
475+
let mut err = false;
476+
let ty = structurally_resolved_type(fcx, ex.span, ty);
477+
match ty::get(ty).sty {
478+
ty::ty_box(boxed_ty) => {
479+
let vtable_opt = lookup_vtable(fcx, ex,
480+
boxed_ty.ty,
481+
target_ty, true,
482+
is_early);
483+
match vtable_opt {
484+
Some(vtable) => {
485+
/*
486+
Map this expression to that vtable (that
487+
is: "ex has vtable <vtable>")
488+
*/
489+
if !is_early {
490+
cx.vtable_map.insert(ex.id,
491+
@~[vtable]);
492+
}
493+
}
494+
None => err = true
495+
}
496+
}
497+
_ => err = true
498+
}
499+
500+
if err {
501+
fcx.tcx().sess.span_fatal(
502+
ex.span,
503+
fmt!("failed to find an implementation of trait \
504+
%s for %s",
505+
ty_to_str(fcx.tcx(), target_ty),
506+
ty_to_str(fcx.tcx(), ty)));
507+
}
508+
}
509+
Some(vtable) => {
510+
/*
511+
Map this expression to that vtable (that is: "ex has
512+
vtable <vtable>")
513+
*/
514+
if !is_early { cx.vtable_map.insert(ex.id, @~[vtable]); }
515+
fcx.tcx().legacy_boxed_traits.insert(ex.id, ());
516+
}
517+
}
469518
}
470519
_ => ()
471520
}

0 commit comments

Comments
 (0)