rustc: de-@ method and vtable maps.

This commit is contained in:
Eduard Burtescu 2014-04-10 14:04:45 +03:00
parent 158d7a19b3
commit c9bf84333d
11 changed files with 210 additions and 227 deletions

View File

@ -146,8 +146,8 @@ fn encode_impl_vtables(ebml_w: &mut Encoder,
ecx: &EncodeContext, ecx: &EncodeContext,
vtables: &typeck::impl_res) { vtables: &typeck::impl_res) {
ebml_w.start_tag(tag_item_impl_vtables); ebml_w.start_tag(tag_item_impl_vtables);
astencode::encode_vtable_res(ecx, ebml_w, vtables.trait_vtables); astencode::encode_vtable_res(ecx, ebml_w, &vtables.trait_vtables);
astencode::encode_vtable_param_res(ecx, ebml_w, vtables.self_vtables); astencode::encode_vtable_param_res(ecx, ebml_w, &vtables.self_vtables);
ebml_w.end_tag(); ebml_w.end_tag();
} }

View File

@ -658,7 +658,7 @@ impl tr for MethodOrigin {
fn encode_vtable_res_with_key(ecx: &e::EncodeContext, fn encode_vtable_res_with_key(ecx: &e::EncodeContext,
ebml_w: &mut Encoder, ebml_w: &mut Encoder,
autoderef: u32, autoderef: u32,
dr: typeck::vtable_res) { dr: &typeck::vtable_res) {
ebml_w.emit_struct("VtableWithKey", 2, |ebml_w| { ebml_w.emit_struct("VtableWithKey", 2, |ebml_w| {
ebml_w.emit_struct_field("autoderef", 0u, |ebml_w| { ebml_w.emit_struct_field("autoderef", 0u, |ebml_w| {
autoderef.encode(ebml_w) autoderef.encode(ebml_w)
@ -671,19 +671,19 @@ fn encode_vtable_res_with_key(ecx: &e::EncodeContext,
pub fn encode_vtable_res(ecx: &e::EncodeContext, pub fn encode_vtable_res(ecx: &e::EncodeContext,
ebml_w: &mut Encoder, ebml_w: &mut Encoder,
dr: typeck::vtable_res) { dr: &typeck::vtable_res) {
// can't autogenerate this code because automatic code of // can't autogenerate this code because automatic code of
// ty::t doesn't work, and there is no way (atm) to have // ty::t doesn't work, and there is no way (atm) to have
// hand-written encoding routines combine with auto-generated // hand-written encoding routines combine with auto-generated
// ones. perhaps we should fix this. // ones. perhaps we should fix this.
ebml_w.emit_from_vec(dr.as_slice(), |ebml_w, param_tables| { ebml_w.emit_from_vec(dr.as_slice(), |ebml_w, param_tables| {
Ok(encode_vtable_param_res(ecx, ebml_w, *param_tables)) Ok(encode_vtable_param_res(ecx, ebml_w, param_tables))
}).unwrap() }).unwrap()
} }
pub fn encode_vtable_param_res(ecx: &e::EncodeContext, pub fn encode_vtable_param_res(ecx: &e::EncodeContext,
ebml_w: &mut Encoder, ebml_w: &mut Encoder,
param_tables: typeck::vtable_param_res) { param_tables: &typeck::vtable_param_res) {
ebml_w.emit_from_vec(param_tables.as_slice(), |ebml_w, vtable_origin| { ebml_w.emit_from_vec(param_tables.as_slice(), |ebml_w, vtable_origin| {
Ok(encode_vtable_origin(ecx, ebml_w, vtable_origin)) Ok(encode_vtable_origin(ecx, ebml_w, vtable_origin))
}).unwrap() }).unwrap()
@ -695,7 +695,7 @@ pub fn encode_vtable_origin(ecx: &e::EncodeContext,
vtable_origin: &typeck::vtable_origin) { vtable_origin: &typeck::vtable_origin) {
ebml_w.emit_enum("vtable_origin", |ebml_w| { ebml_w.emit_enum("vtable_origin", |ebml_w| {
match *vtable_origin { match *vtable_origin {
typeck::vtable_static(def_id, ref tys, vtable_res) => { typeck::vtable_static(def_id, ref tys, ref vtable_res) => {
ebml_w.emit_enum_variant("vtable_static", 0u, 3u, |ebml_w| { ebml_w.emit_enum_variant("vtable_static", 0u, 3u, |ebml_w| {
ebml_w.emit_enum_variant_arg(0u, |ebml_w| { ebml_w.emit_enum_variant_arg(0u, |ebml_w| {
Ok(ebml_w.emit_def_id(def_id)) Ok(ebml_w.emit_def_id(def_id))
@ -756,21 +756,15 @@ impl<'a> vtable_decoder_helpers for reader::Decoder<'a> {
fn read_vtable_res(&mut self, fn read_vtable_res(&mut self,
tcx: &ty::ctxt, cdata: @cstore::crate_metadata) tcx: &ty::ctxt, cdata: @cstore::crate_metadata)
-> typeck::vtable_res { -> typeck::vtable_res {
@self.read_to_vec(|this| self.read_to_vec(|this| Ok(this.read_vtable_param_res(tcx, cdata)))
Ok(this.read_vtable_param_res(tcx, cdata))) .unwrap().move_iter().collect()
.unwrap()
.move_iter()
.collect()
} }
fn read_vtable_param_res(&mut self, fn read_vtable_param_res(&mut self,
tcx: &ty::ctxt, cdata: @cstore::crate_metadata) tcx: &ty::ctxt, cdata: @cstore::crate_metadata)
-> typeck::vtable_param_res { -> typeck::vtable_param_res {
@self.read_to_vec(|this| self.read_to_vec(|this| Ok(this.read_vtable_origin(tcx, cdata)))
Ok(this.read_vtable_origin(tcx, cdata))) .unwrap().move_iter().collect()
.unwrap()
.move_iter()
.collect()
} }
fn read_vtable_origin(&mut self, fn read_vtable_origin(&mut self,
@ -1063,7 +1057,7 @@ fn encode_side_tables_for_id(ecx: &e::EncodeContext,
ebml_w.tag(c::tag_table_vtable_map, |ebml_w| { ebml_w.tag(c::tag_table_vtable_map, |ebml_w| {
ebml_w.id(id); ebml_w.id(id);
ebml_w.tag(c::tag_table_val, |ebml_w| { ebml_w.tag(c::tag_table_val, |ebml_w| {
encode_vtable_res_with_key(ecx, ebml_w, method_call.autoderef, *dr); encode_vtable_res_with_key(ecx, ebml_w, method_call.autoderef, dr);
}) })
}) })
} }
@ -1087,7 +1081,7 @@ fn encode_side_tables_for_id(ecx: &e::EncodeContext,
ebml_w.id(id); ebml_w.id(id);
ebml_w.tag(c::tag_table_val, |ebml_w| { ebml_w.tag(c::tag_table_val, |ebml_w| {
encode_vtable_res_with_key(ecx, ebml_w, encode_vtable_res_with_key(ecx, ebml_w,
method_call.autoderef, *dr); method_call.autoderef, dr);
}) })
}) })
} }

View File

@ -176,14 +176,14 @@ pub fn trans_fn_ref(bcx: &Block, def_id: ast::DefId, node: ExprOrMethodCall) ->
def_id.repr(bcx.tcx()), node, type_params.repr(bcx.tcx()), def_id.repr(bcx.tcx()), node, type_params.repr(bcx.tcx()),
vtables.repr(bcx.tcx())); vtables.repr(bcx.tcx()));
trans_fn_ref_with_vtables(bcx, def_id, node, trans_fn_ref_with_vtables(bcx, def_id, node,
type_params.as_slice(), type_params,
vtables) vtables)
} }
fn trans_fn_ref_with_vtables_to_callee<'a>(bcx: &'a Block<'a>, fn trans_fn_ref_with_vtables_to_callee<'a>(bcx: &'a Block<'a>,
def_id: ast::DefId, def_id: ast::DefId,
ref_id: ast::NodeId, ref_id: ast::NodeId,
type_params: &[ty::t], type_params: Vec<ty::t>,
vtables: Option<typeck::vtable_res>) vtables: Option<typeck::vtable_res>)
-> Callee<'a> { -> Callee<'a> {
Callee {bcx: bcx, Callee {bcx: bcx,
@ -206,29 +206,32 @@ fn resolve_default_method_vtables(bcx: &Block,
let param_substs = Some(@param_substs { let param_substs = Some(@param_substs {
tys: substs.tps.clone(), tys: substs.tps.clone(),
self_ty: substs.self_ty, self_ty: substs.self_ty,
vtables: impl_vtables, vtables: impl_vtables.clone(),
self_vtables: None self_vtables: None
}); });
let trait_vtables_fixed = resolve_vtables_under_param_substs( let mut param_vtables = resolve_vtables_under_param_substs(
bcx.tcx(), param_substs, impl_res.trait_vtables); bcx.tcx(), param_substs, impl_res.trait_vtables.as_slice());
// Now we pull any vtables for parameters on the actual method. // Now we pull any vtables for parameters on the actual method.
let num_method_vtables = method.generics.type_param_defs().len(); let num_method_vtables = method.generics.type_param_defs().len();
let method_vtables = match impl_vtables { match impl_vtables {
Some(vtables) => { Some(ref vtables) => {
let num_impl_type_parameters = let num_impl_type_parameters =
vtables.len() - num_method_vtables; vtables.len() - num_method_vtables;
Vec::from_slice(vtables.tailn(num_impl_type_parameters)) param_vtables.push_all(vtables.tailn(num_impl_type_parameters))
}, },
None => Vec::from_elem(num_method_vtables, @Vec::new()) None => {
}; param_vtables.extend(range(0, num_method_vtables).map(
|_| -> typeck::vtable_param_res {
let method_vtables = method_vtables.as_slice(); Vec::new()
let param_vtables = @((*trait_vtables_fixed).clone().append(method_vtables)); }
))
}
}
let self_vtables = resolve_param_vtables_under_param_substs( let self_vtables = resolve_param_vtables_under_param_substs(
bcx.tcx(), param_substs, impl_res.self_vtables); bcx.tcx(), param_substs, impl_res.self_vtables.as_slice());
(param_vtables, self_vtables) (param_vtables, self_vtables)
} }
@ -238,7 +241,7 @@ pub fn trans_fn_ref_with_vtables(
bcx: &Block, // bcx: &Block, //
def_id: ast::DefId, // def id of fn def_id: ast::DefId, // def id of fn
node: ExprOrMethodCall, // node id of use of fn; may be zero if N/A node: ExprOrMethodCall, // node id of use of fn; may be zero if N/A
type_params: &[ty::t], // values for fn's ty params type_params: Vec<ty::t>, // values for fn's ty params
vtables: Option<typeck::vtable_res>) // vtables for the call vtables: Option<typeck::vtable_res>) // vtables for the call
-> ValueRef { -> ValueRef {
/*! /*!
@ -273,9 +276,11 @@ pub fn trans_fn_ref_with_vtables(
// Polytype of the function item (may have type params) // Polytype of the function item (may have type params)
let fn_tpt = ty::lookup_item_type(tcx, def_id); let fn_tpt = ty::lookup_item_type(tcx, def_id);
let substs = ty::substs { regions: ty::ErasedRegions, let substs = ty::substs {
self_ty: None, regions: ty::ErasedRegions,
tps: /*bad*/ Vec::from_slice(type_params) }; self_ty: None,
tps: type_params
};
// Load the info for the appropriate trait if necessary. // Load the info for the appropriate trait if necessary.
match ty::trait_of_method(tcx, def_id) { match ty::trait_of_method(tcx, def_id) {
@ -318,19 +323,20 @@ pub fn trans_fn_ref_with_vtables(
// And compose them // And compose them
let new_substs = first_subst.subst(tcx, &substs); let new_substs = first_subst.subst(tcx, &substs);
debug!("trans_fn_with_vtables - default method: \
substs = {}, trait_subst = {}, \
first_subst = {}, new_subst = {}, \
vtables = {}",
substs.repr(tcx), trait_ref.substs.repr(tcx),
first_subst.repr(tcx), new_substs.repr(tcx),
vtables.repr(tcx));
let (param_vtables, self_vtables) = let (param_vtables, self_vtables) =
resolve_default_method_vtables(bcx, impl_id, resolve_default_method_vtables(bcx, impl_id,
method, &substs, vtables); method, &substs, vtables);
debug!("trans_fn_with_vtables - default method: \ debug!("trans_fn_with_vtables - default method: \
substs = {}, trait_subst = {}, \
first_subst = {}, new_subst = {}, \
vtables = {}, \
self_vtable = {}, param_vtables = {}", self_vtable = {}, param_vtables = {}",
substs.repr(tcx), trait_ref.substs.repr(tcx),
first_subst.repr(tcx), new_substs.repr(tcx),
vtables.repr(tcx),
self_vtables.repr(tcx), param_vtables.repr(tcx)); self_vtables.repr(tcx), param_vtables.repr(tcx));
(true, source_id, (true, source_id,
@ -352,7 +358,7 @@ pub fn trans_fn_ref_with_vtables(
// intrinsic, or is a default method. In particular, if we see an // intrinsic, or is a default method. In particular, if we see an
// intrinsic that is inlined from a different crate, we want to reemit the // intrinsic that is inlined from a different crate, we want to reemit the
// intrinsic instead of trying to call it in the other crate. // intrinsic instead of trying to call it in the other crate.
let must_monomorphise = if type_params.len() > 0 || is_default { let must_monomorphise = if substs.tps.len() > 0 || is_default {
true true
} else if def_id.krate == ast::LOCAL_CRATE { } else if def_id.krate == ast::LOCAL_CRATE {
let map_node = session::expect( let map_node = session::expect(
@ -504,7 +510,7 @@ pub fn trans_lang_call<'a>(
trans_fn_ref_with_vtables_to_callee(bcx, trans_fn_ref_with_vtables_to_callee(bcx,
did, did,
0, 0,
[], vec!(),
None) None)
}, },
ArgVals(args), ArgVals(args),

View File

@ -797,15 +797,16 @@ pub fn node_id_type_params(bcx: &Block, node: ExprOrMethodCall) -> Vec<ty::t> {
pub fn node_vtables(bcx: &Block, id: typeck::MethodCall) pub fn node_vtables(bcx: &Block, id: typeck::MethodCall)
-> Option<typeck::vtable_res> { -> Option<typeck::vtable_res> {
let vtable_map = bcx.tcx().vtable_map.borrow(); bcx.tcx().vtable_map.borrow().find(&id).map(|vts| {
let raw_vtables = vtable_map.find(&id); resolve_vtables_in_fn_ctxt(bcx.fcx, vts.as_slice())
raw_vtables.map(|vts| resolve_vtables_in_fn_ctxt(bcx.fcx, *vts)) })
} }
// Apply the typaram substitutions in the FunctionContext to some // Apply the typaram substitutions in the FunctionContext to some
// vtables. This should eliminate any vtable_params. // vtables. This should eliminate any vtable_params.
pub fn resolve_vtables_in_fn_ctxt(fcx: &FunctionContext, vts: typeck::vtable_res) pub fn resolve_vtables_in_fn_ctxt(fcx: &FunctionContext,
-> typeck::vtable_res { vts: &[typeck::vtable_param_res])
-> typeck::vtable_res {
resolve_vtables_under_param_substs(fcx.ccx.tcx(), resolve_vtables_under_param_substs(fcx.ccx.tcx(),
fcx.param_substs, fcx.param_substs,
vts) vts)
@ -813,25 +814,25 @@ pub fn resolve_vtables_in_fn_ctxt(fcx: &FunctionContext, vts: typeck::vtable_res
pub fn resolve_vtables_under_param_substs(tcx: &ty::ctxt, pub fn resolve_vtables_under_param_substs(tcx: &ty::ctxt,
param_substs: Option<@param_substs>, param_substs: Option<@param_substs>,
vts: typeck::vtable_res) vts: &[typeck::vtable_param_res])
-> typeck::vtable_res { -> typeck::vtable_res {
@vts.iter().map(|ds| vts.iter().map(|ds| {
resolve_param_vtables_under_param_substs(tcx, resolve_param_vtables_under_param_substs(tcx,
param_substs, param_substs,
*ds)) ds.as_slice())
.collect() }).collect()
} }
pub fn resolve_param_vtables_under_param_substs( pub fn resolve_param_vtables_under_param_substs(
tcx: &ty::ctxt, tcx: &ty::ctxt,
param_substs: Option<@param_substs>, param_substs: Option<@param_substs>,
ds: typeck::vtable_param_res) ds: &[typeck::vtable_origin])
-> typeck::vtable_param_res { -> typeck::vtable_param_res {
@ds.iter().map( ds.iter().map(|d| {
|d| resolve_vtable_under_param_substs(tcx, resolve_vtable_under_param_substs(tcx,
param_substs, param_substs,
d)) d)
.collect() }).collect()
} }
@ -841,7 +842,7 @@ pub fn resolve_vtable_under_param_substs(tcx: &ty::ctxt,
vt: &typeck::vtable_origin) vt: &typeck::vtable_origin)
-> typeck::vtable_origin { -> typeck::vtable_origin {
match *vt { match *vt {
typeck::vtable_static(trait_id, ref tys, sub) => { typeck::vtable_static(trait_id, ref tys, ref sub) => {
let tys = match param_substs { let tys = match param_substs {
Some(substs) => { Some(substs) => {
tys.iter().map(|t| { tys.iter().map(|t| {
@ -855,7 +856,7 @@ pub fn resolve_vtable_under_param_substs(tcx: &ty::ctxt,
}; };
typeck::vtable_static( typeck::vtable_static(
trait_id, tys, trait_id, tys,
resolve_vtables_under_param_substs(tcx, param_substs, sub)) resolve_vtables_under_param_substs(tcx, param_substs, sub.as_slice()))
} }
typeck::vtable_param(n_param, n_bound) => { typeck::vtable_param(n_param, n_bound) => {
match param_substs { match param_substs {
@ -881,11 +882,11 @@ pub fn find_vtable(tcx: &ty::ctxt,
n_param, n_bound, ps.repr(tcx)); n_param, n_bound, ps.repr(tcx));
let param_bounds = match n_param { let param_bounds = match n_param {
typeck::param_self => ps.self_vtables.expect("self vtables missing"), typeck::param_self => ps.self_vtables.as_ref().expect("self vtables missing"),
typeck::param_numbered(n) => { typeck::param_numbered(n) => {
let tables = ps.vtables let tables = ps.vtables.as_ref()
.expect("vtables missing where they are needed"); .expect("vtables missing where they are needed");
*tables.get(n) tables.get(n)
} }
}; };
param_bounds.get(n_bound).clone() param_bounds.get(n_bound).clone()

View File

@ -193,21 +193,21 @@ pub fn trans_static_method_callee(bcx: &Block,
name={}", method_id, expr_id, token::get_name(mname)); name={}", method_id, expr_id, token::get_name(mname));
let vtable_key = MethodCall::expr(expr_id); let vtable_key = MethodCall::expr(expr_id);
let vtbls = ccx.tcx.vtable_map.borrow().get_copy(&vtable_key); let vtbls = resolve_vtables_in_fn_ctxt(bcx.fcx, ccx.tcx.vtable_map.borrow()
let vtbls = resolve_vtables_in_fn_ctxt(bcx.fcx, vtbls); .get(&vtable_key).as_slice());
match vtbls.get(bound_index).get(0) { match vtbls.move_iter().nth(bound_index).unwrap().move_iter().nth(0).unwrap() {
&typeck::vtable_static(impl_did, ref rcvr_substs, rcvr_origins) => { typeck::vtable_static(impl_did, rcvr_substs, rcvr_origins) => {
assert!(rcvr_substs.iter().all(|t| !ty::type_needs_infer(*t))); assert!(rcvr_substs.iter().all(|t| !ty::type_needs_infer(*t)));
let mth_id = method_with_name(ccx, impl_did, mname); let mth_id = method_with_name(ccx, impl_did, mname);
let (callee_substs, callee_origins) = let (callee_substs, callee_origins) =
combine_impl_and_methods_tps( combine_impl_and_methods_tps(
bcx, mth_id, ExprId(expr_id), bcx, mth_id, ExprId(expr_id),
rcvr_substs.as_slice(), rcvr_origins); rcvr_substs, rcvr_origins);
let llfn = trans_fn_ref_with_vtables(bcx, mth_id, ExprId(expr_id), let llfn = trans_fn_ref_with_vtables(bcx, mth_id, ExprId(expr_id),
callee_substs.as_slice(), callee_substs,
Some(callee_origins)); Some(callee_origins));
let callee_ty = node_id_type(bcx, expr_id); let callee_ty = node_id_type(bcx, expr_id);
@ -247,7 +247,7 @@ fn trans_monomorphized_callee<'a>(bcx: &'a Block<'a>,
-> Callee<'a> { -> Callee<'a> {
let _icx = push_ctxt("meth::trans_monomorphized_callee"); let _icx = push_ctxt("meth::trans_monomorphized_callee");
match vtbl { match vtbl {
typeck::vtable_static(impl_did, ref rcvr_substs, rcvr_origins) => { typeck::vtable_static(impl_did, rcvr_substs, rcvr_origins) => {
let ccx = bcx.ccx(); let ccx = bcx.ccx();
let mname = ty::trait_method(ccx.tcx(), trait_id, n_method).ident; let mname = ty::trait_method(ccx.tcx(), trait_id, n_method).ident;
let mth_id = method_with_name(bcx.ccx(), impl_did, mname.name); let mth_id = method_with_name(bcx.ccx(), impl_did, mname.name);
@ -257,13 +257,13 @@ fn trans_monomorphized_callee<'a>(bcx: &'a Block<'a>,
let (callee_substs, callee_origins) = let (callee_substs, callee_origins) =
combine_impl_and_methods_tps( combine_impl_and_methods_tps(
bcx, mth_id, MethodCall(method_call), bcx, mth_id, MethodCall(method_call),
rcvr_substs.as_slice(), rcvr_origins); rcvr_substs, rcvr_origins);
// translate the function // translate the function
let llfn = trans_fn_ref_with_vtables(bcx, let llfn = trans_fn_ref_with_vtables(bcx,
mth_id, mth_id,
MethodCall(method_call), MethodCall(method_call),
callee_substs.as_slice(), callee_substs,
Some(callee_origins)); Some(callee_origins));
Callee { bcx: bcx, data: Fn(llfn) } Callee { bcx: bcx, data: Fn(llfn) }
@ -277,9 +277,9 @@ fn trans_monomorphized_callee<'a>(bcx: &'a Block<'a>,
fn combine_impl_and_methods_tps(bcx: &Block, fn combine_impl_and_methods_tps(bcx: &Block,
mth_did: ast::DefId, mth_did: ast::DefId,
node: ExprOrMethodCall, node: ExprOrMethodCall,
rcvr_substs: &[ty::t], rcvr_substs: Vec<ty::t>,
rcvr_origins: typeck::vtable_res) rcvr_origins: typeck::vtable_res)
-> (Vec<ty::t> , typeck::vtable_res) { -> (Vec<ty::t>, typeck::vtable_res) {
/*! /*!
* *
* Creates a concatenated set of substitutions which includes * Creates a concatenated set of substitutions which includes
@ -302,10 +302,13 @@ fn combine_impl_and_methods_tps(bcx: &Block,
let n_m_tps = method.generics.type_param_defs().len(); let n_m_tps = method.generics.type_param_defs().len();
let node_substs = node_id_type_params(bcx, node); let node_substs = node_id_type_params(bcx, node);
debug!("rcvr_substs={:?}", rcvr_substs.repr(ccx.tcx())); debug!("rcvr_substs={:?}", rcvr_substs.repr(ccx.tcx()));
let ty_substs
= Vec::from_slice(rcvr_substs).append(node_substs.tailn(node_substs.len() - n_m_tps));
debug!("n_m_tps={:?}", n_m_tps);
debug!("node_substs={:?}", node_substs.repr(ccx.tcx())); debug!("node_substs={:?}", node_substs.repr(ccx.tcx()));
let mut ty_substs = rcvr_substs;
{
let start = node_substs.len() - n_m_tps;
ty_substs.extend(node_substs.move_iter().skip(start));
}
debug!("n_m_tps={:?}", n_m_tps);
debug!("ty_substs={:?}", ty_substs.repr(ccx.tcx())); debug!("ty_substs={:?}", ty_substs.repr(ccx.tcx()));
@ -315,14 +318,20 @@ fn combine_impl_and_methods_tps(bcx: &Block,
ExprId(id) => MethodCall::expr(id), ExprId(id) => MethodCall::expr(id),
MethodCall(method_call) => method_call MethodCall(method_call) => method_call
}; };
let vtables = node_vtables(bcx, vtable_key); let mut vtables = rcvr_origins;
let r_m_origins = match vtables { match node_vtables(bcx, vtable_key) {
Some(vt) => vt, Some(vt) => {
None => @Vec::from_elem(node_substs.len(), @Vec::new()) let start = vt.len() - n_m_tps;
}; vtables.extend(vt.move_iter().skip(start));
let vtables }
= @Vec::from_slice(rcvr_origins.as_slice()) None => {
.append(r_m_origins.tailn(r_m_origins.len() - n_m_tps)); vtables.extend(range(0, n_m_tps).map(
|_| -> typeck::vtable_param_res {
Vec::new()
}
));
}
}
(ty_substs, vtables) (ty_substs, vtables)
} }
@ -422,10 +431,10 @@ pub fn vtable_id(ccx: &CrateContext,
origin: &typeck::vtable_origin) origin: &typeck::vtable_origin)
-> mono_id { -> mono_id {
match origin { match origin {
&typeck::vtable_static(impl_id, ref substs, sub_vtables) => { &typeck::vtable_static(impl_id, ref substs, ref sub_vtables) => {
let psubsts = param_substs { let psubsts = param_substs {
tys: (*substs).clone(), tys: (*substs).clone(),
vtables: Some(sub_vtables), vtables: Some(sub_vtables.clone()),
self_ty: None, self_ty: None,
self_vtables: None self_vtables: None
}; };
@ -443,10 +452,10 @@ pub fn vtable_id(ccx: &CrateContext,
/// Creates a returns a dynamic vtable for the given type and vtable origin. /// Creates a returns a dynamic vtable for the given type and vtable origin.
/// This is used only for objects. /// This is used only for objects.
pub fn get_vtable(bcx: &Block, fn get_vtable(bcx: &Block,
self_ty: ty::t, self_ty: ty::t,
origins: typeck::vtable_param_res) origins: typeck::vtable_param_res)
-> ValueRef { -> ValueRef {
let ccx = bcx.ccx(); let ccx = bcx.ccx();
let _icx = push_ctxt("meth::get_vtable"); let _icx = push_ctxt("meth::get_vtable");
@ -458,43 +467,33 @@ pub fn get_vtable(bcx: &Block,
} }
// Not in the cache. Actually build it. // Not in the cache. Actually build it.
let mut methods = Vec::new(); let methods = origins.move_iter().flat_map(|origin| {
for origin in origins.iter() { match origin {
match *origin { typeck::vtable_static(id, substs, sub_vtables) => {
typeck::vtable_static(id, ref substs, sub_vtables) => { emit_vtable_methods(bcx, id, substs, sub_vtables).move_iter()
let vtable_methods = emit_vtable_methods(bcx,
id,
substs.as_slice(),
sub_vtables);
for vtable_method in vtable_methods.move_iter() {
methods.push(vtable_method)
}
} }
_ => ccx.sess().bug("get_vtable: expected a static origin"), _ => ccx.sess().bug("get_vtable: expected a static origin"),
} }
} });
// Generate a destructor for the vtable. // Generate a destructor for the vtable.
let drop_glue = glue::get_drop_glue(ccx, self_ty); let drop_glue = glue::get_drop_glue(ccx, self_ty);
let vtable = make_vtable(ccx, drop_glue, methods.as_slice()); let vtable = make_vtable(ccx, drop_glue, methods);
ccx.vtables.borrow_mut().insert(hash_id, vtable); ccx.vtables.borrow_mut().insert(hash_id, vtable);
return vtable; vtable
} }
/// Helper function to declare and initialize the vtable. /// Helper function to declare and initialize the vtable.
pub fn make_vtable(ccx: &CrateContext, pub fn make_vtable<I: Iterator<ValueRef>>(ccx: &CrateContext,
drop_glue: ValueRef, drop_glue: ValueRef,
ptrs: &[ValueRef]) ptrs: I)
-> ValueRef { -> ValueRef {
let _icx = push_ctxt("meth::make_vtable");
let components: Vec<_> = Some(drop_glue).move_iter().chain(ptrs).collect();
unsafe { unsafe {
let _icx = push_ctxt("meth::make_vtable");
let mut components = vec!(drop_glue);
for &ptr in ptrs.iter() {
components.push(ptr)
}
let tbl = C_struct(ccx, components.as_slice(), false); let tbl = C_struct(ccx, components.as_slice(), false);
let sym = token::gensym("vtable"); let sym = token::gensym("vtable");
let vt_gvar = format!("vtable{}", sym).with_c_str(|buf| { let vt_gvar = format!("vtable{}", sym).with_c_str(|buf| {
@ -509,7 +508,7 @@ pub fn make_vtable(ccx: &CrateContext,
fn emit_vtable_methods(bcx: &Block, fn emit_vtable_methods(bcx: &Block,
impl_id: ast::DefId, impl_id: ast::DefId,
substs: &[ty::t], substs: Vec<ty::t>,
vtables: typeck::vtable_res) vtables: typeck::vtable_res)
-> Vec<ValueRef> { -> Vec<ValueRef> {
let ccx = bcx.ccx(); let ccx = bcx.ccx();
@ -539,7 +538,8 @@ fn emit_vtable_methods(bcx: &Block,
token::get_ident(ident)); token::get_ident(ident));
C_null(Type::nil(ccx).ptr_to()) C_null(Type::nil(ccx).ptr_to())
} else { } else {
trans_fn_ref_with_vtables(bcx, m_id, ExprId(0), substs, Some(vtables)) trans_fn_ref_with_vtables(bcx, m_id, ExprId(0),
substs.clone(), Some(vtables.clone()))
} }
}).collect() }).collect()
} }
@ -576,8 +576,12 @@ pub fn trans_trait_cast<'a>(bcx: &'a Block<'a>,
bcx = datum.store_to(bcx, llboxdest); bcx = datum.store_to(bcx, llboxdest);
// Store the vtable into the second half of pair. // Store the vtable into the second half of pair.
let res = *ccx.tcx.vtable_map.borrow().get(&MethodCall::expr(id)); let origins = {
let origins = *resolve_vtables_in_fn_ctxt(bcx.fcx, res).get(0); let vtable_map = ccx.tcx.vtable_map.borrow();
resolve_param_vtables_under_param_substs(ccx.tcx(),
bcx.fcx.param_substs,
vtable_map.get(&MethodCall::expr(id)).get(0).as_slice())
};
let vtable = get_vtable(bcx, v_ty, origins); let vtable = get_vtable(bcx, v_ty, origins);
let llvtabledest = GEPi(bcx, lldest, [0u, abi::trt_field_vtable]); let llvtabledest = GEPi(bcx, lldest, [0u, abi::trt_field_vtable]);
let llvtabledest = PointerCast(bcx, llvtabledest, val_ty(vtable).ptr_to()); let llvtabledest = PointerCast(bcx, llvtabledest, val_ty(vtable).ptr_to());

View File

@ -296,7 +296,7 @@ pub fn make_mono_id(ccx: &CrateContext,
// .collect() to work. // .collect() to work.
let substs_iter = substs.self_ty.iter().chain(substs.tys.iter()); let substs_iter = substs.self_ty.iter().chain(substs.tys.iter());
let precise_param_ids: Vec<(ty::t, Option<@Vec<mono_id> >)> = match substs.vtables { let precise_param_ids: Vec<(ty::t, Option<@Vec<mono_id> >)> = match substs.vtables {
Some(vts) => { Some(ref vts) => {
debug!("make_mono_id vtables={} substs={}", debug!("make_mono_id vtables={} substs={}",
vts.repr(ccx.tcx()), substs.tys.repr(ccx.tcx())); vts.repr(ccx.tcx()), substs.tys.repr(ccx.tcx()));
let vts_iter = substs.self_vtables.iter().chain(vts.iter()); let vts_iter = substs.self_vtables.iter().chain(vts.iter());

View File

@ -1134,8 +1134,8 @@ pub fn mk_ctxt(s: Session,
upvar_borrow_map: RefCell::new(HashMap::new()), upvar_borrow_map: RefCell::new(HashMap::new()),
extern_const_statics: RefCell::new(DefIdMap::new()), extern_const_statics: RefCell::new(DefIdMap::new()),
extern_const_variants: RefCell::new(DefIdMap::new()), extern_const_variants: RefCell::new(DefIdMap::new()),
method_map: @RefCell::new(FnvHashMap::new()), method_map: RefCell::new(FnvHashMap::new()),
vtable_map: @RefCell::new(FnvHashMap::new()), vtable_map: RefCell::new(FnvHashMap::new()),
} }
} }

View File

@ -265,8 +265,8 @@ impl<'a> Inherited<'a> {
node_types: RefCell::new(NodeMap::new()), node_types: RefCell::new(NodeMap::new()),
node_type_substs: RefCell::new(NodeMap::new()), node_type_substs: RefCell::new(NodeMap::new()),
adjustments: RefCell::new(NodeMap::new()), adjustments: RefCell::new(NodeMap::new()),
method_map: @RefCell::new(FnvHashMap::new()), method_map: RefCell::new(FnvHashMap::new()),
vtable_map: @RefCell::new(FnvHashMap::new()), vtable_map: RefCell::new(FnvHashMap::new()),
upvar_borrow_map: RefCell::new(HashMap::new()), upvar_borrow_map: RefCell::new(HashMap::new()),
} }
} }

View File

@ -29,7 +29,6 @@ use util::ppaux::Repr;
use collections::HashSet; use collections::HashSet;
use std::cell::RefCell; use std::cell::RefCell;
use std::result;
use syntax::ast; use syntax::ast;
use syntax::ast_util; use syntax::ast_util;
use syntax::codemap::Span; use syntax::codemap::Span;
@ -112,7 +111,7 @@ fn lookup_vtables(vcx: &VtableContext,
type_param_defs.repr(vcx.tcx()), type_param_defs.repr(vcx.tcx()),
substs.repr(vcx.tcx()), substs.repr(vcx.tcx()),
result.repr(vcx.tcx())); result.repr(vcx.tcx()));
@result result
} }
fn lookup_vtables_for_param(vcx: &VtableContext, fn lookup_vtables_for_param(vcx: &VtableContext,
@ -170,7 +169,7 @@ fn lookup_vtables_for_param(vcx: &VtableContext,
ty.repr(vcx.tcx()), ty.repr(vcx.tcx()),
param_result.repr(vcx.tcx())); param_result.repr(vcx.tcx()));
return @param_result; param_result
} }
fn relate_trait_refs(vcx: &VtableContext, fn relate_trait_refs(vcx: &VtableContext,
@ -189,8 +188,8 @@ fn relate_trait_refs(vcx: &VtableContext,
infer::RelateTraitRefs(span), infer::RelateTraitRefs(span),
act_trait_ref, act_trait_ref,
exp_trait_ref) { exp_trait_ref) {
result::Ok(()) => {} // Ok. Ok(()) => {} // Ok.
result::Err(ref err) => { Err(ref err) => {
// There is an error, but we need to do some work to make // There is an error, but we need to do some work to make
// the message good. // the message good.
// Resolve any type vars in the trait refs // Resolve any type vars in the trait refs
@ -368,8 +367,8 @@ fn search_for_vtable(vcx: &VtableContext,
infer::RelateSelfType(span), infer::RelateSelfType(span),
ty, ty,
for_ty) { for_ty) {
result::Err(_) => continue, Err(_) => continue,
result::Ok(()) => () Ok(()) => ()
} }
// Now, in the previous example, for_ty is bound to // Now, in the previous example, for_ty is bound to
@ -583,7 +582,7 @@ pub fn early_resolve_expr(ex: &ast::Expr, fcx: &FnCtxt, is_early: bool) {
is_early); is_early);
if !is_early { if !is_early {
insert_vtables(fcx, MethodCall::expr(ex.id), @vec!(vtables)); insert_vtables(fcx, MethodCall::expr(ex.id), vec!(vtables));
} }
// Now, if this is &trait, we need to link the // Now, if this is &trait, we need to link the
@ -743,7 +742,7 @@ pub fn resolve_impl(tcx: &ty::ctxt,
[], [],
impl_item.id); impl_item.id);
let impl_trait_ref = @impl_trait_ref.subst(tcx, &param_env.free_substs); let impl_trait_ref = impl_trait_ref.subst(tcx, &param_env.free_substs);
let infcx = &infer::new_infer_ctxt(tcx); let infcx = &infer::new_infer_ctxt(tcx);
let vcx = VtableContext { infcx: infcx, param_env: &param_env }; let vcx = VtableContext { infcx: infcx, param_env: &param_env };
@ -761,7 +760,7 @@ pub fn resolve_impl(tcx: &ty::ctxt,
// but that falls out of doing this. // but that falls out of doing this.
let param_bounds = ty::ParamBounds { let param_bounds = ty::ParamBounds {
builtin_bounds: ty::EmptyBuiltinBounds(), builtin_bounds: ty::EmptyBuiltinBounds(),
trait_bounds: vec!(impl_trait_ref) trait_bounds: vec!(@impl_trait_ref)
}; };
let t = ty::node_id_to_type(tcx, impl_item.id); let t = ty::node_id_to_type(tcx, impl_item.id);
let t = t.subst(tcx, &param_env.free_substs); let t = t.subst(tcx, &param_env.free_substs);

View File

@ -51,44 +51,31 @@ fn resolve_type_vars_in_type(fcx: &FnCtxt, sp: Span, typ: ty::t)
} }
} }
fn resolve_type_vars_in_types(fcx: &FnCtxt, sp: Span, tys: &[ty::t])
-> Vec<ty::t> {
tys.iter().map(|t| {
match resolve_type_vars_in_type(fcx, sp, *t) {
Some(t1) => t1,
None => ty::mk_err()
}
}).collect()
}
fn resolve_method_map_entry(wbcx: &mut WbCtxt, sp: Span, method_call: MethodCall) { fn resolve_method_map_entry(wbcx: &mut WbCtxt, sp: Span, method_call: MethodCall) {
let fcx = wbcx.fcx; let fcx = wbcx.fcx;
let tcx = fcx.ccx.tcx; let tcx = fcx.ccx.tcx;
// Resolve any method map entry // Resolve any method map entry
match fcx.inh.method_map.borrow().find(&method_call) { match fcx.inh.method_map.borrow_mut().pop(&method_call) {
Some(method) => { Some(method) => {
debug!("writeback::resolve_method_map_entry(call={:?}, entry={:?})", debug!("writeback::resolve_method_map_entry(call={:?}, entry={:?})",
method_call, method.repr(tcx)); method_call, method.repr(tcx));
let method_ty = match resolve_type_vars_in_type(fcx, sp, method.ty) {
Some(t) => t,
None => {
wbcx.success = false;
return;
}
};
let mut new_tps = Vec::new();
for &subst in method.substs.tps.iter() {
match resolve_type_vars_in_type(fcx, sp, subst) {
Some(t) => new_tps.push(t),
None => { wbcx.success = false; return; }
}
}
let new_method = MethodCallee { let new_method = MethodCallee {
origin: method.origin, origin: method.origin,
ty: method_ty, ty: match resolve_type_vars_in_type(fcx, sp, method.ty) {
Some(t) => t,
None => {
wbcx.success = false;
return;
}
},
substs: ty::substs { substs: ty::substs {
tps: new_tps, tps: method.substs.tps.move_iter().map(|subst| {
match resolve_type_vars_in_type(fcx, sp, subst) {
Some(t) => t,
None => { wbcx.success = false; ty::mk_err() }
}
}).collect(),
regions: ty::ErasedRegions, regions: ty::ErasedRegions,
self_ty: None self_ty: None
} }
@ -101,46 +88,46 @@ fn resolve_method_map_entry(wbcx: &mut WbCtxt, sp: Span, method_call: MethodCall
fn resolve_vtable_map_entry(fcx: &FnCtxt, sp: Span, vtable_key: MethodCall) { fn resolve_vtable_map_entry(fcx: &FnCtxt, sp: Span, vtable_key: MethodCall) {
// Resolve any vtable map entry // Resolve any vtable map entry
match fcx.inh.vtable_map.borrow().find_copy(&vtable_key) { match fcx.inh.vtable_map.borrow_mut().pop(&vtable_key) {
Some(origins) => { Some(origins) => {
let r_origins = resolve_origins(fcx, sp, origins); let r_origins = resolve_origins(fcx, sp, origins);
fcx.tcx().vtable_map.borrow_mut().insert(vtable_key, r_origins);
debug!("writeback::resolve_vtable_map_entry(vtable_key={}, vtables={:?})", debug!("writeback::resolve_vtable_map_entry(vtable_key={}, vtables={:?})",
vtable_key, r_origins.repr(fcx.tcx())); vtable_key, r_origins.repr(fcx.tcx()));
fcx.tcx().vtable_map.borrow_mut().insert(vtable_key, r_origins);
} }
None => {} None => {}
} }
fn resolve_origins(fcx: &FnCtxt, sp: Span, fn resolve_origins(fcx: &FnCtxt, sp: Span,
vtbls: vtable_res) -> vtable_res { vtbls: vtable_res) -> vtable_res {
@vtbls.iter().map(|os| @os.iter().map(|origin| { vtbls.move_iter().map(|os| os.move_iter().map(|origin| {
match origin { match origin {
&vtable_static(def_id, ref tys, origins) => { vtable_static(def_id, tys, origins) => {
let r_tys = resolve_type_vars_in_types(fcx, let r_tys = tys.move_iter().map(|t| {
sp, match resolve_type_vars_in_type(fcx, sp, t) {
tys.as_slice()); Some(t1) => t1,
None => ty::mk_err()
}
}).collect();
let r_origins = resolve_origins(fcx, sp, origins); let r_origins = resolve_origins(fcx, sp, origins);
vtable_static(def_id, r_tys, r_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)
}
} }
}).collect()).collect() }).collect()).collect()
} }
} }
fn resolve_type_vars_for_node(wbcx: &mut WbCtxt, sp: Span, id: ast::NodeId) fn resolve_type_vars_for_node(wbcx: &mut WbCtxt, sp: Span, id: ast::NodeId) {
-> Option<ty::t> {
let fcx = wbcx.fcx; let fcx = wbcx.fcx;
let tcx = fcx.ccx.tcx; let tcx = fcx.ccx.tcx;
// Resolve any borrowings for the node with id `id` // Resolve any borrowings for the node with id `id`
match fcx.inh.adjustments.borrow().find_copy(&id) { let resolved_adj = match fcx.inh.adjustments.borrow_mut().pop(&id) {
None => (), None => None,
Some(adjustment) => { Some(adjustment) => {
match *adjustment { Some(match *adjustment {
ty::AutoAddEnv(store) => { ty::AutoAddEnv(store) => {
let r = match store { let r = match store {
ty::RegionTraitStore(r, _) => r, ty::RegionTraitStore(r, _) => r,
@ -156,6 +143,8 @@ fn resolve_type_vars_for_node(wbcx: &mut WbCtxt, sp: Span, id: ast::NodeId)
format!("cannot resolve bound for closure: \ format!("cannot resolve bound for closure: \
{}", {}",
infer::fixup_err_to_str(e))); infer::fixup_err_to_str(e)));
wbcx.success = false;
return;
} }
Ok(r1) => { Ok(r1) => {
// FIXME(eddyb) #2190 Allow only statically resolved // FIXME(eddyb) #2190 Allow only statically resolved
@ -170,15 +159,12 @@ fn resolve_type_vars_for_node(wbcx: &mut WbCtxt, sp: Span, id: ast::NodeId)
"cannot coerce non-statically resolved bare fn") "cannot coerce non-statically resolved bare fn")
} }
let resolved_adj = @ty::AutoAddEnv(match store { ty::AutoAddEnv(match store {
ty::RegionTraitStore(..) => { ty::RegionTraitStore(..) => {
ty::RegionTraitStore(r1, ast::MutMutable) ty::RegionTraitStore(r1, ast::MutMutable)
} }
ty::UniqTraitStore => ty::UniqTraitStore ty::UniqTraitStore => ty::UniqTraitStore
}); })
debug!("Adjustments for node {}: {:?}",
id, resolved_adj);
tcx.adjustments.borrow_mut().insert(id, resolved_adj);
} }
} }
} }
@ -190,42 +176,38 @@ fn resolve_type_vars_for_node(wbcx: &mut WbCtxt, sp: Span, id: ast::NodeId)
resolve_vtable_map_entry(wbcx.fcx, sp, method_call); resolve_vtable_map_entry(wbcx.fcx, sp, method_call);
} }
let fixup_region = |r| { ty::AutoDerefRef(ty::AutoDerefRef {
match resolve_region(fcx.infcx(),
r,
resolve_all | force_all) {
Ok(r1) => r1,
Err(e) => {
// This should not, I think, happen.
tcx.sess.span_err(
sp,
format!("cannot resolve scope of borrow: \
{}",
infer::fixup_err_to_str(e)));
r
}
}
};
let resolved_autoref = match adj.autoref {
None => None,
Some(ref r) => Some(r.map_region(fixup_region))
};
let resolved_adj = @ty::AutoDerefRef(ty::AutoDerefRef {
autoderefs: adj.autoderefs, autoderefs: adj.autoderefs,
autoref: resolved_autoref, autoref: adj.autoref.map(|r| r.map_region(|r| {
}); match resolve_region(fcx.infcx(), r,
debug!("Adjustments for node {}: {:?}", id, resolved_adj); resolve_all | force_all) {
tcx.adjustments.borrow_mut().insert(id, resolved_adj); Ok(r1) => r1,
Err(e) => {
// This should not, I think, happen.
tcx.sess.span_err(
sp,
format!("cannot resolve scope of borrow: \
{}",
infer::fixup_err_to_str(e)));
r
}
}
})),
})
} }
ty::AutoObject(..) => { adjustment => adjustment
debug!("Adjustments for node {}: {:?}", id, adjustment); })
tcx.adjustments.borrow_mut().insert(id, adjustment);
}
}
} }
};
debug!("Adjustments for node {}: {:?}",
id, resolved_adj);
match resolved_adj {
Some(adj) => {
tcx.adjustments.borrow_mut().insert(id, @adj);
}
None => {}
} }
// Resolve the type of the node with id `id` // Resolve the type of the node with id `id`
@ -233,26 +215,23 @@ fn resolve_type_vars_for_node(wbcx: &mut WbCtxt, sp: Span, id: ast::NodeId)
match resolve_type_vars_in_type(fcx, sp, n_ty) { match resolve_type_vars_in_type(fcx, sp, n_ty) {
None => { None => {
wbcx.success = false; wbcx.success = false;
return None;
} }
Some(t) => { Some(t) => {
debug!("resolve_type_vars_for_node(id={}, n_ty={}, t={})", debug!("resolve_type_vars_for_node(id={}, n_ty={}, t={})",
id, ppaux::ty_to_str(tcx, n_ty), ppaux::ty_to_str(tcx, t)); id, ppaux::ty_to_str(tcx, n_ty), ppaux::ty_to_str(tcx, t));
write_ty_to_tcx(tcx, id, t); write_ty_to_tcx(tcx, id, t);
let mut ret = Some(t);
fcx.opt_node_ty_substs(id, |substs| { fcx.opt_node_ty_substs(id, |substs| {
let mut new_tps = Vec::new(); let mut new_tps = Vec::new();
for subst in substs.tps.iter() { for subst in substs.tps.iter() {
match resolve_type_vars_in_type(fcx, sp, *subst) { match resolve_type_vars_in_type(fcx, sp, *subst) {
Some(t) => new_tps.push(t), Some(t) => new_tps.push(t),
None => { wbcx.success = false; ret = None; break } None => { wbcx.success = false; break }
} }
} }
write_substs_to_tcx(tcx, id, new_tps); write_substs_to_tcx(tcx, id, new_tps);
ret.is_some() wbcx.success
}); });
ret
} }
} }
} }

View File

@ -171,11 +171,11 @@ impl MethodCall {
// maps from an expression id that corresponds to a method call to the details // maps from an expression id that corresponds to a method call to the details
// of the method to be invoked // of the method to be invoked
pub type MethodMap = @RefCell<FnvHashMap<MethodCall, MethodCallee>>; pub type MethodMap = RefCell<FnvHashMap<MethodCall, MethodCallee>>;
pub type vtable_param_res = @Vec<vtable_origin> ; pub type vtable_param_res = Vec<vtable_origin>;
// Resolutions for bounds of all parameters, left to right, for a given path. // Resolutions for bounds of all parameters, left to right, for a given path.
pub type vtable_res = @Vec<vtable_param_res> ; pub type vtable_res = Vec<vtable_param_res>;
#[deriving(Clone)] #[deriving(Clone)]
pub enum vtable_origin { pub enum vtable_origin {
@ -184,7 +184,7 @@ pub enum vtable_origin {
from whence comes the vtable, and tys are the type substs. from whence comes the vtable, and tys are the type substs.
vtable_res is the vtable itself vtable_res is the vtable itself
*/ */
vtable_static(ast::DefId, Vec<ty::t> , vtable_res), vtable_static(ast::DefId, Vec<ty::t>, vtable_res),
/* /*
Dynamic vtable, comes from a parameter that has a bound on it: Dynamic vtable, comes from a parameter that has a bound on it:
@ -215,7 +215,7 @@ impl Repr for vtable_origin {
} }
} }
pub type vtable_map = @RefCell<FnvHashMap<MethodCall, vtable_res>>; pub type vtable_map = RefCell<FnvHashMap<MethodCall, vtable_res>>;
// Information about the vtable resolutions for a trait impl. // Information about the vtable resolutions for a trait impl.