提交 088c94ae 编写于 作者: N Niko Matsakis

trans -- stop tracking vtables precisely, instead recompute as needed.

上级 6349a612
......@@ -1470,17 +1470,17 @@ fn check_expr(&mut self, cx: &Context, e: &ast::Expr) {
def_id
}
typeck::MethodParam(typeck::MethodParam {
trait_id: trait_id,
trait_ref: ref trait_ref,
method_num: index,
..
})
| typeck::MethodObject(typeck::MethodObject {
trait_id: trait_id,
}) |
typeck::MethodObject(typeck::MethodObject {
trait_ref: ref trait_ref,
method_num: index,
..
}) => {
match ty::trait_item(cx.tcx,
trait_id,
trait_ref.def_id,
index) {
ty::MethodTraitItem(method) => {
method.def_id
......
......@@ -140,9 +140,10 @@ pub enum astencode_tag { // Reserves 0x40 -- 0x5f
tag_table_unboxed_closures = 0x54,
tag_table_upvar_borrow_map = 0x55,
tag_table_capture_modes = 0x56,
tag_table_object_cast_map = 0x57,
}
static first_astencode_tag: uint = tag_ast as uint;
static last_astencode_tag: uint = tag_table_capture_modes as uint;
static last_astencode_tag: uint = tag_table_object_cast_map as uint;
impl astencode_tag {
pub fn from_uint(value : uint) -> Option<astencode_tag> {
let is_a_tag = first_astencode_tag <= value && value <= last_astencode_tag;
......
......@@ -20,9 +20,7 @@
use metadata::decoder;
use metadata::tyencode;
use middle::ty::{lookup_item_type};
use middle::astencode;
use middle::ty;
use middle::typeck;
use middle::stability;
use middle;
use util::nodemap::{NodeMap, NodeSet};
......@@ -125,14 +123,6 @@ fn encode_trait_ref(rbml_w: &mut Encoder,
rbml_w.end_tag();
}
fn encode_impl_vtables(rbml_w: &mut Encoder,
ecx: &EncodeContext,
vtables: &typeck::vtable_res) {
rbml_w.start_tag(tag_item_impl_vtables);
astencode::encode_vtable_res(ecx, rbml_w, vtables);
rbml_w.end_tag();
}
// Item info table encoding
fn encode_family(rbml_w: &mut Encoder, c: char) {
rbml_w.start_tag(tag_items_data_item_family);
......@@ -191,6 +181,18 @@ pub fn write_type(ecx: &EncodeContext,
tyencode::enc_ty(rbml_w.writer, ty_str_ctxt, typ);
}
pub fn write_trait_ref(ecx: &EncodeContext,
rbml_w: &mut Encoder,
trait_ref: &ty::TraitRef) {
let ty_str_ctxt = &tyencode::ctxt {
diag: ecx.diag,
ds: def_to_string,
tcx: ecx.tcx,
abbrevs: &ecx.type_abbrevs
};
tyencode::enc_trait_ref(rbml_w.writer, ty_str_ctxt, trait_ref);
}
pub fn write_region(ecx: &EncodeContext,
rbml_w: &mut Encoder,
r: ty::Region) {
......@@ -399,7 +401,7 @@ fn encode_reexported_static_base_methods(ecx: &EncodeContext,
let impl_items = ecx.tcx.impl_items.borrow();
match ecx.tcx.inherent_impls.borrow().find(&exp.def_id) {
Some(implementations) => {
for base_impl_did in implementations.borrow().iter() {
for base_impl_did in implementations.iter() {
for &method_did in impl_items.get(base_impl_did).iter() {
let impl_item = ty::impl_or_trait_item(
ecx.tcx,
......@@ -946,7 +948,7 @@ fn encode_inherent_implementations(ecx: &EncodeContext,
match ecx.tcx.inherent_impls.borrow().find(&def_id) {
None => {}
Some(implementations) => {
for &impl_def_id in implementations.borrow().iter() {
for &impl_def_id in implementations.iter() {
rbml_w.start_tag(tag_items_data_item_inherent_impl);
encode_def_id(rbml_w, impl_def_id);
rbml_w.end_tag();
......@@ -1203,8 +1205,6 @@ fn add_to_index(item: &Item, rbml_w: &Encoder,
let trait_ref = ty::node_id_to_trait_ref(
tcx, ast_trait_ref.ref_id);
encode_trait_ref(rbml_w, ecx, &*trait_ref, tag_item_trait_ref);
let impl_vtables = ty::lookup_impl_vtables(tcx, def_id);
encode_impl_vtables(rbml_w, ecx, &impl_vtables);
}
encode_path(rbml_w, path.clone());
encode_stability(rbml_w, stab);
......
......@@ -43,6 +43,7 @@
use std::io::Seek;
use std::mem;
use std::gc::GC;
use std::rc::Rc;
use rbml::io::SeekableMemWriter;
use rbml::{reader, writer};
......@@ -589,7 +590,7 @@ fn encode_method_callee(ecx: &e::EncodeContext,
adjustment.encode(rbml_w)
});
rbml_w.emit_struct_field("origin", 1u, |rbml_w| {
method.origin.encode(rbml_w)
Ok(rbml_w.emit_method_origin(ecx, &method.origin))
});
rbml_w.emit_struct_field("ty", 2u, |rbml_w| {
Ok(rbml_w.emit_ty(ecx, method.ty))
......@@ -610,9 +611,7 @@ fn read_method_callee(&mut self, dcx: &DecodeContext)
}).unwrap();
Ok((adjustment, MethodCallee {
origin: this.read_struct_field("origin", 1, |this| {
let method_origin: MethodOrigin =
Decodable::decode(this).unwrap();
Ok(method_origin.tr(dcx))
Ok(this.read_method_origin(dcx))
}).unwrap(),
ty: this.read_struct_field("ty", 2, |this| {
Ok(this.read_ty(dcx))
......@@ -635,15 +634,16 @@ fn tr(&self, dcx: &DecodeContext) -> MethodOrigin {
typeck::MethodParam(ref mp) => {
typeck::MethodParam(
typeck::MethodParam {
trait_id: mp.trait_id.tr(dcx),
.. *mp
// def-id is already translated when we read it out
trait_ref: mp.trait_ref.clone(),
method_num: mp.method_num,
}
)
}
typeck::MethodObject(ref mo) => {
typeck::MethodObject(
typeck::MethodObject {
trait_id: mo.trait_id.tr(dcx),
trait_ref: mo.trait_ref.clone(),
.. *mo
}
)
......@@ -655,22 +655,6 @@ fn tr(&self, dcx: &DecodeContext) -> MethodOrigin {
// ______________________________________________________________________
// Encoding and decoding vtable_res
fn encode_vtable_res_with_key(ecx: &e::EncodeContext,
rbml_w: &mut Encoder,
adjustment: typeck::ExprAdjustment,
dr: &typeck::vtable_res) {
use serialize::Encoder;
rbml_w.emit_struct("VtableWithKey", 2, |rbml_w| {
rbml_w.emit_struct_field("adjustment", 0u, |rbml_w| {
adjustment.encode(rbml_w)
});
rbml_w.emit_struct_field("vtable_res", 1u, |rbml_w| {
Ok(encode_vtable_res(ecx, rbml_w, dr))
})
}).unwrap()
}
pub fn encode_vtable_res(ecx: &e::EncodeContext,
rbml_w: &mut Encoder,
dr: &typeck::vtable_res) {
......@@ -913,11 +897,15 @@ trait rbml_writer_helpers {
fn emit_closure_type(&mut self,
ecx: &e::EncodeContext,
closure_type: &ty::ClosureTy);
fn emit_method_origin(&mut self,
ecx: &e::EncodeContext,
method_origin: &typeck::MethodOrigin);
fn emit_ty(&mut self, ecx: &e::EncodeContext, ty: ty::t);
fn emit_tys(&mut self, ecx: &e::EncodeContext, tys: &[ty::t]);
fn emit_type_param_def(&mut self,
ecx: &e::EncodeContext,
type_param_def: &ty::TypeParameterDef);
fn emit_trait_ref(&mut self, ecx: &e::EncodeContext, ty: &ty::TraitRef);
fn emit_polytype(&mut self,
ecx: &e::EncodeContext,
pty: ty::Polytype);
......@@ -939,6 +927,63 @@ fn emit_closure_type(&mut self,
});
}
fn emit_method_origin(&mut self,
ecx: &e::EncodeContext,
method_origin: &typeck::MethodOrigin)
{
use serialize::Encoder;
self.emit_enum("MethodOrigin", |this| {
match *method_origin {
typeck::MethodStatic(def_id) => {
this.emit_enum_variant("MethodStatic", 0, 1, |this| {
Ok(this.emit_def_id(def_id))
})
}
typeck::MethodStaticUnboxedClosure(def_id) => {
this.emit_enum_variant("MethodStaticUnboxedClosure", 1, 1, |this| {
Ok(this.emit_def_id(def_id))
})
}
typeck::MethodParam(ref p) => {
this.emit_enum_variant("MethodParam", 2, 1, |this| {
this.emit_struct("MethodParam", 2, |this| {
try!(this.emit_struct_field("trait_ref", 0, |this| {
Ok(this.emit_trait_ref(ecx, &*p.trait_ref))
}));
try!(this.emit_struct_field("method_num", 0, |this| {
this.emit_uint(p.method_num)
}));
Ok(())
})
})
}
typeck::MethodObject(ref o) => {
this.emit_enum_variant("MethodObject", 3, 1, |this| {
this.emit_struct("MethodObject", 2, |this| {
try!(this.emit_struct_field("trait_ref", 0, |this| {
Ok(this.emit_trait_ref(ecx, &*o.trait_ref))
}));
try!(this.emit_struct_field("object_trait_id", 0, |this| {
Ok(this.emit_def_id(o.object_trait_id))
}));
try!(this.emit_struct_field("method_num", 0, |this| {
this.emit_uint(o.method_num)
}));
try!(this.emit_struct_field("real_index", 0, |this| {
this.emit_uint(o.real_index)
}));
Ok(())
})
})
}
}
});
}
fn emit_ty(&mut self, ecx: &e::EncodeContext, ty: ty::t) {
self.emit_opaque(|this| Ok(e::write_type(ecx, this, ty)));
}
......@@ -947,6 +992,12 @@ fn emit_tys(&mut self, ecx: &e::EncodeContext, tys: &[ty::t]) {
self.emit_from_vec(tys, |this, ty| Ok(this.emit_ty(ecx, *ty)));
}
fn emit_trait_ref(&mut self,
ecx: &e::EncodeContext,
trait_ref: &ty::TraitRef) {
self.emit_opaque(|this| Ok(e::write_trait_ref(ecx, this, trait_ref)));
}
fn emit_type_param_def(&mut self,
ecx: &e::EncodeContext,
type_param_def: &ty::TypeParameterDef) {
......@@ -1103,12 +1154,16 @@ fn emit_unsize_kind(&mut self, ecx: &e::EncodeContext, uk: &ty::UnsizeKind) {
this.emit_enum_variant_arg(1, |this| idx.encode(this))
})
}
ty::UnsizeVtable(ref b, def_id, ref substs) => {
this.emit_enum_variant("UnsizeVtable", 2, 3, |this| {
ty::UnsizeVtable(ty::TyTrait { def_id: def_id,
bounds: ref b,
substs: ref substs },
self_ty) => {
this.emit_enum_variant("UnsizeVtable", 2, 4, |this| {
this.emit_enum_variant_arg(
0, |this| Ok(this.emit_existential_bounds(ecx, b)));
this.emit_enum_variant_arg(1, |this| def_id.encode(this));
this.emit_enum_variant_arg(2, |this| Ok(this.emit_substs(ecx, substs)))
this.emit_enum_variant_arg(2, |this| Ok(this.emit_ty(ecx, self_ty)));
this.emit_enum_variant_arg(3, |this| Ok(this.emit_substs(ecx, substs)))
})
}
}
......@@ -1282,11 +1337,11 @@ fn encode_side_tables_for_id(ecx: &e::EncodeContext,
})
}
for &dr in tcx.vtable_map.borrow().find(&method_call).iter() {
rbml_w.tag(c::tag_table_vtable_map, |rbml_w| {
for &trait_ref in tcx.object_cast_map.borrow().find(&id).iter() {
rbml_w.tag(c::tag_table_object_cast_map, |rbml_w| {
rbml_w.id(id);
rbml_w.tag(c::tag_table_val, |rbml_w| {
encode_vtable_res_with_key(ecx, rbml_w, method_call.adjustment, dr);
rbml_w.emit_trait_ref(ecx, &**trait_ref);
})
})
}
......@@ -1303,15 +1358,6 @@ fn encode_side_tables_for_id(ecx: &e::EncodeContext,
})
})
}
for &dr in tcx.vtable_map.borrow().find(&method_call).iter() {
rbml_w.tag(c::tag_table_vtable_map, |rbml_w| {
rbml_w.id(id);
rbml_w.tag(c::tag_table_val, |rbml_w| {
encode_vtable_res_with_key(ecx, rbml_w, method_call.adjustment, dr);
})
})
}
}
ty::AutoDerefRef(ref adj) => {
assert!(!ty::adjust_is_object(adjustment));
......@@ -1326,16 +1372,6 @@ fn encode_side_tables_for_id(ecx: &e::EncodeContext,
})
})
}
for &dr in tcx.vtable_map.borrow().find(&method_call).iter() {
rbml_w.tag(c::tag_table_vtable_map, |rbml_w| {
rbml_w.id(id);
rbml_w.tag(c::tag_table_val, |rbml_w| {
encode_vtable_res_with_key(ecx, rbml_w,
method_call.adjustment, dr);
})
})
}
}
}
_ => {
......@@ -1378,8 +1414,10 @@ fn opt_child(&self, tag: c::astencode_tag) -> Option<rbml::Doc<'a>> {
}
trait rbml_decoder_decoder_helpers {
fn read_method_origin(&mut self, dcx: &DecodeContext) -> typeck::MethodOrigin;
fn read_ty(&mut self, dcx: &DecodeContext) -> ty::t;
fn read_tys(&mut self, dcx: &DecodeContext) -> Vec<ty::t>;
fn read_trait_ref(&mut self, dcx: &DecodeContext) -> Rc<ty::TraitRef>;
fn read_type_param_def(&mut self, dcx: &DecodeContext)
-> ty::TypeParameterDef;
fn read_polytype(&mut self, dcx: &DecodeContext)
......@@ -1447,6 +1485,77 @@ fn read_substs_nodcx(&mut self,
}).unwrap()
}
fn read_method_origin(&mut self, dcx: &DecodeContext)
-> typeck::MethodOrigin
{
self.read_enum("MethodOrigin", |this| {
let variants = ["MethodStatic", "MethodStaticUnboxedClosure",
"MethodParam", "MethodObject"];
this.read_enum_variant(variants, |this, i| {
Ok(match i {
0 => {
let def_id = this.read_def_id(dcx);
typeck::MethodStatic(def_id)
}
1 => {
let def_id = this.read_def_id(dcx);
typeck::MethodStaticUnboxedClosure(def_id)
}
2 => {
this.read_struct("MethodParam", 2, |this| {
Ok(typeck::MethodParam(
typeck::MethodParam {
trait_ref: {
this.read_struct_field("trait_ref", 0, |this| {
Ok(this.read_trait_ref(dcx))
}).unwrap()
},
method_num: {
this.read_struct_field("method_num", 1, |this| {
this.read_uint()
}).unwrap()
}
}))
}).unwrap()
}
3 => {
this.read_struct("MethodObject", 2, |this| {
Ok(typeck::MethodObject(
typeck::MethodObject {
trait_ref: {
this.read_struct_field("trait_ref", 0, |this| {
Ok(this.read_trait_ref(dcx))
}).unwrap()
},
object_trait_id: {
this.read_struct_field("object_trait_id", 1, |this| {
Ok(this.read_def_id(dcx))
}).unwrap()
},
method_num: {
this.read_struct_field("method_num", 2, |this| {
this.read_uint()
}).unwrap()
},
real_index: {
this.read_struct_field("real_index", 3, |this| {
this.read_uint()
}).unwrap()
},
}))
}).unwrap()
}
_ => fail!("..")
})
})
}).unwrap()
}
fn read_ty(&mut self, dcx: &DecodeContext) -> ty::t {
// Note: regions types embed local node ids. In principle, we
// should translate these node ids into the new decode
......@@ -1479,6 +1588,18 @@ fn read_tys(&mut self, dcx: &DecodeContext) -> Vec<ty::t> {
self.read_to_vec(|this| Ok(this.read_ty(dcx))).unwrap().move_iter().collect()
}
fn read_trait_ref(&mut self, dcx: &DecodeContext) -> Rc<ty::TraitRef> {
Rc::new(self.read_opaque(|this, doc| {
let ty = tydecode::parse_trait_ref_data(
doc.data,
dcx.cdata.cnum,
doc.start,
dcx.tcx,
|s, a| this.convert_def_id(dcx, s, a));
Ok(ty)
}).unwrap())
}
fn read_type_param_def(&mut self, dcx: &DecodeContext)
-> ty::TypeParameterDef {
self.read_opaque(|this, doc| {
......@@ -1667,10 +1788,14 @@ fn read_unsize_kind(&mut self, dcx: &DecodeContext) -> ty::UnsizeKind {
0, |this| Ok(this.read_existential_bounds(dcx))).unwrap();
let def_id: ast::DefId =
this.read_enum_variant_arg(1, |this| Decodable::decode(this)).unwrap();
let substs = this.read_enum_variant_arg(2,
let self_ty =
this.read_enum_variant_arg(2, |this| Ok(this.read_ty(dcx))).unwrap();
let substs = this.read_enum_variant_arg(3,
|this| Ok(this.read_substs(dcx))).unwrap();
ty::UnsizeVtable(b, def_id.tr(dcx), substs)
let ty_trait = ty::TyTrait { def_id: def_id.tr(dcx),
bounds: b,
substs: substs };
ty::UnsizeVtable(ty_trait, self_ty)
}
_ => fail!("bad enum variant for ty::UnsizeKind")
})
......@@ -1828,15 +1953,10 @@ fn decode_side_tables(dcx: &DecodeContext,
};
dcx.tcx.method_map.borrow_mut().insert(method_call, method);
}
c::tag_table_vtable_map => {
let (adjustment, vtable_res) =
val_dsr.read_vtable_res_with_key(dcx.tcx,
dcx.cdata);
let vtable_key = MethodCall {
expr_id: id,
adjustment: adjustment
};
dcx.tcx.vtable_map.borrow_mut().insert(vtable_key, vtable_res);
c::tag_table_object_cast_map => {
let trait_ref = val_dsr.read_trait_ref(dcx);
dcx.tcx.object_cast_map.borrow_mut()
.insert(id, trait_ref);
}
c::tag_table_adjustments => {
let adj: ty::AutoAdjustment = val_dsr.read_auto_adjustment(dcx);
......
......@@ -102,17 +102,17 @@ fn lookup_and_handle_method(&mut self, id: ast::NodeId,
}
typeck::MethodStaticUnboxedClosure(_) => {}
typeck::MethodParam(typeck::MethodParam {
trait_id: trait_id,
trait_ref: ref trait_ref,
method_num: index,
..
})
| typeck::MethodObject(typeck::MethodObject {
trait_id: trait_id,
}) |
typeck::MethodObject(typeck::MethodObject {
trait_ref: ref trait_ref,
method_num: index,
..
}) => {
let trait_item = ty::trait_item(self.tcx,
trait_id,
trait_ref.def_id,
index);
match trait_item {
ty::MethodTraitItem(method) => {
......
......@@ -174,11 +174,9 @@ fn from_method_origin(tcx: &ty::ctxt, origin: &MethodOrigin)
MethodStaticUnboxedClosure(def_id) => {
OverloadedCallType::from_unboxed_closure(tcx, def_id)
}
MethodParam(ref method_param) => {
OverloadedCallType::from_trait_id(tcx, method_param.trait_id)
}
MethodObject(ref method_object) => {
OverloadedCallType::from_trait_id(tcx, method_object.trait_id)
MethodParam(MethodParam { trait_ref: ref trait_ref, .. }) |
MethodObject(MethodObject { trait_ref: ref trait_ref, .. }) => {
OverloadedCallType::from_trait_id(tcx, trait_ref.def_id)
}
}
}
......
......@@ -782,19 +782,19 @@ fn check_path(&mut self, span: Span, path_id: ast::NodeId, path: &ast::Path) {
}
// Checks that a method is in scope.
fn check_method(&mut self, span: Span, origin: MethodOrigin,
fn check_method(&mut self, span: Span, origin: &MethodOrigin,
ident: ast::Ident) {
match origin {
match *origin {
MethodStatic(method_id) => {
self.check_static_method(span, method_id, ident)
}
MethodStaticUnboxedClosure(_) => {}
// Trait methods are always all public. The only controlling factor
// is whether the trait itself is accessible or not.
MethodParam(MethodParam { trait_id: trait_id, .. }) |
MethodObject(MethodObject { trait_id: trait_id, .. }) => {
self.report_error(self.ensure_public(span, trait_id, None,
"source trait"));
MethodParam(MethodParam { trait_ref: ref trait_ref, .. }) |
MethodObject(MethodObject { trait_ref: ref trait_ref, .. }) => {
self.report_error(self.ensure_public(span, trait_ref.def_id,
None, "source trait"));
}
}
}
......@@ -835,7 +835,7 @@ fn visit_expr(&mut self, expr: &ast::Expr) {
}
Some(method) => {
debug!("(privacy checking) checking impl method");
self.check_method(expr.span, method.origin, ident.node);
self.check_method(expr.span, &method.origin, ident.node);
}
}
}
......
......@@ -908,10 +908,10 @@ fn process_method_call(&mut self,
};
(Some(def_id), decl_id)
}
typeck::MethodParam(mp) => {
typeck::MethodParam(ref mp) => {
// method invoked on a type parameter
let trait_item = ty::trait_item(&self.analysis.ty_cx,
mp.trait_id,
mp.trait_ref.def_id,
mp.method_num);
match trait_item {
ty::MethodTraitItem(method) => {
......@@ -919,10 +919,10 @@ fn process_method_call(&mut self,
}
}
},
typeck::MethodObject(mo) => {
typeck::MethodObject(ref mo) => {
// method invoked on a trait instance
let trait_item = ty::trait_item(&self.analysis.ty_cx,
mo.trait_id,
mo.trait_ref.def_id,
mo.method_num);
match trait_item {
ty::MethodTraitItem(method) => {
......
......@@ -164,6 +164,11 @@ pub fn with_self_ty(&self, self_ty: ty::t) -> Substs {
s
}
pub fn erase_regions(self) -> Substs {
let Substs { types: types, regions: _ } = self;
Substs { types: types, regions: ErasedRegions }
}
pub fn regions<'a>(&'a self) -> &'a VecPerParamSpace<ty::Region> {
/*!
* Since ErasedRegions are only to be used in trans, most of
......
......@@ -75,7 +75,6 @@
use middle::trans::type_of::*;
use middle::trans::value::Value;
use middle::ty;
use middle::typeck;
use util::common::indenter;
use util::ppaux::{Repr, ty_to_string};
use util::sha2::Sha256;
......@@ -547,8 +546,7 @@ pub fn get_res_dtor(ccx: &CrateContext,
// Since we're in trans we don't care for any region parameters
let ref substs = subst::Substs::erased(substs.types.clone());
let vtables = typeck::check::vtable::trans_resolve_method(ccx.tcx(), did.node, substs);
let (val, _) = monomorphize::monomorphic_fn(ccx, did, substs, vtables, None);
let (val, _) = monomorphize::monomorphic_fn(ccx, did, substs, None);
val
} else if did.krate == ast::LOCAL_CRATE {
......
......@@ -25,7 +25,7 @@
use metadata::csearch;
use middle::def;
use middle::subst;
use middle::subst::{Subst, VecPerParamSpace};
use middle::subst::{Subst};
use middle::trans::adt;
use middle::trans::base;
use middle::trans::base::*;
......@@ -47,7 +47,6 @@
use middle::trans::type_::Type;
use middle::trans::type_of;
use middle::ty;
use middle::typeck;
use middle::typeck::coherence::make_substs_for_receiver_types;
use middle::typeck::MethodCall;
use util::ppaux::Repr;
......@@ -227,61 +226,27 @@ pub fn trans_fn_ref(bcx: Block, def_id: ast::DefId, node: ExprOrMethodCall) -> V
let _icx = push_ctxt("trans_fn_ref");
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={:?}, substs={}, vtables={})",
debug!("trans_fn_ref(def_id={}, node={:?}, substs={})",
def_id.repr(bcx.tcx()),
node,
substs.repr(bcx.tcx()),
vtables.repr(bcx.tcx()));
trans_fn_ref_with_vtables(bcx, def_id, node, substs, vtables)
substs.repr(bcx.tcx()));
trans_fn_ref_with_substs(bcx, def_id, node, substs)
}
fn trans_fn_ref_with_vtables_to_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
def_id: ast::DefId,
ref_id: ast::NodeId,
substs: subst::Substs,
vtables: typeck::vtable_res)
-> Callee<'blk, 'tcx> {
fn trans_fn_ref_with_substs_to_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
def_id: ast::DefId,
ref_id: ast::NodeId,
substs: subst::Substs)
-> Callee<'blk, 'tcx> {
Callee {
bcx: bcx,
data: Fn(trans_fn_ref_with_vtables(bcx,
def_id,
ExprId(ref_id),
substs,
vtables)),
data: Fn(trans_fn_ref_with_substs(bcx,
def_id,
ExprId(ref_id),
substs)),
}
}
fn resolve_default_method_vtables(bcx: Block,
impl_id: ast::DefId,
substs: &subst::Substs,
impl_vtables: typeck::vtable_res)
-> typeck::vtable_res
{
// Get the vtables that the impl implements the trait at
let impl_res = ty::lookup_impl_vtables(bcx.tcx(), impl_id);
// Build up a param_substs that we are going to resolve the
// trait_vtables under.
let param_substs = param_substs {
substs: (*substs).clone(),
vtables: impl_vtables.clone()
};
let mut param_vtables = resolve_vtables_under_param_substs(
bcx.tcx(), &param_substs, &impl_res);
// Now we pull any vtables for parameters on the actual method.
param_vtables.push_all(subst::FnSpace,
impl_vtables.get_slice(subst::FnSpace));
param_vtables
}
/// Translates the adapter that deconstructs a `Box<Trait>` object into
/// `Trait` so that a by-value self method can be called.
pub fn trans_unboxing_shim(bcx: Block,
......@@ -408,12 +373,11 @@ pub fn trans_unboxing_shim(bcx: Block,
llfn
}
pub fn trans_fn_ref_with_vtables(
pub fn trans_fn_ref_with_substs(
bcx: Block, //
def_id: ast::DefId, // def id of fn
node: ExprOrMethodCall, // node id of use of fn; may be zero if N/A
substs: subst::Substs, // values for fn's ty params
vtables: typeck::vtable_res) // vtables for the call
substs: subst::Substs) // vtables for the call
-> ValueRef
{
/*!
......@@ -428,20 +392,18 @@ pub fn trans_fn_ref_with_vtables(
* 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.
* - `substs`: values for each of the fn/method's parameters
* - `vtables`: values for each bound on each of the type parameters
*/
let _icx = push_ctxt("trans_fn_ref_with_vtables");
let _icx = push_ctxt("trans_fn_ref_with_substs");
let ccx = bcx.ccx();
let tcx = bcx.tcx();
debug!("trans_fn_ref_with_vtables(bcx={}, def_id={}, node={:?}, \
substs={}, vtables={})",
debug!("trans_fn_ref_with_substs(bcx={}, def_id={}, node={:?}, \
substs={})",
bcx.to_str(),
def_id.repr(tcx),
node,
substs.repr(tcx),
vtables.repr(tcx));
substs.repr(tcx));
assert!(substs.types.all(|t| !ty::type_needs_infer(*t)));
......@@ -456,9 +418,8 @@ pub fn trans_fn_ref_with_vtables(
// We need to do a bunch of special handling for default methods.
// We need to modify the def_id and our substs in order to monomorphize
// the function.
let (is_default, def_id, substs, vtables) =
match ty::provided_source(tcx, def_id) {
None => (false, def_id, substs, vtables),
let (is_default, def_id, substs) = match ty::provided_source(tcx, def_id) {
None => (false, def_id, substs),
Some(source_id) => {
// There are two relevant substitutions when compiling
// default methods. First, there is the substitution for
......@@ -491,23 +452,11 @@ pub fn trans_fn_ref_with_vtables(
debug!("trans_fn_with_vtables - default method: \
substs = {}, trait_subst = {}, \
first_subst = {}, new_subst = {}, \
vtables = {}",
first_subst = {}, new_subst = {}",
substs.repr(tcx), trait_ref.substs.repr(tcx),
first_subst.repr(tcx), new_substs.repr(tcx),
vtables.repr(tcx));
let param_vtables =
resolve_default_method_vtables(bcx,
impl_id,
&substs,
vtables);
debug!("trans_fn_with_vtables - default method: \
param_vtables = {}",
param_vtables.repr(tcx));
first_subst.repr(tcx), new_substs.repr(tcx));
(true, source_id, new_substs, param_vtables)
(true, source_id, new_substs)
}
}
}
......@@ -556,8 +505,7 @@ pub fn trans_fn_ref_with_vtables(
};
let (val, must_cast) =
monomorphize::monomorphic_fn(ccx, def_id, &substs,
vtables, opt_ref_id);
monomorphize::monomorphic_fn(ccx, def_id, &substs, opt_ref_id);
let mut val = val;
if must_cast && node != ExprId(0) {
// Monotype of the REFERENCE to the function (type params
......@@ -678,11 +626,10 @@ pub fn trans_lang_call<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
None,
fty,
|bcx, _| {
trans_fn_ref_with_vtables_to_callee(bcx,
did,
0,
subst::Substs::empty(),
VecPerParamSpace::empty())
trans_fn_ref_with_substs_to_callee(bcx,
did,
0,
subst::Substs::empty())
},
ArgVals(args),
dest)
......
......@@ -29,8 +29,11 @@
use middle::trans::debuginfo;
use middle::trans::type_::Type;
use middle::trans::type_of;
use middle::traits;
use middle::ty;
use middle::ty_fold;
use middle::typeck;
use middle::typeck::infer;
use util::ppaux::Repr;
use util::nodemap::{DefIdMap, NodeMap};
......@@ -39,6 +42,7 @@
use libc::{c_uint, c_longlong, c_ulonglong, c_char};
use std::c_str::ToCStr;
use std::cell::{Cell, RefCell};
use std::rc::Rc;
use std::vec::Vec;
use syntax::ast::Ident;
use syntax::ast;
......@@ -188,14 +192,12 @@ pub fn BuilderRef_res(b: BuilderRef) -> BuilderRef_res {
// will only be set in the case of default methods.
pub struct param_substs {
pub substs: subst::Substs,
pub vtables: typeck::vtable_res,
}
impl param_substs {
pub fn empty() -> param_substs {
param_substs {
substs: subst::Substs::trans_empty(),
vtables: subst::VecPerParamSpace::empty(),
}
}
......@@ -204,15 +206,9 @@ pub fn validate(&self) {
}
}
fn param_substs_to_string(this: &param_substs, tcx: &ty::ctxt) -> String {
format!("param_substs(substs={},vtables={})",
this.substs.repr(tcx),
this.vtables.repr(tcx))
}
impl Repr for param_substs {
fn repr(&self, tcx: &ty::ctxt) -> String {
param_substs_to_string(self, tcx)
self.substs.repr(tcx)
}
}
......@@ -766,6 +762,98 @@ pub fn expr_ty_adjusted(bcx: Block, ex: &ast::Expr) -> ty::t {
monomorphize_type(bcx, ty::expr_ty_adjusted(bcx.tcx(), ex))
}
pub fn fulfill_obligation(ccx: &CrateContext,
span: Span,
trait_ref: Rc<ty::TraitRef>)
-> traits::Vtable<()>
{
/*!
* Attempts to resolve an obligation. The result is a shallow
* vtable resolution -- meaning that we do not (necessarily) resolve
* all nested obligations on the impl. Note that type check should
* guarantee to us that all nested obligations *could be* resolved
* if we wanted to.
*/
let tcx = ccx.tcx();
// Remove any references to regions; this helps improve caching.
let trait_ref = ty_fold::erase_regions(tcx, trait_ref);
// First check the cache.
match ccx.trait_cache().borrow().find(&trait_ref) {
Some(vtable) => {
info!("Cache hit: {}", trait_ref.repr(ccx.tcx()));
return (*vtable).clone();
}
None => { }
}
ty::populate_implementations_for_trait_if_necessary(tcx, trait_ref.def_id);
let infcx = infer::new_infer_ctxt(tcx);
// Parameter environment is used to give details about type parameters,
// but since we are in trans, everything is fully monomorphized.
let param_env = ty::empty_parameter_environment();
let unboxed_closures = tcx.unboxed_closures.borrow();
// Do the initial selection for the obligation. This yields the
// shallow result we are looking for -- that is, what specific impl.
let selcx = traits::SelectionContext::new(&infcx, &param_env,
&*unboxed_closures);
let obligation = traits::Obligation::misc(span, trait_ref.clone());
let selection = match selcx.select(&obligation) {
Ok(Some(selection)) => selection,
Ok(None) => {
tcx.sess.span_bug(
span,
format!("Encountered ambiguity selecting `{}` during trans",
trait_ref.repr(tcx)).as_slice())
}
Err(e) => {
tcx.sess.span_bug(
span,
format!("Encountered error `{}` selecting `{}` during trans",
e.repr(tcx),
trait_ref.repr(tcx)).as_slice())
}
};
// Currently, we use a fulfillment context to completely resolve
// all nested obligations. This is because they can inform the
// inference of the impl's type parameters. However, in principle,
// we only need to do this until the impl's type parameters are
// fully bound. It could be a slight optimization to stop
// iterating early.
let mut fulfill_cx = traits::FulfillmentContext::new();
let vtable = selection.map_move_nested(|obligation| {
fulfill_cx.register_obligation(tcx, obligation);
});
match fulfill_cx.select_all_or_error(&infcx, &param_env, &*unboxed_closures) {
Ok(()) => { }
Err(e) => {
tcx.sess.span_bug(
span,
format!("Encountered errors `{}` fulfilling `{}` during trans",
e.repr(tcx),
trait_ref.repr(tcx)).as_slice());
}
}
// Use skolemize to simultaneously replace all type variables with
// their bindings and replace all regions with 'static. This is
// sort of overkill because we do not expect there to be any
// unbound type variables, hence no skolemized types should ever
// be inserted.
let vtable = infer::skolemize(&infcx, vtable);
info!("Cache miss: {}", trait_ref.repr(ccx.tcx()));
ccx.trait_cache().borrow_mut().insert(trait_ref,
vtable.clone());
vtable
}
// Key used to lookup values supplied for type parameters in an expr.
#[deriving(PartialEq)]
pub enum ExprOrMethodCall {
......@@ -778,7 +866,8 @@ pub enum ExprOrMethodCall {
pub fn node_id_substs(bcx: Block,
node: ExprOrMethodCall)
-> subst::Substs {
-> subst::Substs
{
let tcx = bcx.tcx();
let substs = match node {
......@@ -798,87 +887,10 @@ pub fn node_id_substs(bcx: Block,
substs.repr(bcx.tcx())).as_slice());
}
let substs = substs.erase_regions();
substs.substp(tcx, bcx.fcx.param_substs)
}
pub fn node_vtables(bcx: Block, id: typeck::MethodCall)
-> typeck::vtable_res {
bcx.tcx().vtable_map.borrow().find(&id).map(|vts| {
resolve_vtables_in_fn_ctxt(bcx.fcx, vts)
}).unwrap_or_else(|| subst::VecPerParamSpace::empty())
}
// Apply the typaram substitutions in the FunctionContext to some
// vtables. This should eliminate any vtable_params.
pub fn resolve_vtables_in_fn_ctxt(fcx: &FunctionContext,
vts: &typeck::vtable_res)
-> typeck::vtable_res {
resolve_vtables_under_param_substs(fcx.ccx.tcx(),
fcx.param_substs,
vts)
}
pub fn resolve_vtables_under_param_substs(tcx: &ty::ctxt,
param_substs: &param_substs,
vts: &typeck::vtable_res)
-> typeck::vtable_res
{
vts.map(|ds| {
resolve_param_vtables_under_param_substs(tcx,
param_substs,
ds)
})
}
pub fn resolve_param_vtables_under_param_substs(tcx: &ty::ctxt,
param_substs: &param_substs,
ds: &typeck::vtable_param_res)
-> typeck::vtable_param_res
{
ds.iter().map(|d| {
resolve_vtable_under_param_substs(tcx,
param_substs,
d)
}).collect()
}
pub fn resolve_vtable_under_param_substs(tcx: &ty::ctxt,
param_substs: &param_substs,
vt: &typeck::vtable_origin)
-> typeck::vtable_origin
{
match *vt {
typeck::vtable_static(trait_id, ref vtable_substs, ref sub) => {
let vtable_substs = vtable_substs.substp(tcx, param_substs);
typeck::vtable_static(
trait_id,
vtable_substs,
resolve_vtables_under_param_substs(tcx, param_substs, sub))
}
typeck::vtable_param(n_param, n_bound) => {
find_vtable(tcx, param_substs, n_param, n_bound)
}
typeck::vtable_unboxed_closure(def_id) => {
typeck::vtable_unboxed_closure(def_id)
}
typeck::vtable_error => typeck::vtable_error
}
}
pub fn find_vtable(tcx: &ty::ctxt,
ps: &param_substs,
n_param: typeck::param_index,
n_bound: uint)
-> typeck::vtable_origin {
debug!("find_vtable(n_param={:?}, n_bound={}, ps={})",
n_param, n_bound, ps.repr(tcx));
let param_bounds = ps.vtables.get(n_param.space, n_param.index);
param_bounds.get(n_bound).clone()
}
pub fn langcall(bcx: Block,
span: Option<Span>,
msg: &str,
......
......@@ -16,6 +16,7 @@
use llvm::mk_target_data;
use metadata::common::LinkMeta;
use middle::resolve;
use middle::traits;
use middle::trans::adt;
use middle::trans::base;
use middle::trans::builder::Builder;
......@@ -103,7 +104,7 @@ pub struct LocalCrateContext {
monomorphized: RefCell<HashMap<MonoId, ValueRef>>,
monomorphizing: RefCell<DefIdMap<uint>>,
/// Cache generated vtables
vtables: RefCell<HashMap<(ty::t, MonoId), ValueRef>>,
vtables: RefCell<HashMap<(ty::t,Rc<ty::TraitRef>), ValueRef>>,
/// Cache of constant strings,
const_cstr_cache: RefCell<HashMap<InternedString, ValueRef>>,
......@@ -150,6 +151,9 @@ pub struct LocalCrateContext {
/// This is used to perform some basic load-balancing to keep all LLVM
/// contexts around the same size.
n_llvm_insns: Cell<uint>,
trait_cache: RefCell<HashMap<Rc<ty::TraitRef>,
traits::Vtable<()>>>,
}
pub struct CrateContext<'a, 'tcx: 'a> {
......@@ -426,6 +430,7 @@ fn new(shared: &SharedCrateContext,
eh_personality: RefCell::new(None),
intrinsics: RefCell::new(HashMap::new()),
n_llvm_insns: Cell::new(0u),
trait_cache: RefCell::new(HashMap::new()),
};
local_ccx.int_type = Type::int(&local_ccx.dummy_ccx(shared));
......@@ -617,7 +622,7 @@ pub fn monomorphizing<'a>(&'a self) -> &'a RefCell<DefIdMap<uint>> {
&self.local.monomorphizing
}
pub fn vtables<'a>(&'a self) -> &'a RefCell<HashMap<(ty::t, MonoId), ValueRef>> {
pub fn vtables<'a>(&'a self) -> &'a RefCell<HashMap<(ty::t,Rc<ty::TraitRef>), ValueRef>> {
&self.local.vtables
}
......@@ -713,6 +718,10 @@ fn intrinsics<'a>(&'a self) -> &'a RefCell<HashMap<&'static str, ValueRef>> {
pub fn count_llvm_insn(&self) {
self.local.n_llvm_insns.set(self.local.n_llvm_insns.get() + 1);
}
pub fn trait_cache(&self) -> &RefCell<HashMap<Rc<ty::TraitRef>, traits::Vtable<()>>> {
&self.local.trait_cache
}
}
fn declare_intrinsic(ccx: &CrateContext, key: & &'static str) -> Option<ValueRef> {
......
......@@ -41,6 +41,7 @@
use middle::lang_items::MallocFnLangItem;
use middle::mem_categorization::Typer;
use middle::subst;
use middle::subst::Subst;
use middle::trans::_match;
use middle::trans::adt;
use middle::trans::asm;
......@@ -78,6 +79,7 @@
use syntax::codemap;
use syntax::print::pprust::{expr_to_string};
use syntax::ptr::P;
use std::rc::Rc;
// Destinations
......@@ -319,10 +321,18 @@ fn unsized_info<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
_ => bcx.sess().bug(format!("UnsizeStruct with bad sty: {}",
bcx.ty_to_string(unsized_ty)).as_slice())
},
&ty::UnsizeVtable(..) =>
&ty::UnsizeVtable(ty::TyTrait { def_id: def_id, substs: ref substs, .. }, _) => {
let substs = substs.with_self_ty(unsized_ty);
let trait_ref =
Rc::new(ty::TraitRef { def_id: def_id,
substs: substs });
let trait_ref =
trait_ref.subst(bcx.tcx(), &bcx.fcx.param_substs.substs);
let box_ty = mk_ty(unsized_ty);
PointerCast(bcx,
meth::vtable_ptr(bcx, id, mk_ty(unsized_ty)),
meth::get_vtable(bcx, box_ty, trait_ref),
Type::vtable_ptr(bcx.ccx()))
}
}
}
......@@ -1052,8 +1062,16 @@ fn trans_rvalue_dps_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
ast::ExprCast(ref val, _) => {
// DPS output mode means this is a trait cast:
if ty::type_is_trait(node_id_type(bcx, expr.id)) {
let trait_ref =
bcx.tcx().object_cast_map.borrow()
.find(&expr.id)
.map(|t| (*t).clone())
.unwrap();
let trait_ref =
trait_ref.subst(bcx.tcx(), &bcx.fcx.param_substs.substs);
let datum = unpack_datum!(bcx, trans(bcx, &**val));
meth::trans_trait_cast(bcx, datum, expr.id, dest)
meth::trans_trait_cast(bcx, datum, expr.id,
trait_ref, dest)
} else {
bcx.tcx().sess.span_bug(expr.span,
"expr_cast of non-trait");
......
此差异已折叠。
......@@ -34,17 +34,14 @@
pub fn monomorphic_fn(ccx: &CrateContext,
fn_id: ast::DefId,
real_substs: &subst::Substs,
vtables: typeck::vtable_res,
ref_id: Option<ast::NodeId>)
-> (ValueRef, bool) {
debug!("monomorphic_fn(\
fn_id={}, \
real_substs={}, \
vtables={}, \
ref_id={:?})",
fn_id.repr(ccx.tcx()),
real_substs.repr(ccx.tcx()),
vtables.repr(ccx.tcx()),
ref_id);
assert!(real_substs.types.all(|t| {
......@@ -69,7 +66,6 @@ pub fn monomorphic_fn(ccx: &CrateContext,
let psubsts = param_substs {
substs: (*real_substs).clone(),
vtables: vtables,
};
debug!("monomorphic_fn(\
......@@ -286,7 +282,7 @@ pub fn monomorphic_fn(ccx: &CrateContext,
(lldecl, true)
}
// Used to identify cached monomorphized functions and vtables
// Used to identify cached monomorphized functions
#[deriving(PartialEq, Eq, Hash)]
pub struct MonoParamId {
pub subst: ty::t,
......
......@@ -28,6 +28,7 @@
use middle::stability;
use middle::subst::{Subst, Substs, VecPerParamSpace};
use middle::subst;
use middle::traits;
use middle::ty;
use middle::typeck;
use middle::ty_fold;
......@@ -272,9 +273,7 @@ pub enum UnsizeKind {
// An unsize coercion applied to the tail field of a struct.
// The uint is the index of the type parameter which is unsized.
UnsizeStruct(Box<UnsizeKind>, uint),
UnsizeVtable(ty::ExistentialBounds,
ast::DefId, /* Trait ID */
subst::Substs /* Trait substitutions */)
UnsizeVtable(TyTrait, /* the self type of the trait */ ty::t)
}
#[deriving(Clone)]
......@@ -365,13 +364,13 @@ pub fn type_of_adjust(cx: &ctxt, adj: &AutoAdjustment) -> Option<t> {
fn type_of_autoref(cx: &ctxt, autoref: &AutoRef) -> Option<t> {
match autoref {
&AutoUnsize(ref k) => match k {
&UnsizeVtable(bounds, def_id, ref substs) => {
&UnsizeVtable(TyTrait { def_id, substs: ref substs, bounds }, _) => {
Some(mk_trait(cx, def_id, substs.clone(), bounds))
}
_ => None
},
&AutoUnsizeUniq(ref k) => match k {
&UnsizeVtable(bounds, def_id, ref substs) => {
&UnsizeVtable(TyTrait { def_id, substs: ref substs, bounds }, _) => {
Some(mk_uniq(cx, mk_trait(cx, def_id, substs.clone(), bounds)))
}
_ => None
......@@ -458,6 +457,10 @@ pub struct ctxt<'tcx> {
pub trait_refs: RefCell<NodeMap<Rc<TraitRef>>>,
pub trait_defs: RefCell<DefIdMap<Rc<TraitDef>>>,
/// Maps from node-id of a trait object cast (like `foo as
/// Box<Trait>`) to the trait reference.
pub object_cast_map: typeck::ObjectCastMap,
pub map: ast_map::Map<'tcx>,
pub intrinsic_defs: RefCell<DefIdMap<t>>,
pub freevars: RefCell<freevars::freevar_map>,
......@@ -499,7 +502,7 @@ pub struct ctxt<'tcx> {
/// Maps a DefId of a type to a list of its inherent impls.
/// Contains implementations of methods that are inherent to a type.
/// Methods in these implementations don't need to be exported.
pub inherent_impls: RefCell<DefIdMap<Rc<RefCell<Vec<ast::DefId>>>>>,
pub inherent_impls: RefCell<DefIdMap<Rc<Vec<ast::DefId>>>>,
/// Maps a DefId of an impl to a list of its items.
/// Note that this contains all of the impls that we know about,
......@@ -516,9 +519,6 @@ pub struct ctxt<'tcx> {
/// about.
pub used_mut_nodes: RefCell<NodeSet>,
/// vtable resolution information for impl declarations
pub impl_vtables: typeck::impl_vtable_map,
/// The set of external nominal types whose implementations have been read.
/// This is used for lazy resolution of methods.
pub populated_external_types: RefCell<DefIdSet>,
......@@ -536,7 +536,6 @@ pub struct ctxt<'tcx> {
pub extern_const_variants: RefCell<DefIdMap<ast::NodeId>>,
pub method_map: typeck::MethodMap,
pub vtable_map: typeck::vtable_map,
pub dependency_formats: RefCell<dependency_format::Dependencies>,
......@@ -1435,6 +1434,7 @@ pub fn mk_ctxt<'tcx>(s: Session,
item_substs: RefCell::new(NodeMap::new()),
trait_refs: RefCell::new(NodeMap::new()),
trait_defs: RefCell::new(DefIdMap::new()),
object_cast_map: RefCell::new(NodeMap::new()),
map: map,
intrinsic_defs: RefCell::new(DefIdMap::new()),
freevars: RefCell::new(freevars),
......@@ -1463,14 +1463,12 @@ pub fn mk_ctxt<'tcx>(s: Session,
impl_items: RefCell::new(DefIdMap::new()),
used_unsafe: RefCell::new(NodeSet::new()),
used_mut_nodes: RefCell::new(NodeSet::new()),
impl_vtables: RefCell::new(DefIdMap::new()),
populated_external_types: RefCell::new(DefIdSet::new()),
populated_external_traits: RefCell::new(DefIdSet::new()),
upvar_borrow_map: RefCell::new(HashMap::new()),
extern_const_statics: RefCell::new(DefIdMap::new()),
extern_const_variants: RefCell::new(DefIdMap::new()),
method_map: RefCell::new(FnvHashMap::new()),
vtable_map: RefCell::new(FnvHashMap::new()),
dependency_formats: RefCell::new(HashMap::new()),
unboxed_closures: RefCell::new(DefIdMap::new()),
node_lint_levels: RefCell::new(HashMap::new()),
......@@ -2944,13 +2942,17 @@ fn type_structurally_recursive(cx: &ctxt, sp: Span, seen: &mut Vec<DefId>,
}
pub fn type_is_trait(ty: t) -> bool {
type_trait_info(ty).is_some()
}
pub fn type_trait_info(ty: t) -> Option<&'static TyTrait> {
match get(ty).sty {
ty_uniq(ty) | ty_rptr(_, mt { ty, ..}) | ty_ptr(mt { ty, ..}) => match get(ty).sty {
ty_trait(..) => true,
_ => false
ty_trait(ref t) => Some(&**t),
_ => None
},
ty_trait(..) => true,
_ => false
ty_trait(ref t) => Some(&**t),
_ => None
}
}
......@@ -3491,7 +3493,7 @@ pub fn unsize_ty(cx: &ctxt,
format!("UnsizeStruct with bad sty: {}",
ty_to_string(cx, ty)).as_slice())
},
&UnsizeVtable(bounds, def_id, ref substs) => {
&UnsizeVtable(TyTrait { def_id, substs: ref substs, bounds }, _) => {
mk_trait(cx, def_id, substs.clone(), bounds)
}
}
......@@ -3511,10 +3513,10 @@ pub fn map_region(&self, f: |Region| -> Region) -> AutoRef {
}
pub fn method_call_type_param_defs<'tcx, T>(typer: &T,
origin: typeck::MethodOrigin)
origin: &typeck::MethodOrigin)
-> VecPerParamSpace<TypeParameterDef>
where T: mc::Typer<'tcx> {
match origin {
match *origin {
typeck::MethodStatic(did) => {
ty::lookup_item_type(typer.tcx(), did).generics.types.clone()
}
......@@ -3529,16 +3531,16 @@ pub fn method_call_type_param_defs<'tcx, T>(typer: &T,
lookup_trait_def(typer.tcx(), def_id).generics.types.clone()
}
typeck::MethodParam(typeck::MethodParam{
trait_id: trt_id,
trait_ref: ref trait_ref,
method_num: n_mth,
..
}) |
typeck::MethodObject(typeck::MethodObject{
trait_id: trt_id,
trait_ref: ref trait_ref,
method_num: n_mth,
..
}) => {
match ty::trait_item(typer.tcx(), trt_id, n_mth) {
match ty::trait_item(typer.tcx(), trait_ref.def_id, n_mth) {
ty::MethodTraitItem(method) => method.generics.types.clone(),
}
}
......@@ -4407,14 +4409,6 @@ pub fn lookup_item_type(cx: &ctxt,
|| csearch::get_type(cx, did))
}
pub fn lookup_impl_vtables(cx: &ctxt,
did: ast::DefId)
-> typeck::vtable_res {
lookup_locally_or_in_crate_store(
"impl_vtables", did, &mut *cx.impl_vtables.borrow_mut(),
|| csearch::get_impl_vtables(cx, did) )
}
/// Given the did of a trait, returns its canonical trait ref.
pub fn lookup_trait_def(cx: &ctxt, did: ast::DefId) -> Rc<ty::TraitDef> {
let mut trait_defs = cx.trait_defs.borrow_mut();
......@@ -4958,6 +4952,7 @@ pub fn populate_implementations_for_type_if_necessary(tcx: &ctxt,
return
}
let mut inherent_impls = Vec::new();
csearch::each_implementation_for_type(&tcx.sess.cstore, type_id,
|impl_def_id| {
let impl_items = csearch::get_impl_items(&tcx.sess.cstore,
......@@ -4989,18 +4984,11 @@ pub fn populate_implementations_for_type_if_necessary(tcx: &ctxt,
// If this is an inherent implementation, record it.
if associated_traits.is_none() {
match tcx.inherent_impls.borrow().find(&type_id) {
Some(implementation_list) => {
implementation_list.borrow_mut().push(impl_def_id);
return;
}
None => {}
}
tcx.inherent_impls.borrow_mut().insert(type_id,
Rc::new(RefCell::new(vec!(impl_def_id))));
inherent_impls.push(impl_def_id);
}
});
tcx.inherent_impls.borrow_mut().insert(type_id, Rc::new(inherent_impls));
tcx.populated_external_types.borrow_mut().insert(type_id);
}
......@@ -5232,7 +5220,7 @@ pub fn hash_crate_independent(tcx: &ctxt, t: t, svh: &Svh) -> u64 {
}
}
}
ty_trait(box ty::TyTrait { def_id: d, bounds, .. }) => {
ty_trait(box TyTrait { def_id: d, bounds, .. }) => {
byte!(17);
did(&mut state, d);
hash!(bounds);
......@@ -5430,6 +5418,26 @@ pub fn from_mutbl(m: ast::Mutability) -> BorrowKind {
}
}
pub fn to_mutbl_lossy(self) -> ast::Mutability {
/*!
* Returns a mutability `m` such that an `&m T` pointer could
* be used to obtain this borrow kind. Because borrow kinds
* are richer than mutabilities, we sometimes have to pick a
* mutability that is stornger than necessary so that it at
* least *would permit* the borrow in question.
*/
match self {
MutBorrow => ast::MutMutable,
ImmBorrow => ast::MutImmutable,
// We have no type correponding to a unique imm borrow, so
// use `&mut`. It gives all the capabilities of an `&uniq`
// and hence is a safe "over approximation".
UniqueImmBorrow => ast::MutMutable,
}
}
pub fn to_user_str(&self) -> &'static str {
match *self {
MutBorrow => "mutable",
......
......@@ -680,3 +680,28 @@ fn fold_region(&mut self, r: ty::Region) -> ty::Region {
}
}
}
///////////////////////////////////////////////////////////////////////////
// Region eraser
//
// Replaces all free regions with 'static. Useful in trans.
pub struct RegionEraser<'a, 'tcx: 'a> {
tcx: &'a ty::ctxt<'tcx>,
}
pub fn erase_regions<T:TypeFoldable>(tcx: &ty::ctxt, t: T) -> T {
let mut eraser = RegionEraser { tcx: tcx };
t.fold_with(&mut eraser)
}
impl<'a, 'tcx> TypeFolder<'tcx> for RegionEraser<'a, 'tcx> {
fn tcx<'a>(&'a self) -> &'a ty::ctxt<'tcx> { self.tcx }
fn fold_region(&mut self, r: ty::Region) -> ty::Region {
match r {
ty::ReLateBound(..) | ty::ReEarlyBound(..) => r,
_ => ty::ReStatic
}
}
}
......@@ -370,7 +370,7 @@ fn coerce_unsized(&self,
}
(&ty::ty_uniq(t_a), &ty::ty_uniq(t_b)) => {
self.unpack_actual_value(t_a, |sty_a| {
match self.unsize_ty(sty_a, t_b) {
match self.unsize_ty(t_a, sty_a, t_b) {
Some((ty, kind)) => {
let ty = ty::mk_uniq(self.get_ref().infcx.tcx, ty);
try!(self.get_ref().infcx.try(|| sub.tys(ty, b)));
......@@ -393,6 +393,7 @@ fn coerce_unsized(&self,
// performed to unsize it.
// E.g., `[T, ..n]` -> `([T], UnsizeLength(n))`
fn unsize_ty(&self,
ty_a: ty::t,
sty_a: &ty::sty,
ty_b: ty::t)
-> Option<(ty::t, ty::UnsizeKind)> {
......@@ -412,9 +413,10 @@ fn unsize_ty(&self,
def_id,
substs.clone(),
bounds);
Some((ty, ty::UnsizeVtable(bounds,
def_id,
substs.clone())))
Some((ty, ty::UnsizeVtable(ty::TyTrait { def_id: def_id,
bounds: bounds,
substs: substs.clone() },
ty_a)))
}
(&ty::ty_struct(did_a, ref substs_a), &ty::ty_struct(did_b, ref substs_b))
if did_a == did_b => {
......@@ -432,7 +434,11 @@ fn unsize_ty(&self,
if self.get_ref().infcx.try(|| sub.tys(*tp_a, *tp_b)).is_ok() {
continue;
}
match self.unpack_actual_value(*tp_a, |tp| self.unsize_ty(tp, *tp_b)) {
match
self.unpack_actual_value(
*tp_a,
|tp| self.unsize_ty(*tp_a, tp, *tp_b))
{
Some((new_tp, k)) => {
// Check that the whole types match.
let mut new_substs = substs_a.clone();
......@@ -471,14 +477,14 @@ fn coerce_borrowed_object(&self,
{
let tcx = self.get_ref().infcx.tcx;
debug!("coerce_borrowed_object(a={}, sty_a={:?}, b={})",
debug!("coerce_borrowed_object(a={}, sty_a={:?}, b={}, b_mutbl={})",
a.repr(tcx), sty_a,
b.repr(tcx));
b.repr(tcx), b_mutbl);
let coercion = Coercion(self.get_ref().trace.clone());
let r_a = self.get_ref().infcx.next_region_var(coercion);
self.coerce_object(a, sty_a, b,
self.coerce_object(a, sty_a, b, b_mutbl,
|tr| ty::mk_rptr(tcx, r_a, ty::mt{ mutbl: b_mutbl, ty: tr }),
|| AutoPtr(r_a, b_mutbl, None))
}
......@@ -491,11 +497,11 @@ fn coerce_unsafe_object(&self,
{
let tcx = self.get_ref().infcx.tcx;
debug!("coerce_unsafe_object(a={}, sty_a={:?}, b={})",
debug!("coerce_unsafe_object(a={}, sty_a={:?}, b={}, b_mutbl={})",
a.repr(tcx), sty_a,
b.repr(tcx));
b.repr(tcx), b_mutbl);
self.coerce_object(a, sty_a, b,
self.coerce_object(a, sty_a, b, b_mutbl,
|tr| ty::mk_ptr(tcx, ty::mt{ mutbl: b_mutbl, ty: tr }),
|| AutoUnsafe(b_mutbl, None))
}
......
......@@ -34,7 +34,7 @@
use middle::subst;
use middle::subst::Substs;
use middle::subst::{ErasedRegions, NonerasedRegions, Substs};
use middle::ty::{FloatVar, FnSig, IntVar, TyVar};
use middle::ty::{IntType, UintType};
use middle::ty::{BuiltinBounds};
......@@ -113,29 +113,40 @@ fn substs(&self,
let a_tps = a_subst.types.get_slice(space);
let b_tps = b_subst.types.get_slice(space);
let tps = try!(self.tps(space, a_tps, b_tps));
substs.types.replace(space, tps);
}
let a_regions = a_subst.regions().get_slice(space);
let b_regions = b_subst.regions().get_slice(space);
let mut invariance = Vec::new();
let r_variances = match variances {
Some(ref variances) => variances.regions.get_slice(space),
None => {
for _ in a_regions.iter() {
invariance.push(ty::Invariant);
}
invariance.as_slice()
}
};
match (&a_subst.regions, &b_subst.regions) {
(&ErasedRegions, _) | (_, &ErasedRegions) => {
substs.regions = ErasedRegions;
}
let regions = try!(relate_region_params(self,
item_def_id,
r_variances,
a_regions,
b_regions));
(&NonerasedRegions(ref a), &NonerasedRegions(ref b)) => {
for &space in subst::ParamSpace::all().iter() {
let a_regions = a.get_slice(space);
let b_regions = b.get_slice(space);
substs.types.replace(space, tps);
substs.mut_regions().replace(space, regions);
let mut invariance = Vec::new();
let r_variances = match variances {
Some(ref variances) => {
variances.regions.get_slice(space)
}
None => {
for _ in a_regions.iter() {
invariance.push(ty::Invariant);
}
invariance.as_slice()
}
};
let regions = try!(relate_region_params(self,
item_def_id,
r_variances,
a_regions,
b_regions));
substs.mut_regions().replace(space, regions);
}
}
}
return Ok(substs);
......
......@@ -71,9 +71,10 @@
use util::common::time;
use util::ppaux::Repr;
use util::ppaux;
use util::nodemap::{DefIdMap, FnvHashMap};
use util::nodemap::{NodeMap, FnvHashMap};
use std::cell::RefCell;
use std::rc::Rc;
use syntax::codemap::Span;
use syntax::print::pprust::*;
use syntax::{ast, ast_map, abi};
......@@ -92,7 +93,7 @@ pub struct param_index {
pub index: uint
}
#[deriving(Clone, Encodable, Decodable)]
#[deriving(Clone)]
pub enum MethodOrigin {
// fully statically resolved method
MethodStatic(ast::DefId),
......@@ -110,27 +111,21 @@ pub enum MethodOrigin {
// details for a method invoked with a receiver whose type is a type parameter
// with a bounded trait.
#[deriving(Clone, Encodable, Decodable)]
#[deriving(Clone)]
pub struct MethodParam {
// the trait containing the method to be invoked
pub trait_id: ast::DefId,
// the precise trait reference that occurs as a bound -- this may
// be a supertrait of what the user actually typed.
pub trait_ref: Rc<ty::TraitRef>,
// index of the method to be invoked amongst the trait's methods
// index of uint in the list of methods for the trait
pub method_num: uint,
// index of the type parameter (from those that are in scope) that is
// the type of the receiver
pub param_num: param_index,
// index of the bound for this type parameter which specifies the trait
pub bound_num: uint,
}
// details for a method invoked with a receiver whose type is an object
#[deriving(Clone, Encodable, Decodable)]
#[deriving(Clone)]
pub struct MethodObject {
// the (super)trait containing the method to be invoked
pub trait_id: ast::DefId,
pub trait_ref: Rc<ty::TraitRef>,
// the actual base trait id of the object
pub object_trait_id: ast::DefId,
......@@ -154,7 +149,7 @@ pub struct MethodCallee {
/**
* With method calls, we store some extra information in
* side tables (i.e method_map, vtable_map). We use
* side tables (i.e method_map). We use
* MethodCall as a key to index into these tables instead of
* just directly using the expression's NodeId. The reason
* for this being that we may apply adjustments (coercions)
......@@ -276,10 +271,9 @@ fn repr(&self, tcx: &ty::ctxt) -> String {
}
}
pub type vtable_map = RefCell<FnvHashMap<MethodCall, vtable_res>>;
pub type impl_vtable_map = RefCell<DefIdMap<vtable_res>>;
// For every explicit cast into an object type, maps from the cast
// expr to the associated trait ref.
pub type ObjectCastMap = RefCell<NodeMap<Rc<ty::TraitRef>>>;
pub struct CrateCtxt<'a, 'tcx: 'a> {
// A mapping from method call sites to traits that have that method.
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册