Skip to content

Commit c2d9b4e

Browse files
ICH: Hash lists of local trait impls as part of the HIR.
1 parent ac254fb commit c2d9b4e

File tree

11 files changed

+127
-17
lines changed

11 files changed

+127
-17
lines changed

src/librustc/dep_graph/dep_node.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,8 @@ pub enum DepNode<D: Clone + Debug> {
116116
// than changes in the impl body.
117117
TraitImpls(D),
118118

119+
AllLocalTraitImpls,
120+
119121
// Nodes representing caches. To properly handle a true cache, we
120122
// don't use a DepTrackingMap, but rather we push a task node.
121123
// Otherwise the write into the map would be incorrectly
@@ -263,6 +265,7 @@ impl<D: Clone + Debug> DepNode<D> {
263265
ConstEval(ref d) => op(d).map(ConstEval),
264266
SymbolName(ref d) => op(d).map(SymbolName),
265267
TraitImpls(ref d) => op(d).map(TraitImpls),
268+
AllLocalTraitImpls => Some(AllLocalTraitImpls),
266269
TraitItems(ref d) => op(d).map(TraitItems),
267270
ReprHints(ref d) => op(d).map(ReprHints),
268271
TraitSelect { ref trait_def_id, ref input_def_id } => {

src/librustc/hir/map/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -497,15 +497,15 @@ impl<'hir> Map<'hir> {
497497
}
498498

499499
pub fn trait_impls(&self, trait_did: DefId) -> &'hir [NodeId] {
500-
self.dep_graph.read(DepNode::TraitImpls(trait_did));
500+
self.dep_graph.read(DepNode::AllLocalTraitImpls);
501501

502502
// NB: intentionally bypass `self.forest.krate()` so that we
503503
// do not trigger a read of the whole krate here
504504
self.forest.krate.trait_impls.get(&trait_did).map_or(&[], |xs| &xs[..])
505505
}
506506

507507
pub fn trait_default_impl(&self, trait_did: DefId) -> Option<NodeId> {
508-
self.dep_graph.read(DepNode::TraitImpls(trait_did));
508+
self.dep_graph.read(DepNode::AllLocalTraitImpls);
509509

510510
// NB: intentionally bypass `self.forest.krate()` so that we
511511
// do not trigger a read of the whole krate here

src/librustc/ich/fingerprint.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,3 +94,11 @@ impl stable_hasher::StableHasherResult for Fingerprint {
9494
fingerprint
9595
}
9696
}
97+
98+
impl<CTX> stable_hasher::HashStable<CTX> for Fingerprint {
99+
fn hash_stable<W: stable_hasher::StableHasherResult>(&self,
100+
_: &mut CTX,
101+
hasher: &mut stable_hasher::StableHasher<W>) {
102+
::std::hash::Hash::hash(&self.0, hasher);
103+
}
104+
}

src/librustc/ich/hcx.rs

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use ty;
1616
use util::nodemap::NodeMap;
1717

1818
use std::hash as std_hash;
19-
use std::collections::{HashMap, HashSet};
19+
use std::collections::{HashMap, HashSet, BTreeMap};
2020

2121
use syntax::ast;
2222
use syntax::attr;
@@ -348,3 +348,25 @@ pub fn hash_stable_nodemap<'a, 'tcx, V, W>(hcx: &mut StableHashingContext<'a, 't
348348
hcx.tcx.hir.definitions().node_to_hir_id(*node_id).local_id
349349
});
350350
}
351+
352+
353+
pub fn hash_stable_btreemap<'a, 'tcx, K, V, SK, F, W>(hcx: &mut StableHashingContext<'a, 'tcx>,
354+
hasher: &mut StableHasher<W>,
355+
map: &BTreeMap<K, V>,
356+
extract_stable_key: F)
357+
where K: Eq + Ord,
358+
V: HashStable<StableHashingContext<'a, 'tcx>>,
359+
SK: HashStable<StableHashingContext<'a, 'tcx>> + Ord + Clone,
360+
F: Fn(&mut StableHashingContext<'a, 'tcx>, &K) -> SK,
361+
W: StableHasherResult,
362+
{
363+
let mut keys: Vec<_> = map.keys()
364+
.map(|k| (extract_stable_key(hcx, k), k))
365+
.collect();
366+
keys.sort_unstable_by_key(|&(ref stable_key, _)| stable_key.clone());
367+
keys.len().hash_stable(hcx, hasher);
368+
for (stable_key, key) in keys {
369+
stable_key.hash_stable(hcx, hasher);
370+
map[key].hash_stable(hcx, hasher);
371+
}
372+
}

src/librustc/ich/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@
1313
pub use self::fingerprint::Fingerprint;
1414
pub use self::caching_codemap_view::CachingCodemapView;
1515
pub use self::hcx::{StableHashingContext, NodeIdHashingMode, hash_stable_hashmap,
16-
hash_stable_hashset, hash_stable_nodemap};
16+
hash_stable_hashset, hash_stable_nodemap,
17+
hash_stable_btreemap};
1718
mod fingerprint;
1819
mod caching_codemap_view;
1920
mod hcx;

src/librustc_incremental/calculate_svh/mod.rs

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,10 @@ use rustc::hir::def_id::{LOCAL_CRATE, CRATE_DEF_INDEX, DefId};
3636
use rustc::hir::itemlikevisit::ItemLikeVisitor;
3737
use rustc::ich::{Fingerprint, StableHashingContext};
3838
use rustc::ty::TyCtxt;
39+
use rustc::util::common::record_time;
3940
use rustc_data_structures::stable_hasher::{StableHasher, HashStable};
4041
use rustc_data_structures::fx::FxHashMap;
41-
use rustc::util::common::record_time;
42+
use rustc_data_structures::accumulate_vec::AccumulateVec;
4243

4344
pub type IchHasher = StableHasher<Fingerprint>;
4445

@@ -159,6 +160,11 @@ impl<'a, 'tcx: 'a> ComputeItemHashesVisitor<'a, 'tcx> {
159160
// difference, filter them out.
160161
return None
161162
}
163+
DepNode::AllLocalTraitImpls => {
164+
// These are already covered by hashing
165+
// the HIR.
166+
return None
167+
}
162168
ref other => {
163169
bug!("Found unexpected DepNode during \
164170
SVH computation: {:?}",
@@ -213,6 +219,49 @@ impl<'a, 'tcx: 'a> ComputeItemHashesVisitor<'a, 'tcx> {
213219
true,
214220
(module, (span, attrs)));
215221
}
222+
223+
fn compute_and_store_ich_for_trait_impls(&mut self, krate: &'tcx hir::Crate)
224+
{
225+
let tcx = self.hcx.tcx();
226+
227+
let mut impls: Vec<(u64, Fingerprint)> = krate
228+
.trait_impls
229+
.iter()
230+
.map(|(&trait_id, impls)| {
231+
let trait_id = tcx.def_path_hash(trait_id);
232+
let mut impls: AccumulateVec<[_; 32]> = impls
233+
.iter()
234+
.map(|&node_id| {
235+
let def_id = tcx.hir.local_def_id(node_id);
236+
tcx.def_path_hash(def_id)
237+
})
238+
.collect();
239+
240+
impls.sort_unstable();
241+
let mut hasher = StableHasher::new();
242+
impls.hash_stable(&mut self.hcx, &mut hasher);
243+
(trait_id, hasher.finish())
244+
})
245+
.collect();
246+
247+
impls.sort_unstable();
248+
249+
let mut default_impls: AccumulateVec<[_; 32]> = krate
250+
.trait_default_impl
251+
.iter()
252+
.map(|(&trait_def_id, &impl_node_id)| {
253+
let impl_def_id = tcx.hir.local_def_id(impl_node_id);
254+
(tcx.def_path_hash(trait_def_id), tcx.def_path_hash(impl_def_id))
255+
})
256+
.collect();
257+
258+
default_impls.sort_unstable();
259+
260+
let mut hasher = StableHasher::new();
261+
impls.hash_stable(&mut self.hcx, &mut hasher);
262+
263+
self.hashes.insert(DepNode::AllLocalTraitImpls, hasher.finish());
264+
}
216265
}
217266

218267
impl<'a, 'tcx: 'a> ItemLikeVisitor<'tcx> for ComputeItemHashesVisitor<'a, 'tcx> {
@@ -235,6 +284,8 @@ impl<'a, 'tcx: 'a> ItemLikeVisitor<'tcx> for ComputeItemHashesVisitor<'a, 'tcx>
235284
}
236285
}
237286

287+
288+
238289
pub fn compute_incremental_hashes_map<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>)
239290
-> IncrementalHashesMap {
240291
let _ignore = tcx.dep_graph.in_ignore();
@@ -272,6 +323,8 @@ pub fn compute_incremental_hashes_map<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>)
272323
let fingerprint = hasher.finish();
273324
visitor.hashes.insert(dep_node, fingerprint);
274325
}
326+
327+
visitor.compute_and_store_ich_for_trait_impls(krate);
275328
});
276329

277330
tcx.sess.perf_stats.incr_comp_hashes_count.set(visitor.hashes.len() as u64);

src/librustc_metadata/creader.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -315,11 +315,20 @@ impl<'a> CrateLoader<'a> {
315315
let exported_symbols = crate_root.exported_symbols
316316
.map(|x| x.decode(&metadata).collect());
317317

318+
let trait_impls = crate_root
319+
.impls
320+
.map(|impls| {
321+
impls.decode(&metadata)
322+
.map(|trait_impls| (trait_impls.trait_id, trait_impls.impls))
323+
.collect()
324+
});
325+
318326
let mut cmeta = cstore::CrateMetadata {
319327
name: name,
320328
extern_crate: Cell::new(None),
321329
def_path_table: def_path_table,
322330
exported_symbols: exported_symbols,
331+
trait_impls: trait_impls,
323332
proc_macros: crate_root.macro_derive_registrar.map(|_| {
324333
self.load_derive_macros(&crate_root, dylib.clone().map(|p| p.0), span)
325334
}),

src/librustc_metadata/cstore.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,8 @@ pub struct CrateMetadata {
8585

8686
pub exported_symbols: Tracked<FxHashSet<DefIndex>>,
8787

88+
pub trait_impls: Tracked<FxHashMap<(u32, DefIndex), schema::LazySeq<DefIndex>>>,
89+
8890
pub dep_kind: Cell<DepKind>,
8991
pub source: CrateSource,
9092

src/librustc_metadata/cstore_impl.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -147,10 +147,8 @@ impl CrateStore for cstore::CStore {
147147

148148
fn implementations_of_trait(&self, filter: Option<DefId>) -> Vec<DefId>
149149
{
150-
if let Some(def_id) = filter {
151-
self.dep_graph.read(DepNode::MetaData(def_id));
152-
}
153150
let mut result = vec![];
151+
154152
self.iter_crate_data(|_, cdata| {
155153
cdata.get_implementations_for_trait(filter, &self.dep_graph, &mut result)
156154
});

src/librustc_metadata/decoder.rs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -961,17 +961,17 @@ impl<'a, 'tcx> CrateMetadata {
961961
None => None,
962962
};
963963

964-
// FIXME(eddyb) Make this O(1) instead of O(n).
965964
let dep_node = self.metadata_dep_node(GlobalMetaDataKind::Impls);
966-
for trait_impls in self.root.impls.get(dep_graph, dep_node).decode(self) {
967-
if filter.is_some() && filter != Some(trait_impls.trait_id) {
968-
continue;
969-
}
970-
971-
result.extend(trait_impls.impls.decode(self).map(|index| self.local_def_id(index)));
972965

973-
if filter.is_some() {
974-
break;
966+
if let Some(filter) = filter {
967+
if let Some(impls) = self.trait_impls
968+
.get(dep_graph, dep_node)
969+
.get(&filter) {
970+
result.extend(impls.decode(self).map(|idx| self.local_def_id(idx)));
971+
}
972+
} else {
973+
for impls in self.trait_impls.get(dep_graph, dep_node).values() {
974+
result.extend(impls.decode(self).map(|idx| self.local_def_id(idx)));
975975
}
976976
}
977977
}

src/librustc_metadata/schema.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,20 @@ impl<T> Tracked<T> {
221221
}
222222
}
223223

224+
impl<'a, 'tcx, T> HashStable<StableHashingContext<'a, 'tcx>> for Tracked<T>
225+
where T: HashStable<StableHashingContext<'a, 'tcx>>
226+
{
227+
fn hash_stable<W: StableHasherResult>(&self,
228+
hcx: &mut StableHashingContext<'a, 'tcx>,
229+
hasher: &mut StableHasher<W>) {
230+
let Tracked {
231+
ref state
232+
} = *self;
233+
234+
state.hash_stable(hcx, hasher);
235+
}
236+
}
237+
224238

225239
#[derive(RustcEncodable, RustcDecodable)]
226240
pub struct CrateRoot {

0 commit comments

Comments
 (0)