rustc: de-@ method and vtable maps.
This commit is contained in:
parent
158d7a19b3
commit
c9bf84333d
@ -146,8 +146,8 @@ fn encode_impl_vtables(ebml_w: &mut Encoder,
|
||||
ecx: &EncodeContext,
|
||||
vtables: &typeck::impl_res) {
|
||||
ebml_w.start_tag(tag_item_impl_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_res(ecx, ebml_w, &vtables.trait_vtables);
|
||||
astencode::encode_vtable_param_res(ecx, ebml_w, &vtables.self_vtables);
|
||||
ebml_w.end_tag();
|
||||
}
|
||||
|
||||
|
@ -658,7 +658,7 @@ impl tr for MethodOrigin {
|
||||
fn encode_vtable_res_with_key(ecx: &e::EncodeContext,
|
||||
ebml_w: &mut Encoder,
|
||||
autoderef: u32,
|
||||
dr: typeck::vtable_res) {
|
||||
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)
|
||||
@ -671,19 +671,19 @@ fn encode_vtable_res_with_key(ecx: &e::EncodeContext,
|
||||
|
||||
pub fn encode_vtable_res(ecx: &e::EncodeContext,
|
||||
ebml_w: &mut Encoder,
|
||||
dr: typeck::vtable_res) {
|
||||
dr: &typeck::vtable_res) {
|
||||
// can't autogenerate this code because automatic code of
|
||||
// ty::t doesn't work, and there is no way (atm) to have
|
||||
// hand-written encoding routines combine with auto-generated
|
||||
// ones. perhaps we should fix this.
|
||||
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()
|
||||
}
|
||||
|
||||
pub fn encode_vtable_param_res(ecx: &e::EncodeContext,
|
||||
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| {
|
||||
Ok(encode_vtable_origin(ecx, ebml_w, vtable_origin))
|
||||
}).unwrap()
|
||||
@ -695,7 +695,7 @@ pub fn encode_vtable_origin(ecx: &e::EncodeContext,
|
||||
vtable_origin: &typeck::vtable_origin) {
|
||||
ebml_w.emit_enum("vtable_origin", |ebml_w| {
|
||||
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_arg(0u, |ebml_w| {
|
||||
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,
|
||||
tcx: &ty::ctxt, cdata: @cstore::crate_metadata)
|
||||
-> typeck::vtable_res {
|
||||
@self.read_to_vec(|this|
|
||||
Ok(this.read_vtable_param_res(tcx, cdata)))
|
||||
.unwrap()
|
||||
.move_iter()
|
||||
.collect()
|
||||
self.read_to_vec(|this| Ok(this.read_vtable_param_res(tcx, cdata)))
|
||||
.unwrap().move_iter().collect()
|
||||
}
|
||||
|
||||
fn read_vtable_param_res(&mut self,
|
||||
tcx: &ty::ctxt, cdata: @cstore::crate_metadata)
|
||||
-> typeck::vtable_param_res {
|
||||
@self.read_to_vec(|this|
|
||||
Ok(this.read_vtable_origin(tcx, cdata)))
|
||||
.unwrap()
|
||||
.move_iter()
|
||||
.collect()
|
||||
self.read_to_vec(|this| Ok(this.read_vtable_origin(tcx, cdata)))
|
||||
.unwrap().move_iter().collect()
|
||||
}
|
||||
|
||||
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.id(id);
|
||||
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.tag(c::tag_table_val, |ebml_w| {
|
||||
encode_vtable_res_with_key(ecx, ebml_w,
|
||||
method_call.autoderef, *dr);
|
||||
method_call.autoderef, dr);
|
||||
})
|
||||
})
|
||||
}
|
||||
|
@ -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()),
|
||||
vtables.repr(bcx.tcx()));
|
||||
trans_fn_ref_with_vtables(bcx, def_id, node,
|
||||
type_params.as_slice(),
|
||||
type_params,
|
||||
vtables)
|
||||
}
|
||||
|
||||
fn trans_fn_ref_with_vtables_to_callee<'a>(bcx: &'a Block<'a>,
|
||||
def_id: ast::DefId,
|
||||
ref_id: ast::NodeId,
|
||||
type_params: &[ty::t],
|
||||
type_params: Vec<ty::t>,
|
||||
vtables: Option<typeck::vtable_res>)
|
||||
-> Callee<'a> {
|
||||
Callee {bcx: bcx,
|
||||
@ -206,29 +206,32 @@ fn resolve_default_method_vtables(bcx: &Block,
|
||||
let param_substs = Some(@param_substs {
|
||||
tys: substs.tps.clone(),
|
||||
self_ty: substs.self_ty,
|
||||
vtables: impl_vtables,
|
||||
vtables: impl_vtables.clone(),
|
||||
self_vtables: None
|
||||
});
|
||||
|
||||
let trait_vtables_fixed = resolve_vtables_under_param_substs(
|
||||
bcx.tcx(), param_substs, impl_res.trait_vtables);
|
||||
let mut param_vtables = resolve_vtables_under_param_substs(
|
||||
bcx.tcx(), param_substs, impl_res.trait_vtables.as_slice());
|
||||
|
||||
// Now we pull any vtables for parameters on the actual method.
|
||||
let num_method_vtables = method.generics.type_param_defs().len();
|
||||
let method_vtables = match impl_vtables {
|
||||
Some(vtables) => {
|
||||
match impl_vtables {
|
||||
Some(ref vtables) => {
|
||||
let num_impl_type_parameters =
|
||||
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())
|
||||
};
|
||||
|
||||
let method_vtables = method_vtables.as_slice();
|
||||
let param_vtables = @((*trait_vtables_fixed).clone().append(method_vtables));
|
||||
None => {
|
||||
param_vtables.extend(range(0, num_method_vtables).map(
|
||||
|_| -> typeck::vtable_param_res {
|
||||
Vec::new()
|
||||
}
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
@ -238,7 +241,7 @@ pub fn trans_fn_ref_with_vtables(
|
||||
bcx: &Block, //
|
||||
def_id: ast::DefId, // def id of fn
|
||||
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
|
||||
-> ValueRef {
|
||||
/*!
|
||||
@ -273,9 +276,11 @@ pub fn trans_fn_ref_with_vtables(
|
||||
// Polytype of the function item (may have type params)
|
||||
let fn_tpt = ty::lookup_item_type(tcx, def_id);
|
||||
|
||||
let substs = ty::substs { regions: ty::ErasedRegions,
|
||||
self_ty: None,
|
||||
tps: /*bad*/ Vec::from_slice(type_params) };
|
||||
let substs = ty::substs {
|
||||
regions: ty::ErasedRegions,
|
||||
self_ty: None,
|
||||
tps: type_params
|
||||
};
|
||||
|
||||
// Load the info for the appropriate trait if necessary.
|
||||
match ty::trait_of_method(tcx, def_id) {
|
||||
@ -318,19 +323,20 @@ pub fn trans_fn_ref_with_vtables(
|
||||
// And compose them
|
||||
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) =
|
||||
resolve_default_method_vtables(bcx, impl_id,
|
||||
method, &substs, vtables);
|
||||
|
||||
debug!("trans_fn_with_vtables - default method: \
|
||||
substs = {}, trait_subst = {}, \
|
||||
first_subst = {}, new_subst = {}, \
|
||||
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));
|
||||
|
||||
(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 that is inlined from a different crate, we want to reemit the
|
||||
// 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
|
||||
} else if def_id.krate == ast::LOCAL_CRATE {
|
||||
let map_node = session::expect(
|
||||
@ -504,7 +510,7 @@ pub fn trans_lang_call<'a>(
|
||||
trans_fn_ref_with_vtables_to_callee(bcx,
|
||||
did,
|
||||
0,
|
||||
[],
|
||||
vec!(),
|
||||
None)
|
||||
},
|
||||
ArgVals(args),
|
||||
|
@ -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)
|
||||
-> Option<typeck::vtable_res> {
|
||||
let vtable_map = bcx.tcx().vtable_map.borrow();
|
||||
let raw_vtables = vtable_map.find(&id);
|
||||
raw_vtables.map(|vts| resolve_vtables_in_fn_ctxt(bcx.fcx, *vts))
|
||||
bcx.tcx().vtable_map.borrow().find(&id).map(|vts| {
|
||||
resolve_vtables_in_fn_ctxt(bcx.fcx, vts.as_slice())
|
||||
})
|
||||
}
|
||||
|
||||
// Apply the typaram substitutions in the FunctionContext to some
|
||||
// vtables. This should eliminate any vtable_params.
|
||||
pub fn resolve_vtables_in_fn_ctxt(fcx: &FunctionContext, vts: typeck::vtable_res)
|
||||
-> typeck::vtable_res {
|
||||
pub fn resolve_vtables_in_fn_ctxt(fcx: &FunctionContext,
|
||||
vts: &[typeck::vtable_param_res])
|
||||
-> typeck::vtable_res {
|
||||
resolve_vtables_under_param_substs(fcx.ccx.tcx(),
|
||||
fcx.param_substs,
|
||||
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,
|
||||
param_substs: Option<@param_substs>,
|
||||
vts: typeck::vtable_res)
|
||||
-> typeck::vtable_res {
|
||||
@vts.iter().map(|ds|
|
||||
vts: &[typeck::vtable_param_res])
|
||||
-> typeck::vtable_res {
|
||||
vts.iter().map(|ds| {
|
||||
resolve_param_vtables_under_param_substs(tcx,
|
||||
param_substs,
|
||||
*ds))
|
||||
.collect()
|
||||
ds.as_slice())
|
||||
}).collect()
|
||||
}
|
||||
|
||||
pub fn resolve_param_vtables_under_param_substs(
|
||||
tcx: &ty::ctxt,
|
||||
param_substs: Option<@param_substs>,
|
||||
ds: typeck::vtable_param_res)
|
||||
ds: &[typeck::vtable_origin])
|
||||
-> typeck::vtable_param_res {
|
||||
@ds.iter().map(
|
||||
|d| resolve_vtable_under_param_substs(tcx,
|
||||
param_substs,
|
||||
d))
|
||||
.collect()
|
||||
ds.iter().map(|d| {
|
||||
resolve_vtable_under_param_substs(tcx,
|
||||
param_substs,
|
||||
d)
|
||||
}).collect()
|
||||
}
|
||||
|
||||
|
||||
@ -841,7 +842,7 @@ pub fn resolve_vtable_under_param_substs(tcx: &ty::ctxt,
|
||||
vt: &typeck::vtable_origin)
|
||||
-> typeck::vtable_origin {
|
||||
match *vt {
|
||||
typeck::vtable_static(trait_id, ref tys, sub) => {
|
||||
typeck::vtable_static(trait_id, ref tys, ref sub) => {
|
||||
let tys = match param_substs {
|
||||
Some(substs) => {
|
||||
tys.iter().map(|t| {
|
||||
@ -855,7 +856,7 @@ pub fn resolve_vtable_under_param_substs(tcx: &ty::ctxt,
|
||||
};
|
||||
typeck::vtable_static(
|
||||
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) => {
|
||||
match param_substs {
|
||||
@ -881,11 +882,11 @@ pub fn find_vtable(tcx: &ty::ctxt,
|
||||
n_param, n_bound, ps.repr(tcx));
|
||||
|
||||
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) => {
|
||||
let tables = ps.vtables
|
||||
let tables = ps.vtables.as_ref()
|
||||
.expect("vtables missing where they are needed");
|
||||
*tables.get(n)
|
||||
tables.get(n)
|
||||
}
|
||||
};
|
||||
param_bounds.get(n_bound).clone()
|
||||
|
@ -193,21 +193,21 @@ pub fn trans_static_method_callee(bcx: &Block,
|
||||
name={}", method_id, expr_id, token::get_name(mname));
|
||||
|
||||
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, vtbls);
|
||||
let vtbls = resolve_vtables_in_fn_ctxt(bcx.fcx, ccx.tcx.vtable_map.borrow()
|
||||
.get(&vtable_key).as_slice());
|
||||
|
||||
match vtbls.get(bound_index).get(0) {
|
||||
&typeck::vtable_static(impl_did, ref rcvr_substs, rcvr_origins) => {
|
||||
match vtbls.move_iter().nth(bound_index).unwrap().move_iter().nth(0).unwrap() {
|
||||
typeck::vtable_static(impl_did, rcvr_substs, rcvr_origins) => {
|
||||
assert!(rcvr_substs.iter().all(|t| !ty::type_needs_infer(*t)));
|
||||
|
||||
let mth_id = method_with_name(ccx, impl_did, mname);
|
||||
let (callee_substs, callee_origins) =
|
||||
combine_impl_and_methods_tps(
|
||||
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),
|
||||
callee_substs.as_slice(),
|
||||
callee_substs,
|
||||
Some(callee_origins));
|
||||
|
||||
let callee_ty = node_id_type(bcx, expr_id);
|
||||
@ -247,7 +247,7 @@ fn trans_monomorphized_callee<'a>(bcx: &'a Block<'a>,
|
||||
-> Callee<'a> {
|
||||
let _icx = push_ctxt("meth::trans_monomorphized_callee");
|
||||
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 mname = ty::trait_method(ccx.tcx(), trait_id, n_method).ident;
|
||||
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) =
|
||||
combine_impl_and_methods_tps(
|
||||
bcx, mth_id, MethodCall(method_call),
|
||||
rcvr_substs.as_slice(), rcvr_origins);
|
||||
rcvr_substs, rcvr_origins);
|
||||
|
||||
// translate the function
|
||||
let llfn = trans_fn_ref_with_vtables(bcx,
|
||||
mth_id,
|
||||
MethodCall(method_call),
|
||||
callee_substs.as_slice(),
|
||||
callee_substs,
|
||||
Some(callee_origins));
|
||||
|
||||
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,
|
||||
mth_did: ast::DefId,
|
||||
node: ExprOrMethodCall,
|
||||
rcvr_substs: &[ty::t],
|
||||
rcvr_substs: Vec<ty::t>,
|
||||
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
|
||||
@ -302,10 +302,13 @@ fn combine_impl_and_methods_tps(bcx: &Block,
|
||||
let n_m_tps = method.generics.type_param_defs().len();
|
||||
let node_substs = node_id_type_params(bcx, node);
|
||||
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()));
|
||||
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()));
|
||||
|
||||
|
||||
@ -315,14 +318,20 @@ fn combine_impl_and_methods_tps(bcx: &Block,
|
||||
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())
|
||||
};
|
||||
let vtables
|
||||
= @Vec::from_slice(rcvr_origins.as_slice())
|
||||
.append(r_m_origins.tailn(r_m_origins.len() - n_m_tps));
|
||||
let mut vtables = rcvr_origins;
|
||||
match node_vtables(bcx, vtable_key) {
|
||||
Some(vt) => {
|
||||
let start = vt.len() - n_m_tps;
|
||||
vtables.extend(vt.move_iter().skip(start));
|
||||
}
|
||||
None => {
|
||||
vtables.extend(range(0, n_m_tps).map(
|
||||
|_| -> typeck::vtable_param_res {
|
||||
Vec::new()
|
||||
}
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
(ty_substs, vtables)
|
||||
}
|
||||
@ -422,10 +431,10 @@ pub fn vtable_id(ccx: &CrateContext,
|
||||
origin: &typeck::vtable_origin)
|
||||
-> mono_id {
|
||||
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 {
|
||||
tys: (*substs).clone(),
|
||||
vtables: Some(sub_vtables),
|
||||
vtables: Some(sub_vtables.clone()),
|
||||
self_ty: 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.
|
||||
/// This is used only for objects.
|
||||
pub fn get_vtable(bcx: &Block,
|
||||
self_ty: ty::t,
|
||||
origins: typeck::vtable_param_res)
|
||||
-> ValueRef {
|
||||
fn get_vtable(bcx: &Block,
|
||||
self_ty: ty::t,
|
||||
origins: typeck::vtable_param_res)
|
||||
-> ValueRef {
|
||||
let ccx = bcx.ccx();
|
||||
let _icx = push_ctxt("meth::get_vtable");
|
||||
|
||||
@ -458,43 +467,33 @@ pub fn get_vtable(bcx: &Block,
|
||||
}
|
||||
|
||||
// Not in the cache. Actually build it.
|
||||
let mut methods = Vec::new();
|
||||
for origin in origins.iter() {
|
||||
match *origin {
|
||||
typeck::vtable_static(id, ref substs, sub_vtables) => {
|
||||
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)
|
||||
}
|
||||
let methods = origins.move_iter().flat_map(|origin| {
|
||||
match origin {
|
||||
typeck::vtable_static(id, substs, sub_vtables) => {
|
||||
emit_vtable_methods(bcx, id, substs, sub_vtables).move_iter()
|
||||
}
|
||||
_ => ccx.sess().bug("get_vtable: expected a static origin"),
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Generate a destructor for the vtable.
|
||||
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);
|
||||
return vtable;
|
||||
vtable
|
||||
}
|
||||
|
||||
/// Helper function to declare and initialize the vtable.
|
||||
pub fn make_vtable(ccx: &CrateContext,
|
||||
drop_glue: ValueRef,
|
||||
ptrs: &[ValueRef])
|
||||
-> ValueRef {
|
||||
pub fn make_vtable<I: Iterator<ValueRef>>(ccx: &CrateContext,
|
||||
drop_glue: ValueRef,
|
||||
ptrs: I)
|
||||
-> ValueRef {
|
||||
let _icx = push_ctxt("meth::make_vtable");
|
||||
|
||||
let components: Vec<_> = Some(drop_glue).move_iter().chain(ptrs).collect();
|
||||
|
||||
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 sym = token::gensym("vtable");
|
||||
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,
|
||||
impl_id: ast::DefId,
|
||||
substs: &[ty::t],
|
||||
substs: Vec<ty::t>,
|
||||
vtables: typeck::vtable_res)
|
||||
-> Vec<ValueRef> {
|
||||
let ccx = bcx.ccx();
|
||||
@ -539,7 +538,8 @@ fn emit_vtable_methods(bcx: &Block,
|
||||
token::get_ident(ident));
|
||||
C_null(Type::nil(ccx).ptr_to())
|
||||
} 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()
|
||||
}
|
||||
@ -576,8 +576,12 @@ 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.
|
||||
let res = *ccx.tcx.vtable_map.borrow().get(&MethodCall::expr(id));
|
||||
let origins = *resolve_vtables_in_fn_ctxt(bcx.fcx, res).get(0);
|
||||
let origins = {
|
||||
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 llvtabledest = GEPi(bcx, lldest, [0u, abi::trt_field_vtable]);
|
||||
let llvtabledest = PointerCast(bcx, llvtabledest, val_ty(vtable).ptr_to());
|
||||
|
@ -296,7 +296,7 @@ pub fn make_mono_id(ccx: &CrateContext,
|
||||
// .collect() to work.
|
||||
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 {
|
||||
Some(vts) => {
|
||||
Some(ref vts) => {
|
||||
debug!("make_mono_id vtables={} substs={}",
|
||||
vts.repr(ccx.tcx()), substs.tys.repr(ccx.tcx()));
|
||||
let vts_iter = substs.self_vtables.iter().chain(vts.iter());
|
||||
|
@ -1134,8 +1134,8 @@ pub fn mk_ctxt(s: Session,
|
||||
upvar_borrow_map: RefCell::new(HashMap::new()),
|
||||
extern_const_statics: RefCell::new(DefIdMap::new()),
|
||||
extern_const_variants: RefCell::new(DefIdMap::new()),
|
||||
method_map: @RefCell::new(FnvHashMap::new()),
|
||||
vtable_map: @RefCell::new(FnvHashMap::new()),
|
||||
method_map: RefCell::new(FnvHashMap::new()),
|
||||
vtable_map: RefCell::new(FnvHashMap::new()),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -265,8 +265,8 @@ impl<'a> Inherited<'a> {
|
||||
node_types: RefCell::new(NodeMap::new()),
|
||||
node_type_substs: RefCell::new(NodeMap::new()),
|
||||
adjustments: RefCell::new(NodeMap::new()),
|
||||
method_map: @RefCell::new(FnvHashMap::new()),
|
||||
vtable_map: @RefCell::new(FnvHashMap::new()),
|
||||
method_map: RefCell::new(FnvHashMap::new()),
|
||||
vtable_map: RefCell::new(FnvHashMap::new()),
|
||||
upvar_borrow_map: RefCell::new(HashMap::new()),
|
||||
}
|
||||
}
|
||||
|
@ -29,7 +29,6 @@ use util::ppaux::Repr;
|
||||
|
||||
use collections::HashSet;
|
||||
use std::cell::RefCell;
|
||||
use std::result;
|
||||
use syntax::ast;
|
||||
use syntax::ast_util;
|
||||
use syntax::codemap::Span;
|
||||
@ -112,7 +111,7 @@ fn lookup_vtables(vcx: &VtableContext,
|
||||
type_param_defs.repr(vcx.tcx()),
|
||||
substs.repr(vcx.tcx()),
|
||||
result.repr(vcx.tcx()));
|
||||
@result
|
||||
result
|
||||
}
|
||||
|
||||
fn lookup_vtables_for_param(vcx: &VtableContext,
|
||||
@ -170,7 +169,7 @@ fn lookup_vtables_for_param(vcx: &VtableContext,
|
||||
ty.repr(vcx.tcx()),
|
||||
param_result.repr(vcx.tcx()));
|
||||
|
||||
return @param_result;
|
||||
param_result
|
||||
}
|
||||
|
||||
fn relate_trait_refs(vcx: &VtableContext,
|
||||
@ -189,8 +188,8 @@ fn relate_trait_refs(vcx: &VtableContext,
|
||||
infer::RelateTraitRefs(span),
|
||||
act_trait_ref,
|
||||
exp_trait_ref) {
|
||||
result::Ok(()) => {} // Ok.
|
||||
result::Err(ref err) => {
|
||||
Ok(()) => {} // Ok.
|
||||
Err(ref err) => {
|
||||
// There is an error, but we need to do some work to make
|
||||
// the message good.
|
||||
// Resolve any type vars in the trait refs
|
||||
@ -368,8 +367,8 @@ fn search_for_vtable(vcx: &VtableContext,
|
||||
infer::RelateSelfType(span),
|
||||
ty,
|
||||
for_ty) {
|
||||
result::Err(_) => continue,
|
||||
result::Ok(()) => ()
|
||||
Err(_) => continue,
|
||||
Ok(()) => ()
|
||||
}
|
||||
|
||||
// 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);
|
||||
|
||||
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
|
||||
@ -743,7 +742,7 @@ pub fn resolve_impl(tcx: &ty::ctxt,
|
||||
[],
|
||||
impl_item.id);
|
||||
|
||||
let impl_trait_ref = @impl_trait_ref.subst(tcx, ¶m_env.free_substs);
|
||||
let impl_trait_ref = impl_trait_ref.subst(tcx, ¶m_env.free_substs);
|
||||
|
||||
let infcx = &infer::new_infer_ctxt(tcx);
|
||||
let vcx = VtableContext { infcx: infcx, param_env: ¶m_env };
|
||||
@ -761,7 +760,7 @@ pub fn resolve_impl(tcx: &ty::ctxt,
|
||||
// but that falls out of doing this.
|
||||
let param_bounds = ty::ParamBounds {
|
||||
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 = t.subst(tcx, ¶m_env.free_substs);
|
||||
|
@ -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) {
|
||||
let fcx = wbcx.fcx;
|
||||
let tcx = fcx.ccx.tcx;
|
||||
|
||||
// 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) => {
|
||||
debug!("writeback::resolve_method_map_entry(call={:?}, entry={:?})",
|
||||
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 {
|
||||
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 {
|
||||
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,
|
||||
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) {
|
||||
// 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) => {
|
||||
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={:?})",
|
||||
vtable_key, r_origins.repr(fcx.tcx()));
|
||||
fcx.tcx().vtable_map.borrow_mut().insert(vtable_key, r_origins);
|
||||
}
|
||||
None => {}
|
||||
}
|
||||
|
||||
fn resolve_origins(fcx: &FnCtxt, sp: Span,
|
||||
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 {
|
||||
&vtable_static(def_id, ref tys, origins) => {
|
||||
let r_tys = resolve_type_vars_in_types(fcx,
|
||||
sp,
|
||||
tys.as_slice());
|
||||
vtable_static(def_id, tys, origins) => {
|
||||
let r_tys = tys.move_iter().map(|t| {
|
||||
match resolve_type_vars_in_type(fcx, sp, t) {
|
||||
Some(t1) => t1,
|
||||
None => ty::mk_err()
|
||||
}
|
||||
}).collect();
|
||||
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)
|
||||
}
|
||||
}).collect()).collect()
|
||||
}
|
||||
}
|
||||
|
||||
fn resolve_type_vars_for_node(wbcx: &mut WbCtxt, sp: Span, id: ast::NodeId)
|
||||
-> Option<ty::t> {
|
||||
fn resolve_type_vars_for_node(wbcx: &mut WbCtxt, sp: Span, id: ast::NodeId) {
|
||||
let fcx = wbcx.fcx;
|
||||
let tcx = fcx.ccx.tcx;
|
||||
|
||||
// Resolve any borrowings for the node with id `id`
|
||||
match fcx.inh.adjustments.borrow().find_copy(&id) {
|
||||
None => (),
|
||||
let resolved_adj = match fcx.inh.adjustments.borrow_mut().pop(&id) {
|
||||
None => None,
|
||||
|
||||
Some(adjustment) => {
|
||||
match *adjustment {
|
||||
Some(match *adjustment {
|
||||
ty::AutoAddEnv(store) => {
|
||||
let r = match store {
|
||||
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: \
|
||||
{}",
|
||||
infer::fixup_err_to_str(e)));
|
||||
wbcx.success = false;
|
||||
return;
|
||||
}
|
||||
Ok(r1) => {
|
||||
// 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")
|
||||
}
|
||||
|
||||
let resolved_adj = @ty::AutoAddEnv(match store {
|
||||
ty::AutoAddEnv(match store {
|
||||
ty::RegionTraitStore(..) => {
|
||||
ty::RegionTraitStore(r1, ast::MutMutable)
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
let fixup_region = |r| {
|
||||
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 {
|
||||
ty::AutoDerefRef(ty::AutoDerefRef {
|
||||
autoderefs: adj.autoderefs,
|
||||
autoref: resolved_autoref,
|
||||
});
|
||||
debug!("Adjustments for node {}: {:?}", id, resolved_adj);
|
||||
tcx.adjustments.borrow_mut().insert(id, resolved_adj);
|
||||
autoref: adj.autoref.map(|r| r.map_region(|r| {
|
||||
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
|
||||
}
|
||||
}
|
||||
})),
|
||||
})
|
||||
}
|
||||
|
||||
ty::AutoObject(..) => {
|
||||
debug!("Adjustments for node {}: {:?}", id, adjustment);
|
||||
tcx.adjustments.borrow_mut().insert(id, adjustment);
|
||||
}
|
||||
}
|
||||
adjustment => 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`
|
||||
@ -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) {
|
||||
None => {
|
||||
wbcx.success = false;
|
||||
return None;
|
||||
}
|
||||
|
||||
Some(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));
|
||||
write_ty_to_tcx(tcx, id, t);
|
||||
let mut ret = Some(t);
|
||||
fcx.opt_node_ty_substs(id, |substs| {
|
||||
let mut new_tps = Vec::new();
|
||||
for subst in substs.tps.iter() {
|
||||
match resolve_type_vars_in_type(fcx, sp, *subst) {
|
||||
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);
|
||||
ret.is_some()
|
||||
wbcx.success
|
||||
});
|
||||
ret
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -171,11 +171,11 @@ impl MethodCall {
|
||||
|
||||
// maps from an expression id that corresponds to a method call to the details
|
||||
// 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.
|
||||
pub type vtable_res = @Vec<vtable_param_res> ;
|
||||
pub type vtable_res = Vec<vtable_param_res>;
|
||||
|
||||
#[deriving(Clone)]
|
||||
pub enum vtable_origin {
|
||||
@ -184,7 +184,7 @@ pub enum vtable_origin {
|
||||
from whence comes the vtable, and tys are the type substs.
|
||||
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:
|
||||
@ -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.
|
||||
|
Loading…
Reference in New Issue
Block a user