Add provided method information to ty::Method. Get rid of ProvidedMethodSource.

This commit is contained in:
Michael Sullivan 2013-07-15 17:26:56 -07:00
parent 2ea61204f6
commit 585e283769
12 changed files with 77 additions and 95 deletions

View File

@ -174,14 +174,6 @@ fn item_parent_item(d: ebml::Doc) -> Option<ast::def_id> {
None
}
fn translated_parent_item_opt(cnum: ast::crate_num, d: ebml::Doc) ->
Option<ast::def_id> {
let trait_did_opt = item_parent_item(d);
do trait_did_opt.map |trait_did| {
ast::def_id { crate: cnum, node: trait_did.node }
}
}
fn item_reqd_and_translated_parent_item(cnum: ast::crate_num,
d: ebml::Doc) -> ast::def_id {
let trait_did = item_parent_item(d).expect("item without parent");
@ -323,13 +315,19 @@ fn item_to_def_like(item: ebml::Doc, did: ast::def_id, cnum: ast::crate_num)
UnsafeFn => dl_def(ast::def_fn(did, ast::unsafe_fn)),
Fn => dl_def(ast::def_fn(did, ast::impure_fn)),
ForeignFn => dl_def(ast::def_fn(did, ast::extern_fn)),
UnsafeStaticMethod => {
let trait_did_opt = translated_parent_item_opt(cnum, item);
dl_def(ast::def_static_method(did, trait_did_opt, ast::unsafe_fn))
}
StaticMethod => {
let trait_did_opt = translated_parent_item_opt(cnum, item);
dl_def(ast::def_static_method(did, trait_did_opt, ast::impure_fn))
StaticMethod | UnsafeStaticMethod => {
let purity = if fam == UnsafeStaticMethod { ast::unsafe_fn } else
{ ast::impure_fn };
// def_static_method carries an optional field of its enclosing
// *trait*, but not an inclosing Impl (if this is an inherent
// static method). So we need to detect whether this is in
// a trait or not, which we do through the mildly hacky
// way of checking whether there is a trait_method_sort.
let trait_did_opt = if reader::maybe_get_doc(
item, tag_item_trait_method_sort).is_some() {
Some(item_reqd_and_translated_parent_item(cnum, item))
} else { None };
dl_def(ast::def_static_method(did, trait_did_opt, purity))
}
Type | ForeignType => dl_def(ast::def_ty(did)),
Mod => dl_def(ast::def_mod(did)),
@ -837,6 +835,8 @@ pub fn get_method(intr: @ident_interner, cdata: cmd, id: ast::node_id,
{
let method_doc = lookup_item(id, cdata.data);
let def_id = item_def_id(method_doc, cdata);
let container_id = item_reqd_and_translated_parent_item(cdata.cnum,
method_doc);
let name = item_name(intr, method_doc);
let type_param_defs = item_ty_param_defs(method_doc, tcx, cdata,
tag_item_method_tps);
@ -855,7 +855,9 @@ pub fn get_method(intr: @ident_interner, cdata: cmd, id: ast::node_id,
fty,
explicit_self,
vis,
def_id
def_id,
container_id,
None
)
}

View File

@ -772,6 +772,7 @@ fn encode_info_for_method(ecx: &EncodeContext,
let method_def_id = local_def(m.id);
let method_ty = ty::method(ecx.tcx, method_def_id);
encode_method_ty_fields(ecx, ebml_w, method_ty);
encode_parent_item(ebml_w, local_def(parent_id));
match m.explicit_self.node {
ast::sty_static => {

View File

@ -106,29 +106,6 @@ pub fn check_crate<'mm>(tcx: ty::ctxt,
}
};
// Returns the ID of the container (impl or trait) that a crate-local
// method belongs to.
let local_method_container_id:
@fn(span: span, method_id: node_id) -> def_id =
|span, method_id| {
match tcx.items.find(&method_id) {
Some(&node_method(_, impl_id, _)) => impl_id,
Some(&node_trait_method(_, trait_id, _)) => trait_id,
Some(_) => {
tcx.sess.span_bug(span,
fmt!("method was a %s?!",
ast_map::node_id_to_str(
tcx.items,
method_id,
token::get_ident_interner())));
}
None => {
tcx.sess.span_bug(span, "method not found in \
AST map?!");
}
}
};
// Returns true if a crate-local method is private and false otherwise.
let method_is_private: @fn(span: span, method_id: node_id) -> bool =
|span, method_id| {
@ -248,15 +225,12 @@ pub fn check_crate<'mm>(tcx: ty::ctxt,
// If the method is a default method, we need to use the def_id of
// the default implementation.
// Having to do this this is really unfortunate.
let method_id = match tcx.provided_method_sources.find(&method_id) {
None => method_id,
Some(source) => source.method_id
};
let method_id = ty::method(tcx, method_id).provided_source
.get_or_default(method_id);
if method_id.crate == local_crate {
let is_private = method_is_private(span, method_id.node);
let container_id = local_method_container_id(span,
method_id.node);
let container_id = ty::method(tcx, method_id).container_id;
if is_private &&
(container_id.crate != local_crate ||
!privileged_items.iter().any(|x| x == &(container_id.node))) {

View File

@ -524,7 +524,6 @@ pub fn get_res_dtor(ccx: @mut CrateContext,
&tsubsts,
None,
None,
None,
None);
val

View File

@ -296,10 +296,10 @@ 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 (def_id, opt_impl_did, substs, self_vtable, vtables) =
match tcx.provided_method_sources.find(&def_id) {
None => (def_id, None, substs, None, vtables),
Some(source) => {
let (is_default, def_id, substs, self_vtable, vtables) =
match ty::provided_source(tcx, def_id) {
None => (false, def_id, substs, None, vtables),
Some(source_id) => {
// There are two relevant substitutions when compiling
// default methods. First, there is the substitution for
// the type parameters of the impl we are using and the
@ -313,10 +313,11 @@ pub fn trans_fn_ref_with_vtables(
// So, what we need to do is find this substitution and
// compose it with the one we already have.
let trait_ref = ty::impl_trait_ref(tcx, source.impl_id)
let impl_id = ty::method(tcx, def_id).container_id;
let method = ty::method(tcx, source_id);
let trait_ref = ty::impl_trait_ref(tcx, impl_id)
.expect("could not find trait_ref for impl with \
default methods");
let method = ty::method(tcx, source.method_id);
// Get all of the type params for the receiver
let param_defs = method.generics.type_param_defs;
@ -330,18 +331,18 @@ pub fn trans_fn_ref_with_vtables(
};
let self_vtable =
typeck::vtable_static(source.impl_id, receiver_substs,
typeck::vtable_static(impl_id, receiver_substs,
receiver_vtables);
// Compute the first substitution
let first_subst = make_substs_for_receiver_types(
tcx, source.impl_id, trait_ref, method);
tcx, impl_id, trait_ref, method);
// And compose them
let new_substs = first_subst.subst(tcx, &substs);
let vtables =
resolve_default_method_vtables(bcx, source.impl_id,
resolve_default_method_vtables(bcx, impl_id,
method, &new_substs, vtables);
debug!("trans_fn_with_vtables - default method: \
@ -352,7 +353,7 @@ pub fn trans_fn_ref_with_vtables(
first_subst.repr(tcx), new_substs.repr(tcx),
self_vtable.repr(tcx), vtables.repr(tcx));
(source.method_id, Some(source.impl_id),
(true, source_id,
new_substs, Some(self_vtable), Some(vtables))
}
};
@ -372,7 +373,7 @@ pub fn trans_fn_ref_with_vtables(
// intrinsic that is inlined from a different crate, we want to reemit the
// intrinsic instead of trying to call it in the other crate.
let must_monomorphise;
if type_params.len() > 0 || opt_impl_did.is_some() {
if type_params.len() > 0 || is_default {
must_monomorphise = true;
} else if def_id.crate == ast::local_crate {
let map_node = session::expect(
@ -400,7 +401,7 @@ pub fn trans_fn_ref_with_vtables(
let (val, must_cast) =
monomorphize::monomorphic_fn(ccx, def_id, &substs,
vtables, self_vtable,
opt_impl_did, Some(ref_id));
Some(ref_id));
let mut val = val;
if must_cast && ref_id != 0 {
// Monotype of the REFERENCE to the function (type params

View File

@ -938,8 +938,7 @@ pub fn mono_data_classify(t: ty::t) -> MonoDataClass {
#[deriving(Eq,IterBytes)]
pub struct mono_id_ {
def: ast::def_id,
params: ~[mono_param_id],
impl_did_opt: Option<ast::def_id>
params: ~[mono_param_id]
}
pub type mono_id = @mono_id_;

View File

@ -617,7 +617,6 @@ pub fn vtable_id(ccx: @mut CrateContext,
monomorphize::make_mono_id(
ccx,
impl_id,
None,
&psubsts,
None)
}

View File

@ -42,7 +42,6 @@ pub fn monomorphic_fn(ccx: @mut CrateContext,
real_substs: &ty::substs,
vtables: Option<typeck::vtable_res>,
self_vtable: Option<typeck::vtable_origin>,
impl_did_opt: Option<ast::def_id>,
ref_id: Option<ast::node_id>)
-> (ValueRef, bool)
{
@ -51,13 +50,11 @@ pub fn monomorphic_fn(ccx: @mut CrateContext,
real_substs=%s, \
vtables=%s, \
self_vtable=%s, \
impl_did_opt=%s, \
ref_id=%?)",
fn_id.repr(ccx.tcx),
real_substs.repr(ccx.tcx),
vtables.repr(ccx.tcx),
self_vtable.repr(ccx.tcx),
impl_did_opt.repr(ccx.tcx),
ref_id);
assert!(real_substs.tps.iter().all(|t| !ty::type_needs_infer(*t)));
@ -83,9 +80,7 @@ pub fn monomorphic_fn(ccx: @mut CrateContext,
let param_uses = type_use::type_uses_for(ccx, fn_id, psubsts.tys.len());
let hash_id = make_mono_id(ccx, fn_id, impl_did_opt,
&*psubsts,
Some(param_uses));
let hash_id = make_mono_id(ccx, fn_id, &*psubsts, Some(param_uses));
if hash_id.params.iter().any(
|p| match *p { mono_precise(_, _) => false, _ => true }) {
must_cast = true;
@ -367,7 +362,6 @@ pub fn normalize_for_monomorphization(tcx: ty::ctxt,
pub fn make_mono_id(ccx: @mut CrateContext,
item: ast::def_id,
impl_did_opt: Option<ast::def_id>,
substs: &param_substs,
param_uses: Option<@~[type_use::type_uses]>) -> mono_id {
// FIXME (possibly #5801): Need a lot of type hints to get
@ -442,5 +436,5 @@ pub fn make_mono_id(ccx: @mut CrateContext,
}).collect()
}
};
@mono_id_ {def: item, params: param_ids, impl_did_opt: impl_did_opt}
@mono_id_ {def: item, params: param_ids}
}

View File

@ -90,7 +90,7 @@ pub fn type_uses_for(ccx: @mut CrateContext, fn_id: def_id, n_tps: uint)
// used. This is imprecise, but simple. Getting it right is
// tricky because the substs on the call and the substs on the
// default method differ, because of substs on the trait/impl.
let is_default = ccx.tcx.provided_method_sources.contains_key(&fn_id_loc);
let is_default = ty::provided_source(ccx.tcx, fn_id_loc).is_some();
// We also mark all of the params as used if it is an extern thing
// that we haven't been able to inline yet.
if is_default || fn_id_loc.crate != local_crate {

View File

@ -64,7 +64,11 @@ pub struct Method {
fty: BareFnTy,
explicit_self: ast::explicit_self_,
vis: ast::visibility,
def_id: ast::def_id
def_id: ast::def_id,
container_id: ast::def_id,
// If this method is provided, we need to know where it came from
provided_source: Option<ast::def_id>
}
impl Method {
@ -74,7 +78,9 @@ impl Method {
fty: BareFnTy,
explicit_self: ast::explicit_self_,
vis: ast::visibility,
def_id: ast::def_id)
def_id: ast::def_id,
container_id: ast::def_id,
provided_source: Option<ast::def_id>)
-> Method {
// Check the invariants.
if explicit_self == ast::sty_static {
@ -90,7 +96,9 @@ impl Method {
fty: fty,
explicit_self: explicit_self,
vis: vis,
def_id: def_id
def_id: def_id,
container_id: container_id,
provided_source: provided_source
}
}
}
@ -219,11 +227,6 @@ pub enum AutoRef {
AutoUnsafe(ast::mutability)
}
pub struct ProvidedMethodSource {
method_id: ast::def_id,
impl_id: ast::def_id
}
pub type ctxt = @ctxt_;
struct ctxt_ {
@ -278,7 +281,7 @@ struct ctxt_ {
normalized_cache: @mut HashMap<t, t>,
lang_items: middle::lang_items::LanguageItems,
// A mapping of fake provided method def_ids to the default implementation
provided_method_sources: @mut HashMap<ast::def_id, ProvidedMethodSource>,
provided_method_sources: @mut HashMap<ast::def_id, ast::def_id>,
supertraits: @mut HashMap<ast::def_id, @~[@TraitRef]>,
// A mapping from the def ID of an enum or struct type to the def ID
@ -3511,6 +3514,11 @@ pub fn def_has_ty_params(def: ast::def) -> bool {
}
}
pub fn provided_source(cx: ctxt, id: ast::def_id)
-> Option<ast::def_id> {
cx.provided_method_sources.find(&id).map(|x| **x)
}
pub fn provided_trait_methods(cx: ctxt, id: ast::def_id) -> ~[@Method] {
if is_local(id) {
match cx.items.find(&id.node) {

View File

@ -19,7 +19,7 @@ use metadata::csearch::{each_path, get_impl_trait};
use metadata::csearch;
use metadata::cstore::iter_crate_data;
use metadata::decoder::{dl_def, dl_field, dl_impl};
use middle::ty::{ProvidedMethodSource, get};
use middle::ty::get;
use middle::ty::{lookup_item_type, subst};
use middle::ty::{substs, t, ty_bool, ty_bot, ty_box, ty_enum, ty_err};
use middle::ty::{ty_estr, ty_evec, ty_float, ty_infer, ty_int, ty_nil};
@ -303,7 +303,8 @@ impl CoherenceChecker {
impl_id,
trait_ref,
new_did,
*trait_method);
*trait_method,
Some(trait_method.def_id));
debug!("new_method_ty=%s", new_method_ty.repr(tcx));
all_methods.push(new_method_ty);
@ -328,13 +329,8 @@ impl CoherenceChecker {
// Pair the new synthesized ID up with the
// ID of the method.
let source = ProvidedMethodSource {
method_id: trait_method.def_id,
impl_id: impl_id
};
self.crate_context.tcx.provided_method_sources.insert(new_did,
source);
self.crate_context.tcx.provided_method_sources
.insert(new_did, trait_method.def_id);
}
}
@ -864,7 +860,8 @@ fn subst_receiver_types_in_method_ty(tcx: ty::ctxt,
impl_id: ast::def_id,
trait_ref: &ty::TraitRef,
new_def_id: ast::def_id,
method: &ty::Method)
method: &ty::Method,
provided_source: Option<ast::def_id>)
-> ty::Method {
let combined_substs = make_substs_for_receiver_types(
@ -884,7 +881,9 @@ fn subst_receiver_types_in_method_ty(tcx: ty::ctxt,
method.explicit_self,
method.vis,
new_def_id
new_def_id,
impl_id,
provided_source
)
}

View File

@ -376,7 +376,9 @@ pub fn ensure_trait_methods(ccx: &CrateCtxt,
m_explicit_self.node,
// assume public, because this is only invoked on trait methods
ast::public,
local_def(*m_id)
local_def(*m_id),
local_def(trait_id),
None
)
}
}
@ -720,6 +722,7 @@ pub struct ConvertedMethod {
}
pub fn convert_methods(ccx: &CrateCtxt,
container_id: ast::node_id,
ms: &[@ast::method],
untransformed_rcvr_ty: ty::t,
rcvr_ty_generics: &ty::Generics,
@ -734,7 +737,7 @@ pub fn convert_methods(ccx: &CrateCtxt,
ty_generics(ccx, rcvr_ty_generics.region_param, &m.generics,
num_rcvr_ty_params);
let mty =
@ty_of_method(ccx, *m, rcvr_ty_generics.region_param,
@ty_of_method(ccx, container_id, *m, rcvr_ty_generics.region_param,
untransformed_rcvr_ty,
rcvr_ast_generics, rcvr_visibility,
&m.generics);
@ -760,6 +763,7 @@ pub fn convert_methods(ccx: &CrateCtxt,
}).collect();
fn ty_of_method(ccx: &CrateCtxt,
container_id: ast::node_id,
m: &ast::method,
rp: Option<ty::region_variance>,
untransformed_rcvr_ty: ty::t,
@ -790,7 +794,9 @@ pub fn convert_methods(ccx: &CrateCtxt,
fty,
m.explicit_self.node,
method_vis,
local_def(m.id)
local_def(m.id),
local_def(container_id),
None
)
}
}
@ -849,7 +855,7 @@ pub fn convert(ccx: &CrateCtxt, it: &ast::item) {
it.vis
};
let cms = convert_methods(ccx, *ms, selfty,
let cms = convert_methods(ccx, it.id, *ms, selfty,
&i_ty_generics, generics,
parent_visibility);
for opt_trait_ref.iter().advance |t| {
@ -867,7 +873,7 @@ pub fn convert(ccx: &CrateCtxt, it: &ast::item) {
let untransformed_rcvr_ty = ty::mk_self(tcx, local_def(it.id));
let (ty_generics, _) = mk_item_substs(ccx, generics, rp,
Some(untransformed_rcvr_ty));
let _ = convert_methods(ccx, provided_methods,
let _ = convert_methods(ccx, it.id, provided_methods,
untransformed_rcvr_ty,
&ty_generics, generics,
it.vis);