Skip to content

Commit 56fcf07

Browse files
Avoid nondeterminism in trimmed_def_paths
Previously this query depended on the global interning order of Symbols, which meant that irrelevant changes could influence the query and cause recompilations. This commit ensures that the return set is stable and will not be affected by the global order by deterministically (in lexicographic order) choosing a name to use if there are multiple names for a single DefId.
1 parent 69c1c6a commit 56fcf07

File tree

1 file changed

+23
-2
lines changed

1 file changed

+23
-2
lines changed

compiler/rustc_middle/src/ty/print/pretty.rs

+23-2
Original file line numberDiff line numberDiff line change
@@ -2408,7 +2408,7 @@ fn for_each_def(tcx: TyCtxt<'_>, mut collect_fn: impl for<'b> FnMut(&'b Ident, N
24082408
///
24092409
/// The implementation uses similar import discovery logic to that of 'use' suggestions.
24102410
fn trimmed_def_paths(tcx: TyCtxt<'_>, (): ()) -> FxHashMap<DefId, Symbol> {
2411-
let mut map = FxHashMap::default();
2411+
let mut map: FxHashMap<DefId, Symbol> = FxHashMap::default();
24122412

24132413
if let TrimmedDefPaths::GoodPath = tcx.sess.opts.trimmed_def_paths {
24142414
// For good paths causing this bug, the `rustc_middle::ty::print::with_no_trimmed_paths`
@@ -2446,8 +2446,29 @@ fn trimmed_def_paths(tcx: TyCtxt<'_>, (): ()) -> FxHashMap<DefId, Symbol> {
24462446
});
24472447

24482448
for ((_, symbol), opt_def_id) in unique_symbols_rev.drain() {
2449+
use std::collections::hash_map::Entry::{Occupied, Vacant};
2450+
24492451
if let Some(def_id) = opt_def_id {
2450-
map.insert(def_id, symbol);
2452+
match map.entry(def_id) {
2453+
Occupied(mut v) => {
2454+
// A single DefId can be known under multiple names (e.g.,
2455+
// with a `pub use ... as ...;`). We need to ensure that the
2456+
// name placed in this map is chosen deterministically, so
2457+
// if we find multiple names (`symbol`) resolving to the
2458+
// same `def_id`, we prefer the lexicographically smallest
2459+
// name.
2460+
//
2461+
// Any stable ordering would be fine here though.
2462+
if *v.get() != symbol {
2463+
if v.get().as_str() > symbol.as_str() {
2464+
v.insert(symbol);
2465+
}
2466+
}
2467+
}
2468+
Vacant(v) => {
2469+
v.insert(symbol);
2470+
}
2471+
}
24512472
}
24522473
}
24532474

0 commit comments

Comments
 (0)