Skip to content

Commit 3b75a3d

Browse files
incr.comp.: Make sure traits_in_scope results are hashed in a stable way.
1 parent 5499683 commit 3b75a3d

File tree

5 files changed

+67
-9
lines changed

5 files changed

+67
-9
lines changed

src/librustc/ich/hcx.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,11 @@ impl<'gcx> StableHashingContext<'gcx> {
168168
self.definitions.def_path_hash(def_index)
169169
}
170170

171+
#[inline]
172+
pub fn node_to_hir_id(&self, node_id: ast::NodeId) -> hir::HirId {
173+
self.definitions.node_to_hir_id(node_id)
174+
}
175+
171176
#[inline]
172177
pub fn hash_spans(&self) -> bool {
173178
self.hash_spans

src/librustc/ich/impls_hir.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1160,6 +1160,25 @@ for hir::TraitCandidate {
11601160
}
11611161
}
11621162

1163+
impl<'gcx> ToStableHashKey<StableHashingContext<'gcx>> for hir::TraitCandidate {
1164+
type KeyType = (DefPathHash, Option<(DefPathHash, hir::ItemLocalId)>);
1165+
1166+
fn to_stable_hash_key(&self,
1167+
hcx: &StableHashingContext<'gcx>)
1168+
-> Self::KeyType {
1169+
let hir::TraitCandidate {
1170+
def_id,
1171+
import_id,
1172+
} = *self;
1173+
1174+
let import_id = import_id.map(|node_id| hcx.node_to_hir_id(node_id))
1175+
.map(|hir_id| (hcx.local_def_path_hash(hir_id.owner),
1176+
hir_id.local_id));
1177+
(hcx.def_path_hash(def_id), import_id)
1178+
}
1179+
}
1180+
1181+
11631182
impl_stable_hash_for!(struct hir::Freevar {
11641183
def,
11651184
span

src/librustc/ty/context.rs

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,8 @@ use util::nodemap::{NodeMap, NodeSet, DefIdSet, ItemLocalMap};
5050
use util::nodemap::{FxHashMap, FxHashSet};
5151
use rustc_data_structures::accumulate_vec::AccumulateVec;
5252
use rustc_data_structures::stable_hasher::{HashStable, hash_stable_hashmap,
53-
StableHasher, StableHasherResult};
54-
53+
StableHasher, StableHasherResult,
54+
StableVec};
5555
use arena::{TypedArena, DroplessArena};
5656
use rustc_const_math::{ConstInt, ConstUsize};
5757
use rustc_data_structures::indexed_vec::IndexVec;
@@ -828,7 +828,9 @@ pub struct GlobalCtxt<'tcx> {
828828

829829
/// Map indicating what traits are in scope for places where this
830830
/// is relevant; generated by resolve.
831-
trait_map: FxHashMap<DefIndex, Rc<FxHashMap<ItemLocalId, Rc<Vec<TraitCandidate>>>>>,
831+
trait_map: FxHashMap<DefIndex,
832+
Rc<FxHashMap<ItemLocalId,
833+
Rc<StableVec<TraitCandidate>>>>>,
832834

833835
/// Export map produced by name resolution.
834836
export_map: FxHashMap<DefId, Rc<Vec<Export>>>,
@@ -1081,15 +1083,14 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
10811083
None
10821084
};
10831085

1084-
// FIXME(mw): Each of the Vecs in the trait_map should be brought into
1085-
// a deterministic order here. Otherwise we might end up with
1086-
// unnecessarily unstable incr. comp. hashes.
10871086
let mut trait_map = FxHashMap();
10881087
for (k, v) in resolutions.trait_map {
10891088
let hir_id = hir.node_to_hir_id(k);
10901089
let map = trait_map.entry(hir_id.owner)
10911090
.or_insert_with(|| Rc::new(FxHashMap()));
1092-
Rc::get_mut(map).unwrap().insert(hir_id.local_id, Rc::new(v));
1091+
Rc::get_mut(map).unwrap()
1092+
.insert(hir_id.local_id,
1093+
Rc::new(StableVec::new(v)));
10931094
}
10941095
let mut defs = FxHashMap();
10951096
for (k, v) in named_region_map.defs {
@@ -2103,7 +2104,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
21032104
lint::struct_lint_level(self.sess, lint, level, src, None, msg)
21042105
}
21052106

2106-
pub fn in_scope_traits(self, id: HirId) -> Option<Rc<Vec<TraitCandidate>>> {
2107+
pub fn in_scope_traits(self, id: HirId) -> Option<Rc<StableVec<TraitCandidate>>> {
21072108
self.in_scope_traits_map(id.owner)
21082109
.and_then(|map| map.get(&id.local_id).cloned())
21092110
}

src/librustc/ty/maps/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ use rustc_data_structures::indexed_set::IdxSetBuf;
4242
use rustc_back::PanicStrategy;
4343
use rustc_data_structures::indexed_vec::IndexVec;
4444
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
45+
use rustc_data_structures::stable_hasher::StableVec;
4546
use std::cell::{RefCell, Cell};
4647

4748
use std::ops::Deref;
@@ -259,7 +260,7 @@ define_maps! { <'tcx>
259260

260261
[] fn specializes: specializes_node((DefId, DefId)) -> bool,
261262
[] fn in_scope_traits_map: InScopeTraits(DefIndex)
262-
-> Option<Rc<FxHashMap<ItemLocalId, Rc<Vec<TraitCandidate>>>>>,
263+
-> Option<Rc<FxHashMap<ItemLocalId, Rc<StableVec<TraitCandidate>>>>>,
263264
[] fn module_exports: ModuleExports(DefId) -> Option<Rc<Vec<Export>>>,
264265
[] fn lint_levels: lint_levels_node(CrateNum) -> Rc<lint::LintLevelMap>,
265266

src/librustc_data_structures/stable_hasher.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -558,3 +558,35 @@ pub fn hash_stable_hashmap<HCX, K, V, R, SK, F, W>(
558558
entries.hash_stable(hcx, hasher);
559559
}
560560

561+
pub struct StableVec<T>(Vec<T>);
562+
563+
impl<T> StableVec<T> {
564+
565+
pub fn new(v: Vec<T>) -> Self {
566+
StableVec(v)
567+
}
568+
}
569+
570+
impl<T> ::std::ops::Deref for StableVec<T> {
571+
type Target = Vec<T>;
572+
573+
fn deref(&self) -> &Vec<T> {
574+
&self.0
575+
}
576+
}
577+
578+
impl<T, HCX> HashStable<HCX> for StableVec<T>
579+
where T: HashStable<HCX> + ToStableHashKey<HCX>
580+
{
581+
fn hash_stable<W: StableHasherResult>(&self,
582+
hcx: &mut HCX,
583+
hasher: &mut StableHasher<W>) {
584+
let StableVec(ref v) = *self;
585+
586+
let mut sorted: Vec<_> = v.iter()
587+
.map(|x| x.to_stable_hash_key(hcx))
588+
.collect();
589+
sorted.sort_unstable();
590+
sorted.hash_stable(hcx, hasher);
591+
}
592+
}

0 commit comments

Comments
 (0)