Optimize seen Predicate filtering.

This speeds up a few rustc-perf benchmark runs, most notably ones
involving 'coercions', the best by 2%.
This commit is contained in:
Nicholas Nethercote 2018-05-08 11:17:18 +10:00
parent 4c26e2e3fb
commit 2ff632484c

View File

@ -3356,13 +3356,28 @@ fn impl_or_trait_obligations(&mut self,
predicate: predicate.value
}))
}).collect();
// We are performing deduplication here to avoid exponential blowups
// (#38528) from happening, but the real cause of the duplication is
// unknown. What we know is that the deduplication avoids exponential
// amount of predicates being propogated when processing deeply nested
// amount of predicates being propagated when processing deeply nested
// types.
let mut seen = FxHashSet();
predicates.retain(|i| seen.insert(i.clone()));
//
// This code is hot enough that it's worth avoiding the allocation
// required for the FxHashSet when possible. Special-casing lengths 0,
// 1 and 2 covers roughly 75--80% of the cases.
if predicates.len() <= 1 {
// No possibility of duplicates.
} else if predicates.len() == 2 {
// Only two elements. Drop the second if they are equal.
if predicates[0] == predicates[1] {
predicates.truncate(1);
}
} else {
// Three or more elements. Use a general deduplication process.
let mut seen = FxHashSet();
predicates.retain(|i| seen.insert(i.clone()));
}
self.infcx().plug_leaks(skol_map, snapshot, predicates)
}
}