about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJohn Kåre Alsaker <john.kare.alsaker@gmail.com>2017-08-20 14:20:33 +0200
committerJohn Kåre Alsaker <john.kare.alsaker@gmail.com>2017-08-20 14:20:33 +0200
commitbf3ebcc98788d805f96b171362d272c93e0a50a0 (patch)
tree691ffc563972355272002a02923c028942c34efa
parente70cc2733b9902ae660f60fce7ba0bb5191a0d0c (diff)
downloadrust-bf3ebcc98788d805f96b171362d272c93e0a50a0.tar.gz
rust-bf3ebcc98788d805f96b171362d272c93e0a50a0.zip
Make gathering generator interior types O(n log n)
-rw-r--r--src/librustc_typeck/check/generator_interior.rs22
1 files changed, 14 insertions, 8 deletions
diff --git a/src/librustc_typeck/check/generator_interior.rs b/src/librustc_typeck/check/generator_interior.rs
index f50fb7e4a13..7b25a3739c3 100644
--- a/src/librustc_typeck/check/generator_interior.rs
+++ b/src/librustc_typeck/check/generator_interior.rs
@@ -23,9 +23,7 @@ use util::nodemap::FxHashMap;
 struct InteriorVisitor<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
     fcx: &'a FnCtxt<'a, 'gcx, 'tcx>,
     cache: FxHashMap<NodeId, Option<Span>>,
-
-    // FIXME: Use an ordered hash map here
-    types: Vec<Ty<'tcx>>,
+    types: FxHashMap<Ty<'tcx>, usize>,
     region_maps: Rc<RegionMaps>,
 }
 
@@ -46,9 +44,9 @@ impl<'a, 'gcx, 'tcx> InteriorVisitor<'a, 'gcx, 'tcx> {
                        expr, scope, ty, span);
             }
 
-            if !self.types.contains(&ty) {
-                self.types.push(ty);
-            }
+            // Map the type to the number of types added before it
+            let entries = self.types.len();
+            self.types.entry(&ty).or_insert(entries);
         } else {
             debug!("no type in expr = {:?}, span = {:?}", expr, expr.map(|e| e.span));
         }
@@ -62,13 +60,21 @@ pub fn resolve_interior<'a, 'gcx, 'tcx>(fcx: &'a FnCtxt<'a, 'gcx, 'tcx>,
     let body = fcx.tcx.hir.body(body_id);
     let mut visitor = InteriorVisitor {
         fcx,
-        types: Vec::new(),
+        types: FxHashMap(),
         cache: FxHashMap(),
         region_maps: fcx.tcx.region_maps(def_id),
     };
     intravisit::walk_body(&mut visitor, body);
 
-    let tuple = fcx.tcx.intern_tup(&visitor.types, false);
+    let mut types: Vec<_> = visitor.types.drain().collect();
+
+    // Sort types by insertion order
+    types.sort_by_key(|t| t.1);
+
+    // Extract type components
+    let types: Vec<_> = types.into_iter().map(|t| t.0).collect();
+
+    let tuple = fcx.tcx.intern_tup(&types, false);
 
     debug!("Types in generator {:?}, span = {:?}", tuple, body.value.span);