Skip to content

Commit a91f6f7

Browse files
committed
Tweak nearest_common_ancestor().
- Remove the "no nearest common ancestor found" case, because it's never hit in practise. (This means `closure_is_enclosed_by` can also be removed.) - Add a comment about why `SmallVec` is used for the "seen" structures. - Use `&Scope` instead of `Scope` to avoid some `map()` calls. - Use `any(p)` instead of `position(p).is_some()`.
1 parent f9bfe84 commit a91f6f7

File tree

1 file changed

+19
-59
lines changed

1 file changed

+19
-59
lines changed

src/librustc/middle/region.rs

+19-59
Original file line numberDiff line numberDiff line change
@@ -542,18 +542,6 @@ impl<'tcx> ScopeTree {
542542
assert!(previous.is_none());
543543
}
544544

545-
fn closure_is_enclosed_by(&self,
546-
mut sub_closure: hir::ItemLocalId,
547-
sup_closure: hir::ItemLocalId) -> bool {
548-
loop {
549-
if sub_closure == sup_closure { return true; }
550-
match self.closure_tree.get(&sub_closure) {
551-
Some(&s) => { sub_closure = s; }
552-
None => { return false; }
553-
}
554-
}
555-
}
556-
557545
fn record_var_scope(&mut self, var: hir::ItemLocalId, lifetime: Scope) {
558546
debug!("record_var_scope(sub={:?}, sup={:?})", var, lifetime);
559547
assert!(var != lifetime.item_local_id());
@@ -688,65 +676,37 @@ impl<'tcx> ScopeTree {
688676
// requires a hash table lookup, and we often have very long scope
689677
// chains (10s or 100s of scopes) that only differ by a few elements at
690678
// the start. So this algorithm is faster.
691-
let mut ma = Some(scope_a);
692-
let mut mb = Some(scope_b);
693-
let mut seen_a: SmallVec<[Scope; 32]> = SmallVec::new();
694-
let mut seen_b: SmallVec<[Scope; 32]> = SmallVec::new();
679+
680+
let mut ma = Some(&scope_a);
681+
let mut mb = Some(&scope_b);
682+
683+
// A HashSet<Scope> is a more obvious choice for these, but SmallVec is
684+
// faster because the set size is normally small so linear search is
685+
// as good or better than a hash table lookup, plus the size is usually
686+
// small enough to avoid a heap allocation.
687+
let mut seen_a: SmallVec<[&Scope; 32]> = SmallVec::new();
688+
let mut seen_b: SmallVec<[&Scope; 32]> = SmallVec::new();
689+
695690
loop {
696691
if let Some(a) = ma {
697-
if seen_b.iter().position(|s| *s == a).is_some() {
698-
return a;
692+
if seen_b.iter().any(|s| *s == a) {
693+
return *a;
699694
}
700695
seen_a.push(a);
701-
ma = self.parent_map.get(&a).map(|s| *s);
696+
ma = self.parent_map.get(&a);
702697
}
703698

704699
if let Some(b) = mb {
705-
if seen_a.iter().position(|s| *s == b).is_some() {
706-
return b;
700+
if seen_a.iter().any(|s| *s == b) {
701+
return *b;
707702
}
708703
seen_b.push(b);
709-
mb = self.parent_map.get(&b).map(|s| *s);
704+
mb = self.parent_map.get(&b);
710705
}
711706

712707
if ma.is_none() && mb.is_none() {
713-
break;
714-
}
715-
};
716-
717-
fn outermost_scope(parent_map: &FxHashMap<Scope, Scope>, scope: Scope) -> Scope {
718-
let mut scope = scope;
719-
loop {
720-
match parent_map.get(&scope) {
721-
Some(&superscope) => scope = superscope,
722-
None => break scope,
723-
}
724-
}
725-
}
726-
727-
// In this (rare) case, the two regions belong to completely different
728-
// functions. Compare those fn for lexical nesting. The reasoning
729-
// behind this is subtle. See the "Modeling closures" section of the
730-
// README in infer::region_constraints for more details.
731-
let a_root_scope = outermost_scope(&self.parent_map, scope_a);
732-
let b_root_scope = outermost_scope(&self.parent_map, scope_b);
733-
match (a_root_scope.data(), b_root_scope.data()) {
734-
(ScopeData::Destruction(a_root_id),
735-
ScopeData::Destruction(b_root_id)) => {
736-
if self.closure_is_enclosed_by(a_root_id, b_root_id) {
737-
// `a` is enclosed by `b`, hence `b` is the ancestor of everything in `a`
738-
scope_b
739-
} else if self.closure_is_enclosed_by(b_root_id, a_root_id) {
740-
// `b` is enclosed by `a`, hence `a` is the ancestor of everything in `b`
741-
scope_a
742-
} else {
743-
// neither fn encloses the other
744-
bug!()
745-
}
746-
}
747-
_ => {
748-
// root ids are always Node right now
749-
bug!()
708+
// No nearest common ancestor found.
709+
bug!();
750710
}
751711
}
752712
}

0 commit comments

Comments
 (0)