diff --git a/src/librustc/middle/trans/meth.rs b/src/librustc/middle/trans/meth.rs index 6d0f851d83d9..1da56767602a 100644 --- a/src/librustc/middle/trans/meth.rs +++ b/src/librustc/middle/trans/meth.rs @@ -177,9 +177,7 @@ pub fn trans_method_callee(bcx: block, // Now that we know the impl ID, we can look up the method // ID from its name origin = typeck::method_static( - method_with_name_or_default(bcx.ccx(), - impl_id, - method_name)); + method_with_name(bcx.ccx(), impl_id, method_name)); } typeck::method_self(*) | typeck::method_static(*) | typeck::method_param(*) | @@ -308,12 +306,10 @@ pub fn trans_static_method_callee(bcx: block, typeck::vtable_static(impl_did, ref rcvr_substs, rcvr_origins) => { assert!(rcvr_substs.iter().all(|t| !ty::type_needs_infer(*t))); - let mth_id = method_with_name_or_default(bcx.ccx(), - impl_did, - mname); + let mth_id = method_with_name(bcx.ccx(), impl_did, mname); let (callee_substs, callee_origins) = combine_impl_and_methods_tps( - bcx, mth_id, impl_did, callee_id, + bcx, mth_id, callee_id, *rcvr_substs, rcvr_origins); let FnData {llfn: lval} = @@ -334,58 +330,22 @@ pub fn trans_static_method_callee(bcx: block, } } -pub fn method_from_methods(ms: &[@ast::method], name: ast::ident) - -> Option { - ms.iter().find_(|m| m.ident == name).map(|m| ast_util::local_def(m.id)) -} - -pub fn method_with_name_or_default(ccx: &mut CrateContext, - impl_id: ast::def_id, - name: ast::ident) -> ast::def_id { - let imp = ccx.impl_method_cache.find_copy(&(impl_id, name)); - match imp { +pub fn method_with_name(ccx: &mut CrateContext, + impl_id: ast::def_id, + name: ast::ident) -> ast::def_id { + let meth_id_opt = ccx.impl_method_cache.find_copy(&(impl_id, name)); + match meth_id_opt { Some(m) => return m, None => {} } - // None of this feels like it should be the best way to do this. - let mut did = if impl_id.crate == ast::local_crate { - match ccx.tcx.items.get_copy(&impl_id.node) { - ast_map::node_item(@ast::item { - node: ast::item_impl(_, _, _, ref ms), _ - }, _) => { method_from_methods(*ms, name) }, - _ => fail!("method_with_name") - } - } else { - csearch::get_impl_method(ccx.sess.cstore, impl_id, name) - }; + let imp = ccx.tcx.impls.find(&impl_id) + .expect("could not find impl while translating"); + let meth = imp.methods.iter().find_(|m| m.ident == name) + .expect("could not find method while translating"); - if did.is_none() { - // Look for a default method - let pmm = ccx.tcx.provided_methods; - match pmm.find(&impl_id) { - Some(pmis) => { - for pmis.iter().advance |pmi| { - if pmi.method_info.ident == name { - debug!("pmi.method_info.did = %?", - pmi.method_info.did); - did = Some(pmi.method_info.did); - } - } - } - None => {} - } - } - - let imp = did.expect("could not find method while translating"); - ccx.impl_method_cache.insert((impl_id, name), imp); - imp -} - -pub fn method_ty_param_count(ccx: &CrateContext, m_id: ast::def_id, - i_id: ast::def_id) -> uint { - debug!("method_ty_param_count: m_id: %?, i_id: %?", m_id, i_id); - ty::method(ccx.tcx, m_id).generics.type_param_defs.len() + ccx.impl_method_cache.insert((impl_id, name), meth.did); + meth.did } pub fn trans_monomorphized_callee(bcx: block, @@ -401,8 +361,7 @@ pub fn trans_monomorphized_callee(bcx: block, typeck::vtable_static(impl_did, ref rcvr_substs, rcvr_origins) => { let ccx = bcx.ccx(); let mname = ty::trait_method(ccx.tcx, trait_id, n_method).ident; - let mth_id = method_with_name_or_default( - bcx.ccx(), impl_did, mname); + let mth_id = method_with_name(bcx.ccx(), impl_did, mname); // obtain the `self` value: let mut temp_cleanups = ~[]; @@ -413,7 +372,7 @@ pub fn trans_monomorphized_callee(bcx: block, // those from the impl and those from the method: let (callee_substs, callee_origins) = combine_impl_and_methods_tps( - bcx, mth_id, impl_did, callee_id, + bcx, mth_id, callee_id, *rcvr_substs, rcvr_origins); // translate the function @@ -452,7 +411,6 @@ pub fn trans_monomorphized_callee(bcx: block, pub fn combine_impl_and_methods_tps(bcx: block, mth_did: ast::def_id, - impl_did: ast::def_id, callee_id: ast::node_id, rcvr_substs: &[ty::t], rcvr_origins: typeck::vtable_res) @@ -475,15 +433,16 @@ pub fn combine_impl_and_methods_tps(bcx: block, * mapped to. */ let ccx = bcx.ccx(); - let n_m_tps = method_ty_param_count(ccx, mth_did, impl_did); + let method = ty::method(ccx.tcx, mth_did); + let n_m_tps = method.generics.type_param_defs.len(); let node_substs = node_id_type_params(bcx, callee_id); - debug!("rcvr_substs=%?", rcvr_substs.map(|t| bcx.ty_to_str(*t))); + debug!("rcvr_substs=%?", rcvr_substs.repr(ccx.tcx)); let ty_substs = vec::append(rcvr_substs.to_owned(), node_substs.tailn(node_substs.len() - n_m_tps)); debug!("n_m_tps=%?", n_m_tps); - debug!("node_substs=%?", node_substs.map(|t| bcx.ty_to_str(*t))); - debug!("ty_substs=%?", ty_substs.map(|t| bcx.ty_to_str(*t))); + debug!("node_substs=%?", node_substs.repr(ccx.tcx)); + debug!("ty_substs=%?", ty_substs.repr(ccx.tcx)); // Now, do the same work for the vtables. The vtables might not @@ -744,7 +703,7 @@ pub fn make_impl_vtable(bcx: block, } else { debug!("(making impl vtable) adding method to vtable: %s", tcx.sess.str_of(im.ident)); - let m_id = method_with_name_or_default(ccx, impl_id, im.ident); + let m_id = method_with_name(ccx, impl_id, im.ident); trans_fn_ref_with_vtables(bcx, m_id, 0, substs, Some(vtables)).llfn diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index bad29b1c6184..cd8160d900ed 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -214,21 +214,6 @@ pub enum AutoRef { AutoUnsafe(ast::mutability) } -// Stores information about provided methods (a.k.a. default methods) in -// implementations. -// -// This is a map from ID of each implementation to the method info and trait -// method ID of each of the default methods belonging to the trait that -// implementation implements. -pub type ProvidedMethodsMap = @mut HashMap; - -// Stores the method info and definition ID of the associated trait method for -// each instantiation of each provided method. -pub struct ProvidedMethodInfo { - method_info: @MethodInfo, - trait_method_def_id: def_id -} - pub struct ProvidedMethodSource { method_id: ast::def_id, impl_id: ast::def_id @@ -287,10 +272,7 @@ struct ctxt_ { adjustments: @mut HashMap, normalized_cache: @mut HashMap, lang_items: middle::lang_items::LanguageItems, - // A mapping from an implementation ID to the method info and trait - // method ID of the provided (a.k.a. default) methods in the traits that - // that implementation implements. - provided_methods: ProvidedMethodsMap, + // A mapping of fake provided method def_ids to the default implementation provided_method_sources: @mut HashMap, supertraits: @mut HashMap, @@ -311,6 +293,12 @@ struct ctxt_ { // Methods in these implementations don't need to be exported. inherent_impls: @mut HashMap, + // Maps a def_id of an impl to an Impl structure. + // Note that this contains all of the impls that we know about, + // including ones in other crates. It's not clear that this is the best + // way to do it. + impls: @mut HashMap, + // Set of used unsafe nodes (functions or blocks). Unsafe nodes not // present in this set can be warned about. used_unsafe: @mut HashSet, @@ -904,13 +892,13 @@ pub fn mk_ctxt(s: session::Session, adjustments: @mut HashMap::new(), normalized_cache: new_ty_hash(), lang_items: lang_items, - provided_methods: @mut HashMap::new(), provided_method_sources: @mut HashMap::new(), supertraits: @mut HashMap::new(), destructor_for_type: @mut HashMap::new(), destructors: @mut HashSet::new(), trait_impls: @mut HashMap::new(), inherent_impls: @mut HashMap::new(), + impls: @mut HashMap::new(), used_unsafe: @mut HashSet::new(), used_mut_nodes: @mut HashSet::new(), } diff --git a/src/librustc/middle/typeck/coherence.rs b/src/librustc/middle/typeck/coherence.rs index b6555625f659..a0be0d201f46 100644 --- a/src/librustc/middle/typeck/coherence.rs +++ b/src/librustc/middle/typeck/coherence.rs @@ -20,7 +20,7 @@ use metadata::csearch; use metadata::cstore::{CStore, iter_crate_data}; use metadata::decoder::{dl_def, dl_field, dl_impl}; use middle::resolve::{Impl, MethodInfo}; -use middle::ty::{ProvidedMethodSource, ProvidedMethodInfo, get}; +use middle::ty::{ProvidedMethodSource, 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}; @@ -250,27 +250,16 @@ impl CoherenceChecker { } } - // We only want to generate one Impl structure. When we generate one, - // we store it here so that we don't recreate it. - let mut implementation_opt = None; + let implementation = self.create_impl_from_item(item); + for associated_traits.iter().advance |associated_trait| { - let trait_ref = - ty::node_id_to_trait_ref( - self.crate_context.tcx, - associated_trait.ref_id); + let trait_ref = ty::node_id_to_trait_ref( + self.crate_context.tcx, associated_trait.ref_id); debug!("(checking implementation) adding impl for trait '%s', item '%s'", trait_ref.repr(self.crate_context.tcx), self.crate_context.tcx.sess.str_of(item.ident)); - self.instantiate_default_methods(local_def(item.id), trait_ref); - - let implementation; - if implementation_opt.is_none() { - implementation = self.create_impl_from_item(item); - implementation_opt = Some(implementation); - } - - self.add_trait_impl(trait_ref.def_id, implementation_opt.get()); + self.add_trait_impl(trait_ref.def_id, implementation); } // Add the implementation to the mapping from implementation to base @@ -285,17 +274,6 @@ impl CoherenceChecker { Some(base_type_def_id) => { // XXX: Gather up default methods? if associated_traits.len() == 0 { - let implementation; - match implementation_opt { - None => { - implementation = - self.create_impl_from_item(item); - } - Some(existing_implementation) => { - implementation = existing_implementation; - } - } - self.add_inherent_impl(base_type_def_id, implementation); } @@ -303,6 +281,8 @@ impl CoherenceChecker { base_type_def_id); } } + + tcx.impls.insert(implementation.did, implementation); } // Creates default method IDs and performs type substitutions for an impl @@ -310,7 +290,8 @@ impl CoherenceChecker { // `ProvidedMethodInfo` instance into the `provided_method_sources` map. pub fn instantiate_default_methods(&self, impl_id: ast::def_id, - trait_ref: &ty::TraitRef) { + trait_ref: &ty::TraitRef, + all_methods: &mut ~[@MethodInfo]) { let tcx = self.crate_context.tcx; debug!("instantiate_default_methods(impl_id=%?, trait_ref=%s)", impl_id, trait_ref.repr(tcx)); @@ -364,39 +345,13 @@ impl CoherenceChecker { self.crate_context.tcx.provided_method_sources.insert(new_did, source); - let provided_method_info = - @ProvidedMethodInfo { - method_info: @MethodInfo { - did: new_did, - n_tps: trait_method.generics.type_param_defs.len(), - ident: trait_method.ident, - explicit_self: trait_method.explicit_self - }, - trait_method_def_id: trait_method.def_id - }; - - let pmm = self.crate_context.tcx.provided_methods; - match pmm.find(&impl_id) { - Some(&mis) => { - // If the trait already has an entry in the - // provided_methods_map, we just need to add this - // method to that entry. - debug!("(checking implementation) adding method `%s` \ - to entry for existing trait", - self.crate_context.tcx.sess.str_of( - provided_method_info.method_info.ident)); - mis.push(provided_method_info); - } - None => { - // If the trait doesn't have an entry yet, create one. - debug!("(checking implementation) creating new entry \ - for method `%s`", - self.crate_context.tcx.sess.str_of( - provided_method_info.method_info.ident)); - pmm.insert(impl_id, - @mut ~[provided_method_info]); - } - } + let method_info = @MethodInfo { + did: new_did, + n_tps: trait_method.generics.type_param_defs.len(), + ident: trait_method.ident, + explicit_self: trait_method.explicit_self + }; + all_methods.push(method_info); } } @@ -606,13 +561,11 @@ impl CoherenceChecker { // This check doesn't really have anything to do with coherence. It's // here for historical reasons - pub fn please_check_that_trait_methods_are_implemented(&self, - all_methods: - &mut - ~[@MethodInfo], - trait_did: def_id, - trait_ref_span: - span) { + pub fn check_trait_methods_are_implemented( + &self, + all_methods: &mut ~[@MethodInfo], + trait_did: def_id, + trait_ref_span: span) { let tcx = self.crate_context.tcx; @@ -621,12 +574,6 @@ impl CoherenceChecker { for uint::range(0, all_methods.len()) |i| { provided_names.insert(all_methods[i].ident); } - // Default methods - let r = ty::provided_trait_methods(tcx, trait_did); - for r.iter().advance |method| { - debug!("inserting provided method %s", method.ident.repr(tcx)); - provided_names.insert(method.ident); - } let r = ty::trait_methods(tcx, trait_did); for r.iter().advance |method| { @@ -679,39 +626,6 @@ impl CoherenceChecker { } } - fn add_provided_methods_to_impl( - &self, - all_methods: &mut ~[@MethodInfo], - trait_did: &ast::def_id, - impl_id: &ast::def_id) { - - - match self.crate_context.tcx - .provided_methods - .find(impl_id) { - None => { - debug!("(creating impl) trait with node_id `%d` \ - has no provided methods", trait_did.node); - /* fall through */ - } - Some(&all_provided_methods) => { - debug!("(creating impl) trait with node_id `%d` \ - has provided methods", trait_did.node); - // Add all provided methods. - for all_provided_methods.iter().advance |provided_method| { - debug!( - "(creating impl) adding provided method \ - `%s` to impl", - provided_method.method_info - .ident.repr(self.crate_context.tcx)); - all_methods.push(provided_method.method_info); - } - } - } - - - } - // Converts an implementation in the AST to an Impl structure. pub fn create_impl_from_item(&self, item: @item) -> @Impl { match item.node { @@ -721,28 +635,23 @@ impl CoherenceChecker { methods.push(method_to_MethodInfo(*ast_method)); } - // Check that we have implementations of every trait method for trait_refs.iter().advance |trait_ref| { - let trait_did = - self.trait_ref_to_trait_def_id(trait_ref); - self.please_check_that_trait_methods_are_implemented( + let ty_trait_ref = ty::node_id_to_trait_ref( + self.crate_context.tcx, + trait_ref.ref_id); + let trait_did = ty_trait_ref.def_id; + + self.instantiate_default_methods(local_def(item.id), + ty_trait_ref, + &mut methods); + + // Check that we have implementations of every trait method + self.check_trait_methods_are_implemented( &mut methods, trait_did, trait_ref.path.span); } - // For each trait that the impl implements, see which - // methods are provided. For each of those methods, - // if a method of that name is not inherent to the - // impl, use the provided definition in the trait. - for trait_refs.iter().advance |trait_ref| { - let trait_did = self.trait_ref_to_trait_def_id(trait_ref); - self.add_provided_methods_to_impl( - &mut methods, - &trait_did, - &local_def(item.id)); - } - return @Impl { did: local_def(item.id), ident: item.ident, @@ -813,15 +722,13 @@ impl CoherenceChecker { // Record all the trait methods. let mut implementation = @implementation; for associated_traits.iter().advance |trait_ref| { - self.instantiate_default_methods(implementation.did, - *trait_ref); - // XXX(sully): We could probably avoid this copy if there are no // default methods. let mut methods = implementation.methods.clone(); - self.add_provided_methods_to_impl(&mut methods, - &trait_ref.def_id, - &implementation.did); + self.instantiate_default_methods(implementation.did, + *trait_ref, + &mut methods); + implementation = @Impl { methods: methods, ..*implementation @@ -848,6 +755,9 @@ impl CoherenceChecker { base_type_def_id); } } + + self.crate_context.tcx.impls.insert(implementation.did, + implementation); } // Adds implementations and traits from external crates to the coherence