rustc: Implement simple uses of &trait
This commit is contained in:
parent
f8bc0d2545
commit
04497ea7b9
17 changed files with 201 additions and 69 deletions
|
@ -34,6 +34,7 @@ export metadata_encoding_version;
|
||||||
export def_to_str;
|
export def_to_str;
|
||||||
export encode_ctxt;
|
export encode_ctxt;
|
||||||
export write_type;
|
export write_type;
|
||||||
|
export write_vstore;
|
||||||
export encode_def_id;
|
export encode_def_id;
|
||||||
|
|
||||||
type abbrev_map = map::HashMap<ty::t, tyencode::ty_abbrev>;
|
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);
|
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) {
|
fn encode_type(ecx: @encode_ctxt, ebml_w: ebml::Writer, typ: ty::t) {
|
||||||
ebml_w.start_tag(tag_items_data_item_type);
|
ebml_w.start_tag(tag_items_data_item_type);
|
||||||
write_type(ecx, ebml_w, typ);
|
write_type(ecx, ebml_w, typ);
|
||||||
|
|
|
@ -16,6 +16,7 @@ export enc_ty;
|
||||||
export enc_bounds;
|
export enc_bounds;
|
||||||
export enc_mode;
|
export enc_mode;
|
||||||
export enc_arg;
|
export enc_arg;
|
||||||
|
export enc_vstore;
|
||||||
|
|
||||||
type ctxt = {
|
type ctxt = {
|
||||||
diag: span_handler,
|
diag: span_handler,
|
||||||
|
|
|
@ -490,8 +490,8 @@ impl method_origin: tr {
|
||||||
typeck::method_param(mp) => {
|
typeck::method_param(mp) => {
|
||||||
typeck::method_param({trait_id:mp.trait_id.tr(xcx),.. mp})
|
typeck::method_param({trait_id:mp.trait_id.tr(xcx),.. mp})
|
||||||
}
|
}
|
||||||
typeck::method_trait(did, m) => {
|
typeck::method_trait(did, m, vstore) => {
|
||||||
typeck::method_trait(did.tr(xcx), m)
|
typeck::method_trait(did.tr(xcx), m, vstore)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -631,6 +631,7 @@ impl @e::encode_ctxt: get_ty_str_ctxt {
|
||||||
trait ebml_writer_helpers {
|
trait ebml_writer_helpers {
|
||||||
fn emit_arg(ecx: @e::encode_ctxt, arg: ty::arg);
|
fn emit_arg(ecx: @e::encode_ctxt, arg: ty::arg);
|
||||||
fn emit_ty(ecx: @e::encode_ctxt, ty: ty::t);
|
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_tys(ecx: @e::encode_ctxt, tys: ~[ty::t]);
|
||||||
fn emit_bounds(ecx: @e::encode_ctxt, bs: ty::param_bounds);
|
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);
|
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) {
|
fn emit_arg(ecx: @e::encode_ctxt, arg: ty::arg) {
|
||||||
do self.emit_opaque {
|
do self.emit_opaque {
|
||||||
tyencode::enc_arg(self.writer, ecx.ty_str_ctxt(), arg);
|
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_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 {
|
if trait_id.crate == local_crate {
|
||||||
match tcx.items.find(trait_id.node) {
|
match tcx.items.find(trait_id.node) {
|
||||||
Some(node_item(item, _)) => {
|
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)));
|
return T_struct(vec::from_elem::<TypeRef>(n, T_ptr(cx.tydesc_type)));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn T_opaque_trait(cx: @crate_ctxt) -> TypeRef {
|
fn T_opaque_trait(cx: @crate_ctxt, vstore: ty::vstore) -> TypeRef {
|
||||||
T_struct(~[T_ptr(cx.tydesc_type), T_opaque_box_ptr(cx)])
|
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()); }
|
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(_) => {
|
ty::ty_fn(_) => {
|
||||||
closure::make_fn_glue(bcx, v0, t, drop_ty)
|
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]));
|
let llbox = Load(bcx, GEPi(bcx, v0, [0u, 1u]));
|
||||||
decr_refcnt_maybe_free(bcx, llbox, ty::mk_opaque_box(ccx.tcx))
|
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) => {
|
ty::ty_opaque_closure_ptr(ck) => {
|
||||||
closure::make_opaque_cbox_drop_glue(bcx, ck, v0)
|
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"
|
None => fail ~"trans_method_callee: missing param_substs"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
typeck::method_trait(_, off) => {
|
typeck::method_trait(_, off, vstore) => {
|
||||||
trans_trait_callee(bcx, callee_id, off, self)
|
trans_trait_callee(bcx, callee_id, off, self, vstore)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -288,8 +288,8 @@ fn trans_monomorphized_callee(bcx: block,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
typeck::vtable_trait(*) => {
|
typeck::vtable_trait(_, _) => {
|
||||||
trans_trait_callee(bcx, callee_id, n_method, base)
|
trans_trait_callee(bcx, callee_id, n_method, base, ty::vstore_box)
|
||||||
}
|
}
|
||||||
typeck::vtable_param(*) => {
|
typeck::vtable_param(*) => {
|
||||||
fail ~"vtable_param left in monomorphized function's vtable substs";
|
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,
|
fn trans_trait_callee(bcx: block,
|
||||||
callee_id: ast::node_id,
|
callee_id: ast::node_id,
|
||||||
n_method: uint,
|
n_method: uint,
|
||||||
self_expr: @ast::expr)
|
self_expr: @ast::expr,
|
||||||
|
vstore: ty::vstore)
|
||||||
-> Callee
|
-> Callee
|
||||||
{
|
{
|
||||||
//!
|
//!
|
||||||
|
@ -398,8 +399,8 @@ fn trans_trait_callee(bcx: block,
|
||||||
// Create a method callee where the method is coming from a trait
|
// Create a method callee where the method is coming from a trait
|
||||||
// instance (e.g., @Trait type). In this case, we must pull the
|
// instance (e.g., @Trait type). In this case, we must pull the
|
||||||
// fn pointer out of the vtable that is packaged up with the
|
// fn pointer out of the vtable that is packaged up with the
|
||||||
// @Trait instance. @Traits are represented as a pair, so we first
|
// @/~/&Trait instance. @/~/&Traits are represented as a pair, so we
|
||||||
// evaluate the self expression (expected a by-ref result) and then
|
// first evaluate the self expression (expected a by-ref result) and then
|
||||||
// extract the self data and vtable out of the pair.
|
// extract the self data and vtable out of the pair.
|
||||||
|
|
||||||
let _icx = bcx.insn_ctxt("impl::trans_trait_callee");
|
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 self_datum = unpack_datum!(bcx, expr::trans_to_datum(bcx, self_expr));
|
||||||
let llpair = self_datum.to_ref_llval(bcx);
|
let llpair = self_datum.to_ref_llval(bcx);
|
||||||
let callee_ty = node_id_type(bcx, callee_id);
|
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,
|
fn trans_trait_callee_from_llval(bcx: block,
|
||||||
callee_ty: ty::t,
|
callee_ty: ty::t,
|
||||||
n_method: uint,
|
n_method: uint,
|
||||||
llpair: ValueRef)
|
llpair: ValueRef,
|
||||||
|
vstore: ty::vstore)
|
||||||
-> Callee
|
-> Callee
|
||||||
{
|
{
|
||||||
//!
|
//!
|
||||||
|
@ -431,9 +433,21 @@ fn trans_trait_callee_from_llval(bcx: block,
|
||||||
GEPi(bcx, llpair, [0u, 0u]),
|
GEPi(bcx, llpair, [0u, 0u]),
|
||||||
T_ptr(T_ptr(T_vtable()))));
|
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 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.
|
// 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);
|
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.
|
// XXX: This should support multiple traits.
|
||||||
let trt_id = driver::session::expect(
|
let trt_id = driver::session::expect(
|
||||||
tcx.sess,
|
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");
|
|| ~"make_impl_vtable: non-trait-type implemented");
|
||||||
|
|
||||||
let has_tps = (*ty::lookup_item_type(ccx.tcx, impl_id).bounds).len() > 0u;
|
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 bool_ty = ty::mk_bool(tcx);
|
||||||
let scratch = scratch_datum(bcx, bool_ty, false);
|
let scratch = scratch_datum(bcx, bool_ty, false);
|
||||||
|
// XXX: Should not be vstore_box!
|
||||||
let bcx = callee::trans_call_inner(
|
let bcx = callee::trans_call_inner(
|
||||||
self.bcx, None, mth_ty, bool_ty,
|
self.bcx, None, mth_ty, bool_ty,
|
||||||
|bcx| meth::trans_trait_callee_from_llval(bcx, mth_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);
|
ArgVals(args), SaveIn(scratch.val), DontAutorefArg);
|
||||||
let result = scratch.to_value_llval(bcx);
|
let result = scratch.to_value_llval(bcx);
|
||||||
let next_bcx = sub_block(bcx, ~"next");
|
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)])
|
T_struct(~[T_struct(tys)])
|
||||||
}
|
}
|
||||||
ty::ty_fn(_) => T_fn_pair(cx, type_of_fn_from_ty(cx, t)),
|
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_type => T_ptr(cx.tydesc_type),
|
||||||
ty::ty_tup(elts) => {
|
ty::ty_tup(elts) => {
|
||||||
let mut tys = ~[];
|
let mut tys = ~[];
|
||||||
|
|
|
@ -247,7 +247,7 @@ fn mark_for_expr(cx: ctx, e: @expr) {
|
||||||
typeck::method_param({param_num: param, _}) => {
|
typeck::method_param({param_num: param, _}) => {
|
||||||
cx.uses[param] |= use_tydesc;
|
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_evec, mk_evec, type_is_vec;
|
||||||
export ty_unboxed_vec, mk_unboxed_vec, mk_mut_unboxed_vec;
|
export ty_unboxed_vec, mk_unboxed_vec, mk_mut_unboxed_vec;
|
||||||
export vstore, vstore_fixed, vstore_uniq, vstore_box, vstore_slice;
|
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_nil, mk_nil, type_is_nil;
|
||||||
export ty_trait, mk_trait;
|
export ty_trait, mk_trait;
|
||||||
export ty_param, mk_param, ty_params_to_tys;
|
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};
|
type mt = {ty: t, mutbl: ast::mutability};
|
||||||
|
|
||||||
|
#[auto_serialize]
|
||||||
enum vstore {
|
enum vstore {
|
||||||
vstore_fixed(uint),
|
vstore_fixed(uint),
|
||||||
vstore_uniq,
|
vstore_uniq,
|
||||||
|
@ -1624,7 +1626,10 @@ fn type_needs_drop(cx: ctxt, ty: t) -> bool {
|
||||||
ty_evec(_, vstore_uniq) |
|
ty_evec(_, vstore_uniq) |
|
||||||
ty_evec(_, vstore_box) => true,
|
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,
|
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,
|
typeck::method_param({trait_id:trt_id,
|
||||||
method_num:n_mth, _}) |
|
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
|
// ...trait methods bounds, in contrast, include only the
|
||||||
// method bounds, so we must preprend the tps from the
|
// method bounds, so we must preprend the tps from the
|
||||||
// trait itself. This ought to be harmonized.
|
// 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?
|
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 {
|
if id.crate == ast::local_crate {
|
||||||
debug!("(impl_traits) searching for trait impl %?", id);
|
debug!("(impl_traits) searching for trait impl %?", id);
|
||||||
match cx.items.find(id.node) {
|
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| {
|
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,_),
|
Some(ast_map::node_item(@{node: ast::item_class(sd,_),
|
||||||
_},_)) => {
|
_},_)) => {
|
||||||
do vec::map(sd.traits) |trait_ref| {
|
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 {
|
} 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_param(method_param),
|
||||||
|
|
||||||
// method invoked on a trait instance
|
// 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
|
// 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);
|
type_def_id, path);
|
||||||
match ty::get(result.ty).sty {
|
match ty::get(result.ty).sty {
|
||||||
ty::ty_trait(trait_def_id, substs, _) => {
|
ty::ty_trait(trait_def_id, substs, _) => {
|
||||||
if vst != ty::vstore_box {
|
match vst {
|
||||||
tcx.sess.span_unimpl(path.span,
|
ty::vstore_box | ty::vstore_slice(*) => {}
|
||||||
~"`~trait` and `&trait` are \
|
_ => {
|
||||||
unimplemented; use \
|
tcx.sess.span_unimpl(path.span,
|
||||||
`@trait` instead for now");
|
~"`~trait` is \
|
||||||
|
unimplemented; use \
|
||||||
|
`@trait` instead for \
|
||||||
|
now");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return ty::mk_trait(tcx, trait_def_id, substs, vst);
|
return ty::mk_trait(tcx, trait_def_id, substs, vst);
|
||||||
}
|
}
|
||||||
_ =>
|
_ => {}
|
||||||
{}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => ()
|
_ => ()
|
||||||
|
|
|
@ -221,9 +221,9 @@ impl LookupContext {
|
||||||
ty_param(p) => {
|
ty_param(p) => {
|
||||||
self.push_inherent_candidates_from_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.push_inherent_candidates_from_trait(
|
||||||
self_ty, did, substs);
|
self_ty, did, substs, vstore);
|
||||||
self.push_inherent_impl_candidates_for_type(did);
|
self.push_inherent_impl_candidates_for_type(did);
|
||||||
}
|
}
|
||||||
ty_self => {
|
ty_self => {
|
||||||
|
@ -233,7 +233,8 @@ impl LookupContext {
|
||||||
~"unexpected `none` for self_impl_def_id");
|
~"unexpected `none` for self_impl_def_id");
|
||||||
let substs = {self_r: None, self_ty: None, tps: ~[]};
|
let substs = {self_r: None, self_ty: None, tps: ~[]};
|
||||||
self.push_inherent_candidates_from_trait(
|
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, _) => {
|
ty_enum(did, _) | ty_class(did, _) => {
|
||||||
self.push_inherent_impl_candidates_for_type(did);
|
self.push_inherent_impl_candidates_for_type(did);
|
||||||
|
@ -347,7 +348,8 @@ impl LookupContext {
|
||||||
fn push_inherent_candidates_from_trait(&self,
|
fn push_inherent_candidates_from_trait(&self,
|
||||||
self_ty: ty::t,
|
self_ty: ty::t,
|
||||||
did: def_id,
|
did: def_id,
|
||||||
substs: &ty::substs)
|
substs: &ty::substs,
|
||||||
|
vstore: ty::vstore)
|
||||||
{
|
{
|
||||||
debug!("push_inherent_candidates_from_trait(did=%s, substs=%s)",
|
debug!("push_inherent_candidates_from_trait(did=%s, substs=%s)",
|
||||||
self.did_to_str(did),
|
self.did_to_str(did),
|
||||||
|
@ -391,7 +393,7 @@ impl LookupContext {
|
||||||
rcvr_substs: move rcvr_substs,
|
rcvr_substs: move rcvr_substs,
|
||||||
num_method_tps: method.tps.len(),
|
num_method_tps: method.tps.len(),
|
||||||
self_mode: get_mode_from_self_type(method.self_ty),
|
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) => {
|
method_param(ref mp) => {
|
||||||
type_of_trait_method(self.tcx(), mp.trait_id, mp.method_num)
|
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)
|
type_of_trait_method(self.tcx(), did, idx)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -791,7 +793,7 @@ impl LookupContext {
|
||||||
method_param(mp) => {
|
method_param(mp) => {
|
||||||
self.report_param_candidate(idx, mp.trait_id)
|
self.report_param_candidate(idx, mp.trait_id)
|
||||||
}
|
}
|
||||||
method_trait(trait_did, _) => {
|
method_trait(trait_did, _, _) => {
|
||||||
self.report_param_candidate(idx, 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::Err(_) => { return; /*typeck will fail anyhow*/ }
|
||||||
result::Ok(target_ty) => {
|
result::Ok(target_ty) => {
|
||||||
match ty::get(target_ty).sty {
|
match ty::get(target_ty).sty {
|
||||||
ty::ty_trait(_, substs, _) => {
|
ty::ty_trait(_, _, vstore_slice(trait_region)) => {
|
||||||
let trait_region = match substs.self_r {
|
|
||||||
Some(r) => {r}
|
|
||||||
None => {ty::re_static}
|
|
||||||
};
|
|
||||||
let source_ty = rcx.fcx.expr_ty(source);
|
let source_ty = rcx.fcx.expr_ty(source);
|
||||||
constrain_regions_in_type(rcx, trait_region,
|
constrain_regions_in_type(rcx, trait_region,
|
||||||
expr.span, source_ty);
|
expr.span, source_ty);
|
||||||
|
|
|
@ -156,8 +156,8 @@ fn lookup_vtable_invariant(fcx: @fn_ctxt,
|
||||||
let _i = indenter();
|
let _i = indenter();
|
||||||
|
|
||||||
let tcx = fcx.ccx.tcx;
|
let tcx = fcx.ccx.tcx;
|
||||||
let (trait_id, trait_substs) = match ty::get(trait_ty).sty {
|
let (trait_id, trait_substs, trait_vstore) = match ty::get(trait_ty).sty {
|
||||||
ty::ty_trait(did, substs, _) => (did, substs),
|
ty::ty_trait(did, substs, vstore) => (did, substs, vstore),
|
||||||
_ => tcx.sess.impossible_case(expr.span,
|
_ => tcx.sess.impossible_case(expr.span,
|
||||||
"lookup_vtable_invariant: \
|
"lookup_vtable_invariant: \
|
||||||
don't know how to handle a non-trait")
|
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
|
// it's the same trait as trait_ty, we need to
|
||||||
// unify it with trait_ty in order to get all
|
// unify it with trait_ty in order to get all
|
||||||
// the ty vars sorted out.
|
// 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 {
|
match ty::get(*of_ty).sty {
|
||||||
ty::ty_trait(id, _, _) => {
|
ty::ty_trait(id, _, _) => {
|
||||||
// Not the trait we're looking for
|
// Not the trait we're looking for
|
||||||
|
@ -378,7 +379,8 @@ fn lookup_vtable_invariant(fcx: @fn_ctxt,
|
||||||
// lists of types to unify pairwise.
|
// lists of types to unify pairwise.
|
||||||
|
|
||||||
connect_trait_tps(fcx, expr, substs_f.tps,
|
connect_trait_tps(fcx, expr, substs_f.tps,
|
||||||
trait_tps, im.did);
|
trait_tps, im.did,
|
||||||
|
trait_vstore);
|
||||||
let subres = lookup_vtables(
|
let subres = lookup_vtables(
|
||||||
fcx, expr, im_bs, &substs_f,
|
fcx, expr, im_bs, &substs_f,
|
||||||
false, is_early);
|
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],
|
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;
|
let tcx = fcx.ccx.tcx;
|
||||||
|
|
||||||
// XXX: This should work for multiple traits.
|
// 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);
|
let trait_ty = ty::subst_tps(tcx, impl_tys, ity);
|
||||||
debug!("(connect trait tps) trait type is %?, impl did is %?",
|
debug!("(connect trait tps) trait type is %?, impl did is %?",
|
||||||
ty::get(trait_ty).sty, impl_did);
|
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, _) => {
|
ast::expr_cast(src, _) => {
|
||||||
let target_ty = fcx.expr_ty(ex);
|
let target_ty = fcx.expr_ty(ex);
|
||||||
match ty::get(target_ty).sty {
|
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
|
// Look up vtables for the type we're casting to, passing in the
|
||||||
// source and target type.
|
// source and target type.
|
||||||
//
|
//
|
||||||
|
@ -520,26 +523,73 @@ fn early_resolve_expr(ex: @ast::expr, &&fcx: @fn_ctxt, is_early: bool) {
|
||||||
match vtable_opt {
|
match vtable_opt {
|
||||||
None => {
|
None => {
|
||||||
// Try the new-style boxed trait; "@int as @Trait".
|
// Try the new-style boxed trait; "@int as @Trait".
|
||||||
|
// Or the new-style region trait; "&int as &Trait".
|
||||||
let mut err = false;
|
let mut err = false;
|
||||||
let ty = structurally_resolved_type(fcx, ex.span, ty);
|
let ty = structurally_resolved_type(fcx, ex.span, ty);
|
||||||
match ty::get(ty).sty {
|
match ty::get(ty).sty {
|
||||||
ty::ty_box(boxed_ty) => {
|
ty::ty_box(mt) | ty::ty_rptr(_, mt) => {
|
||||||
let vtable_opt =
|
// Ensure that the trait vstore and the pointer
|
||||||
lookup_vtable_invariant(fcx, ex, boxed_ty.ty,
|
// type match.
|
||||||
target_ty, true,
|
match (ty::get(ty).sty, vstore) {
|
||||||
is_early);
|
(ty::ty_box(_), ty::vstore_box) |
|
||||||
match vtable_opt {
|
(ty::ty_rptr(*), ty::vstore_slice(*)) => {
|
||||||
Some(vtable) => {
|
let vtable_opt =
|
||||||
/*
|
lookup_vtable_invariant(fcx,
|
||||||
Map this expression to that vtable (that
|
ex,
|
||||||
is: "ex has vtable <vtable>")
|
mt.ty,
|
||||||
*/
|
target_ty,
|
||||||
if !is_early {
|
true,
|
||||||
cx.vtable_map.insert(ex.id,
|
is_early);
|
||||||
@~[vtable]);
|
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
|
_ => 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…
Add table
Add a link
Reference in a new issue