From 585e283769faaef8898f82b37224e0a16a4f5e2b Mon Sep 17 00:00:00 2001 From: Michael Sullivan Date: Mon, 15 Jul 2013 17:26:56 -0700 Subject: [PATCH] Add provided method information to ty::Method. Get rid of ProvidedMethodSource. --- src/librustc/metadata/decoder.rs | 34 ++++++++++++----------- src/librustc/metadata/encoder.rs | 1 + src/librustc/middle/privacy.rs | 32 ++------------------- src/librustc/middle/trans/base.rs | 1 - src/librustc/middle/trans/callee.rs | 25 +++++++++-------- src/librustc/middle/trans/common.rs | 3 +- src/librustc/middle/trans/meth.rs | 1 - src/librustc/middle/trans/monomorphize.rs | 10 ++----- src/librustc/middle/trans/type_use.rs | 2 +- src/librustc/middle/ty.rs | 26 +++++++++++------ src/librustc/middle/typeck/coherence.rs | 21 +++++++------- src/librustc/middle/typeck/collect.rs | 16 +++++++---- 12 files changed, 77 insertions(+), 95 deletions(-) diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs index 7d515fe62b5..6604ef5df34 100644 --- a/src/librustc/metadata/decoder.rs +++ b/src/librustc/metadata/decoder.rs @@ -174,14 +174,6 @@ fn item_parent_item(d: ebml::Doc) -> Option { None } -fn translated_parent_item_opt(cnum: ast::crate_num, d: ebml::Doc) -> - Option { - 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 ) } diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index 722f8ff9580..aa4f5d0267c 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -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 => { diff --git a/src/librustc/middle/privacy.rs b/src/librustc/middle/privacy.rs index 036c0751483..c602a143253 100644 --- a/src/librustc/middle/privacy.rs +++ b/src/librustc/middle/privacy.rs @@ -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))) { diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index 588b0b5c75f..6741637ae9a 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -524,7 +524,6 @@ pub fn get_res_dtor(ccx: @mut CrateContext, &tsubsts, None, None, - None, None); val diff --git a/src/librustc/middle/trans/callee.rs b/src/librustc/middle/trans/callee.rs index 0885c5086e8..f03a2a62e0c 100644 --- a/src/librustc/middle/trans/callee.rs +++ b/src/librustc/middle/trans/callee.rs @@ -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 diff --git a/src/librustc/middle/trans/common.rs b/src/librustc/middle/trans/common.rs index 29cc8d81973..d90614ebc02 100644 --- a/src/librustc/middle/trans/common.rs +++ b/src/librustc/middle/trans/common.rs @@ -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 + params: ~[mono_param_id] } pub type mono_id = @mono_id_; diff --git a/src/librustc/middle/trans/meth.rs b/src/librustc/middle/trans/meth.rs index 03dbe0869fb..bcf3aa6ad50 100644 --- a/src/librustc/middle/trans/meth.rs +++ b/src/librustc/middle/trans/meth.rs @@ -617,7 +617,6 @@ pub fn vtable_id(ccx: @mut CrateContext, monomorphize::make_mono_id( ccx, impl_id, - None, &psubsts, None) } diff --git a/src/librustc/middle/trans/monomorphize.rs b/src/librustc/middle/trans/monomorphize.rs index 3e5f7267972..789532abc61 100644 --- a/src/librustc/middle/trans/monomorphize.rs +++ b/src/librustc/middle/trans/monomorphize.rs @@ -42,7 +42,6 @@ pub fn monomorphic_fn(ccx: @mut CrateContext, real_substs: &ty::substs, vtables: Option, self_vtable: Option, - impl_did_opt: Option, ref_id: Option) -> (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, 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} } diff --git a/src/librustc/middle/trans/type_use.rs b/src/librustc/middle/trans/type_use.rs index 2c63079ad8f..53c290ec029 100644 --- a/src/librustc/middle/trans/type_use.rs +++ b/src/librustc/middle/trans/type_use.rs @@ -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 { diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 6f3c3d9037e..b63117d25bb 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -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 } 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) -> 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, lang_items: middle::lang_items::LanguageItems, // A mapping of fake provided method def_ids to the default implementation - provided_method_sources: @mut HashMap, + provided_method_sources: @mut HashMap, supertraits: @mut HashMap, // 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 { + 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) { diff --git a/src/librustc/middle/typeck/coherence.rs b/src/librustc/middle/typeck/coherence.rs index 2bdb2f2932a..51b206428e3 100644 --- a/src/librustc/middle/typeck/coherence.rs +++ b/src/librustc/middle/typeck/coherence.rs @@ -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) -> 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 ) } diff --git a/src/librustc/middle/typeck/collect.rs b/src/librustc/middle/typeck/collect.rs index 791774999c2..1941317ede5 100644 --- a/src/librustc/middle/typeck/collect.rs +++ b/src/librustc/middle/typeck/collect.rs @@ -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, 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);