diff --git a/src/rustc/metadata/encoder.rs b/src/rustc/metadata/encoder.rs index 87ef3b4749c..597640ef410 100644 --- a/src/rustc/metadata/encoder.rs +++ b/src/rustc/metadata/encoder.rs @@ -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; @@ -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); diff --git a/src/rustc/metadata/tyencode.rs b/src/rustc/metadata/tyencode.rs index 88d83ca23f4..611ffb598ae 100644 --- a/src/rustc/metadata/tyencode.rs +++ b/src/rustc/metadata/tyencode.rs @@ -16,6 +16,7 @@ export enc_ty; export enc_bounds; export enc_mode; export enc_arg; +export enc_vstore; type ctxt = { diag: span_handler, diff --git a/src/rustc/middle/astencode.rs b/src/rustc/middle/astencode.rs index 29368ae95b8..f2ee3df6610 100644 --- a/src/rustc/middle/astencode.rs +++ b/src/rustc/middle/astencode.rs @@ -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); diff --git a/src/rustc/middle/privacy.rs b/src/rustc/middle/privacy.rs index 4d291ceb590..f15ace40d30 100644 --- a/src/rustc/middle/privacy.rs +++ b/src/rustc/middle/privacy.rs @@ -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, _)) => { diff --git a/src/rustc/middle/trans/common.rs b/src/rustc/middle/trans/common.rs index 6768f3e71a0..68e957bfe70 100644 --- a/src/rustc/middle/trans/common.rs +++ b/src/rustc/middle/trans/common.rs @@ -963,8 +963,13 @@ fn T_captured_tydescs(cx: @crate_ctxt, n: uint) -> TypeRef { return T_struct(vec::from_elem::(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()); } diff --git a/src/rustc/middle/trans/glue.rs b/src/rustc/middle/trans/glue.rs index a8a750cd4be..d60a5a0bd7d 100644 --- a/src/rustc/middle/trans/glue.rs +++ b/src/rustc/middle/trans/glue.rs @@ -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) } diff --git a/src/rustc/middle/trans/meth.rs b/src/rustc/middle/trans/meth.rs index a94519306a4..6710a64054d 100644 --- a/src/rustc/middle/trans/meth.rs +++ b/src/rustc/middle/trans/meth.rs @@ -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; diff --git a/src/rustc/middle/trans/reflect.rs b/src/rustc/middle/trans/reflect.rs index cdd11ee85c5..3996f0ff5ee 100644 --- a/src/rustc/middle/trans/reflect.rs +++ b/src/rustc/middle/trans/reflect.rs @@ -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"); diff --git a/src/rustc/middle/trans/type_of.rs b/src/rustc/middle/trans/type_of.rs index b45da3b2700..7b5a912ed7f 100644 --- a/src/rustc/middle/trans/type_of.rs +++ b/src/rustc/middle/trans/type_of.rs @@ -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 = ~[]; diff --git a/src/rustc/middle/trans/type_use.rs b/src/rustc/middle/trans/type_use.rs index 6bd3c22f626..8bd5bd7afc7 100644 --- a/src/rustc/middle/trans/type_use.rs +++ b/src/rustc/middle/trans/type_use.rs @@ -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(*) => (), } } } diff --git a/src/rustc/middle/ty.rs b/src/rustc/middle/ty.rs index 109db9ace09..78949ec5f79 100644 --- a/src/rustc/middle/ty.rs +++ b/src/rustc/middle/ty.rs @@ -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)) } } diff --git a/src/rustc/middle/typeck.rs b/src/rustc/middle/typeck.rs index 3a9471139f9..6c461126853 100644 --- a/src/rustc/middle/typeck.rs +++ b/src/rustc/middle/typeck.rs @@ -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 diff --git a/src/rustc/middle/typeck/astconv.rs b/src/rustc/middle/typeck/astconv.rs index 45a7c22e2f9..14797fcdd6b 100644 --- a/src/rustc/middle/typeck/astconv.rs +++ b/src/rustc/middle/typeck/astconv.rs @@ -189,16 +189,19 @@ fn ast_ty_to_ty( 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); } - _ => - {} + _ => {} } } _ => () diff --git a/src/rustc/middle/typeck/check/method.rs b/src/rustc/middle/typeck/check/method.rs index d08d3e9b847..d55f9facc62 100644 --- a/src/rustc/middle/typeck/check/method.rs +++ b/src/rustc/middle/typeck/check/method.rs @@ -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) } } diff --git a/src/rustc/middle/typeck/check/regionck.rs b/src/rustc/middle/typeck/check/regionck.rs index d8ea330ee11..0b258da5672 100644 --- a/src/rustc/middle/typeck/check/regionck.rs +++ b/src/rustc/middle/typeck/check/regionck.rs @@ -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); diff --git a/src/rustc/middle/typeck/check/vtable.rs b/src/rustc/middle/typeck/check/vtable.rs index e8926468b3a..00fb134f2be 100644 --- a/src/rustc/middle/typeck/check/vtable.rs +++ b/src/rustc/middle/typeck/check/vtable.rs @@ -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 ") - */ - 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 + // ") + 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 diff --git a/src/test/run-pass/trait-region-pointer-simple.rs b/src/test/run-pass/trait-region-pointer-simple.rs new file mode 100644 index 00000000000..dfcbfc3993f --- /dev/null +++ b/src/test/run-pass/trait-region-pointer-simple.rs @@ -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; +} +