rustc: Implement simple uses of &trait
This commit is contained in:
parent
f8bc0d2545
commit
04497ea7b9
@ -34,6 +34,7 @@ export metadata_encoding_version;
|
||||
export def_to_str;
|
||||
export encode_ctxt;
|
||||
export write_type;
|
||||
export write_vstore;
|
||||
export encode_def_id;
|
||||
|
||||
type abbrev_map = map::HashMap<ty::t, tyencode::ty_abbrev>;
|
||||
@ -180,6 +181,16 @@ fn write_type(ecx: @encode_ctxt, ebml_w: ebml::Writer, typ: ty::t) {
|
||||
tyencode::enc_ty(ebml_w.writer, ty_str_ctxt, typ);
|
||||
}
|
||||
|
||||
fn write_vstore(ecx: @encode_ctxt, ebml_w: ebml::Writer, vstore: ty::vstore) {
|
||||
let ty_str_ctxt =
|
||||
@{diag: ecx.diag,
|
||||
ds: def_to_str,
|
||||
tcx: ecx.tcx,
|
||||
reachable: |a| reachable(ecx, a),
|
||||
abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs)};
|
||||
tyencode::enc_vstore(ebml_w.writer, ty_str_ctxt, vstore);
|
||||
}
|
||||
|
||||
fn encode_type(ecx: @encode_ctxt, ebml_w: ebml::Writer, typ: ty::t) {
|
||||
ebml_w.start_tag(tag_items_data_item_type);
|
||||
write_type(ecx, ebml_w, typ);
|
||||
|
@ -16,6 +16,7 @@ export enc_ty;
|
||||
export enc_bounds;
|
||||
export enc_mode;
|
||||
export enc_arg;
|
||||
export enc_vstore;
|
||||
|
||||
type ctxt = {
|
||||
diag: span_handler,
|
||||
|
@ -490,8 +490,8 @@ impl method_origin: tr {
|
||||
typeck::method_param(mp) => {
|
||||
typeck::method_param({trait_id:mp.trait_id.tr(xcx),.. mp})
|
||||
}
|
||||
typeck::method_trait(did, m) => {
|
||||
typeck::method_trait(did.tr(xcx), m)
|
||||
typeck::method_trait(did, m, vstore) => {
|
||||
typeck::method_trait(did.tr(xcx), m, vstore)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -631,6 +631,7 @@ impl @e::encode_ctxt: get_ty_str_ctxt {
|
||||
trait ebml_writer_helpers {
|
||||
fn emit_arg(ecx: @e::encode_ctxt, arg: ty::arg);
|
||||
fn emit_ty(ecx: @e::encode_ctxt, ty: ty::t);
|
||||
fn emit_vstore(ecx: @e::encode_ctxt, vstore: ty::vstore);
|
||||
fn emit_tys(ecx: @e::encode_ctxt, tys: ~[ty::t]);
|
||||
fn emit_bounds(ecx: @e::encode_ctxt, bs: ty::param_bounds);
|
||||
fn emit_tpbt(ecx: @e::encode_ctxt, tpbt: ty::ty_param_bounds_and_ty);
|
||||
@ -643,6 +644,12 @@ impl ebml::Writer: ebml_writer_helpers {
|
||||
}
|
||||
}
|
||||
|
||||
fn emit_vstore(ecx: @e::encode_ctxt, vstore: ty::vstore) {
|
||||
do self.emit_opaque {
|
||||
e::write_vstore(ecx, self, vstore)
|
||||
}
|
||||
}
|
||||
|
||||
fn emit_arg(ecx: @e::encode_ctxt, arg: ty::arg) {
|
||||
do self.emit_opaque {
|
||||
tyencode::enc_arg(self.writer, ecx.ty_str_ctxt(), arg);
|
||||
|
@ -81,7 +81,7 @@ fn check_crate(tcx: ty::ctxt, method_map: &method_map, crate: @ast::crate) {
|
||||
}
|
||||
}
|
||||
method_param({trait_id: trait_id, method_num: method_num, _}) |
|
||||
method_trait(trait_id, method_num) => {
|
||||
method_trait(trait_id, method_num, _) => {
|
||||
if trait_id.crate == local_crate {
|
||||
match tcx.items.find(trait_id.node) {
|
||||
Some(node_item(item, _)) => {
|
||||
|
@ -963,8 +963,13 @@ fn T_captured_tydescs(cx: @crate_ctxt, n: uint) -> TypeRef {
|
||||
return T_struct(vec::from_elem::<TypeRef>(n, T_ptr(cx.tydesc_type)));
|
||||
}
|
||||
|
||||
fn T_opaque_trait(cx: @crate_ctxt) -> TypeRef {
|
||||
T_struct(~[T_ptr(cx.tydesc_type), T_opaque_box_ptr(cx)])
|
||||
fn T_opaque_trait(cx: @crate_ctxt, vstore: ty::vstore) -> TypeRef {
|
||||
match vstore {
|
||||
ty::vstore_box =>
|
||||
T_struct(~[T_ptr(cx.tydesc_type), T_opaque_box_ptr(cx)]),
|
||||
_ =>
|
||||
T_struct(~[T_ptr(cx.tydesc_type), T_ptr(T_i8())])
|
||||
}
|
||||
}
|
||||
|
||||
fn T_opaque_port_ptr() -> TypeRef { return T_ptr(T_i8()); }
|
||||
|
@ -477,10 +477,13 @@ fn make_drop_glue(bcx: block, v0: ValueRef, t: ty::t) {
|
||||
ty::ty_fn(_) => {
|
||||
closure::make_fn_glue(bcx, v0, t, drop_ty)
|
||||
}
|
||||
ty::ty_trait(_, _, _) => {
|
||||
ty::ty_trait(_, _, ty::vstore_box) => {
|
||||
let llbox = Load(bcx, GEPi(bcx, v0, [0u, 1u]));
|
||||
decr_refcnt_maybe_free(bcx, llbox, ty::mk_opaque_box(ccx.tcx))
|
||||
}
|
||||
ty::ty_trait(_, _, ty::vstore_uniq) => {
|
||||
ccx.tcx.sess.unimpl(~"drop of unique trait");
|
||||
}
|
||||
ty::ty_opaque_closure_ptr(ck) => {
|
||||
closure::make_opaque_cbox_drop_glue(bcx, ck, v0)
|
||||
}
|
||||
|
@ -142,8 +142,8 @@ fn trans_method_callee(bcx: block, callee_id: ast::node_id,
|
||||
None => fail ~"trans_method_callee: missing param_substs"
|
||||
}
|
||||
}
|
||||
typeck::method_trait(_, off) => {
|
||||
trans_trait_callee(bcx, callee_id, off, self)
|
||||
typeck::method_trait(_, off, vstore) => {
|
||||
trans_trait_callee(bcx, callee_id, off, self, vstore)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -288,8 +288,8 @@ fn trans_monomorphized_callee(bcx: block,
|
||||
})
|
||||
}
|
||||
}
|
||||
typeck::vtable_trait(*) => {
|
||||
trans_trait_callee(bcx, callee_id, n_method, base)
|
||||
typeck::vtable_trait(_, _) => {
|
||||
trans_trait_callee(bcx, callee_id, n_method, base, ty::vstore_box)
|
||||
}
|
||||
typeck::vtable_param(*) => {
|
||||
fail ~"vtable_param left in monomorphized function's vtable substs";
|
||||
@ -390,7 +390,8 @@ fn combine_impl_and_methods_origins(bcx: block,
|
||||
fn trans_trait_callee(bcx: block,
|
||||
callee_id: ast::node_id,
|
||||
n_method: uint,
|
||||
self_expr: @ast::expr)
|
||||
self_expr: @ast::expr,
|
||||
vstore: ty::vstore)
|
||||
-> Callee
|
||||
{
|
||||
//!
|
||||
@ -398,8 +399,8 @@ fn trans_trait_callee(bcx: block,
|
||||
// Create a method callee where the method is coming from a trait
|
||||
// instance (e.g., @Trait type). In this case, we must pull the
|
||||
// fn pointer out of the vtable that is packaged up with the
|
||||
// @Trait instance. @Traits are represented as a pair, so we first
|
||||
// evaluate the self expression (expected a by-ref result) and then
|
||||
// @/~/&Trait instance. @/~/&Traits are represented as a pair, so we
|
||||
// first evaluate the self expression (expected a by-ref result) and then
|
||||
// extract the self data and vtable out of the pair.
|
||||
|
||||
let _icx = bcx.insn_ctxt("impl::trans_trait_callee");
|
||||
@ -407,13 +408,14 @@ fn trans_trait_callee(bcx: block,
|
||||
let self_datum = unpack_datum!(bcx, expr::trans_to_datum(bcx, self_expr));
|
||||
let llpair = self_datum.to_ref_llval(bcx);
|
||||
let callee_ty = node_id_type(bcx, callee_id);
|
||||
trans_trait_callee_from_llval(bcx, callee_ty, n_method, llpair)
|
||||
trans_trait_callee_from_llval(bcx, callee_ty, n_method, llpair, vstore)
|
||||
}
|
||||
|
||||
fn trans_trait_callee_from_llval(bcx: block,
|
||||
callee_ty: ty::t,
|
||||
n_method: uint,
|
||||
llpair: ValueRef)
|
||||
llpair: ValueRef,
|
||||
vstore: ty::vstore)
|
||||
-> Callee
|
||||
{
|
||||
//!
|
||||
@ -431,9 +433,21 @@ fn trans_trait_callee_from_llval(bcx: block,
|
||||
GEPi(bcx, llpair, [0u, 0u]),
|
||||
T_ptr(T_ptr(T_vtable()))));
|
||||
|
||||
// Load the box from the @Trait pair and GEP over the box header:
|
||||
// Load the box from the @Trait pair and GEP over the box header if
|
||||
// necessary:
|
||||
let llself;
|
||||
let llbox = Load(bcx, GEPi(bcx, llpair, [0u, 1u]));
|
||||
let llself = GEPi(bcx, llbox, [0u, abi::box_field_body]);
|
||||
match vstore {
|
||||
ty::vstore_box | ty::vstore_uniq => {
|
||||
llself = GEPi(bcx, llbox, [0u, abi::box_field_body]);
|
||||
}
|
||||
ty::vstore_slice(_) => {
|
||||
llself = llbox;
|
||||
}
|
||||
ty::vstore_fixed(*) => {
|
||||
bcx.tcx().sess.bug(~"vstore_fixed trait");
|
||||
}
|
||||
}
|
||||
|
||||
// Load the function from the vtable and cast it to the expected type.
|
||||
let llcallee_ty = type_of::type_of_fn_from_ty(ccx, callee_ty);
|
||||
@ -503,7 +517,7 @@ fn make_impl_vtable(ccx: @crate_ctxt, impl_id: ast::def_id, substs: ~[ty::t],
|
||||
// XXX: This should support multiple traits.
|
||||
let trt_id = driver::session::expect(
|
||||
tcx.sess,
|
||||
ty::ty_to_def_id(ty::impl_traits(tcx, impl_id)[0]),
|
||||
ty::ty_to_def_id(ty::impl_traits(tcx, impl_id, ty::vstore_box)[0]),
|
||||
|| ~"make_impl_vtable: non-trait-type implemented");
|
||||
|
||||
let has_tps = (*ty::lookup_item_type(ccx.tcx, impl_id).bounds).len() > 0u;
|
||||
|
@ -70,10 +70,12 @@ impl reflector {
|
||||
}
|
||||
let bool_ty = ty::mk_bool(tcx);
|
||||
let scratch = scratch_datum(bcx, bool_ty, false);
|
||||
// XXX: Should not be vstore_box!
|
||||
let bcx = callee::trans_call_inner(
|
||||
self.bcx, None, mth_ty, bool_ty,
|
||||
|bcx| meth::trans_trait_callee_from_llval(bcx, mth_ty,
|
||||
mth_idx, v),
|
||||
mth_idx, v,
|
||||
ty::vstore_box),
|
||||
ArgVals(args), SaveIn(scratch.val), DontAutorefArg);
|
||||
let result = scratch.to_value_llval(bcx);
|
||||
let next_bcx = sub_block(bcx, ~"next");
|
||||
|
@ -159,7 +159,7 @@ fn type_of(cx: @crate_ctxt, t: ty::t) -> TypeRef {
|
||||
T_struct(~[T_struct(tys)])
|
||||
}
|
||||
ty::ty_fn(_) => T_fn_pair(cx, type_of_fn_from_ty(cx, t)),
|
||||
ty::ty_trait(_, _, _) => T_opaque_trait(cx),
|
||||
ty::ty_trait(_, _, vstore) => T_opaque_trait(cx, vstore),
|
||||
ty::ty_type => T_ptr(cx.tydesc_type),
|
||||
ty::ty_tup(elts) => {
|
||||
let mut tys = ~[];
|
||||
|
@ -247,7 +247,7 @@ fn mark_for_expr(cx: ctx, e: @expr) {
|
||||
typeck::method_param({param_num: param, _}) => {
|
||||
cx.uses[param] |= use_tydesc;
|
||||
}
|
||||
typeck::method_trait(_, _) => (),
|
||||
typeck::method_trait(*) => (),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -90,6 +90,7 @@ export ty_estr, mk_estr, type_is_str;
|
||||
export ty_evec, mk_evec, type_is_vec;
|
||||
export ty_unboxed_vec, mk_unboxed_vec, mk_mut_unboxed_vec;
|
||||
export vstore, vstore_fixed, vstore_uniq, vstore_box, vstore_slice;
|
||||
export serialize_vstore, deserialize_vstore;
|
||||
export ty_nil, mk_nil, type_is_nil;
|
||||
export ty_trait, mk_trait;
|
||||
export ty_param, mk_param, ty_params_to_tys;
|
||||
@ -217,6 +218,7 @@ type method = {ident: ast::ident,
|
||||
|
||||
type mt = {ty: t, mutbl: ast::mutability};
|
||||
|
||||
#[auto_serialize]
|
||||
enum vstore {
|
||||
vstore_fixed(uint),
|
||||
vstore_uniq,
|
||||
@ -1624,7 +1626,10 @@ fn type_needs_drop(cx: ctxt, ty: t) -> bool {
|
||||
ty_evec(_, vstore_uniq) |
|
||||
ty_evec(_, vstore_box) => true,
|
||||
|
||||
ty_trait(*) => true,
|
||||
ty_trait(_, _, vstore_box) |
|
||||
ty_trait(_, _, vstore_uniq) => true,
|
||||
ty_trait(_, _, vstore_fixed(_)) |
|
||||
ty_trait(_, _, vstore_slice(_)) => false,
|
||||
|
||||
ty_param(*) | ty_infer(*) => true,
|
||||
|
||||
@ -2821,7 +2826,7 @@ fn method_call_bounds(tcx: ctxt, method_map: typeck::method_map,
|
||||
}
|
||||
typeck::method_param({trait_id:trt_id,
|
||||
method_num:n_mth, _}) |
|
||||
typeck::method_trait(trt_id, n_mth) => {
|
||||
typeck::method_trait(trt_id, n_mth, _) => {
|
||||
// ...trait methods bounds, in contrast, include only the
|
||||
// method bounds, so we must preprend the tps from the
|
||||
// trait itself. This ought to be harmonized.
|
||||
@ -3362,7 +3367,15 @@ fn trait_methods(cx: ctxt, id: ast::def_id) -> @~[method] {
|
||||
/*
|
||||
Could this return a list of (def_id, substs) pairs?
|
||||
*/
|
||||
fn impl_traits(cx: ctxt, id: ast::def_id) -> ~[t] {
|
||||
fn impl_traits(cx: ctxt, id: ast::def_id, vstore: vstore) -> ~[t] {
|
||||
fn vstoreify(cx: ctxt, ty: t, vstore: vstore) -> t {
|
||||
match ty::get(ty).sty {
|
||||
ty::ty_trait(_, _, trait_vstore) if vstore == trait_vstore => ty,
|
||||
ty::ty_trait(did, substs, _) => mk_trait(cx, did, substs, vstore),
|
||||
_ => cx.sess.bug(~"impl_traits: not a trait")
|
||||
}
|
||||
}
|
||||
|
||||
if id.crate == ast::local_crate {
|
||||
debug!("(impl_traits) searching for trait impl %?", id);
|
||||
match cx.items.find(id.node) {
|
||||
@ -3372,19 +3385,23 @@ fn impl_traits(cx: ctxt, id: ast::def_id) -> ~[t] {
|
||||
_)) => {
|
||||
|
||||
do option::map_default(&opt_trait, ~[]) |trait_ref| {
|
||||
~[node_id_to_type(cx, trait_ref.ref_id)]
|
||||
~[vstoreify(cx,
|
||||
node_id_to_type(cx, trait_ref.ref_id),
|
||||
vstore)]
|
||||
}
|
||||
}
|
||||
Some(ast_map::node_item(@{node: ast::item_class(sd,_),
|
||||
_},_)) => {
|
||||
do vec::map(sd.traits) |trait_ref| {
|
||||
node_id_to_type(cx, trait_ref.ref_id)
|
||||
vstoreify(cx, node_id_to_type(cx, trait_ref.ref_id),
|
||||
vstore)
|
||||
}
|
||||
}
|
||||
_ => ~[]
|
||||
}
|
||||
} else {
|
||||
csearch::get_impl_traits(cx, id)
|
||||
vec::map(csearch::get_impl_traits(cx, id),
|
||||
|x| vstoreify(cx, *x, vstore))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -86,7 +86,7 @@ enum method_origin {
|
||||
method_param(method_param),
|
||||
|
||||
// method invoked on a trait instance
|
||||
method_trait(ast::def_id, uint),
|
||||
method_trait(ast::def_id, uint, ty::vstore),
|
||||
}
|
||||
|
||||
// details for a method invoked with a receiver whose type is a type parameter
|
||||
|
@ -189,16 +189,19 @@ fn ast_ty_to_ty<AC: ast_conv, RS: region_scope Copy Owned>(
|
||||
type_def_id, path);
|
||||
match ty::get(result.ty).sty {
|
||||
ty::ty_trait(trait_def_id, substs, _) => {
|
||||
if vst != ty::vstore_box {
|
||||
tcx.sess.span_unimpl(path.span,
|
||||
~"`~trait` and `&trait` are \
|
||||
unimplemented; use \
|
||||
`@trait` instead for now");
|
||||
match vst {
|
||||
ty::vstore_box | ty::vstore_slice(*) => {}
|
||||
_ => {
|
||||
tcx.sess.span_unimpl(path.span,
|
||||
~"`~trait` is \
|
||||
unimplemented; use \
|
||||
`@trait` instead for \
|
||||
now");
|
||||
}
|
||||
}
|
||||
return ty::mk_trait(tcx, trait_def_id, substs, vst);
|
||||
}
|
||||
_ =>
|
||||
{}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
_ => ()
|
||||
|
@ -221,9 +221,9 @@ impl LookupContext {
|
||||
ty_param(p) => {
|
||||
self.push_inherent_candidates_from_param(p);
|
||||
}
|
||||
ty_trait(did, ref substs, _) => {
|
||||
ty_trait(did, ref substs, vstore) => {
|
||||
self.push_inherent_candidates_from_trait(
|
||||
self_ty, did, substs);
|
||||
self_ty, did, substs, vstore);
|
||||
self.push_inherent_impl_candidates_for_type(did);
|
||||
}
|
||||
ty_self => {
|
||||
@ -233,7 +233,8 @@ impl LookupContext {
|
||||
~"unexpected `none` for self_impl_def_id");
|
||||
let substs = {self_r: None, self_ty: None, tps: ~[]};
|
||||
self.push_inherent_candidates_from_trait(
|
||||
self_ty, self_did, &substs);
|
||||
self_ty, self_did, &substs,
|
||||
ty::vstore_slice(ty::re_static)); // XXX: Wrong!
|
||||
}
|
||||
ty_enum(did, _) | ty_class(did, _) => {
|
||||
self.push_inherent_impl_candidates_for_type(did);
|
||||
@ -347,7 +348,8 @@ impl LookupContext {
|
||||
fn push_inherent_candidates_from_trait(&self,
|
||||
self_ty: ty::t,
|
||||
did: def_id,
|
||||
substs: &ty::substs)
|
||||
substs: &ty::substs,
|
||||
vstore: ty::vstore)
|
||||
{
|
||||
debug!("push_inherent_candidates_from_trait(did=%s, substs=%s)",
|
||||
self.did_to_str(did),
|
||||
@ -391,7 +393,7 @@ impl LookupContext {
|
||||
rcvr_substs: move rcvr_substs,
|
||||
num_method_tps: method.tps.len(),
|
||||
self_mode: get_mode_from_self_type(method.self_ty),
|
||||
origin: method_trait(did, index)
|
||||
origin: method_trait(did, index, vstore)
|
||||
});
|
||||
}
|
||||
|
||||
@ -770,7 +772,7 @@ impl LookupContext {
|
||||
method_param(ref mp) => {
|
||||
type_of_trait_method(self.tcx(), mp.trait_id, mp.method_num)
|
||||
}
|
||||
method_trait(did, idx) => {
|
||||
method_trait(did, idx, _) => {
|
||||
type_of_trait_method(self.tcx(), did, idx)
|
||||
}
|
||||
};
|
||||
@ -791,7 +793,7 @@ impl LookupContext {
|
||||
method_param(mp) => {
|
||||
self.report_param_candidate(idx, mp.trait_id)
|
||||
}
|
||||
method_trait(trait_did, _) => {
|
||||
method_trait(trait_did, _, _) => {
|
||||
self.report_param_candidate(idx, trait_did)
|
||||
}
|
||||
}
|
||||
|
@ -221,11 +221,7 @@ fn visit_expr(expr: @ast::expr, &&rcx: @rcx, v: rvt) {
|
||||
result::Err(_) => { return; /*typeck will fail anyhow*/ }
|
||||
result::Ok(target_ty) => {
|
||||
match ty::get(target_ty).sty {
|
||||
ty::ty_trait(_, substs, _) => {
|
||||
let trait_region = match substs.self_r {
|
||||
Some(r) => {r}
|
||||
None => {ty::re_static}
|
||||
};
|
||||
ty::ty_trait(_, _, vstore_slice(trait_region)) => {
|
||||
let source_ty = rcx.fcx.expr_ty(source);
|
||||
constrain_regions_in_type(rcx, trait_region,
|
||||
expr.span, source_ty);
|
||||
|
@ -156,8 +156,8 @@ fn lookup_vtable_invariant(fcx: @fn_ctxt,
|
||||
let _i = indenter();
|
||||
|
||||
let tcx = fcx.ccx.tcx;
|
||||
let (trait_id, trait_substs) = match ty::get(trait_ty).sty {
|
||||
ty::ty_trait(did, substs, _) => (did, substs),
|
||||
let (trait_id, trait_substs, trait_vstore) = match ty::get(trait_ty).sty {
|
||||
ty::ty_trait(did, substs, vstore) => (did, substs, vstore),
|
||||
_ => tcx.sess.impossible_case(expr.span,
|
||||
"lookup_vtable_invariant: \
|
||||
don't know how to handle a non-trait")
|
||||
@ -270,7 +270,8 @@ fn lookup_vtable_invariant(fcx: @fn_ctxt,
|
||||
// it's the same trait as trait_ty, we need to
|
||||
// unify it with trait_ty in order to get all
|
||||
// the ty vars sorted out.
|
||||
for vec::each(ty::impl_traits(tcx, im.did)) |of_ty| {
|
||||
for vec::each(ty::impl_traits(tcx, im.did,
|
||||
trait_vstore)) |of_ty| {
|
||||
match ty::get(*of_ty).sty {
|
||||
ty::ty_trait(id, _, _) => {
|
||||
// Not the trait we're looking for
|
||||
@ -378,7 +379,8 @@ fn lookup_vtable_invariant(fcx: @fn_ctxt,
|
||||
// lists of types to unify pairwise.
|
||||
|
||||
connect_trait_tps(fcx, expr, substs_f.tps,
|
||||
trait_tps, im.did);
|
||||
trait_tps, im.did,
|
||||
trait_vstore);
|
||||
let subres = lookup_vtables(
|
||||
fcx, expr, im_bs, &substs_f,
|
||||
false, is_early);
|
||||
@ -436,11 +438,12 @@ fn fixup_ty(fcx: @fn_ctxt,
|
||||
}
|
||||
|
||||
fn connect_trait_tps(fcx: @fn_ctxt, expr: @ast::expr, impl_tys: ~[ty::t],
|
||||
trait_tys: ~[ty::t], impl_did: ast::def_id) {
|
||||
trait_tys: ~[ty::t], impl_did: ast::def_id,
|
||||
vstore: ty::vstore) {
|
||||
let tcx = fcx.ccx.tcx;
|
||||
|
||||
// XXX: This should work for multiple traits.
|
||||
let ity = ty::impl_traits(tcx, impl_did)[0];
|
||||
let ity = ty::impl_traits(tcx, impl_did, vstore)[0];
|
||||
let trait_ty = ty::subst_tps(tcx, impl_tys, ity);
|
||||
debug!("(connect trait tps) trait type is %?, impl did is %?",
|
||||
ty::get(trait_ty).sty, impl_did);
|
||||
@ -508,7 +511,7 @@ fn early_resolve_expr(ex: @ast::expr, &&fcx: @fn_ctxt, is_early: bool) {
|
||||
ast::expr_cast(src, _) => {
|
||||
let target_ty = fcx.expr_ty(ex);
|
||||
match ty::get(target_ty).sty {
|
||||
ty::ty_trait(*) => {
|
||||
ty::ty_trait(_, _, vstore) => {
|
||||
// Look up vtables for the type we're casting to, passing in the
|
||||
// source and target type.
|
||||
//
|
||||
@ -520,26 +523,73 @@ fn early_resolve_expr(ex: @ast::expr, &&fcx: @fn_ctxt, is_early: bool) {
|
||||
match vtable_opt {
|
||||
None => {
|
||||
// Try the new-style boxed trait; "@int as @Trait".
|
||||
// Or the new-style region 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_invariant(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]);
|
||||
ty::ty_box(mt) | ty::ty_rptr(_, mt) => {
|
||||
// Ensure that the trait vstore and the pointer
|
||||
// type match.
|
||||
match (ty::get(ty).sty, vstore) {
|
||||
(ty::ty_box(_), ty::vstore_box) |
|
||||
(ty::ty_rptr(*), ty::vstore_slice(*)) => {
|
||||
let vtable_opt =
|
||||
lookup_vtable_invariant(fcx,
|
||||
ex,
|
||||
mt.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
|
||||
}
|
||||
|
||||
// Now, if this is &trait, we need to link
|
||||
// the regions.
|
||||
match (ty::get(ty).sty, vstore) {
|
||||
(ty::ty_rptr(ra, _),
|
||||
ty::vstore_slice(rb)) => {
|
||||
infer::mk_subr(fcx.infcx(),
|
||||
false,
|
||||
ex.span,
|
||||
rb,
|
||||
ra);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
None => err = true
|
||||
(ty::ty_box(_), _) => {
|
||||
fcx.ccx.tcx.sess.span_err(ex.span,
|
||||
~"must cast \
|
||||
a boxed \
|
||||
pointer to \
|
||||
a boxed
|
||||
trait");
|
||||
err = true;
|
||||
}
|
||||
(ty::ty_rptr(*), _) => {
|
||||
fcx.ccx.tcx.sess.span_err(ex.span,
|
||||
~"must cast \
|
||||
a borrowed \
|
||||
pointer to \
|
||||
a borrowed \
|
||||
trait");
|
||||
}
|
||||
_ => {
|
||||
fcx.ccx.tcx.sess.impossible_case(
|
||||
ex.span,
|
||||
~"impossible combination of type and \
|
||||
trait vstore");
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => err = true
|
||||
|
21
src/test/run-pass/trait-region-pointer-simple.rs
Normal file
21
src/test/run-pass/trait-region-pointer-simple.rs
Normal file
@ -0,0 +1,21 @@
|
||||
trait Foo {
|
||||
fn f() -> int;
|
||||
}
|
||||
|
||||
struct A {
|
||||
x: int
|
||||
}
|
||||
|
||||
impl A : Foo {
|
||||
fn f() -> int {
|
||||
io::println(~"Today's number is " + self.x.to_str());
|
||||
return self.x;
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let a = A { x: 3 };
|
||||
let b = (&a) as &Foo;
|
||||
assert b.f() == 3;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user