about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Sullivan <sully@msully.net>2013-07-15 14:19:36 -0700
committerMichael Sullivan <sully@msully.net>2013-07-18 13:56:14 -0700
commitf0a69b1a43f5785a533566b892411bc041f887f6 (patch)
treeccd0545c5d837edd2056d33e0922db52c6803b5d
parent37702216ebc5761d2f709583f678c19daddc602f (diff)
Refactor some coherence/method trans code, add an impls map to tcx.
Rewrite method_with_name_or_default to use the new impls map.
Get rid of ProvidedMethodsMap.
-rw-r--r--src/librustc/middle/trans/meth.rs85
-rw-r--r--src/librustc/middle/ty.rs28
-rw-r--r--src/librustc/middle/typeck/coherence.rs170
3 files changed, 70 insertions, 213 deletions
diff --git a/src/librustc/middle/trans/meth.rs b/src/librustc/middle/trans/meth.rs
index 6d0f851d83d..1da56767602 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<ast::def_id> {
-    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)
-    };
-
-    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
-}
+    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");
 
-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 bad29b1c618..cd8160d900e 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<def_id,@mut ~[@ProvidedMethodInfo]>;
-
-// 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<ast::node_id, @AutoAdjustment>,
     normalized_cache: @mut HashMap<t, t>,
     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<ast::def_id, ProvidedMethodSource>,
     supertraits: @mut HashMap<ast::def_id, @~[@TraitRef]>,
 
@@ -311,6 +293,12 @@ struct ctxt_ {
     // Methods in these implementations don't need to be exported.
     inherent_impls: @mut HashMap<ast::def_id, @mut ~[@Impl]>,
 
+    // 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<ast::def_id, @Impl>,
+
     // Set of used unsafe nodes (functions or blocks). Unsafe nodes not
     // present in this set can be warned about.
     used_unsafe: @mut HashSet<ast::node_id>,
@@ -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 b6555625f65..a0be0d201f4 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