Skip to content

Commit f3fc547

Browse files
committed
Auto merge of #41709 - michaelwoerister:close-metadata-ich-holes, r=nikomatsakis
incr.comp.: Hash more pieces of crate metadata to detect changes there. This PR adds incr. comp. hashes for non-`Entry` pieces of data in crate metadata. The first part of it I like: `EntryBuilder` is refactored into the more generally applicable `IsolatedEncoder` which provides means of encoding something into metadata while also feeding the encoded data into an incr. comp. hash. We already did this for `Entry`, now we are doing it for various other pieces of data too, like the set of exported symbols and so on. The hashes generated there are persisted together with the per-`Entry` hashes and are also used for dep-graph dirtying the same way. The second part of the PR I'm not entirely happy with: In order to make sure that we don't forget registering a read to the new `DepNodes` introduced here, I added the `Tracked<T>` struct. This struct wraps a value and requires a `DepNode` when accessing the wrapped value. This makes it harder to overlook adding read edges in the right places and works just fine. However, crate metadata is already used in places where there is no `tcx` yet or even in places where no `cnum` has been assigned -- this makes it harder to apply this feature consistently or implement it ergonomically. The result is not too bad but there's a bit more code churn and a bit more opportunity to get something wrong than I would have liked. On the other hand, wrapping things in `Tracked<T>` already has revealed some bugs, so there's definitely some value in it. This is still a work in progress: - [x] I need to write some test cases. - [x] Accessing the CodeMap should really be dependency tracked too, especially with the new path-remapping feature. cc @nikomatsakis
2 parents c2d53dc + 115602b commit f3fc547

File tree

33 files changed

+1506
-852
lines changed

33 files changed

+1506
-852
lines changed

src/librustc/dep_graph/dep_node.rs

+19-2
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,9 @@ pub enum DepNode<D: Clone + Debug> {
5151
// in an extern crate.
5252
MetaData(D),
5353

54+
// Represents some piece of metadata global to its crate.
55+
GlobalMetaData(D, GlobalMetaDataKind),
56+
5457
// Represents some artifact that we save to disk. Note that these
5558
// do not have a def-id as part of their identifier.
5659
WorkProduct(Arc<WorkProductId>),
@@ -79,7 +82,6 @@ pub enum DepNode<D: Clone + Debug> {
7982
MirKeys,
8083
LateLintCheck,
8184
TransCrateItem(D),
82-
TransInlinedItem(D),
8385
TransWriteMetadata,
8486
CrateVariances,
8587

@@ -157,6 +159,7 @@ pub enum DepNode<D: Clone + Debug> {
157159
DefSpan(D),
158160
Stability(D),
159161
Deprecation(D),
162+
FileMap(D, Arc<String>),
160163
}
161164

162165
impl<D: Clone + Debug> DepNode<D> {
@@ -234,7 +237,6 @@ impl<D: Clone + Debug> DepNode<D> {
234237
RegionMaps(ref d) => op(d).map(RegionMaps),
235238
RvalueCheck(ref d) => op(d).map(RvalueCheck),
236239
TransCrateItem(ref d) => op(d).map(TransCrateItem),
237-
TransInlinedItem(ref d) => op(d).map(TransInlinedItem),
238240
AssociatedItems(ref d) => op(d).map(AssociatedItems),
239241
ItemSignature(ref d) => op(d).map(ItemSignature),
240242
ItemVariances(ref d) => op(d).map(ItemVariances),
@@ -271,6 +273,8 @@ impl<D: Clone + Debug> DepNode<D> {
271273
DefSpan(ref d) => op(d).map(DefSpan),
272274
Stability(ref d) => op(d).map(Stability),
273275
Deprecation(ref d) => op(d).map(Deprecation),
276+
GlobalMetaData(ref d, kind) => op(d).map(|d| GlobalMetaData(d, kind)),
277+
FileMap(ref d, ref file_name) => op(d).map(|d| FileMap(d, file_name.clone())),
274278
}
275279
}
276280
}
@@ -282,3 +286,16 @@ impl<D: Clone + Debug> DepNode<D> {
282286
/// them even in the absence of a tcx.)
283287
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
284288
pub struct WorkProductId(pub String);
289+
290+
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
291+
pub enum GlobalMetaDataKind {
292+
Krate,
293+
CrateDeps,
294+
DylibDependencyFormats,
295+
LangItems,
296+
LangItemsMissing,
297+
NativeLibraries,
298+
CodeMap,
299+
Impls,
300+
ExportedSymbols,
301+
}

src/librustc/dep_graph/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ mod thread;
2222
pub use self::dep_tracking_map::{DepTrackingMap, DepTrackingMapConfig};
2323
pub use self::dep_node::DepNode;
2424
pub use self::dep_node::WorkProductId;
25+
pub use self::dep_node::GlobalMetaDataKind;
2526
pub use self::graph::DepGraph;
2627
pub use self::graph::WorkProduct;
2728
pub use self::query::DepGraphQuery;

src/librustc/hir/def_id.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,10 @@ pub const LOCAL_CRATE: CrateNum = CrateNum(0);
3636

3737
/// Virtual crate for builtin macros
3838
// FIXME(jseyfried): this is also used for custom derives until proc-macro crates get `CrateNum`s.
39-
pub const BUILTIN_MACROS_CRATE: CrateNum = CrateNum(!0);
39+
pub const BUILTIN_MACROS_CRATE: CrateNum = CrateNum(u32::MAX);
40+
41+
/// A CrateNum value that indicates that something is wrong.
42+
pub const INVALID_CRATE: CrateNum = CrateNum(u32::MAX - 1);
4043

4144
impl CrateNum {
4245
pub fn new(x: usize) -> CrateNum {

src/librustc/hir/svh.rs

+4
Original file line numberDiff line numberDiff line change
@@ -66,3 +66,7 @@ impl Decodable for Svh {
6666
.map(Svh::new)
6767
}
6868
}
69+
70+
impl_stable_hash_for!(struct Svh {
71+
hash
72+
});

src/librustc/ich/caching_codemap_view.rs

+32-3
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,14 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
use ty::TyCtxt;
11+
use dep_graph::{DepGraph, DepNode};
12+
use hir::def_id::{DefId, CrateNum, CRATE_DEF_INDEX};
13+
use rustc_data_structures::bitvec::BitVector;
1214
use std::rc::Rc;
15+
use std::sync::Arc;
1316
use syntax::codemap::CodeMap;
1417
use syntax_pos::{BytePos, FileMap};
18+
use ty::TyCtxt;
1519

1620
#[derive(Clone)]
1721
struct CacheEntry {
@@ -20,30 +24,37 @@ struct CacheEntry {
2024
line_start: BytePos,
2125
line_end: BytePos,
2226
file: Rc<FileMap>,
27+
file_index: usize,
2328
}
2429

2530
pub struct CachingCodemapView<'tcx> {
2631
codemap: &'tcx CodeMap,
2732
line_cache: [CacheEntry; 3],
2833
time_stamp: usize,
34+
dep_graph: DepGraph,
35+
dep_tracking_reads: BitVector,
2936
}
3037

3138
impl<'tcx> CachingCodemapView<'tcx> {
3239
pub fn new<'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> CachingCodemapView<'tcx> {
3340
let codemap = tcx.sess.codemap();
34-
let first_file = codemap.files.borrow()[0].clone();
41+
let files = codemap.files_untracked();
42+
let first_file = files[0].clone();
3543
let entry = CacheEntry {
3644
time_stamp: 0,
3745
line_number: 0,
3846
line_start: BytePos(0),
3947
line_end: BytePos(0),
4048
file: first_file,
49+
file_index: 0,
4150
};
4251

4352
CachingCodemapView {
53+
dep_graph: tcx.dep_graph.clone(),
4454
codemap: codemap,
4555
line_cache: [entry.clone(), entry.clone(), entry.clone()],
4656
time_stamp: 0,
57+
dep_tracking_reads: BitVector::new(files.len()),
4758
}
4859
}
4960

@@ -56,6 +67,10 @@ impl<'tcx> CachingCodemapView<'tcx> {
5667
for cache_entry in self.line_cache.iter_mut() {
5768
if pos >= cache_entry.line_start && pos < cache_entry.line_end {
5869
cache_entry.time_stamp = self.time_stamp;
70+
if self.dep_tracking_reads.insert(cache_entry.file_index) {
71+
self.dep_graph.read(dep_node(cache_entry));
72+
}
73+
5974
return Some((cache_entry.file.clone(),
6075
cache_entry.line_number,
6176
pos - cache_entry.line_start));
@@ -75,14 +90,15 @@ impl<'tcx> CachingCodemapView<'tcx> {
7590
// If the entry doesn't point to the correct file, fix it up
7691
if pos < cache_entry.file.start_pos || pos >= cache_entry.file.end_pos {
7792
let file_valid;
78-
let files = self.codemap.files.borrow();
93+
let files = self.codemap.files_untracked();
7994

8095
if files.len() > 0 {
8196
let file_index = self.codemap.lookup_filemap_idx(pos);
8297
let file = files[file_index].clone();
8398

8499
if pos >= file.start_pos && pos < file.end_pos {
85100
cache_entry.file = file;
101+
cache_entry.file_index = file_index;
86102
file_valid = true;
87103
} else {
88104
file_valid = false;
@@ -104,8 +120,21 @@ impl<'tcx> CachingCodemapView<'tcx> {
104120
cache_entry.line_end = line_bounds.1;
105121
cache_entry.time_stamp = self.time_stamp;
106122

123+
if self.dep_tracking_reads.insert(cache_entry.file_index) {
124+
self.dep_graph.read(dep_node(cache_entry));
125+
}
126+
107127
return Some((cache_entry.file.clone(),
108128
cache_entry.line_number,
109129
pos - cache_entry.line_start));
110130
}
111131
}
132+
133+
fn dep_node(cache_entry: &CacheEntry) -> DepNode<DefId> {
134+
let def_id = DefId {
135+
krate: CrateNum::from_u32(cache_entry.file.crate_of_origin),
136+
index: CRATE_DEF_INDEX,
137+
};
138+
let name = Arc::new(cache_entry.file.name.clone());
139+
DepNode::FileMap(def_id, name)
140+
}

src/librustc/ich/impls_cstore.rs

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
//! This module contains `HashStable` implementations for various data types
12+
//! from rustc::middle::cstore in no particular order.
13+
14+
use middle;
15+
16+
impl_stable_hash_for!(enum middle::cstore::DepKind {
17+
UnexportedMacrosOnly,
18+
MacrosOnly,
19+
Implicit,
20+
Explicit
21+
});
22+
23+
impl_stable_hash_for!(enum middle::cstore::NativeLibraryKind {
24+
NativeStatic,
25+
NativeStaticNobundle,
26+
NativeFramework,
27+
NativeUnknown
28+
});
29+
30+
impl_stable_hash_for!(struct middle::cstore::NativeLibrary {
31+
kind,
32+
name,
33+
cfg,
34+
foreign_items
35+
});
36+
37+
impl_stable_hash_for!(enum middle::cstore::LinkagePreference {
38+
RequireDynamic,
39+
RequireStatic
40+
});

src/librustc/ich/impls_hir.rs

+8
Original file line numberDiff line numberDiff line change
@@ -1120,3 +1120,11 @@ impl_stable_hash_for!(struct hir::def::Export {
11201120
def,
11211121
span
11221122
});
1123+
1124+
impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ::middle::lang_items::LangItem {
1125+
fn hash_stable<W: StableHasherResult>(&self,
1126+
_: &mut StableHashingContext<'a, 'tcx>,
1127+
hasher: &mut StableHasher<W>) {
1128+
::std::hash::Hash::hash(self, hasher);
1129+
}
1130+
}

src/librustc/ich/impls_syntax.rs

+79-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@ use std::mem;
1919
use syntax::ast;
2020
use syntax::parse::token;
2121
use syntax::tokenstream;
22-
use syntax_pos::Span;
22+
use syntax_pos::{Span, FileMap};
23+
24+
use hir::def_id::{DefId, CrateNum, CRATE_DEF_INDEX};
2325

2426
use rustc_data_structures::stable_hasher::{HashStable, StableHasher,
2527
StableHasherResult};
@@ -299,3 +301,79 @@ fn hash_token<'a, 'tcx, W: StableHasherResult>(token: &token::Token,
299301
token::Token::Shebang(val) => val.hash_stable(hcx, hasher),
300302
}
301303
}
304+
305+
impl_stable_hash_for_spanned!(::syntax::ast::NestedMetaItemKind);
306+
307+
impl_stable_hash_for!(enum ::syntax::ast::NestedMetaItemKind {
308+
MetaItem(meta_item),
309+
Literal(lit)
310+
});
311+
312+
impl_stable_hash_for!(struct ::syntax::ast::MetaItem {
313+
name,
314+
node,
315+
span
316+
});
317+
318+
impl_stable_hash_for!(enum ::syntax::ast::MetaItemKind {
319+
Word,
320+
List(nested_items),
321+
NameValue(lit)
322+
});
323+
324+
impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for FileMap {
325+
fn hash_stable<W: StableHasherResult>(&self,
326+
hcx: &mut StableHashingContext<'a, 'tcx>,
327+
hasher: &mut StableHasher<W>) {
328+
let FileMap {
329+
ref name,
330+
name_was_remapped,
331+
crate_of_origin,
332+
// Do not hash the source as it is not encoded
333+
src: _,
334+
start_pos,
335+
end_pos: _,
336+
ref lines,
337+
ref multibyte_chars,
338+
} = *self;
339+
340+
name.hash_stable(hcx, hasher);
341+
name_was_remapped.hash_stable(hcx, hasher);
342+
343+
DefId {
344+
krate: CrateNum::from_u32(crate_of_origin),
345+
index: CRATE_DEF_INDEX,
346+
}.hash_stable(hcx, hasher);
347+
348+
// We only hash the relative position within this filemap
349+
let lines = lines.borrow();
350+
lines.len().hash_stable(hcx, hasher);
351+
for &line in lines.iter() {
352+
stable_byte_pos(line, start_pos).hash_stable(hcx, hasher);
353+
}
354+
355+
// We only hash the relative position within this filemap
356+
let multibyte_chars = multibyte_chars.borrow();
357+
multibyte_chars.len().hash_stable(hcx, hasher);
358+
for &char_pos in multibyte_chars.iter() {
359+
stable_multibyte_char(char_pos, start_pos).hash_stable(hcx, hasher);
360+
}
361+
}
362+
}
363+
364+
fn stable_byte_pos(pos: ::syntax_pos::BytePos,
365+
filemap_start: ::syntax_pos::BytePos)
366+
-> u32 {
367+
pos.0 - filemap_start.0
368+
}
369+
370+
fn stable_multibyte_char(mbc: ::syntax_pos::MultiByteChar,
371+
filemap_start: ::syntax_pos::BytePos)
372+
-> (u32, u32) {
373+
let ::syntax_pos::MultiByteChar {
374+
pos,
375+
bytes,
376+
} = mbc;
377+
378+
(pos.0 - filemap_start.0, bytes as u32)
379+
}

src/librustc/ich/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ mod caching_codemap_view;
1919
mod hcx;
2020

2121
mod impls_const_math;
22+
mod impls_cstore;
2223
mod impls_hir;
2324
mod impls_mir;
2425
mod impls_ty;

src/librustc/middle/cstore.rs

+29-1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
// probably get a better home if someone can find one.
2424

2525
use hir::def;
26+
use dep_graph::DepNode;
2627
use hir::def_id::{CrateNum, DefId, DefIndex};
2728
use hir::map as hir_map;
2829
use hir::map::definitions::{Definitions, DefKey, DisambiguatedDefPathData};
@@ -161,7 +162,16 @@ pub struct ExternCrate {
161162

162163
pub struct EncodedMetadata {
163164
pub raw_data: Vec<u8>,
164-
pub hashes: Vec<EncodedMetadataHash>,
165+
pub hashes: EncodedMetadataHashes,
166+
}
167+
168+
impl EncodedMetadata {
169+
pub fn new() -> EncodedMetadata {
170+
EncodedMetadata {
171+
raw_data: Vec::new(),
172+
hashes: EncodedMetadataHashes::new(),
173+
}
174+
}
165175
}
166176

167177
/// The hash for some metadata that (when saving) will be exported
@@ -173,6 +183,24 @@ pub struct EncodedMetadataHash {
173183
pub hash: ich::Fingerprint,
174184
}
175185

186+
/// The hash for some metadata that (when saving) will be exported
187+
/// from this crate, or which (when importing) was exported by an
188+
/// upstream crate.
189+
#[derive(Debug, RustcEncodable, RustcDecodable, Clone)]
190+
pub struct EncodedMetadataHashes {
191+
pub entry_hashes: Vec<EncodedMetadataHash>,
192+
pub global_hashes: Vec<(DepNode<()>, ich::Fingerprint)>,
193+
}
194+
195+
impl EncodedMetadataHashes {
196+
pub fn new() -> EncodedMetadataHashes {
197+
EncodedMetadataHashes {
198+
entry_hashes: Vec::new(),
199+
global_hashes: Vec::new(),
200+
}
201+
}
202+
}
203+
176204
/// A store of Rust crates, through with their metadata
177205
/// can be accessed.
178206
pub trait CrateStore {

0 commit comments

Comments
 (0)