Closes #13042.
})
}
- 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| {
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 vtable_key = MethodCall::expr(id);
+ 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);
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,
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,
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()));
}
}
-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);
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) {
// 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())
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());
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()),
}
}
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) {
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
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
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);
}
}
}
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,
b);
resolve_object_cast(ex, object_ty);
}
- AutoAddEnv(..) | AutoDerefRef(..) => {}
+ AutoAddEnv(..) => {}
}
}
None => {}
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;
}
}
-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)
- }
- &vtable_param(n, b) => {
- vtable_param(n, b)
+ @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)
+ }
}
- }
+ }))
}
}
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| {
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, _) => {
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;
substs: ty::substs
}
-#[deriving(Clone, Eq, Hash)]
+#[deriving(Clone, Eq, Hash, Show)]
pub struct MethodCall {
expr_id: ast::NodeId,
autoderef: u32
}
}
-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.
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
};
--- /dev/null
+// 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);
+}