auto merge of #13087 : eddyb/rust/fix-autoderef, r=cmr
Implements vtable support for generic Deref impls with trait bounds. Also fixes cross-crate inlining when using autoderef.
This commit is contained in:
commit
94e4e91724
@ -581,41 +581,48 @@ impl tr for moves::CaptureVar {
|
||||
// Encoding and decoding of MethodCallee
|
||||
|
||||
trait read_method_callee_helper {
|
||||
fn read_method_callee(&mut self, xcx: &ExtendedDecodeContext) -> MethodCallee;
|
||||
fn read_method_callee(&mut self, xcx: &ExtendedDecodeContext) -> (u32, MethodCallee);
|
||||
}
|
||||
|
||||
fn encode_method_callee(ecx: &e::EncodeContext,
|
||||
ebml_w: &mut writer::Encoder,
|
||||
autoderef: u32,
|
||||
method: &MethodCallee) {
|
||||
ebml_w.emit_struct("MethodCallee", 3, |ebml_w| {
|
||||
ebml_w.emit_struct_field("origin", 0u, |ebml_w| {
|
||||
ebml_w.emit_struct("MethodCallee", 4, |ebml_w| {
|
||||
ebml_w.emit_struct_field("autoderef", 0u, |ebml_w| {
|
||||
autoderef.encode(ebml_w);
|
||||
});
|
||||
ebml_w.emit_struct_field("origin", 1u, |ebml_w| {
|
||||
method.origin.encode(ebml_w);
|
||||
});
|
||||
ebml_w.emit_struct_field("ty", 1u, |ebml_w| {
|
||||
ebml_w.emit_struct_field("ty", 2u, |ebml_w| {
|
||||
ebml_w.emit_ty(ecx, method.ty);
|
||||
});
|
||||
ebml_w.emit_struct_field("substs", 2u, |ebml_w| {
|
||||
ebml_w.emit_struct_field("substs", 3u, |ebml_w| {
|
||||
ebml_w.emit_substs(ecx, &method.substs);
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
impl<'a> read_method_callee_helper for reader::Decoder<'a> {
|
||||
fn read_method_callee(&mut self, xcx: &ExtendedDecodeContext) -> MethodCallee {
|
||||
self.read_struct("MethodCallee", 3, |this| {
|
||||
MethodCallee {
|
||||
origin: this.read_struct_field("origin", 0, |this| {
|
||||
fn read_method_callee(&mut self, xcx: &ExtendedDecodeContext) -> (u32, MethodCallee) {
|
||||
self.read_struct("MethodCallee", 4, |this| {
|
||||
let autoderef = this.read_struct_field("autoderef", 0, |this| {
|
||||
Decodable::decode(this)
|
||||
});
|
||||
(autoderef, MethodCallee {
|
||||
origin: this.read_struct_field("origin", 1, |this| {
|
||||
let method_origin: MethodOrigin =
|
||||
Decodable::decode(this);
|
||||
method_origin.tr(xcx)
|
||||
}),
|
||||
ty: this.read_struct_field("ty", 1, |this| {
|
||||
ty: this.read_struct_field("ty", 2, |this| {
|
||||
this.read_ty(xcx)
|
||||
}),
|
||||
substs: this.read_struct_field("substs", 2, |this| {
|
||||
substs: this.read_struct_field("substs", 3, |this| {
|
||||
this.read_substs(xcx)
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -647,6 +654,20 @@ impl tr for MethodOrigin {
|
||||
// ______________________________________________________________________
|
||||
// Encoding and decoding vtable_res
|
||||
|
||||
fn encode_vtable_res_with_key(ecx: &e::EncodeContext,
|
||||
ebml_w: &mut writer::Encoder,
|
||||
autoderef: u32,
|
||||
dr: typeck::vtable_res) {
|
||||
ebml_w.emit_struct("VtableWithKey", 2, |ebml_w| {
|
||||
ebml_w.emit_struct_field("autoderef", 0u, |ebml_w| {
|
||||
autoderef.encode(ebml_w);
|
||||
});
|
||||
ebml_w.emit_struct_field("vtable_res", 1u, |ebml_w| {
|
||||
encode_vtable_res(ecx, ebml_w, dr);
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
pub fn encode_vtable_res(ecx: &e::EncodeContext,
|
||||
ebml_w: &mut writer::Encoder,
|
||||
dr: typeck::vtable_res) {
|
||||
@ -701,6 +722,10 @@ pub fn encode_vtable_origin(ecx: &e::EncodeContext,
|
||||
}
|
||||
|
||||
pub trait vtable_decoder_helpers {
|
||||
fn read_vtable_res_with_key(&mut self,
|
||||
tcx: &ty::ctxt,
|
||||
cdata: @cstore::crate_metadata)
|
||||
-> (u32, typeck::vtable_res);
|
||||
fn read_vtable_res(&mut self,
|
||||
tcx: &ty::ctxt, cdata: @cstore::crate_metadata)
|
||||
-> typeck::vtable_res;
|
||||
@ -713,6 +738,20 @@ pub trait vtable_decoder_helpers {
|
||||
}
|
||||
|
||||
impl<'a> vtable_decoder_helpers for reader::Decoder<'a> {
|
||||
fn read_vtable_res_with_key(&mut self,
|
||||
tcx: &ty::ctxt,
|
||||
cdata: @cstore::crate_metadata)
|
||||
-> (u32, typeck::vtable_res) {
|
||||
self.read_struct("VtableWithKey", 2, |this| {
|
||||
let autoderef = this.read_struct_field("autoderef", 0, |this| {
|
||||
Decodable::decode(this)
|
||||
});
|
||||
(autoderef, this.read_struct_field("vtable_res", 1, |this| {
|
||||
this.read_vtable_res(tcx, cdata)
|
||||
}))
|
||||
})
|
||||
}
|
||||
|
||||
fn read_vtable_res(&mut self,
|
||||
tcx: &ty::ctxt, cdata: @cstore::crate_metadata)
|
||||
-> typeck::vtable_res {
|
||||
@ -1018,21 +1057,48 @@ fn encode_side_tables_for_id(ecx: &e::EncodeContext,
|
||||
ebml_w.tag(c::tag_table_method_map, |ebml_w| {
|
||||
ebml_w.id(id);
|
||||
ebml_w.tag(c::tag_table_val, |ebml_w| {
|
||||
encode_method_callee(ecx, ebml_w, method)
|
||||
encode_method_callee(ecx, ebml_w, method_call.autoderef, method)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
for &dr in maps.vtable_map.borrow().find(&id).iter() {
|
||||
for &dr in maps.vtable_map.borrow().find(&method_call).iter() {
|
||||
ebml_w.tag(c::tag_table_vtable_map, |ebml_w| {
|
||||
ebml_w.id(id);
|
||||
ebml_w.tag(c::tag_table_val, |ebml_w| {
|
||||
encode_vtable_res(ecx, ebml_w, *dr);
|
||||
encode_vtable_res_with_key(ecx, ebml_w, method_call.autoderef, *dr);
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
for adj in tcx.adjustments.borrow().find(&id).iter() {
|
||||
match ***adj {
|
||||
ty::AutoDerefRef(adj) => {
|
||||
for autoderef in range(0, adj.autoderefs) {
|
||||
let method_call = MethodCall::autoderef(id, autoderef as u32);
|
||||
for &method in maps.method_map.borrow().find(&method_call).iter() {
|
||||
ebml_w.tag(c::tag_table_method_map, |ebml_w| {
|
||||
ebml_w.id(id);
|
||||
ebml_w.tag(c::tag_table_val, |ebml_w| {
|
||||
encode_method_callee(ecx, ebml_w, method_call.autoderef, method)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
for &dr in maps.vtable_map.borrow().find(&method_call).iter() {
|
||||
ebml_w.tag(c::tag_table_vtable_map, |ebml_w| {
|
||||
ebml_w.id(id);
|
||||
ebml_w.tag(c::tag_table_val, |ebml_w| {
|
||||
encode_vtable_res_with_key(ecx, ebml_w,
|
||||
method_call.autoderef, *dr);
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
ebml_w.tag(c::tag_table_adjustments, |ebml_w| {
|
||||
ebml_w.id(id);
|
||||
ebml_w.tag(c::tag_table_val, |ebml_w| {
|
||||
@ -1336,15 +1402,22 @@ fn decode_side_tables(xcx: &ExtendedDecodeContext,
|
||||
dcx.tcx.ty_param_defs.borrow_mut().insert(id, bounds);
|
||||
}
|
||||
c::tag_table_method_map => {
|
||||
let method = val_dsr.read_method_callee(xcx);
|
||||
let method_call = MethodCall::expr(id);
|
||||
let (autoderef, method) = val_dsr.read_method_callee(xcx);
|
||||
let method_call = MethodCall {
|
||||
expr_id: id,
|
||||
autoderef: autoderef
|
||||
};
|
||||
dcx.maps.method_map.borrow_mut().insert(method_call, method);
|
||||
}
|
||||
c::tag_table_vtable_map => {
|
||||
let vtable_res =
|
||||
val_dsr.read_vtable_res(xcx.dcx.tcx,
|
||||
xcx.dcx.cdata);
|
||||
dcx.maps.vtable_map.borrow_mut().insert(id, vtable_res);
|
||||
let (autoderef, vtable_res) =
|
||||
val_dsr.read_vtable_res_with_key(xcx.dcx.tcx,
|
||||
xcx.dcx.cdata);
|
||||
let vtable_key = MethodCall {
|
||||
expr_id: id,
|
||||
autoderef: autoderef
|
||||
};
|
||||
dcx.maps.vtable_map.borrow_mut().insert(vtable_key, vtable_res);
|
||||
}
|
||||
c::tag_table_adjustments => {
|
||||
let adj: @ty::AutoAdjustment = @val_dsr.read_auto_adjustment(xcx);
|
||||
|
@ -129,7 +129,7 @@ pub fn lookup_variant_by_id(tcx: &ty::ctxt,
|
||||
let maps = astencode::Maps {
|
||||
root_map: @RefCell::new(HashMap::new()),
|
||||
method_map: @RefCell::new(FnvHashMap::new()),
|
||||
vtable_map: @RefCell::new(NodeMap::new()),
|
||||
vtable_map: @RefCell::new(FnvHashMap::new()),
|
||||
capture_map: RefCell::new(NodeMap::new())
|
||||
};
|
||||
let e = match csearch::maybe_get_item_ast(tcx, enum_def,
|
||||
@ -170,7 +170,7 @@ pub fn lookup_const_by_id(tcx: &ty::ctxt, def_id: ast::DefId)
|
||||
let maps = astencode::Maps {
|
||||
root_map: @RefCell::new(HashMap::new()),
|
||||
method_map: @RefCell::new(FnvHashMap::new()),
|
||||
vtable_map: @RefCell::new(NodeMap::new()),
|
||||
vtable_map: @RefCell::new(FnvHashMap::new()),
|
||||
capture_map: RefCell::new(NodeMap::new())
|
||||
};
|
||||
let e = match csearch::maybe_get_item_ast(tcx, def_id,
|
||||
|
@ -170,16 +170,11 @@ pub fn trans_fn_ref(bcx: &Block, def_id: ast::DefId, node: ExprOrMethodCall) ->
|
||||
let _icx = push_ctxt("trans_fn_ref");
|
||||
|
||||
let type_params = node_id_type_params(bcx, node);
|
||||
let vtables = match node {
|
||||
ExprId(id) => node_vtables(bcx, id),
|
||||
MethodCall(ref method_call) => {
|
||||
if method_call.autoderef == 0 {
|
||||
node_vtables(bcx, method_call.expr_id)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
let vtable_key = match node {
|
||||
ExprId(id) => MethodCall::expr(id),
|
||||
MethodCall(method_call) => method_call
|
||||
};
|
||||
let vtables = node_vtables(bcx, vtable_key);
|
||||
debug!("trans_fn_ref(def_id={}, node={:?}, type_params={}, vtables={})",
|
||||
def_id.repr(bcx.tcx()), node, type_params.repr(bcx.tcx()),
|
||||
vtables.repr(bcx.tcx()));
|
||||
|
@ -829,7 +829,7 @@ pub fn node_id_type_params(bcx: &Block, node: ExprOrMethodCall) -> Vec<ty::t> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn node_vtables(bcx: &Block, id: ast::NodeId)
|
||||
pub fn node_vtables(bcx: &Block, id: typeck::MethodCall)
|
||||
-> Option<typeck::vtable_res> {
|
||||
let vtable_map = bcx.ccx().maps.vtable_map.borrow();
|
||||
let raw_vtables = vtable_map.find(&id);
|
||||
|
@ -208,7 +208,8 @@ pub fn trans_static_method_callee(bcx: &Block,
|
||||
debug!("trans_static_method_callee: method_id={:?}, expr_id={:?}, \
|
||||
name={}", method_id, expr_id, token::get_name(mname));
|
||||
|
||||
let vtbls = ccx.maps.vtable_map.borrow().get_copy(&expr_id);
|
||||
let vtable_key = MethodCall::expr(expr_id);
|
||||
let vtbls = ccx.maps.vtable_map.borrow().get_copy(&vtable_key);
|
||||
let vtbls = resolve_vtables_in_fn_ctxt(bcx.fcx, vtbls);
|
||||
|
||||
match vtbls.get(bound_index).get(0) {
|
||||
@ -327,16 +328,11 @@ fn combine_impl_and_methods_tps(bcx: &Block,
|
||||
|
||||
// Now, do the same work for the vtables. The vtables might not
|
||||
// exist, in which case we need to make them.
|
||||
let vtables = match node {
|
||||
ExprId(id) => node_vtables(bcx, id),
|
||||
MethodCall(method_call) => {
|
||||
if method_call.autoderef == 0 {
|
||||
node_vtables(bcx, method_call.expr_id)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
let vtable_key = match node {
|
||||
ExprId(id) => MethodCall::expr(id),
|
||||
MethodCall(method_call) => method_call
|
||||
};
|
||||
let vtables = node_vtables(bcx, vtable_key);
|
||||
let r_m_origins = match vtables {
|
||||
Some(vt) => vt,
|
||||
None => @Vec::from_elem(node_substs.len(), @Vec::new())
|
||||
@ -597,10 +593,8 @@ pub fn trans_trait_cast<'a>(bcx: &'a Block<'a>,
|
||||
bcx = datum.store_to(bcx, llboxdest);
|
||||
|
||||
// Store the vtable into the second half of pair.
|
||||
// This is structured a bit funny because of dynamic borrow failures.
|
||||
let res = *ccx.maps.vtable_map.borrow().get(&id);
|
||||
let res = resolve_vtables_in_fn_ctxt(bcx.fcx, res);
|
||||
let origins = *res.get(0);
|
||||
let res = *ccx.maps.vtable_map.borrow().get(&MethodCall::expr(id));
|
||||
let origins = *resolve_vtables_in_fn_ctxt(bcx.fcx, res).get(0);
|
||||
let vtable = get_vtable(bcx, v_ty, origins);
|
||||
let llvtabledest = GEPi(bcx, lldest, [0u, abi::trt_field_vtable]);
|
||||
let llvtabledest = PointerCast(bcx, llvtabledest, val_ty(vtable).ptr_to());
|
||||
|
@ -267,7 +267,7 @@ impl<'a> Inherited<'a> {
|
||||
node_type_substs: RefCell::new(NodeMap::new()),
|
||||
adjustments: RefCell::new(NodeMap::new()),
|
||||
method_map: @RefCell::new(FnvHashMap::new()),
|
||||
vtable_map: @RefCell::new(NodeMap::new()),
|
||||
vtable_map: @RefCell::new(FnvHashMap::new()),
|
||||
upvar_borrow_map: RefCell::new(HashMap::new()),
|
||||
}
|
||||
}
|
||||
|
@ -516,10 +516,10 @@ fn connect_trait_tps(vcx: &VtableContext,
|
||||
relate_trait_refs(vcx, span, impl_trait_ref, trait_ref);
|
||||
}
|
||||
|
||||
fn insert_vtables(fcx: &FnCtxt, expr_id: ast::NodeId, vtables: vtable_res) {
|
||||
debug!("insert_vtables(expr_id={}, vtables={:?})",
|
||||
expr_id, vtables.repr(fcx.tcx()));
|
||||
fcx.inh.vtable_map.borrow_mut().insert(expr_id, vtables);
|
||||
fn insert_vtables(fcx: &FnCtxt, vtable_key: MethodCall, vtables: vtable_res) {
|
||||
debug!("insert_vtables(vtable_key={}, vtables={:?})",
|
||||
vtable_key, vtables.repr(fcx.tcx()));
|
||||
fcx.inh.vtable_map.borrow_mut().insert(vtable_key, vtables);
|
||||
}
|
||||
|
||||
pub fn early_resolve_expr(ex: &ast::Expr, fcx: &FnCtxt, is_early: bool) {
|
||||
@ -591,7 +591,7 @@ pub fn early_resolve_expr(ex: &ast::Expr, fcx: &FnCtxt, is_early: bool) {
|
||||
is_early);
|
||||
|
||||
if !is_early {
|
||||
insert_vtables(fcx, ex.id, @vec!(vtables));
|
||||
insert_vtables(fcx, MethodCall::expr(ex.id), @vec!(vtables));
|
||||
}
|
||||
|
||||
// Now, if this is &trait, we need to link the
|
||||
@ -648,7 +648,7 @@ pub fn early_resolve_expr(ex: &ast::Expr, fcx: &FnCtxt, is_early: bool) {
|
||||
item_ty.generics.type_param_defs(),
|
||||
substs, is_early);
|
||||
if !is_early {
|
||||
insert_vtables(fcx, ex.id, vtbls);
|
||||
insert_vtables(fcx, MethodCall::expr(ex.id), vtbls);
|
||||
}
|
||||
}
|
||||
true
|
||||
@ -673,7 +673,7 @@ pub fn early_resolve_expr(ex: &ast::Expr, fcx: &FnCtxt, is_early: bool) {
|
||||
type_param_defs.as_slice(),
|
||||
&substs, is_early);
|
||||
if !is_early {
|
||||
insert_vtables(fcx, ex.id, vtbls);
|
||||
insert_vtables(fcx, MethodCall::expr(ex.id), vtbls);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -692,6 +692,30 @@ pub fn early_resolve_expr(ex: &ast::Expr, fcx: &FnCtxt, is_early: bool) {
|
||||
match fcx.inh.adjustments.borrow().find(&ex.id) {
|
||||
Some(adjustment) => {
|
||||
match **adjustment {
|
||||
AutoDerefRef(adj) => {
|
||||
for autoderef in range(0, adj.autoderefs) {
|
||||
let method_call = MethodCall::autoderef(ex.id, autoderef as u32);
|
||||
match fcx.inh.method_map.borrow().find(&method_call) {
|
||||
Some(method) => {
|
||||
debug!("vtable resolution on parameter bounds for autoderef {}",
|
||||
ex.repr(fcx.tcx()));
|
||||
let type_param_defs =
|
||||
ty::method_call_type_param_defs(cx.tcx, method.origin);
|
||||
if has_trait_bounds(type_param_defs.deref().as_slice()) {
|
||||
let vcx = fcx.vtable_context();
|
||||
let vtbls = lookup_vtables(&vcx, ex.span,
|
||||
type_param_defs.deref()
|
||||
.as_slice(),
|
||||
&method.substs, is_early);
|
||||
if !is_early {
|
||||
insert_vtables(fcx, method_call, vtbls);
|
||||
}
|
||||
}
|
||||
}
|
||||
None => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
AutoObject(ref sigil,
|
||||
ref region,
|
||||
m,
|
||||
@ -713,7 +737,7 @@ pub fn early_resolve_expr(ex: &ast::Expr, fcx: &FnCtxt, is_early: bool) {
|
||||
b);
|
||||
resolve_object_cast(ex, object_ty);
|
||||
}
|
||||
AutoAddEnv(..) | AutoDerefRef(..) => {}
|
||||
AutoAddEnv(..) => {}
|
||||
}
|
||||
}
|
||||
None => {}
|
||||
|
@ -21,8 +21,7 @@ use middle::typeck::infer::{force_all, resolve_all, resolve_region};
|
||||
use middle::typeck::infer::resolve_type;
|
||||
use middle::typeck::infer;
|
||||
use middle::typeck::{MethodCall, MethodCallee};
|
||||
use middle::typeck::{vtable_res, vtable_origin};
|
||||
use middle::typeck::{vtable_static, vtable_param};
|
||||
use middle::typeck::{vtable_res, vtable_static, vtable_param};
|
||||
use middle::typeck::write_substs_to_tcx;
|
||||
use middle::typeck::write_ty_to_tcx;
|
||||
use util::ppaux;
|
||||
@ -100,38 +99,34 @@ fn resolve_method_map_entry(wbcx: &mut WbCtxt, sp: Span, method_call: MethodCall
|
||||
}
|
||||
}
|
||||
|
||||
fn resolve_vtable_map_entry(fcx: &FnCtxt, sp: Span, id: ast::NodeId) {
|
||||
fn resolve_vtable_map_entry(fcx: &FnCtxt, sp: Span, vtable_key: MethodCall) {
|
||||
// Resolve any vtable map entry
|
||||
match fcx.inh.vtable_map.borrow().find_copy(&id) {
|
||||
match fcx.inh.vtable_map.borrow().find_copy(&vtable_key) {
|
||||
Some(origins) => {
|
||||
let r_origins = resolve_origins(fcx, sp, origins);
|
||||
fcx.ccx.vtable_map.borrow_mut().insert(id, r_origins);
|
||||
debug!("writeback::resolve_vtable_map_entry(id={}, vtables={:?})",
|
||||
id, r_origins.repr(fcx.tcx()));
|
||||
fcx.ccx.vtable_map.borrow_mut().insert(vtable_key, r_origins);
|
||||
debug!("writeback::resolve_vtable_map_entry(vtable_key={}, vtables={:?})",
|
||||
vtable_key, r_origins.repr(fcx.tcx()));
|
||||
}
|
||||
None => {}
|
||||
}
|
||||
|
||||
fn resolve_origins(fcx: &FnCtxt, sp: Span,
|
||||
vtbls: vtable_res) -> vtable_res {
|
||||
@vtbls.map(|os| @os.map(|o| resolve_origin(fcx, sp, o)))
|
||||
}
|
||||
|
||||
fn resolve_origin(fcx: &FnCtxt,
|
||||
sp: Span,
|
||||
origin: &vtable_origin) -> vtable_origin {
|
||||
match origin {
|
||||
&vtable_static(def_id, ref tys, origins) => {
|
||||
let r_tys = resolve_type_vars_in_types(fcx,
|
||||
sp,
|
||||
tys.as_slice());
|
||||
let r_origins = resolve_origins(fcx, sp, origins);
|
||||
vtable_static(def_id, r_tys, r_origins)
|
||||
@vtbls.map(|os| @os.map(|origin| {
|
||||
match origin {
|
||||
&vtable_static(def_id, ref tys, origins) => {
|
||||
let r_tys = resolve_type_vars_in_types(fcx,
|
||||
sp,
|
||||
tys.as_slice());
|
||||
let r_origins = resolve_origins(fcx, sp, origins);
|
||||
vtable_static(def_id, r_tys, r_origins)
|
||||
}
|
||||
&vtable_param(n, b) => {
|
||||
vtable_param(n, b)
|
||||
}
|
||||
}
|
||||
&vtable_param(n, b) => {
|
||||
vtable_param(n, b)
|
||||
}
|
||||
}
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
@ -183,6 +178,7 @@ fn resolve_type_vars_for_node(wbcx: &mut WbCtxt, sp: Span, id: ast::NodeId)
|
||||
for autoderef in range(0, adj.autoderefs) {
|
||||
let method_call = MethodCall::autoderef(id, autoderef as u32);
|
||||
resolve_method_map_entry(wbcx, sp, method_call);
|
||||
resolve_vtable_map_entry(wbcx.fcx, sp, method_call);
|
||||
}
|
||||
|
||||
let fixup_region = |r| {
|
||||
@ -273,7 +269,7 @@ fn visit_expr(e: &ast::Expr, wbcx: &mut WbCtxt) {
|
||||
|
||||
resolve_type_vars_for_node(wbcx, e.span, e.id);
|
||||
resolve_method_map_entry(wbcx, e.span, MethodCall::expr(e.id));
|
||||
resolve_vtable_map_entry(wbcx.fcx, e.span, e.id);
|
||||
resolve_vtable_map_entry(wbcx.fcx, e.span, MethodCall::expr(e.id));
|
||||
|
||||
match e.node {
|
||||
ast::ExprFnBlock(ref decl, _) | ast::ExprProc(ref decl, _) => {
|
||||
|
@ -68,7 +68,7 @@ use middle::ty;
|
||||
use util::common::time;
|
||||
use util::ppaux::Repr;
|
||||
use util::ppaux;
|
||||
use util::nodemap::{DefIdMap, FnvHashMap, NodeMap};
|
||||
use util::nodemap::{DefIdMap, FnvHashMap};
|
||||
|
||||
use std::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
@ -148,7 +148,7 @@ pub struct MethodCallee {
|
||||
substs: ty::substs
|
||||
}
|
||||
|
||||
#[deriving(Clone, Eq, Hash)]
|
||||
#[deriving(Clone, Eq, Hash, Show)]
|
||||
pub struct MethodCall {
|
||||
expr_id: ast::NodeId,
|
||||
autoderef: u32
|
||||
@ -216,7 +216,7 @@ impl Repr for vtable_origin {
|
||||
}
|
||||
}
|
||||
|
||||
pub type vtable_map = @RefCell<NodeMap<vtable_res>>;
|
||||
pub type vtable_map = @RefCell<FnvHashMap<MethodCall, vtable_res>>;
|
||||
|
||||
|
||||
// Information about the vtable resolutions for a trait impl.
|
||||
@ -461,7 +461,7 @@ pub fn check_crate(tcx: &ty::ctxt,
|
||||
let ccx = CrateCtxt {
|
||||
trait_map: trait_map,
|
||||
method_map: @RefCell::new(FnvHashMap::new()),
|
||||
vtable_map: @RefCell::new(NodeMap::new()),
|
||||
vtable_map: @RefCell::new(FnvHashMap::new()),
|
||||
tcx: tcx
|
||||
};
|
||||
|
||||
|
37
src/test/auxiliary/overloaded_autoderef_xc.rs
Normal file
37
src/test/auxiliary/overloaded_autoderef_xc.rs
Normal file
@ -0,0 +1,37 @@
|
||||
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use std::ops::Deref;
|
||||
|
||||
struct DerefWithHelper<H, T> {
|
||||
helper: H
|
||||
}
|
||||
|
||||
trait Helper<T> {
|
||||
fn helper_borrow<'a>(&'a self) -> &'a T;
|
||||
}
|
||||
|
||||
impl<T> Helper<T> for Option<T> {
|
||||
fn helper_borrow<'a>(&'a self) -> &'a T {
|
||||
self.as_ref().unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, H: Helper<T>> Deref<T> for DerefWithHelper<H, T> {
|
||||
fn deref<'a>(&'a self) -> &'a T {
|
||||
self.helper.helper_borrow()
|
||||
}
|
||||
}
|
||||
|
||||
// Test cross-crate autoderef + vtable.
|
||||
pub fn check<T: Eq>(x: T, y: T) -> bool {
|
||||
let d: DerefWithHelper<Option<T>, T> = DerefWithHelper { helper: Some(x) };
|
||||
d.eq(&y)
|
||||
}
|
42
src/test/run-pass/overloaded-autoderef-vtable.rs
Normal file
42
src/test/run-pass/overloaded-autoderef-vtable.rs
Normal file
@ -0,0 +1,42 @@
|
||||
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use std::ops::Deref;
|
||||
|
||||
struct DerefWithHelper<H, T> {
|
||||
helper: H
|
||||
}
|
||||
|
||||
trait Helper<T> {
|
||||
fn helper_borrow<'a>(&'a self) -> &'a T;
|
||||
}
|
||||
|
||||
impl<T> Helper<T> for Option<T> {
|
||||
fn helper_borrow<'a>(&'a self) -> &'a T {
|
||||
self.as_ref().unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, H: Helper<T>> Deref<T> for DerefWithHelper<H, T> {
|
||||
fn deref<'a>(&'a self) -> &'a T {
|
||||
self.helper.helper_borrow()
|
||||
}
|
||||
}
|
||||
|
||||
struct Foo {x: int}
|
||||
|
||||
impl Foo {
|
||||
fn foo(&self) -> int {self.x}
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
let x: DerefWithHelper<Option<Foo>, Foo> = DerefWithHelper { helper: Some(Foo {x: 5}) };
|
||||
assert!(x.foo() == 5);
|
||||
}
|
18
src/test/run-pass/overloaded-autoderef-xcrate.rs
Normal file
18
src/test/run-pass/overloaded-autoderef-xcrate.rs
Normal file
@ -0,0 +1,18 @@
|
||||
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// ignore-fast
|
||||
// aux-build:overloaded_autoderef_xc.rs
|
||||
|
||||
extern crate overloaded_autoderef_xc;
|
||||
|
||||
fn main() {
|
||||
assert!(overloaded_autoderef_xc::check(5, 5));
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user