auto merge of #14055 : nikomatsakis/rust/issue-5527-use-substs-in-trans, r=pcwalton
Code to use `ty::substs` in trans. As part of this, uncovered (and fixed) issue #14050. r? @pcwalton
This commit is contained in:
commit
3d6cf1d525
@ -128,7 +128,7 @@ pub enum astencode_tag { // Reserves 0x40 -- 0x5f
|
||||
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,
|
||||
|
@ -657,13 +657,13 @@ 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, 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))
|
||||
@ -744,7 +744,7 @@ impl<'a> vtable_decoder_helpers for reader::Decoder<'a> {
|
||||
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))
|
||||
@ -962,11 +962,11 @@ fn encode_side_tables_for_id(ecx: &e::EncodeContext,
|
||||
})
|
||||
}
|
||||
|
||||
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);
|
||||
})
|
||||
})
|
||||
}
|
||||
@ -1091,6 +1091,9 @@ trait ebml_decoder_decoder_helpers {
|
||||
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> {
|
||||
@ -1115,6 +1118,21 @@ 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
|
||||
@ -1312,9 +1330,12 @@ fn decode_side_tables(xcx: &ExtendedDecodeContext,
|
||||
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| {
|
||||
|
@ -245,10 +245,10 @@ pub fn check_expr(cx: &mut Context, e: &Expr) {
|
||||
{
|
||||
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();
|
||||
@ -341,15 +341,19 @@ fn check_trait_cast(cx: &mut Context, source_ty: ty::t, target_ty: ty::t, span:
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -195,6 +195,17 @@ impl Subst for ty::substs {
|
||||
}
|
||||
}
|
||||
|
||||
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,
|
||||
|
@ -478,7 +478,7 @@ pub fn note_unique_llvm_symbol(ccx: &CrateContext, sym: ~str) {
|
||||
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 {
|
||||
@ -486,16 +486,12 @@ pub fn get_res_dtor(ccx: &CrateContext,
|
||||
} else {
|
||||
did
|
||||
};
|
||||
if !substs.is_empty() {
|
||||
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);
|
||||
if !substs.tps.is_empty() || !substs.self_ty.is_none() {
|
||||
assert_eq!(did.krate, ast::LOCAL_CRATE);
|
||||
|
||||
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 {
|
||||
@ -503,10 +499,8 @@ pub fn get_res_dtor(ccx: &CrateContext,
|
||||
} 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,
|
||||
@ -670,7 +664,7 @@ pub fn iter_structural_ty<'r,
|
||||
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");
|
||||
@ -680,7 +674,7 @@ pub fn iter_structural_ty<'r,
|
||||
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;
|
||||
}
|
||||
@ -722,7 +716,7 @@ pub fn iter_structural_ty<'r,
|
||||
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());
|
||||
@ -748,7 +742,7 @@ pub fn iter_structural_ty<'r,
|
||||
&*repr,
|
||||
av,
|
||||
&**variant,
|
||||
substs.tps.as_slice(),
|
||||
substs,
|
||||
|x,y,z| f(x,y,z));
|
||||
Br(variant_cx, next_cx.llbb);
|
||||
}
|
||||
@ -1153,15 +1147,7 @@ pub fn new_fn_ctxt<'a>(ccx: &'a CrateContext,
|
||||
},
|
||||
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);
|
||||
|
||||
@ -1213,15 +1199,7 @@ pub fn init_function<'a>(fcx: &'a FunctionContext<'a>,
|
||||
|
||||
// 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
|
||||
@ -1508,18 +1486,8 @@ fn trans_enum_variant_or_tuple_like_struct(ccx: &CrateContext,
|
||||
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,
|
||||
|
@ -159,36 +159,36 @@ fn trans<'a>(bcx: &'a Block<'a>, expr: &ast::Expr) -> Callee<'a> {
|
||||
|
||||
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,
|
||||
@ -204,8 +204,7 @@ 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
|
||||
};
|
||||
@ -241,7 +240,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: 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 {
|
||||
/*!
|
||||
@ -255,7 +254,7 @@ pub fn trans_fn_ref_with_vtables(
|
||||
* - `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
|
||||
*/
|
||||
|
||||
@ -264,24 +263,18 @@ pub fn trans_fn_ref_with_vtables(
|
||||
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 => {}
|
||||
@ -510,7 +503,7 @@ pub fn trans_lang_call<'a>(
|
||||
trans_fn_ref_with_vtables_to_callee(bcx,
|
||||
did,
|
||||
0,
|
||||
vec!(),
|
||||
ty::substs::empty(),
|
||||
None)
|
||||
},
|
||||
ArgVals(args),
|
||||
|
@ -25,6 +25,7 @@ use middle::trans::datum::{Datum, Lvalue};
|
||||
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;
|
||||
@ -177,23 +178,24 @@ pub type ExternMap = HashMap<~str, ValueRef>;
|
||||
// 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 {
|
||||
@ -202,6 +204,25 @@ 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>;
|
||||
@ -676,7 +697,7 @@ pub fn is_null(val: ValueRef) -> bool {
|
||||
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));
|
||||
@ -710,32 +731,28 @@ pub enum ExprOrMethodCall {
|
||||
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)
|
||||
@ -785,20 +802,10 @@ 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, 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) => {
|
||||
|
@ -793,16 +793,7 @@ pub fn create_function_debug_context(cx: &CrateContext,
|
||||
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));
|
||||
}
|
||||
}
|
||||
@ -811,16 +802,7 @@ pub fn create_function_debug_context(cx: &CrateContext,
|
||||
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));
|
||||
}
|
||||
|
||||
@ -834,7 +816,7 @@ pub fn create_function_debug_context(cx: &CrateContext,
|
||||
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
|
||||
};
|
||||
|
||||
@ -890,7 +872,7 @@ pub fn create_function_debug_context(cx: &CrateContext,
|
||||
|
||||
// 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());
|
||||
}
|
||||
|
@ -236,7 +236,7 @@ fn trans_struct_drop<'a>(bcx: &'a Block<'a>,
|
||||
|
||||
// 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 {
|
||||
|
@ -295,7 +295,7 @@ pub fn trans_intrinsic(ccx: &CrateContext,
|
||||
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));
|
||||
}
|
||||
@ -305,7 +305,7 @@ pub fn trans_intrinsic(ccx: &CrateContext,
|
||||
// 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,
|
||||
@ -314,17 +314,17 @@ pub fn trans_intrinsic(ccx: &CrateContext,
|
||||
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);
|
||||
|
||||
@ -339,7 +339,7 @@ pub fn trans_intrinsic(ccx: &CrateContext,
|
||||
"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
|
||||
@ -354,7 +354,7 @@ pub fn trans_intrinsic(ccx: &CrateContext,
|
||||
}
|
||||
}
|
||||
"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); }
|
||||
@ -364,7 +364,7 @@ pub fn trans_intrinsic(ccx: &CrateContext,
|
||||
}
|
||||
"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()));
|
||||
@ -377,7 +377,8 @@ pub fn trans_intrinsic(ccx: &CrateContext,
|
||||
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);
|
||||
|
||||
@ -444,11 +445,11 @@ pub fn trans_intrinsic(ccx: &CrateContext,
|
||||
}
|
||||
}
|
||||
"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" => {
|
||||
@ -464,14 +465,20 @@ pub fn trans_intrinsic(ccx: &CrateContext,
|
||||
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"),
|
||||
|
@ -198,7 +198,7 @@ pub fn trans_static_method_callee(bcx: &Block,
|
||||
|
||||
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) =
|
||||
@ -277,39 +277,41 @@ 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: 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
|
||||
@ -333,6 +335,12 @@ fn combine_impl_and_methods_tps(bcx: &Block,
|
||||
}
|
||||
}
|
||||
|
||||
let ty_substs = ty::substs {
|
||||
tps: tps,
|
||||
regions: ty::ErasedRegions,
|
||||
self_ty: rcvr_self_ty
|
||||
};
|
||||
|
||||
(ty_substs, vtables)
|
||||
}
|
||||
|
||||
@ -485,7 +493,7 @@ pub fn make_vtable<I: Iterator<ValueRef>>(ccx: &CrateContext,
|
||||
|
||||
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();
|
||||
|
@ -85,9 +85,8 @@ pub fn monomorphic_fn(ccx: &CrateContext,
|
||||
}
|
||||
|
||||
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
|
||||
};
|
||||
|
||||
@ -139,8 +138,7 @@ pub fn monomorphic_fn(ccx: &CrateContext,
|
||||
|
||||
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.
|
||||
@ -157,13 +155,19 @@ pub fn monomorphic_fn(ccx: &CrateContext,
|
||||
// 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)
|
||||
}
|
||||
};
|
||||
|
||||
@ -334,7 +338,10 @@ pub fn make_vtable_id(ccx: &CrateContext,
|
||||
&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?
|
||||
|
@ -255,9 +255,9 @@ pub struct ctxt {
|
||||
|
||||
// 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>>>,
|
||||
@ -1060,6 +1060,13 @@ pub struct TraitDef {
|
||||
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
|
||||
@ -1086,7 +1093,7 @@ pub fn mk_ctxt(s: Session,
|
||||
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,
|
||||
@ -1510,47 +1517,13 @@ pub fn walk_regions_and_ty(cx: &ctxt, ty: t, fldr: |r: Region|, fldt: |t: t|)
|
||||
|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)
|
||||
}
|
||||
}
|
||||
|
||||
@ -2669,11 +2642,10 @@ pub fn node_id_to_type_opt(cx: &ctxt, id: ast::NodeId) -> Option<t> {
|
||||
}
|
||||
}
|
||||
|
||||
// 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(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -2991,21 +2963,6 @@ impl AutoRef {
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
|
@ -52,7 +52,7 @@ can be broken down into several distinct phases:
|
||||
|
||||
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
|
||||
@ -161,7 +161,7 @@ pub struct Inherited<'a> {
|
||||
|
||||
// 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,
|
||||
@ -268,7 +268,7 @@ impl<'a> Inherited<'a> {
|
||||
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()),
|
||||
@ -1111,22 +1111,22 @@ impl<'a> FnCtxt<'a> {
|
||||
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);
|
||||
}
|
||||
@ -1204,8 +1204,8 @@ impl<'a> FnCtxt<'a> {
|
||||
|
||||
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 => { }
|
||||
}
|
||||
@ -3963,10 +3963,10 @@ pub fn instantiate_path(fcx: &FnCtxt,
|
||||
(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!("<<<");
|
||||
|
@ -299,7 +299,7 @@ pub fn regionck_expr(fcx: &FnCtxt, e: &ast::Expr) {
|
||||
// regionck assumes typeck succeeded
|
||||
rcx.visit_expr(e, ());
|
||||
}
|
||||
fcx.infcx().resolve_regions();
|
||||
fcx.infcx().resolve_regions_and_report_errors();
|
||||
}
|
||||
|
||||
pub fn regionck_fn(fcx: &FnCtxt, blk: &ast::Block) {
|
||||
@ -309,7 +309,7 @@ pub fn regionck_fn(fcx: &FnCtxt, blk: &ast::Block) {
|
||||
// regionck assumes typeck succeeded
|
||||
rcx.visit_block(blk, ());
|
||||
}
|
||||
fcx.infcx().resolve_regions();
|
||||
fcx.infcx().resolve_regions_and_report_errors();
|
||||
}
|
||||
|
||||
impl<'a> Visitor<()> for Rcx<'a> {
|
||||
|
@ -15,6 +15,7 @@ use middle::ty_fold::TypeFolder;
|
||||
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;
|
||||
@ -444,7 +445,7 @@ fn search_for_vtable(vcx: &VtableContext,
|
||||
// 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() {
|
||||
@ -625,7 +626,7 @@ pub fn early_resolve_expr(ex: &ast::Expr, fcx: &FnCtxt, is_early: bool) {
|
||||
};
|
||||
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);
|
||||
@ -639,7 +640,7 @@ pub fn early_resolve_expr(ex: &ast::Expr, fcx: &FnCtxt, is_early: bool) {
|
||||
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);
|
||||
}
|
||||
@ -734,6 +735,9 @@ pub fn resolve_impl(tcx: &ty::ctxt,
|
||||
impl_item: &ast::Item,
|
||||
impl_generics: &ty::Generics,
|
||||
impl_trait_ref: &ty::TraitRef) {
|
||||
debug!("resolve_impl(impl_item.id={})",
|
||||
impl_item.id);
|
||||
|
||||
let param_env = ty::construct_parameter_environment(
|
||||
tcx,
|
||||
None,
|
||||
@ -744,6 +748,7 @@ pub fn resolve_impl(tcx: &ty::ctxt,
|
||||
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 };
|
||||
@ -774,13 +779,19 @@ pub fn resolve_impl(tcx: &ty::ctxt,
|
||||
lookup_vtables_for_param(&vcx, impl_item.span, None,
|
||||
¶m_bounds, t, false);
|
||||
|
||||
infcx.resolve_regions_and_report_errors();
|
||||
|
||||
let res = impl_res {
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -21,12 +21,15 @@ use middle::typeck::check::FnCtxt;
|
||||
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;
|
||||
@ -61,6 +64,17 @@ pub fn resolve_type_vars_in_fn(fcx: &FnCtxt,
|
||||
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
|
||||
@ -159,7 +173,7 @@ impl<'cx> Visitor<()> for WritebackCx<'cx> {
|
||||
}
|
||||
|
||||
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, ());
|
||||
}
|
||||
@ -177,7 +191,7 @@ impl<'cx> WritebackCx<'cx> {
|
||||
|
||||
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 {}",
|
||||
@ -194,17 +208,14 @@ impl<'cx> WritebackCx<'cx> {
|
||||
|
||||
// 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));
|
||||
});
|
||||
}
|
||||
|
||||
@ -228,12 +239,12 @@ impl<'cx> WritebackCx<'cx> {
|
||||
}
|
||||
_ => {
|
||||
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) => {
|
||||
@ -245,7 +256,7 @@ impl<'cx> WritebackCx<'cx> {
|
||||
|
||||
ty::AutoDerefRef(ty::AutoDerefRef {
|
||||
autoderefs: adj.autoderefs,
|
||||
autoref: adj.autoref.resolve(self.fcx, reason),
|
||||
autoref: self.resolve(&adj.autoref, reason),
|
||||
})
|
||||
}
|
||||
|
||||
@ -269,8 +280,8 @@ impl<'cx> WritebackCx<'cx> {
|
||||
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
|
||||
@ -297,7 +308,7 @@ impl<'cx> WritebackCx<'cx> {
|
||||
// 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()));
|
||||
@ -306,6 +317,10 @@ impl<'cx> WritebackCx<'cx> {
|
||||
None => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn resolve<T:ResolveIn>(&self, t: &T, reason: ResolveReason) -> T {
|
||||
t.resolve_in(&mut Resolver::new(self.fcx, reason))
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
@ -315,18 +330,20 @@ enum ResolveReason {
|
||||
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,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -334,59 +351,67 @@ impl ResolveReason {
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// 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)
|
||||
@ -395,12 +420,23 @@ impl Resolve for vtable_origin {
|
||||
}
|
||||
}
|
||||
|
||||
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,
|
||||
}
|
||||
|
||||
@ -409,15 +445,29 @@ impl<'cx> Resolver<'cx> {
|
||||
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: {}",
|
||||
@ -425,7 +475,7 @@ impl<'cx> Resolver<'cx> {
|
||||
}
|
||||
|
||||
ResolvingLocal(span) => {
|
||||
self.tcx().sess.span_err(
|
||||
self.tcx.sess.span_err(
|
||||
span,
|
||||
format!("cannot determine a type for \
|
||||
this local variable: {}",
|
||||
@ -433,7 +483,7 @@ impl<'cx> Resolver<'cx> {
|
||||
}
|
||||
|
||||
ResolvingPattern(span) => {
|
||||
self.tcx().sess.span_err(
|
||||
self.tcx.sess.span_err(
|
||||
span,
|
||||
format!("cannot determine a type for \
|
||||
this pattern binding: {}",
|
||||
@ -441,16 +491,22 @@ impl<'cx> Resolver<'cx> {
|
||||
}
|
||||
|
||||
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"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -458,7 +514,7 @@ impl<'cx> Resolver<'cx> {
|
||||
|
||||
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 {
|
||||
@ -466,7 +522,7 @@ impl<'cx> TypeFolder for Resolver<'cx> {
|
||||
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);
|
||||
@ -476,7 +532,7 @@ impl<'cx> TypeFolder for Resolver<'cx> {
|
||||
}
|
||||
|
||||
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);
|
||||
|
@ -644,7 +644,7 @@ impl<'a> InferCtxt<'a> {
|
||||
self.region_vars.new_bound(binder_id)
|
||||
}
|
||||
|
||||
pub fn resolve_regions(&self) {
|
||||
pub fn resolve_regions_and_report_errors(&self) {
|
||||
let errors = self.region_vars.resolve_regions();
|
||||
self.report_region_errors(&errors); // see error_reporting.rs
|
||||
}
|
||||
|
@ -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, ty::substs, vtable_res),
|
||||
|
||||
/*
|
||||
Dynamic vtable, comes from a parameter that has a bound on it:
|
||||
@ -253,13 +253,16 @@ pub fn write_ty_to_tcx(tcx: &ty::ctxt, node_id: ast::NodeId, ty: ty::t) {
|
||||
}
|
||||
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 {
|
||||
|
@ -561,6 +561,12 @@ impl Repr for ty::substs {
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
|
@ -0,0 +1,41 @@
|
||||
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// Check that when we test the supertrait we ensure consistent use of
|
||||
// lifetime parameters. In this case, implementing T2<'a,'b> requires
|
||||
// an impl of T1<'a>, but we have an impl of T1<'b>.
|
||||
|
||||
trait T1<'x> {
|
||||
fn x(&self) -> &'x int;
|
||||
}
|
||||
|
||||
trait T2<'x, 'y> : T1<'x> {
|
||||
fn y(&self) -> &'y int;
|
||||
}
|
||||
|
||||
struct S<'a, 'b> {
|
||||
a: &'a int,
|
||||
b: &'b int
|
||||
}
|
||||
|
||||
impl<'a,'b> T1<'b> for S<'a, 'b> {
|
||||
fn x(&self) -> &'b int {
|
||||
self.b
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a,'b> T2<'a, 'b> for S<'a, 'b> { //~ ERROR cannot infer an appropriate lifetime
|
||||
fn y(&self) -> &'b int {
|
||||
self.b
|
||||
}
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
}
|
Loading…
Reference in New Issue
Block a user