tag_table_val = 0x45,
tag_table_def = 0x46,
tag_table_node_type = 0x47,
- tag_table_node_type_subst = 0x48,
+ tag_table_item_subst = 0x48,
tag_table_freevars = 0x49,
tag_table_tcache = 0x4a,
tag_table_param_defs = 0x4b,
vtable_origin: &typeck::vtable_origin) {
ebml_w.emit_enum("vtable_origin", |ebml_w| {
match *vtable_origin {
- typeck::vtable_static(def_id, ref tys, ref vtable_res) => {
+ typeck::vtable_static(def_id, ref substs, 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))
});
ebml_w.emit_enum_variant_arg(1u, |ebml_w| {
- Ok(ebml_w.emit_tys(ecx, tys.as_slice()))
+ Ok(ebml_w.emit_substs(ecx, substs))
});
ebml_w.emit_enum_variant_arg(2u, |ebml_w| {
Ok(encode_vtable_res(ecx, ebml_w, vtable_res))
Ok(this.read_def_id_noxcx(cdata))
}).unwrap(),
this.read_enum_variant_arg(1u, |this| {
- Ok(this.read_tys_noxcx(tcx, cdata))
+ Ok(this.read_substs_noxcx(tcx, cdata))
}).unwrap(),
this.read_enum_variant_arg(2u, |this| {
Ok(this.read_vtable_res(tcx, cdata))
})
}
- for tys in tcx.node_type_substs.borrow().find(&id).iter() {
- ebml_w.tag(c::tag_table_node_type_subst, |ebml_w| {
+ for &item_substs in tcx.item_substs.borrow().find(&id).iter() {
+ ebml_w.tag(c::tag_table_item_subst, |ebml_w| {
ebml_w.id(id);
ebml_w.tag(c::tag_table_val, |ebml_w| {
- ebml_w.emit_tys(ecx, tys.as_slice())
+ ebml_w.emit_substs(ecx, &item_substs.substs);
})
})
}
fn read_tys_noxcx(&mut self,
tcx: &ty::ctxt,
cdata: &cstore::crate_metadata) -> Vec<ty::t>;
+ fn read_substs_noxcx(&mut self, tcx: &ty::ctxt,
+ cdata: &cstore::crate_metadata)
+ -> ty::substs;
}
impl<'a> ebml_decoder_decoder_helpers for reader::Decoder<'a> {
.collect()
}
+ fn read_substs_noxcx(&mut self,
+ tcx: &ty::ctxt,
+ cdata: &cstore::crate_metadata)
+ -> ty::substs
+ {
+ self.read_opaque(|_, doc| {
+ Ok(tydecode::parse_substs_data(
+ doc.data,
+ cdata.cnum,
+ doc.start,
+ tcx,
+ |_, id| decoder::translate_def_id(cdata, id)))
+ }).unwrap()
+ }
+
fn read_ty(&mut self, xcx: &ExtendedDecodeContext) -> ty::t {
// Note: regions types embed local node ids. In principle, we
// should translate these node ids into the new decode
id, ty_to_str(dcx.tcx, ty));
dcx.tcx.node_types.borrow_mut().insert(id as uint, ty);
}
- c::tag_table_node_type_subst => {
- let tys = val_dsr.read_tys(xcx);
- dcx.tcx.node_type_substs.borrow_mut().insert(id, tys);
+ c::tag_table_item_subst => {
+ let item_substs = ty::ItemSubsts {
+ substs: val_dsr.read_substs(xcx)
+ };
+ dcx.tcx.item_substs.borrow_mut().insert(
+ id, item_substs);
}
c::tag_table_freevars => {
let fv_info = val_dsr.read_to_vec(|val_dsr| {
{
let method_map = cx.tcx.method_map.borrow();
let method = method_map.find(&typeck::MethodCall::expr(e.id));
- let node_type_substs = cx.tcx.node_type_substs.borrow();
+ let item_substs = cx.tcx.item_substs.borrow();
let r = match method {
Some(method) => Some(&method.substs.tps),
- None => node_type_substs.find(&e.id)
+ None => item_substs.find(&e.id).map(|s| &s.substs.tps)
};
for ts in r.iter() {
let def_map = cx.tcx.def_map.borrow();
fn check_ty(cx: &mut Context, aty: &Ty) {
match aty.node {
TyPath(_, _, id) => {
- let node_type_substs = cx.tcx.node_type_substs.borrow();
- let r = node_type_substs.find(&id);
- for ts in r.iter() {
- let def_map = cx.tcx.def_map.borrow();
- let did = ast_util::def_id_of_def(def_map.get_copy(&id));
- let generics = ty::lookup_item_type(cx.tcx, did).generics;
- let type_param_defs = generics.type_param_defs();
- for (&ty, type_param_def) in ts.iter().zip(type_param_defs.iter()) {
- check_typaram_bounds(cx, aty.span, ty, type_param_def)
+ match cx.tcx.item_substs.borrow().find(&id) {
+ None => { }
+ Some(ref item_substs) => {
+ let def_map = cx.tcx.def_map.borrow();
+ let did = ast_util::def_id_of_def(def_map.get_copy(&id));
+ let generics = ty::lookup_item_type(cx.tcx, did).generics;
+ let type_param_defs = generics.type_param_defs();
+ for (&ty, type_param_def) in
+ item_substs.substs.tps.iter().zip(
+ type_param_defs.iter())
+ {
+ check_typaram_bounds(cx, aty.span, ty, type_param_def)
+ }
}
}
}
}
}
+impl Subst for ty::ItemSubsts {
+ fn subst_spanned(&self, tcx: &ty::ctxt,
+ substs: &ty::substs,
+ span: Option<Span>)
+ -> ty::ItemSubsts {
+ ty::ItemSubsts {
+ substs: self.substs.subst_spanned(tcx, substs, span)
+ }
+ }
+}
+
impl Subst for ty::RegionSubsts {
fn subst_spanned(&self, tcx: &ty::ctxt,
substs: &ty::substs,
pub fn get_res_dtor(ccx: &CrateContext,
did: ast::DefId,
parent_id: ast::DefId,
- substs: &[ty::t])
+ substs: &ty::substs)
-> ValueRef {
let _icx = push_ctxt("trans_res_dtor");
let did = if did.krate != ast::LOCAL_CRATE {
} else {
did
};
- if !substs.is_empty() {
+
+ if !substs.tps.is_empty() || !substs.self_ty.is_none() {
assert_eq!(did.krate, ast::LOCAL_CRATE);
- let tsubsts = ty::substs {
- regions: ty::ErasedRegions,
- self_ty: None,
- tps: Vec::from_slice(substs),
- };
- let vtables = typeck::check::vtable::trans_resolve_method(ccx.tcx(), did.node, &tsubsts);
- let (val, _) = monomorphize::monomorphic_fn(ccx, did, &tsubsts, vtables, None, None);
+ let vtables = typeck::check::vtable::trans_resolve_method(ccx.tcx(), did.node, substs);
+ let (val, _) = monomorphize::monomorphic_fn(ccx, did, substs, vtables, None, None);
val
} else if did.krate == ast::LOCAL_CRATE {
} else {
let tcx = ccx.tcx();
let name = csearch::get_symbol(&ccx.sess().cstore, did);
- let class_ty = ty::subst_tps(tcx,
- substs,
- None,
- ty::lookup_item_type(tcx, parent_id).ty);
+ let class_ty = ty::subst(tcx, substs,
+ ty::lookup_item_type(tcx, parent_id).ty);
let llty = type_of_dtor(ccx, class_ty);
get_extern_fn(&mut *ccx.externs.borrow_mut(), ccx.llmod, name,
repr: &adt::Repr,
av: ValueRef,
variant: &ty::VariantInfo,
- tps: &[ty::t],
+ substs: &ty::substs,
f: val_and_ty_fn<'r,'b>)
-> &'b Block<'b> {
let _icx = push_ctxt("iter_variant");
for (i, &arg) in variant.args.iter().enumerate() {
cx = f(cx,
adt::trans_field_ptr(cx, repr, av, variant.disr_val, i),
- ty::subst_tps(tcx, tps, None, arg));
+ ty::subst(tcx, substs, arg));
}
return cx;
}
match adt::trans_switch(cx, &*repr, av) {
(_match::single, None) => {
cx = iter_variant(cx, &*repr, av, &**variants.get(0),
- substs.tps.as_slice(), f);
+ substs, f);
}
(_match::switch, Some(lldiscrim_a)) => {
cx = f(cx, lldiscrim_a, ty::mk_int());
&*repr,
av,
&**variant,
- substs.tps.as_slice(),
+ substs,
|x,y,z| f(x,y,z));
Br(variant_cx, next_cx.llbb);
}
},
id, param_substs.map(|s| s.repr(ccx.tcx())));
- let substd_output_type = match param_substs {
- None => output_type,
- Some(substs) => {
- ty::subst_tps(ccx.tcx(),
- substs.tys.as_slice(),
- substs.self_ty,
- output_type)
- }
- };
+ let substd_output_type = output_type.substp(ccx.tcx(), param_substs);
let uses_outptr = type_of::return_uses_outptr(ccx, substd_output_type);
let debug_context = debuginfo::create_function_debug_context(ccx, id, param_substs, llfndecl);
// This shouldn't need to recompute the return type,
// as new_fn_ctxt did it already.
- let substd_output_type = match fcx.param_substs {
- None => output_type,
- Some(substs) => {
- ty::subst_tps(fcx.ccx.tcx(),
- substs.tys.as_slice(),
- substs.self_ty,
- output_type)
- }
- };
+ let substd_output_type = output_type.substp(fcx.ccx.tcx(), fcx.param_substs);
if !return_type_is_void(fcx.ccx, substd_output_type) {
// If the function returns nil/bot, there is no real return
disr: ty::Disr,
param_substs: Option<¶m_substs>,
llfndecl: ValueRef) {
- let ctor_ty = {
- let no_substs: &[ty::t] = [];
- let ty_param_substs: &[ty::t] = match param_substs {
- Some(substs) => substs.tys.as_slice(),
- None => no_substs
- };
-
- ty::subst_tps(ccx.tcx(),
- ty_param_substs,
- None,
- ty::node_id_to_type(ccx.tcx(), ctor_id))
- };
+ let ctor_ty = ty::node_id_to_type(ccx.tcx(), ctor_id);
+ let ctor_ty = ctor_ty.substp(ccx.tcx(), param_substs);
let result_ty = match ty::get(ctor_ty).sty {
ty::ty_bare_fn(ref bft) => bft.sig.output,
pub fn trans_fn_ref(bcx: &Block, def_id: ast::DefId, node: ExprOrMethodCall) -> ValueRef {
/*!
- *
* Translates a reference (with id `ref_id`) to the fn/method
* with id `def_id` into a function pointer. This may require
- * monomorphization or inlining. */
+ * monomorphization or inlining.
+ */
let _icx = push_ctxt("trans_fn_ref");
- let type_params = node_id_type_params(bcx, node);
+ let substs = node_id_substs(bcx, node);
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()),
+ debug!("trans_fn_ref(def_id={}, node={:?}, substs={}, vtables={})",
+ def_id.repr(bcx.tcx()),
+ node,
+ substs.repr(bcx.tcx()),
vtables.repr(bcx.tcx()));
- trans_fn_ref_with_vtables(bcx, def_id, node,
- type_params,
- vtables)
+ trans_fn_ref_with_vtables(bcx, def_id, node, substs, vtables)
}
fn trans_fn_ref_with_vtables_to_callee<'a>(bcx: &'a Block<'a>,
def_id: ast::DefId,
ref_id: ast::NodeId,
- type_params: Vec<ty::t>,
+ substs: ty::substs,
vtables: Option<typeck::vtable_res>)
-> Callee<'a> {
Callee {bcx: bcx,
data: Fn(trans_fn_ref_with_vtables(bcx, def_id, ExprId(ref_id),
- type_params, vtables))}
+ substs, vtables))}
}
fn resolve_default_method_vtables(bcx: &Block,
// Build up a param_substs that we are going to resolve the
// trait_vtables under.
let param_substs = param_substs {
- tys: substs.tps.clone(),
- self_ty: substs.self_ty,
+ substs: (*substs).clone(),
vtables: impl_vtables.clone(),
self_vtables: None
};
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: Vec<ty::t>, // values for fn's ty params
+ substs: ty::substs, // values for fn's ty params
vtables: Option<typeck::vtable_res>) // vtables for the call
-> ValueRef {
/*!
* - `node`: node id of the reference to the fn/method, if applicable.
* This parameter may be zero; but, if so, the resulting value may not
* have the right type, so it must be cast before being used.
- * - `type_params`: values for each of the fn/method's type parameters
+ * - `substs`: values for each of the fn/method's parameters
* - `vtables`: values for each bound on each of the type parameters
*/
let tcx = bcx.tcx();
debug!("trans_fn_ref_with_vtables(bcx={}, def_id={}, node={:?}, \
- type_params={}, vtables={})",
+ substs={}, vtables={})",
bcx.to_str(),
def_id.repr(tcx),
node,
- type_params.repr(tcx),
+ substs.repr(tcx),
vtables.repr(tcx));
- assert!(type_params.iter().all(|t| !ty::type_needs_infer(*t)));
+ assert!(substs.tps.iter().all(|t| !ty::type_needs_infer(*t)));
// 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: type_params
- };
-
// Load the info for the appropriate trait if necessary.
match ty::trait_of_method(tcx, def_id) {
None => {}
trans_fn_ref_with_vtables_to_callee(bcx,
did,
0,
- vec!(),
+ ty::substs::empty(),
None)
},
ArgVals(args),
use middle::trans::debuginfo;
use middle::trans::type_::Type;
use middle::ty;
+use middle::subst::Subst;
use middle::typeck;
use util::ppaux::Repr;
use util::nodemap::NodeMap;
// Here `self_ty` is the real type of the self parameter to this method. It
// will only be set in the case of default methods.
pub struct param_substs {
- pub tys: Vec<ty::t> ,
- pub self_ty: Option<ty::t>,
+ pub substs: ty::substs,
pub vtables: Option<typeck::vtable_res>,
pub self_vtables: Option<typeck::vtable_param_res>
}
impl param_substs {
pub fn validate(&self) {
- for t in self.tys.iter() { assert!(!ty::type_needs_infer(*t)); }
- for t in self.self_ty.iter() { assert!(!ty::type_needs_infer(*t)); }
+ for t in self.substs.tps.iter() {
+ assert!(!ty::type_needs_infer(*t));
+ }
+ for t in self.substs.self_ty.iter() {
+ assert!(!ty::type_needs_infer(*t));
+ }
}
}
fn param_substs_to_str(this: ¶m_substs, tcx: &ty::ctxt) -> ~str {
- format!("param_substs \\{tys:{}, vtables:{}\\}",
- this.tys.repr(tcx),
- this.vtables.repr(tcx))
+ format!("param_substs({})", this.substs.repr(tcx))
}
impl Repr for param_substs {
}
}
+pub trait SubstP {
+ fn substp(&self, tcx: &ty::ctxt, param_substs: Option<¶m_substs>)
+ -> Self;
+}
+
+impl<T:Subst+Clone> SubstP for T {
+ fn substp(&self, tcx: &ty::ctxt, param_substs: Option<¶m_substs>)
+ -> T {
+ match param_substs {
+ Some(substs) => {
+ self.subst(tcx, &substs.substs)
+ }
+ None => {
+ (*self).clone()
+ }
+ }
+ }
+}
+
// work around bizarre resolve errors
pub type RvalueDatum = datum::Datum<datum::Rvalue>;
pub type LvalueDatum = datum::Datum<datum::Lvalue>;
pub fn monomorphize_type(bcx: &Block, t: ty::t) -> ty::t {
match bcx.fcx.param_substs {
Some(ref substs) => {
- ty::subst_tps(bcx.tcx(), substs.tys.as_slice(), substs.self_ty, t)
+ ty::subst(bcx.tcx(), &substs.substs, t)
}
_ => {
assert!(!ty::type_has_params(t));
MethodCall(typeck::MethodCall)
}
-pub fn node_id_type_params(bcx: &Block, node: ExprOrMethodCall) -> Vec<ty::t> {
+pub fn node_id_substs(bcx: &Block,
+ node: ExprOrMethodCall)
+ -> ty::substs {
let tcx = bcx.tcx();
- let params = match node {
- ExprId(id) => ty::node_id_to_type_params(tcx, id),
+
+ let substs = match node {
+ ExprId(id) => {
+ ty::node_id_item_substs(tcx, id).substs
+ }
MethodCall(method_call) => {
- tcx.method_map.borrow().get(&method_call).substs.tps.clone()
+ tcx.method_map.borrow().get(&method_call).substs.clone()
}
};
- if !params.iter().all(|t| !ty::type_needs_infer(*t)) {
+ if !substs.tps.iter().all(|t| !ty::type_needs_infer(*t)) {
bcx.sess().bug(
format!("type parameters for node {:?} include inference types: {}",
- node, params.iter()
- .map(|t| bcx.ty_to_str(*t))
- .collect::<Vec<~str>>()
- .connect(",")));
+ node,
+ substs.repr(bcx.tcx())));
}
- match bcx.fcx.param_substs {
- Some(ref substs) => {
- params.iter().map(|t| {
- ty::subst_tps(tcx, substs.tys.as_slice(), substs.self_ty, *t)
- }).collect()
- }
- _ => params
- }
+ substs.substp(tcx, bcx.fcx.param_substs)
}
pub fn node_vtables(bcx: &Block, id: typeck::MethodCall)
vt: &typeck::vtable_origin)
-> typeck::vtable_origin {
match *vt {
- typeck::vtable_static(trait_id, ref tys, ref sub) => {
- let tys = match param_substs {
- Some(substs) => {
- tys.iter().map(|t| {
- ty::subst_tps(tcx,
- substs.tys.as_slice(),
- substs.self_ty,
- *t)
- }).collect()
- }
- _ => Vec::from_slice(tys.as_slice())
- };
+ typeck::vtable_static(trait_id, ref vtable_substs, ref sub) => {
+ let vtable_substs = vtable_substs.substp(tcx, param_substs);
typeck::vtable_static(
- trait_id, tys,
+ trait_id, vtable_substs,
resolve_vtables_under_param_substs(tcx, param_substs, sub.as_slice()))
}
typeck::vtable_param(n_param, n_bound) => {
assert_type_for_node_id(cx, fn_ast_id, error_span);
let return_type = ty::node_id_to_type(cx.tcx(), fn_ast_id);
- let return_type = match param_substs {
- None => return_type,
- Some(substs) => {
- ty::subst_tps(cx.tcx(),
- substs.tys.as_slice(),
- substs.self_ty,
- return_type)
- }
- };
-
+ let return_type = return_type.substp(cx.tcx(), param_substs);
signature.push(type_metadata(cx, return_type, codemap::DUMMY_SP));
}
}
for arg in fn_decl.inputs.iter() {
assert_type_for_node_id(cx, arg.pat.id, arg.pat.span);
let arg_type = ty::node_id_to_type(cx.tcx(), arg.pat.id);
- let arg_type = match param_substs {
- None => arg_type,
- Some(substs) => {
- ty::subst_tps(cx.tcx(),
- substs.tys.as_slice(),
- substs.self_ty,
- arg_type)
- }
- };
-
+ let arg_type = arg_type.substp(cx.tcx(), param_substs);
signature.push(type_metadata(cx, arg_type, codemap::DUMMY_SP));
}
name_to_append_suffix_to: &mut StrBuf)
-> DIArray {
let self_type = match param_substs {
- Some(param_substs) => param_substs.self_ty,
+ Some(param_substs) => param_substs.substs.self_ty,
_ => None
};
// Handle other generic parameters
let actual_types = match param_substs {
- Some(param_substs) => ¶m_substs.tys,
+ Some(param_substs) => ¶m_substs.substs.tps,
None => {
return create_DIArray(DIB(cx), template_params.as_slice());
}
// Find and call the actual destructor
let dtor_addr = get_res_dtor(bcx.ccx(), dtor_did,
- class_did, substs.tps.as_slice());
+ class_did, substs);
// The second argument is the "self" argument for drop
let params = unsafe {
RetVoid(bcx);
}
"size_of" => {
- let tp_ty = *substs.tys.get(0);
+ let tp_ty = *substs.substs.tps.get(0);
let lltp_ty = type_of::type_of(ccx, tp_ty);
Ret(bcx, C_uint(ccx, machine::llsize_of_real(ccx, lltp_ty) as uint));
}
// if the value is non-immediate. Note that, with
// intrinsics, there are no argument cleanups to
// concern ourselves with, so we can use an rvalue datum.
- let tp_ty = *substs.tys.get(0);
+ let tp_ty = *substs.substs.tps.get(0);
let mode = appropriate_rvalue_mode(ccx, tp_ty);
let src = Datum {val: get_param(decl, first_real_arg + 1u),
ty: tp_ty,
RetVoid(bcx);
}
"min_align_of" => {
- let tp_ty = *substs.tys.get(0);
+ let tp_ty = *substs.substs.tps.get(0);
let lltp_ty = type_of::type_of(ccx, tp_ty);
Ret(bcx, C_uint(ccx, machine::llalign_of_min(ccx, lltp_ty) as uint));
}
"pref_align_of"=> {
- let tp_ty = *substs.tys.get(0);
+ let tp_ty = *substs.substs.tps.get(0);
let lltp_ty = type_of::type_of(ccx, tp_ty);
Ret(bcx, C_uint(ccx, machine::llalign_of_pref(ccx, lltp_ty) as uint));
}
"get_tydesc" => {
- let tp_ty = *substs.tys.get(0);
+ let tp_ty = *substs.substs.tps.get(0);
let static_ti = get_tydesc(ccx, tp_ty);
glue::lazily_emit_visit_glue(ccx, &*static_ti);
"type_id" => {
let hash = ty::hash_crate_independent(
ccx.tcx(),
- *substs.tys.get(0),
+ *substs.substs.tps.get(0),
&ccx.link_meta.crate_hash);
// NB: This needs to be kept in lockstep with the TypeId struct in
// libstd/unstable/intrinsics.rs
}
}
"init" => {
- let tp_ty = *substs.tys.get(0);
+ let tp_ty = *substs.substs.tps.get(0);
let lltp_ty = type_of::type_of(ccx, tp_ty);
match bcx.fcx.llretptr.get() {
Some(ptr) => { Store(bcx, C_null(lltp_ty), ptr); RetVoid(bcx); }
}
"uninit" => {
// Do nothing, this is effectively a no-op
- let retty = *substs.tys.get(0);
+ let retty = *substs.substs.tps.get(0);
if type_is_immediate(ccx, retty) && !return_type_is_void(ccx, retty) {
unsafe {
Ret(bcx, lib::llvm::llvm::LLVMGetUndef(type_of(ccx, retty).to_ref()));
RetVoid(bcx);
}
"transmute" => {
- let (in_type, out_type) = (*substs.tys.get(0), *substs.tys.get(1));
+ let (in_type, out_type) = (*substs.substs.tps.get(0),
+ *substs.substs.tps.get(1));
let llintype = type_of::type_of(ccx, in_type);
let llouttype = type_of::type_of(ccx, out_type);
}
}
"needs_drop" => {
- let tp_ty = *substs.tys.get(0);
+ let tp_ty = *substs.substs.tps.get(0);
Ret(bcx, C_bool(ccx, ty::type_needs_drop(ccx.tcx(), tp_ty)));
}
"owns_managed" => {
- let tp_ty = *substs.tys.get(0);
+ let tp_ty = *substs.substs.tps.get(0);
Ret(bcx, C_bool(ccx, ty::type_contents(ccx.tcx(), tp_ty).owns_managed()));
}
"visit_tydesc" => {
let lladdr = InBoundsGEP(bcx, ptr, [offset]);
Ret(bcx, lladdr);
}
- "copy_nonoverlapping_memory" => copy_intrinsic(bcx, false, false, *substs.tys.get(0)),
- "copy_memory" => copy_intrinsic(bcx, true, false, *substs.tys.get(0)),
- "set_memory" => memset_intrinsic(bcx, false, *substs.tys.get(0)),
+ "copy_nonoverlapping_memory" => {
+ copy_intrinsic(bcx, false, false, *substs.substs.tps.get(0))
+ }
+ "copy_memory" => {
+ copy_intrinsic(bcx, true, false, *substs.substs.tps.get(0))
+ }
+ "set_memory" => {
+ memset_intrinsic(bcx, false, *substs.substs.tps.get(0))
+ }
"volatile_copy_nonoverlapping_memory" =>
- copy_intrinsic(bcx, false, true, *substs.tys.get(0)),
- "volatile_copy_memory" => copy_intrinsic(bcx, true, true, *substs.tys.get(0)),
- "volatile_set_memory" => memset_intrinsic(bcx, true, *substs.tys.get(0)),
+ copy_intrinsic(bcx, false, true, *substs.substs.tps.get(0)),
+ "volatile_copy_memory" => copy_intrinsic(bcx, true, true, *substs.substs.tps.get(0)),
+ "volatile_set_memory" => memset_intrinsic(bcx, true, *substs.substs.tps.get(0)),
"ctlz8" => count_zeros_intrinsic(bcx, "llvm.ctlz.i8"),
"ctlz16" => count_zeros_intrinsic(bcx, "llvm.ctlz.i16"),
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)));
+ assert!(rcvr_substs.tps.iter().all(|t| !ty::type_needs_infer(*t)));
let mth_id = method_with_name(ccx, impl_did, mname);
let (callee_substs, callee_origins) =
fn combine_impl_and_methods_tps(bcx: &Block,
mth_did: ast::DefId,
node: ExprOrMethodCall,
- rcvr_substs: Vec<ty::t>,
+ rcvr_substs: ty::substs,
rcvr_origins: typeck::vtable_res)
- -> (Vec<ty::t>, typeck::vtable_res) {
+ -> (ty::substs, typeck::vtable_res)
+{
/*!
- *
- * Creates a concatenated set of substitutions which includes
- * those from the impl and those from the method. This are
- * some subtle complications here. Statically, we have a list
- * of type parameters like `[T0, T1, T2, M1, M2, M3]` where
- * `Tn` are type parameters that appear on the receiver. For
- * example, if the receiver is a method parameter `A` with a
- * bound like `trait<B,C,D>` then `Tn` would be `[B,C,D]`.
- *
- * The weird part is that the type `A` might now be bound to
- * any other type, such as `foo<X>`. In that case, the vector
- * we want is: `[X, M1, M2, M3]`. Therefore, what we do now is
- * to slice off the method type parameters and append them to
- * the type parameters from the type that the receiver is
- * mapped to. */
+ * Creates a concatenated set of substitutions which includes
+ * those from the impl and those from the method. This are
+ * some subtle complications here. Statically, we have a list
+ * of type parameters like `[T0, T1, T2, M1, M2, M3]` where
+ * `Tn` are type parameters that appear on the receiver. For
+ * example, if the receiver is a method parameter `A` with a
+ * bound like `trait<B,C,D>` then `Tn` would be `[B,C,D]`.
+ *
+ * The weird part is that the type `A` might now be bound to
+ * any other type, such as `foo<X>`. In that case, the vector
+ * we want is: `[X, M1, M2, M3]`. Therefore, what we do now is
+ * to slice off the method type parameters and append them to
+ * the type parameters from the type that the receiver is
+ * mapped to.
+ */
let ccx = bcx.ccx();
let method = ty::method(ccx.tcx(), mth_did);
let n_m_tps = method.generics.type_param_defs().len();
- let node_substs = node_id_type_params(bcx, node);
+ let node_substs = node_id_substs(bcx, node);
debug!("rcvr_substs={:?}", rcvr_substs.repr(ccx.tcx()));
debug!("node_substs={:?}", node_substs.repr(ccx.tcx()));
- let mut ty_substs = rcvr_substs;
+ let rcvr_self_ty = rcvr_substs.self_ty;
+ let mut tps = rcvr_substs.tps;
{
- let start = node_substs.len() - n_m_tps;
- ty_substs.extend(node_substs.move_iter().skip(start));
+ let start = node_substs.tps.len() - n_m_tps;
+ tps.extend(node_substs.tps.move_iter().skip(start));
}
debug!("n_m_tps={:?}", n_m_tps);
- debug!("ty_substs={:?}", ty_substs.repr(ccx.tcx()));
+ debug!("tps={}", tps.repr(ccx.tcx()));
// Now, do the same work for the vtables. The vtables might not
}
}
+ let ty_substs = ty::substs {
+ tps: tps,
+ regions: ty::ErasedRegions,
+ self_ty: rcvr_self_ty
+ };
+
(ty_substs, vtables)
}
fn emit_vtable_methods(bcx: &Block,
impl_id: ast::DefId,
- substs: Vec<ty::t>,
+ substs: ty::substs,
vtables: typeck::vtable_res)
-> Vec<ValueRef> {
let ccx = bcx.ccx();
}
let psubsts = param_substs {
- tys: real_substs.tps.clone(),
+ substs: (*real_substs).clone(),
vtables: vtables,
- self_ty: real_substs.self_ty.clone(),
self_vtables: self_vtables
};
debug!("monomorphic_fn about to subst into {}", llitem_ty.repr(ccx.tcx()));
let mono_ty = match is_static_provided {
- None => ty::subst_tps(ccx.tcx(), real_substs.tps.as_slice(),
- real_substs.self_ty, llitem_ty),
+ None => ty::subst(ccx.tcx(), real_substs, llitem_ty),
Some(num_method_ty_params) => {
// Static default methods are a little unfortunate, in
// that the "internal" and "external" type of them differ.
// This is a bit unfortunate.
let idx = real_substs.tps.len() - num_method_ty_params;
- let substs = Vec::from_slice(real_substs.tps.slice(0, idx))
- .append([real_substs.self_ty.unwrap()])
- .append(real_substs.tps.tailn(idx));
+ let mut tps = Vec::new();
+ tps.push_all(real_substs.tps.slice(0, idx));
+ tps.push(real_substs.self_ty.unwrap());
+ tps.push_all(real_substs.tps.tailn(idx));
+
+ let substs = ty::substs { regions: ty::ErasedRegions,
+ self_ty: None,
+ tps: tps };
+
debug!("static default: changed substitution to {}",
substs.repr(ccx.tcx()));
- ty::subst_tps(ccx.tcx(), substs.as_slice(), None, llitem_ty)
+ ty::subst(ccx.tcx(), &substs, llitem_ty)
}
};
&typeck::vtable_static(impl_id, ref substs, ref sub_vtables) => {
MonoId {
def: impl_id,
- params: sub_vtables.iter().zip(substs.iter()).map(|(vtable, subst)| {
+ // FIXME(NDM) -- this is pretty bogus. It ignores self-type,
+ // and vtables are not necessary, AND they are not guaranteed
+ // to be same length as the number of TPS ANYHOW!
+ params: sub_vtables.iter().zip(substs.tps.iter()).map(|(vtable, subst)| {
MonoParamId {
subst: *subst,
// Do we really need the vtables to be hashed? Isn't the type enough?
// Stores the type parameters which were substituted to obtain the type
// of this node. This only applies to nodes that refer to entities
- // parameterized by type parameters, such as generic fns, types, or
+ // param<eterized by type parameters, such as generic fns, types, or
// other items.
- pub node_type_substs: RefCell<NodeMap<Vec<t>>>,
+ pub item_substs: RefCell<NodeMap<ItemSubsts>>,
// Maps from a method to the method "descriptor"
pub methods: RefCell<DefIdMap<Rc<Method>>>,
pub trait_ref: Rc<ty::TraitRef>,
}
+/// Records the substitutions used to translate the polytype for an
+/// item into the monotype of an item reference.
+#[deriving(Clone)]
+pub struct ItemSubsts {
+ pub substs: ty::substs,
+}
+
pub struct ty_param_substs_and_ty {
pub substs: ty::substs,
pub ty: ty::t
def_map: dm,
region_maps: region_maps,
node_types: RefCell::new(HashMap::new()),
- node_type_substs: RefCell::new(NodeMap::new()),
+ item_substs: RefCell::new(NodeMap::new()),
trait_refs: RefCell::new(NodeMap::new()),
trait_defs: RefCell::new(DefIdMap::new()),
map: map,
|t| { fldt(t); t }).fold_ty(ty)
}
-// Substitute *only* type parameters. Used in trans where regions are erased.
-pub fn subst_tps(tcx: &ctxt, tps: &[t], self_ty_opt: Option<t>, typ: t) -> t {
- let mut subst = TpsSubst { tcx: tcx, self_ty_opt: self_ty_opt, tps: tps };
- return subst.fold_ty(typ);
-
- struct TpsSubst<'a> {
- tcx: &'a ctxt,
- self_ty_opt: Option<t>,
- tps: &'a [t],
+impl ItemSubsts {
+ pub fn empty() -> ItemSubsts {
+ ItemSubsts { substs: substs::empty() }
}
- impl<'a> TypeFolder for TpsSubst<'a> {
- fn tcx<'a>(&'a self) -> &'a ctxt { self.tcx }
-
- fn fold_ty(&mut self, t: ty::t) -> ty::t {
- if self.tps.len() == 0u && self.self_ty_opt.is_none() {
- return t;
- }
-
- let tb = ty::get(t);
- if self.self_ty_opt.is_none() && !tbox_has_flag(tb, has_params) {
- return t;
- }
-
- match ty::get(t).sty {
- ty_param(p) => {
- self.tps[p.idx]
- }
-
- ty_self(_) => {
- match self.self_ty_opt {
- None => self.tcx.sess.bug("ty_self unexpected here"),
- Some(self_ty) => self_ty
- }
- }
-
- _ => {
- ty_fold::super_fold_ty(self, t)
- }
- }
- }
+ pub fn is_noop(&self) -> bool {
+ ty::substs_is_noop(&self.substs)
}
}
}
}
-// FIXME(pcwalton): Makes a copy, bleh. Probably better to not do that.
-pub fn node_id_to_type_params(cx: &ctxt, id: ast::NodeId) -> Vec<t> {
- match cx.node_type_substs.borrow().find(&id) {
- None => return Vec::new(),
- Some(ts) => return (*ts).clone(),
+pub fn node_id_item_substs(cx: &ctxt, id: ast::NodeId) -> ItemSubsts {
+ match cx.item_substs.borrow().find(&id) {
+ None => ItemSubsts::empty(),
+ Some(ts) => ts.clone(),
}
}
}
}
-pub struct ParamsTy {
- pub params: Vec<t>,
- pub ty: t
-}
-
-#[allow(dead_code)] // this may be useful?
-pub fn expr_ty_params_and_ty(cx: &ctxt,
- expr: &ast::Expr)
- -> ParamsTy {
- ParamsTy {
- params: node_id_to_type_params(cx, expr.id),
- ty: node_id_to_type(cx, expr.id)
- }
-}
-
pub fn method_call_type_param_defs(tcx: &ctxt, origin: typeck::MethodOrigin)
-> Rc<Vec<TypeParameterDef>> {
match origin {
While type checking a function, the intermediate types for the
expressions, blocks, and so forth contained within the function are
-stored in `fcx.node_types` and `fcx.node_type_substs`. These types
+stored in `fcx.node_types` and `fcx.item_substs`. These types
may contain unresolved type variables. After type checking is
complete, the functions in the writeback module are used to take the
types from this table, resolve them, and then write them into their
// Temporary tables:
node_types: RefCell<NodeMap<ty::t>>,
- node_type_substs: RefCell<NodeMap<ty::substs>>,
+ item_substs: RefCell<NodeMap<ty::ItemSubsts>>,
adjustments: RefCell<NodeMap<ty::AutoAdjustment>>,
method_map: MethodMap,
vtable_map: vtable_map,
locals: RefCell::new(NodeMap::new()),
param_env: param_env,
node_types: RefCell::new(NodeMap::new()),
- node_type_substs: RefCell::new(NodeMap::new()),
+ item_substs: RefCell::new(NodeMap::new()),
adjustments: RefCell::new(NodeMap::new()),
method_map: RefCell::new(FnvHashMap::new()),
vtable_map: RefCell::new(FnvHashMap::new()),
self.inh.node_types.borrow_mut().insert(node_id, ty);
}
- pub fn write_substs(&self, node_id: ast::NodeId, substs: ty::substs) {
- if !ty::substs_is_noop(&substs) {
+ pub fn write_substs(&self, node_id: ast::NodeId, substs: ty::ItemSubsts) {
+ if !ty::substs_is_noop(&substs.substs) {
debug!("write_substs({}, {}) in fcx {}",
node_id,
- ty::substs_to_str(self.tcx(), &substs),
+ substs.repr(self.tcx()),
self.tag());
- self.inh.node_type_substs.borrow_mut().insert(node_id, substs);
+ self.inh.item_substs.borrow_mut().insert(node_id, substs);
}
}
pub fn write_ty_substs(&self,
node_id: ast::NodeId,
ty: ty::t,
- substs: ty::substs) {
- let ty = ty::subst(self.tcx(), &substs, ty);
+ substs: ty::ItemSubsts) {
+ let ty = ty::subst(self.tcx(), &substs.substs, ty);
self.write_ty(node_id, ty);
self.write_substs(node_id, substs);
}
pub fn opt_node_ty_substs(&self,
id: ast::NodeId,
- f: |&ty::substs|) {
- match self.inh.node_type_substs.borrow().find(&id) {
+ f: |&ty::ItemSubsts|) {
+ match self.inh.item_substs.borrow().find(&id) {
Some(s) => { f(s) }
None => { }
}
(tps, regions)
};
- fcx.write_ty_substs(node_id, tpt.ty, substs {
- regions: regions,
- self_ty: None,
- tps: tps
+ fcx.write_ty_substs(node_id, tpt.ty, ty::ItemSubsts {
+ substs: substs { regions: regions,
+ self_ty: None,
+ tps: tps }
});
debug!("<<<");
use middle::typeck::astconv::AstConv;
use middle::typeck::check::{FnCtxt, impl_self_ty};
use middle::typeck::check::{structurally_resolved_type};
+use middle::typeck::check::writeback;
use middle::typeck::infer::fixup_err_to_str;
use middle::typeck::infer::{resolve_and_force_all_but_regions, resolve_type};
use middle::typeck::infer;
// Finally, we register that we found a matching impl, and
// record the def ID of the impl as well as the resolved list
// of type substitutions for the target trait.
- found.push(vtable_static(impl_did, substs_f.tps.clone(), subres));
+ found.push(vtable_static(impl_did, substs_f, subres));
}
match found.len() {
};
match ex.node {
ast::ExprPath(..) => {
- fcx.opt_node_ty_substs(ex.id, |substs| {
+ fcx.opt_node_ty_substs(ex.id, |item_substs| {
debug!("vtable resolution on parameter bounds for expr {}",
ex.repr(fcx.tcx()));
let def = cx.tcx.def_map.borrow().get_copy(&ex.id);
let vcx = fcx.vtable_context();
let vtbls = lookup_vtables(&vcx, ex.span,
item_ty.generics.type_param_defs(),
- substs, is_early);
+ &item_substs.substs, is_early);
if !is_early {
insert_vtables(fcx, MethodCall::expr(ex.id), vtbls);
}
pub fn resolve_impl(tcx: &ty::ctxt,
impl_item: &ast::Item,
impl_generics: &ty::Generics,
- impl_trait_ref: &ty::TraitRef)
-{
+ impl_trait_ref: &ty::TraitRef) {
+ debug!("resolve_impl(impl_item.id={})",
+ impl_item.id);
+
let param_env = ty::construct_parameter_environment(
tcx,
None,
impl_item.id);
let impl_trait_ref = impl_trait_ref.subst(tcx, ¶m_env.free_substs);
+ debug!("impl_trait_ref={}", impl_trait_ref.repr(tcx));
let infcx = &infer::new_infer_ctxt(tcx);
let vcx = VtableContext { infcx: infcx, param_env: ¶m_env };
trait_vtables: vtbls,
self_vtables: self_vtable_res
};
+ let res = writeback::resolve_impl_res(infcx, impl_item.span, &res);
let impl_def_id = ast_util::local_def(impl_item.id);
+ debug!("impl_vtables for {} are {}",
+ impl_def_id.repr(tcx),
+ res.repr(tcx));
+
tcx.impl_vtables.borrow_mut().insert(impl_def_id, res);
}
use middle::typeck::infer::{force_all, resolve_all, resolve_region};
use middle::typeck::infer::resolve_type;
use middle::typeck::infer;
+use middle::typeck::impl_res;
use middle::typeck::{MethodCall, MethodCallee};
use middle::typeck::{vtable_origin, vtable_static, vtable_param};
use middle::typeck::write_substs_to_tcx;
use middle::typeck::write_ty_to_tcx;
use util::ppaux::Repr;
+use std::cell::Cell;
+
use syntax::ast;
use syntax::codemap::Span;
use syntax::print::pprust::pat_to_str;
wbcx.visit_upvar_borrow_map();
}
+pub fn resolve_impl_res(infcx: &infer::InferCtxt,
+ span: Span,
+ impl_res: &impl_res)
+ -> impl_res {
+ let errors = Cell::new(false); // nobody cares
+ let mut resolver = Resolver::from_infcx(infcx,
+ &errors,
+ ResolvingImplRes(span));
+ impl_res.resolve_in(&mut resolver)
+}
+
///////////////////////////////////////////////////////////////////////////
// The Writerback context. This visitor walks the AST, checking the
// fn-specific tables to find references to types or regions. It
}
let var_ty = self.fcx.local_ty(l.span, l.id);
- let var_ty = var_ty.resolve(self.fcx, ResolvingLocal(l.span));
+ let var_ty = self.resolve(&var_ty, ResolvingLocal(l.span));
write_ty_to_tcx(self.tcx(), l.id, var_ty);
visit::walk_local(self, l, ());
}
for (upvar_id, upvar_borrow) in self.fcx.inh.upvar_borrow_map.borrow().iter() {
let r = upvar_borrow.region;
- let r = r.resolve(self.fcx, ResolvingUpvar(*upvar_id));
+ let r = self.resolve(&r, ResolvingUpvar(*upvar_id));
let new_upvar_borrow = ty::UpvarBorrow { kind: upvar_borrow.kind,
region: r };
debug!("Upvar borrow for {} resolved to {}",
// Resolve the type of the node with id `id`
let n_ty = self.fcx.node_ty(id);
- let n_ty = n_ty.resolve(self.fcx, reason);
+ let n_ty = self.resolve(&n_ty, reason);
write_ty_to_tcx(self.tcx(), id, n_ty);
debug!("Node {} has type {}", id, n_ty.repr(self.tcx()));
// Resolve any substitutions
- self.fcx.opt_node_ty_substs(id, |node_substs| {
- let mut new_tps = Vec::new();
- for subst in node_substs.tps.iter() {
- new_tps.push(subst.resolve(self.fcx, reason));
- }
- write_substs_to_tcx(self.tcx(), id, new_tps);
+ self.fcx.opt_node_ty_substs(id, |item_substs| {
+ write_substs_to_tcx(self.tcx(), id,
+ self.resolve(item_substs, reason));
});
}
}
_ => {
self.tcx().sess.span_err(
- reason.span(self.fcx),
+ reason.span(self.tcx()),
"cannot coerce non-statically resolved bare fn")
}
}
- ty::AutoAddEnv(store.resolve(self.fcx, reason))
+ ty::AutoAddEnv(self.resolve(&store, reason))
}
ty::AutoDerefRef(adj) => {
ty::AutoDerefRef(ty::AutoDerefRef {
autoderefs: adj.autoderefs,
- autoref: adj.autoref.resolve(self.fcx, reason),
+ autoref: self.resolve(&adj.autoref, reason),
})
}
method.repr(self.tcx()));
let mut new_method = MethodCallee {
origin: method.origin,
- ty: method.ty.resolve(self.fcx, reason),
- substs: method.substs.resolve(self.fcx, reason),
+ ty: self.resolve(&method.ty, reason),
+ substs: self.resolve(&method.substs, reason),
};
// Wack. For some reason I don't quite know, we always
// Resolve any vtable map entry
match self.fcx.inh.vtable_map.borrow_mut().pop(&vtable_key) {
Some(origins) => {
- let r_origins = origins.resolve(self.fcx, reason);
+ let r_origins = self.resolve(&origins, reason);
debug!("writeback::resolve_vtable_map_entry(\
vtable_key={}, vtables={:?})",
vtable_key, r_origins.repr(self.tcx()));
None => {}
}
}
+
+ fn resolve<T:ResolveIn>(&self, t: &T, reason: ResolveReason) -> T {
+ t.resolve_in(&mut Resolver::new(self.fcx, reason))
+ }
}
///////////////////////////////////////////////////////////////////////////
ResolvingExpr(Span),
ResolvingLocal(Span),
ResolvingPattern(Span),
- ResolvingUpvar(ty::UpvarId)
+ ResolvingUpvar(ty::UpvarId),
+ ResolvingImplRes(Span),
}
impl ResolveReason {
- fn span(&self, fcx: &FnCtxt) -> Span {
+ fn span(&self, tcx: &ty::ctxt) -> Span {
match *self {
ResolvingExpr(s) => s,
ResolvingLocal(s) => s,
ResolvingPattern(s) => s,
ResolvingUpvar(upvar_id) => {
- ty::expr_span(fcx.tcx(), upvar_id.closure_expr_id)
+ ty::expr_span(tcx, upvar_id.closure_expr_id)
}
+ ResolvingImplRes(s) => s,
}
}
}
///////////////////////////////////////////////////////////////////////////
// Convenience methods for resolving different kinds of things.
-trait Resolve {
- fn resolve(&self, fcx: &FnCtxt, reason: ResolveReason) -> Self;
+trait ResolveIn {
+ fn resolve_in(&self, resolver: &mut Resolver) -> Self;
}
-impl<T:Resolve> Resolve for Option<T> {
- fn resolve(&self, fcx: &FnCtxt, reason: ResolveReason) -> Option<T> {
- self.as_ref().map(|t| t.resolve(fcx, reason))
+impl<T:ResolveIn> ResolveIn for Option<T> {
+ fn resolve_in(&self, resolver: &mut Resolver) -> Option<T> {
+ self.as_ref().map(|t| t.resolve_in(resolver))
}
}
-impl<T:Resolve> Resolve for Vec<T> {
- fn resolve(&self, fcx: &FnCtxt, reason: ResolveReason) -> Vec<T> {
- self.iter().map(|t| t.resolve(fcx, reason)).collect()
+impl<T:ResolveIn> ResolveIn for Vec<T> {
+ fn resolve_in(&self, resolver: &mut Resolver) -> Vec<T> {
+ self.iter().map(|t| t.resolve_in(resolver)).collect()
}
}
-impl Resolve for ty::TraitStore {
- fn resolve(&self, fcx: &FnCtxt, reason: ResolveReason) -> ty::TraitStore {
- Resolver::new(fcx, reason).fold_trait_store(*self)
+impl ResolveIn for ty::TraitStore {
+ fn resolve_in(&self, resolver: &mut Resolver) -> ty::TraitStore {
+ resolver.fold_trait_store(*self)
}
}
-impl Resolve for ty::t {
- fn resolve(&self, fcx: &FnCtxt, reason: ResolveReason) -> ty::t {
- Resolver::new(fcx, reason).fold_ty(*self)
+impl ResolveIn for ty::t {
+ fn resolve_in(&self, resolver: &mut Resolver) -> ty::t {
+ resolver.fold_ty(*self)
}
}
-impl Resolve for ty::Region {
- fn resolve(&self, fcx: &FnCtxt, reason: ResolveReason) -> ty::Region {
- Resolver::new(fcx, reason).fold_region(*self)
+impl ResolveIn for ty::Region {
+ fn resolve_in(&self, resolver: &mut Resolver) -> ty::Region {
+ resolver.fold_region(*self)
}
}
-impl Resolve for ty::substs {
- fn resolve(&self, fcx: &FnCtxt, reason: ResolveReason) -> ty::substs {
- Resolver::new(fcx, reason).fold_substs(self)
+impl ResolveIn for ty::substs {
+ fn resolve_in(&self, resolver: &mut Resolver) -> ty::substs {
+ resolver.fold_substs(self)
}
}
-impl Resolve for ty::AutoRef {
- fn resolve(&self, fcx: &FnCtxt, reason: ResolveReason) -> ty::AutoRef {
- Resolver::new(fcx, reason).fold_autoref(self)
+impl ResolveIn for ty::ItemSubsts {
+ fn resolve_in(&self, resolver: &mut Resolver) -> ty::ItemSubsts {
+ ty::ItemSubsts {
+ substs: self.substs.resolve_in(resolver)
+ }
}
}
-impl Resolve for vtable_origin {
- fn resolve(&self, fcx: &FnCtxt, reason: ResolveReason) -> vtable_origin {
+impl ResolveIn for ty::AutoRef {
+ fn resolve_in(&self, resolver: &mut Resolver) -> ty::AutoRef {
+ resolver.fold_autoref(self)
+ }
+}
+
+impl ResolveIn for vtable_origin {
+ fn resolve_in(&self, resolver: &mut Resolver) -> vtable_origin {
match *self {
- vtable_static(def_id, ref tys, ref origins) => {
- let r_tys = tys.resolve(fcx, reason);
- let r_origins = origins.resolve(fcx, reason);
- vtable_static(def_id, r_tys, r_origins)
+ vtable_static(def_id, ref substs, ref origins) => {
+ let r_substs = substs.resolve_in(resolver);
+ let r_origins = origins.resolve_in(resolver);
+ vtable_static(def_id, r_substs, r_origins)
}
vtable_param(n, b) => {
vtable_param(n, b)
}
}
+impl ResolveIn for impl_res {
+ fn resolve_in(&self, resolver: &mut Resolver) -> impl_res {
+ impl_res {
+ trait_vtables: self.trait_vtables.resolve_in(resolver),
+ self_vtables: self.self_vtables.resolve_in(resolver),
+ }
+ }
+}
+
///////////////////////////////////////////////////////////////////////////
// The Resolver. This is the type folding engine that detects
// unresolved types and so forth.
struct Resolver<'cx> {
- fcx: &'cx FnCtxt<'cx>,
+ tcx: &'cx ty::ctxt,
+ infcx: &'cx infer::InferCtxt<'cx>,
+ writeback_errors: &'cx Cell<bool>,
reason: ResolveReason,
}
reason: ResolveReason)
-> Resolver<'cx>
{
- Resolver { fcx: fcx, reason: reason }
+ Resolver { infcx: fcx.infcx(),
+ tcx: fcx.tcx(),
+ writeback_errors: &fcx.writeback_errors,
+ reason: reason }
+ }
+
+ fn from_infcx(infcx: &'cx infer::InferCtxt<'cx>,
+ writeback_errors: &'cx Cell<bool>,
+ reason: ResolveReason)
+ -> Resolver<'cx>
+ {
+ Resolver { infcx: infcx,
+ tcx: infcx.tcx,
+ writeback_errors: writeback_errors,
+ reason: reason }
}
fn report_error(&self, e: infer::fixup_err) {
- self.fcx.writeback_errors.set(true);
- if !self.tcx().sess.has_errors() {
+ self.writeback_errors.set(true);
+ if !self.tcx.sess.has_errors() {
match self.reason {
ResolvingExpr(span) => {
- self.tcx().sess.span_err(
+ self.tcx.sess.span_err(
span,
format!("cannot determine a type for \
this expression: {}",
}
ResolvingLocal(span) => {
- self.tcx().sess.span_err(
+ self.tcx.sess.span_err(
span,
format!("cannot determine a type for \
this local variable: {}",
}
ResolvingPattern(span) => {
- self.tcx().sess.span_err(
+ self.tcx.sess.span_err(
span,
format!("cannot determine a type for \
this pattern binding: {}",
}
ResolvingUpvar(upvar_id) => {
- let span = self.reason.span(self.fcx);
- self.tcx().sess.span_err(
+ let span = self.reason.span(self.tcx);
+ self.tcx.sess.span_err(
span,
format!("cannot resolve lifetime for \
captured variable `{}`: {}",
ty::local_var_name_str(
- self.tcx(),
+ self.tcx,
upvar_id.var_id).get().to_str(),
infer::fixup_err_to_str(e)));
}
+
+ ResolvingImplRes(span) => {
+ self.tcx.sess.span_err(
+ span,
+ format!("cannot determine a type for impl supertrait"));
+ }
}
}
}
impl<'cx> TypeFolder for Resolver<'cx> {
fn tcx<'a>(&'a self) -> &'a ty::ctxt {
- self.fcx.tcx()
+ self.tcx
}
fn fold_ty(&mut self, t: ty::t) -> ty::t {
return t;
}
- match resolve_type(self.fcx.infcx(), t, resolve_all | force_all) {
+ match resolve_type(self.infcx, t, resolve_all | force_all) {
Ok(t) => t,
Err(e) => {
self.report_error(e);
}
fn fold_region(&mut self, r: ty::Region) -> ty::Region {
- match resolve_region(self.fcx.infcx(), r, resolve_all | force_all) {
+ match resolve_region(self.infcx, r, resolve_all | force_all) {
Ok(r) => r,
Err(e) => {
self.report_error(e);
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, ty::substs, vtable_res),
/*
Dynamic vtable, comes from a parameter that has a bound on it:
}
pub fn write_substs_to_tcx(tcx: &ty::ctxt,
node_id: ast::NodeId,
- substs: Vec<ty::t> ) {
- if substs.len() > 0u {
- debug!("write_substs_to_tcx({}, {:?})", node_id,
- substs.iter().map(|t| ppaux::ty_to_str(tcx, *t)).collect::<Vec<~str>>());
- assert!(substs.iter().all(|t| !ty::type_needs_infer(*t)));
+ item_substs: ty::ItemSubsts) {
+ if !item_substs.is_noop() {
+ debug!("write_substs_to_tcx({}, {})",
+ node_id,
+ item_substs.repr(tcx));
- tcx.node_type_substs.borrow_mut().insert(node_id, substs);
+ assert!(item_substs.substs.tps.iter().
+ all(|t| !ty::type_needs_infer(*t)));
+
+ tcx.item_substs.borrow_mut().insert(node_id, item_substs);
}
}
pub fn lookup_def_tcx(tcx:&ty::ctxt, sp: Span, id: ast::NodeId) -> ast::Def {
}
}
+impl Repr for ty::ItemSubsts {
+ fn repr(&self, tcx: &ctxt) -> ~str {
+ format!("ItemSubsts({})", self.substs.repr(tcx))
+ }
+}
+
impl Repr for ty::RegionSubsts {
fn repr(&self, tcx: &ctxt) -> ~str {
match *self {