Add provided method information to ty::Method. Get rid of ProvidedMethodSource.
This commit is contained in:
parent
2ea61204f6
commit
585e283769
@ -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
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -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 => {
|
||||
|
@ -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))) {
|
||||
|
@ -524,7 +524,6 @@ pub fn get_res_dtor(ccx: @mut CrateContext,
|
||||
&tsubsts,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
None);
|
||||
|
||||
val
|
||||
|
@ -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
|
||||
|
@ -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_;
|
||||
|
@ -617,7 +617,6 @@ pub fn vtable_id(ccx: @mut CrateContext,
|
||||
monomorphize::make_mono_id(
|
||||
ccx,
|
||||
impl_id,
|
||||
None,
|
||||
&psubsts,
|
||||
None)
|
||||
}
|
||||
|
@ -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: ¶m_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}
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user