Replaced method_map_entry with method_origin and cleaned up vtable checking a bit.

This commit is contained in:
Eduard Burtescu 2014-02-19 22:11:45 +02:00
parent 1ca1ff23d3
commit efef078cfa
14 changed files with 79 additions and 133 deletions

@ -20,7 +20,7 @@ use metadata::tydecode;
use metadata::tydecode::{DefIdSource, NominalType, TypeWithId, TypeParameter,
RegionParameter};
use metadata::tyencode;
use middle::typeck::{method_origin, method_map_entry};
use middle::typeck::method_origin;
use middle::{ty, typeck, moves};
use middle;
use util::ppaux::ty_to_str;
@ -573,35 +573,7 @@ impl tr for moves::CaptureVar {
}
// ______________________________________________________________________
// Encoding and decoding of method_map_entry
trait read_method_map_entry_helper {
fn read_method_map_entry(&mut self, xcx: @ExtendedDecodeContext)
-> method_map_entry;
}
fn encode_method_map_entry(ebml_w: &mut writer::Encoder, mme: method_map_entry) {
ebml_w.emit_struct("method_map_entry", 3, |ebml_w| {
ebml_w.emit_struct_field("origin", 1u, |ebml_w| {
mme.origin.encode(ebml_w);
});
})
}
impl<'a> read_method_map_entry_helper for reader::Decoder<'a> {
fn read_method_map_entry(&mut self, xcx: @ExtendedDecodeContext)
-> method_map_entry {
self.read_struct("method_map_entry", 3, |this| {
method_map_entry {
origin: this.read_struct_field("origin", 1, |this| {
let method_origin: method_origin =
Decodable::decode(this);
method_origin.tr(xcx)
})
}
})
}
}
// Encoding and decoding of method_origin
impl tr for method_origin {
fn tr(&self, xcx: @ExtendedDecodeContext) -> method_origin {
@ -1023,11 +995,11 @@ fn encode_side_tables_for_id(ecx: &e::EncodeContext,
{
let method_map = maps.method_map.borrow();
let r = method_map.get().find(&id);
for &mme in r.iter() {
for &origin in r.iter() {
ebml_w.tag(c::tag_table_method_map, |ebml_w| {
ebml_w.id(id);
ebml_w.tag(c::tag_table_val, |ebml_w| {
encode_method_map_entry(ebml_w, *mme)
origin.encode(ebml_w);
})
})
}
@ -1364,9 +1336,9 @@ fn decode_side_tables(xcx: @ExtendedDecodeContext,
ty_param_defs.get().insert(id, bounds);
}
c::tag_table_method_map => {
let entry = val_dsr.read_method_map_entry(xcx);
let origin: method_origin = Decodable::decode(val_dsr);
let mut method_map = dcx.maps.method_map.borrow_mut();
method_map.get().insert(id, entry);
method_map.get().insert(id, origin.tr(xcx));
}
c::tag_table_vtable_map => {
let vtable_res =

@ -94,7 +94,7 @@ impl MarkSymbolVisitor {
span: codemap::Span) {
let method_map = self.method_map.borrow();
match method_map.get().find(id) {
Some(&typeck::method_map_entry { origin, .. }) => {
Some(&origin) => {
match origin {
typeck::method_static(def_id) => {
match ty::provided_source(self.tcx, def_id) {

@ -285,8 +285,15 @@ pub fn check_expr(cx: &mut Context, e: &Expr) {
// Even though the callee_id may have been the id with
// node_type_substs, e.id is correct here.
ty::method_call_type_param_defs(cx.tcx, cx.method_map, e.id).expect(
"non path/method call expr has type substs??")
match cx.method_map.borrow().get().find(&e.id) {
Some(origin) => {
ty::method_call_type_param_defs(cx.tcx, *origin)
}
None => {
cx.tcx.sess.span_bug(e.span,
"non path/method call expr has type substs??");
}
}
}
};
let type_param_defs = type_param_defs.borrow();

@ -1402,7 +1402,7 @@ fn check_stability(cx: &Context, e: &ast::Expr) {
ast::ExprMethodCall(..) => {
let method_map = cx.method_map.borrow();
match method_map.get().find(&e.id) {
Some(&typeck::method_map_entry { origin, .. }) => {
Some(&origin) => {
match origin {
typeck::method_static(def_id) => {
// If this implements a trait method, get def_id

@ -790,17 +790,17 @@ impl<'a> Visitor<()> for PrivacyVisitor<'a> {
let t = ty::type_autoderef(ty::expr_ty(self.tcx, args[0]));
match ty::get(t).sty {
ty::ty_enum(_, _) | ty::ty_struct(_, _) => {
let method_map = self.method_map.borrow();
let entry = match method_map.get().find(&expr.id) {
match self.method_map.borrow().get().find(&expr.id) {
None => {
self.tcx.sess.span_bug(expr.span,
"method call not in \
method map");
}
Some(entry) => entry
};
debug!("(privacy checking) checking impl method");
self.check_method(expr.span, &entry.origin, ident);
Some(origin) => {
debug!("(privacy checking) checking impl method");
self.check_method(expr.span, origin, ident);
}
}
}
_ => {}
}

@ -149,10 +149,7 @@ impl Visitor<()> for MarkSymbolVisitor {
ast::ExprMethodCall(..) => {
let method_map = self.method_map.borrow();
match method_map.get().find(&expr.id) {
Some(&typeck::method_map_entry {
origin: typeck::method_static(def_id),
..
}) => {
Some(&typeck::method_static(def_id)) => {
if is_local(def_id) {
if ReachableContext::
def_id_represents_local_inlined_item(
@ -174,8 +171,7 @@ impl Visitor<()> for MarkSymbolVisitor {
Some(_) => {}
None => {
self.tcx.sess.span_bug(expr.span,
"method call expression \
not in method map?!")
"method call expression not in method map?!")
}
}
}

@ -95,16 +95,15 @@ pub fn trans_method_callee<'a>(
bcx: &'a Block<'a>,
callee_id: ast::NodeId,
this: &ast::Expr,
mentry: typeck::method_map_entry,
origin: typeck::method_origin,
arg_cleanup_scope: cleanup::ScopeId)
-> Callee<'a> {
let _icx = push_ctxt("meth::trans_method_callee");
debug!("trans_method_callee(callee_id={:?}, mentry={})",
callee_id,
mentry.repr(bcx.tcx()));
debug!("trans_method_callee(callee_id={:?}, origin={})",
callee_id, origin.repr(bcx.tcx()));
match mentry.origin {
match origin {
typeck::method_static(did) => {
Callee {
bcx: bcx,

@ -3242,25 +3242,21 @@ pub fn expr_has_ty_params(cx: ctxt, expr: &ast::Expr) -> bool {
return node_id_has_type_params(cx, expr.id);
}
pub fn method_call_type_param_defs(tcx: ctxt,
method_map: typeck::method_map,
id: ast::NodeId)
-> Option<Rc<~[TypeParameterDef]>> {
let method_map = method_map.borrow();
method_map.get().find(&id).map(|method| {
match method.origin {
typeck::method_static(did) => {
pub fn method_call_type_param_defs(tcx: ctxt, origin: typeck::method_origin)
-> Rc<~[TypeParameterDef]> {
match origin {
typeck::method_static(did) => {
// n.b.: When we encode impl methods, the bounds
// that we encode include both the impl bounds
// and then the method bounds themselves...
ty::lookup_item_type(tcx, did).generics.type_param_defs
}
typeck::method_param(typeck::method_param {
trait_id: trt_id,
method_num: n_mth, ..}) |
typeck::method_object(typeck::method_object {
trait_id: trt_id,
method_num: n_mth, ..}) => {
}
typeck::method_param(typeck::method_param {
trait_id: trt_id,
method_num: n_mth, ..}) |
typeck::method_object(typeck::method_object {
trait_id: trt_id,
method_num: n_mth, ..}) => {
// ...trait methods bounds, in contrast, include only the
// method bounds, so we must preprend the tps from the
// trait itself. This ought to be harmonized.
@ -3271,9 +3267,8 @@ pub fn method_call_type_param_defs(tcx: ctxt,
ty::trait_method(tcx,
trt_id,
n_mth).generics.type_param_defs()))
}
}
})
}
}
pub fn resolve_expr(tcx: ctxt, expr: &ast::Expr) -> ast::Def {

@ -20,17 +20,17 @@ use syntax::codemap::Span;
// Requires that the two types unify, and prints an error message if they
// don't.
pub fn suptype(fcx: @FnCtxt, sp: Span, expected: ty::t, actual: ty::t) {
pub fn suptype(fcx: &FnCtxt, sp: Span, expected: ty::t, actual: ty::t) {
suptype_with_fn(fcx, sp, false, expected, actual,
|sp, e, a, s| { fcx.report_mismatched_types(sp, e, a, s) })
}
pub fn subtype(fcx: @FnCtxt, sp: Span, expected: ty::t, actual: ty::t) {
pub fn subtype(fcx: &FnCtxt, sp: Span, expected: ty::t, actual: ty::t) {
suptype_with_fn(fcx, sp, true, actual, expected,
|sp, a, e, s| { fcx.report_mismatched_types(sp, e, a, s) })
}
pub fn suptype_with_fn(fcx: @FnCtxt,
pub fn suptype_with_fn(fcx: &FnCtxt,
sp: Span,
b_is_expected: bool,
ty_a: ty::t,

@ -90,7 +90,7 @@ use middle::typeck::check::{structurally_resolved_type};
use middle::typeck::check::vtable;
use middle::typeck::check;
use middle::typeck::infer;
use middle::typeck::{method_map_entry, method_origin, method_param};
use middle::typeck::{method_origin, method_param};
use middle::typeck::{method_static, method_object};
use middle::typeck::{param_numbered, param_self, param_index};
use middle::typeck::check::regionmanip::replace_bound_regions_in_fn_sig;
@ -133,7 +133,7 @@ pub fn lookup(
deref_args: check::DerefArgs, // Whether we autopointer first.
check_traits: CheckTraitsFlag, // Whether we check traits only.
autoderef_receiver: AutoderefReceiverFlag)
-> Option<method_map_entry> {
-> Option<method_origin> {
let impl_dups = @RefCell::new(HashSet::new());
let lcx = LookupContext {
fcx: fcx,
@ -211,7 +211,7 @@ enum RcvrMatchCondition {
}
impl<'a> LookupContext<'a> {
fn search(&self, self_ty: ty::t) -> Option<method_map_entry> {
fn search(&self, self_ty: ty::t) -> Option<method_origin> {
let mut self_ty = self_ty;
let mut autoderefs = 0;
loop {
@ -592,7 +592,7 @@ impl<'a> LookupContext<'a> {
fn search_for_autoderefd_method(&self,
self_ty: ty::t,
autoderefs: uint)
-> Option<method_map_entry> {
-> Option<method_origin> {
let (self_ty, autoadjust) =
self.consider_reborrow(self_ty, autoderefs);
match self.search_for_method(self_ty) {
@ -686,9 +686,9 @@ impl<'a> LookupContext<'a> {
}
fn search_for_autosliced_method(&self,
self_ty: ty::t,
autoderefs: uint)
-> Option<method_map_entry> {
self_ty: ty::t,
autoderefs: uint)
-> Option<method_origin> {
/*!
*
* Searches for a candidate by converting things like
@ -763,7 +763,7 @@ impl<'a> LookupContext<'a> {
}
fn search_for_autoptrd_method(&self, self_ty: ty::t, autoderefs: uint)
-> Option<method_map_entry> {
-> Option<method_origin> {
/*!
*
* Converts any type `T` to `&M T` where `M` is an
@ -799,7 +799,7 @@ impl<'a> LookupContext<'a> {
autoderefs: uint,
mutbls: &[ast::Mutability],
mk_autoref_ty: |ast::Mutability, ty::Region| -> ty::t)
-> Option<method_map_entry> {
-> Option<method_origin> {
// This is hokey. We should have mutability inference as a
// variable. But for now, try &const, then &, then &mut:
let region =
@ -823,7 +823,7 @@ impl<'a> LookupContext<'a> {
}
fn search_for_method(&self, rcvr_ty: ty::t)
-> Option<method_map_entry> {
-> Option<method_origin> {
debug!("search_for_method(rcvr_ty={})", self.ty_to_str(rcvr_ty));
let _indenter = indenter();
@ -855,7 +855,7 @@ impl<'a> LookupContext<'a> {
fn consider_candidates(&self,
rcvr_ty: ty::t,
candidates: &mut ~[Candidate])
-> Option<method_map_entry> {
-> Option<method_origin> {
// FIXME(pcwalton): Do we need to clone here?
let relevant_candidates: ~[Candidate] =
candidates.iter().map(|c| (*c).clone()).
@ -926,7 +926,7 @@ impl<'a> LookupContext<'a> {
}
fn confirm_candidate(&self, rcvr_ty: ty::t, candidate: &Candidate)
-> method_map_entry {
-> method_origin {
// This method performs two sets of substitutions, one after the other:
// 1. Substitute values for any type/lifetime parameters from the impl and
// method declaration into the method type. This is the function type
@ -1037,9 +1037,7 @@ impl<'a> LookupContext<'a> {
self.fcx.write_ty(self.callee_id, fty);
self.fcx.write_substs(self.callee_id, all_substs);
method_map_entry {
origin: candidate.origin
}
candidate.origin
}
fn construct_transformed_self_ty_for_object(

@ -590,8 +590,7 @@ pub fn check_item(ccx: @CrateCtxt, it: &ast::Item) {
ast_trait_ref,
impl_trait_ref,
*ms);
vtable::resolve_impl(ccx, it, &impl_tpt.generics,
impl_trait_ref);
vtable::resolve_impl(ccx.tcx, it, &impl_tpt.generics, impl_trait_ref);
}
None => { }
}
@ -3831,8 +3830,7 @@ pub fn instantiate_path(fcx: @FnCtxt,
// Resolves `typ` by a single level if `typ` is a type variable. If no
// resolution is possible, then an error is reported.
pub fn structurally_resolved_type(fcx: @FnCtxt, sp: Span, tp: ty::t)
-> ty::t {
pub fn structurally_resolved_type(fcx: &FnCtxt, sp: Span, tp: ty::t) -> ty::t {
match infer::resolve_type(fcx.infcx(), tp, force_tvar) {
Ok(t_s) if !ty::type_is_ty_var(t_s) => t_s,
_ => {

@ -18,7 +18,7 @@ use middle::typeck::check::{structurally_resolved_type};
use middle::typeck::infer::fixup_err_to_str;
use middle::typeck::infer::{resolve_and_force_all_but_regions, resolve_type};
use middle::typeck::infer;
use middle::typeck::{CrateCtxt, vtable_origin, vtable_res, vtable_param_res};
use middle::typeck::{vtable_origin, vtable_res, vtable_param_res};
use middle::typeck::{vtable_static, vtable_param, impl_res};
use middle::typeck::{param_numbered, param_self, param_index};
use middle::subst::Subst;
@ -537,9 +537,7 @@ fn connect_trait_tps(vcx: &VtableContext,
relate_trait_refs(vcx, location_info, impl_trait_ref, trait_ref);
}
fn insert_vtables(fcx: @FnCtxt,
callee_id: ast::NodeId,
vtables: vtable_res) {
fn insert_vtables(fcx: &FnCtxt, callee_id: ast::NodeId, vtables: vtable_res) {
debug!("insert_vtables(callee_id={}, vtables={:?})",
callee_id, vtables.repr(fcx.tcx()));
let mut vtable_map = fcx.inh.vtable_map.borrow_mut();
@ -559,7 +557,7 @@ pub fn location_info_for_item(item: &ast::Item) -> LocationInfo {
}
}
pub fn early_resolve_expr(ex: &ast::Expr, fcx: @FnCtxt, is_early: bool) {
pub fn early_resolve_expr(ex: &ast::Expr, fcx: &FnCtxt, is_early: bool) {
debug!("vtable: early_resolve_expr() ex with id {:?} (early: {}): {}",
ex.id, is_early, expr_to_str(ex));
let _indent = indenter();
@ -699,10 +697,11 @@ pub fn early_resolve_expr(ex: &ast::Expr, fcx: @FnCtxt, is_early: bool) {
ast::ExprAssignOp(callee_id, _, _, _) |
ast::ExprIndex(callee_id, _, _) |
ast::ExprMethodCall(callee_id, _, _, _) => {
match ty::method_call_type_param_defs(cx.tcx, fcx.inh.method_map, ex.id) {
Some(type_param_defs) => {
match fcx.inh.method_map.borrow().get().find(&ex.id) {
Some(origin) => {
debug!("vtable resolution on parameter bounds for method call {}",
ex.repr(fcx.tcx()));
let type_param_defs = ty::method_call_type_param_defs(cx.tcx, *origin);
if has_trait_bounds(*type_param_defs.borrow()) {
let substs = fcx.node_ty_substs(callee_id);
let vcx = fcx.vtable_context();
@ -713,7 +712,7 @@ pub fn early_resolve_expr(ex: &ast::Expr, fcx: @FnCtxt, is_early: bool) {
}
}
}
None => ()
None => {}
}
}
ast::ExprCast(src, _) => {
@ -757,33 +756,27 @@ pub fn early_resolve_expr(ex: &ast::Expr, fcx: @FnCtxt, is_early: bool) {
}
}
fn resolve_expr(fcx: @FnCtxt, ex: &ast::Expr) {
let mut fcx = fcx;
early_resolve_expr(ex, fcx, false);
visit::walk_expr(&mut fcx, ex, ());
}
pub fn resolve_impl(ccx: @CrateCtxt,
pub fn resolve_impl(tcx: ty::ctxt,
impl_item: &ast::Item,
impl_generics: &ty::Generics,
impl_trait_ref: &ty::TraitRef) {
let param_env = ty::construct_parameter_environment(
ccx.tcx,
tcx,
None,
impl_generics.type_param_defs(),
[],
impl_generics.region_param_defs(),
impl_item.id);
let impl_trait_ref = @impl_trait_ref.subst(ccx.tcx, &param_env.free_substs);
let impl_trait_ref = @impl_trait_ref.subst(tcx, &param_env.free_substs);
let infcx = &infer::new_infer_ctxt(ccx.tcx);
let infcx = &infer::new_infer_ctxt(tcx);
let vcx = VtableContext { infcx: infcx, param_env: &param_env };
let loc_info = location_info_for_item(impl_item);
// First, check that the impl implements any trait bounds
// on the trait.
let trait_def = ty::lookup_trait_def(ccx.tcx, impl_trait_ref.def_id);
let trait_def = ty::lookup_trait_def(tcx, impl_trait_ref.def_id);
let vtbls = lookup_vtables(&vcx,
&loc_info,
trait_def.generics.type_param_defs(),
@ -797,8 +790,8 @@ pub fn resolve_impl(ccx: @CrateCtxt,
builtin_bounds: ty::EmptyBuiltinBounds(),
trait_bounds: ~[impl_trait_ref]
};
let t = ty::node_id_to_type(ccx.tcx, impl_item.id);
let t = t.subst(ccx.tcx, &param_env.free_substs);
let t = ty::node_id_to_type(tcx, impl_item.id);
let t = t.subst(tcx, &param_env.free_substs);
debug!("=== Doing a self lookup now.");
// Right now, we don't have any place to store this.
@ -815,13 +808,14 @@ pub fn resolve_impl(ccx: @CrateCtxt,
};
let impl_def_id = ast_util::local_def(impl_item.id);
let mut impl_vtables = ccx.tcx.impl_vtables.borrow_mut();
let mut impl_vtables = tcx.impl_vtables.borrow_mut();
impl_vtables.get().insert(impl_def_id, res);
}
impl visit::Visitor<()> for @FnCtxt {
impl<'a> visit::Visitor<()> for &'a FnCtxt {
fn visit_expr(&mut self, ex: &ast::Expr, _: ()) {
resolve_expr(*self, ex);
early_resolve_expr(ex, *self, false);
visit::walk_expr(self, ex, ());
}
fn visit_item(&mut self, _: &ast::Item, _: ()) {
// no-op
@ -830,6 +824,6 @@ impl visit::Visitor<()> for @FnCtxt {
// Detect points where a trait-bounded type parameter is
// instantiated, resolve the impls for the parameters.
pub fn resolve_in_block(mut fcx: @FnCtxt, bl: &ast::Block) {
pub fn resolve_in_block(mut fcx: &FnCtxt, bl: &ast::Block) {
visit::walk_block(&mut fcx, bl, ());
}

@ -141,16 +141,9 @@ pub struct method_object {
real_index: uint,
}
#[deriving(Clone)]
pub struct method_map_entry {
// method details being invoked
origin: method_origin,
}
// maps from an expression id that corresponds to a method call to the details
// of the method to be invoked
pub type method_map = @RefCell<HashMap<ast::NodeId, method_map_entry>>;
pub type method_map = @RefCell<HashMap<ast::NodeId, method_origin>>;
pub type vtable_param_res = @~[vtable_origin];
// Resolutions for bounds of all parameters, left to right, for a given path.

@ -870,12 +870,6 @@ impl Repr for ty::FnSig {
}
}
impl Repr for typeck::method_map_entry {
fn repr(&self, tcx: ctxt) -> ~str {
format!("method_map_entry \\{origin: {}\\}", self.origin.repr(tcx))
}
}
impl Repr for typeck::method_origin {
fn repr(&self, tcx: ctxt) -> ~str {
match self {