about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJeffrey Seyfried <jeffrey.seyfried@gmail.com>2016-04-18 00:00:18 +0000
committerAlex Crichton <alex@alexcrichton.com>2016-05-04 11:28:52 -0700
commit23cf2eb4a1742fdf72f77daace6fb89cb8a0046f (patch)
tree2654e059ac48985825e724d60de74fbd9fbf11ab
parentba43dbade94203e0fd2cbd15b719522077d32f80 (diff)
downloadrust-23cf2eb4a1742fdf72f77daace6fb89cb8a0046f.tar.gz
rust-23cf2eb4a1742fdf72f77daace6fb89cb8a0046f.zip
resolve: improve performance
-rw-r--r--src/librustc_resolve/lib.rs36
1 files changed, 25 insertions, 11 deletions
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index 5f4244caa62..a0c4d636fd3 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -850,6 +850,9 @@ pub struct ModuleS<'a> {
     glob_importers: RefCell<Vec<(Module<'a>, &'a ImportDirective<'a>)>>,
     globs: RefCell<Vec<&'a ImportDirective<'a>>>,
 
+    // Used to memoize the traits in this module for faster searches through all traits in scope.
+    traits: RefCell<Option<Box<[&'a NameBinding<'a>]>>>,
+
     // Whether this module is populated. If not populated, any attempt to
     // access the children must be preceded with a
     // `populate_module_if_necessary` call.
@@ -877,6 +880,7 @@ impl<'a> ModuleS<'a> {
             prelude: RefCell::new(None),
             glob_importers: RefCell::new(Vec::new()),
             globs: RefCell::new((Vec::new())),
+            traits: RefCell::new(None),
             populated: Cell::new(!external),
             arenas: arenas
         }
@@ -3233,18 +3237,28 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         let mut search_module = self.current_module;
         loop {
             // Look for trait children.
-            let mut search_in_module = |module: Module<'a>| module.for_each_child(|_, ns, binding| {
-                if ns != TypeNS { return }
-                let trait_def_id = match binding.def() {
-                    Some(Def::Trait(trait_def_id)) => trait_def_id,
-                    Some(..) | None => return,
-                };
-                if self.trait_item_map.contains_key(&(name, trait_def_id)) {
-                    add_trait_info(&mut found_traits, trait_def_id, name);
-                    let trait_name = self.get_trait_name(trait_def_id);
-                    self.record_use(trait_name, TypeNS, binding);
+            let mut search_in_module = |module: Module<'a>| {
+                let mut traits = module.traits.borrow_mut();
+                if traits.is_none() {
+                    let mut collected_traits = Vec::new();
+                    module.for_each_child(|_, ns, binding| {
+                        if ns != TypeNS { return }
+                        if let Some(Def::Trait(_)) = binding.def() {
+                            collected_traits.push(binding);
+                        }
+                    });
+                    *traits = Some(collected_traits.into_boxed_slice());
                 }
-            });
+
+                for binding in traits.as_ref().unwrap().iter() {
+                    let trait_def_id = binding.def().unwrap().def_id();
+                    if self.trait_item_map.contains_key(&(name, trait_def_id)) {
+                        add_trait_info(&mut found_traits, trait_def_id, name);
+                        let trait_name = self.get_trait_name(trait_def_id);
+                        self.record_use(trait_name, TypeNS, binding);
+                    }
+                }
+            };
             search_in_module(search_module);
 
             match search_module.parent_link {