Skip to content

Commit f55425d

Browse files
incr.comp.: Implement query diagnostic persistence.
1 parent 686d2a7 commit f55425d

File tree

15 files changed

+362
-36
lines changed

15 files changed

+362
-36
lines changed

src/librustc/dep_graph/graph.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
use errors::DiagnosticBuilder;
1112
use rustc_data_structures::stable_hasher::{HashStable, StableHasher,
1213
StableHashingContextProvider};
1314
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
@@ -568,6 +569,24 @@ impl DepGraph {
568569
"DepGraph::try_mark_green() - Duplicate fingerprint \
569570
insertion for {:?}", dep_node);
570571

572+
// ... emitting any stored diagnostic ...
573+
{
574+
let diagnostics = tcx.on_disk_query_result_cache
575+
.load_diagnostics(prev_dep_node_index);
576+
577+
if diagnostics.len() > 0 {
578+
let handle = tcx.sess.diagnostic();
579+
580+
// Promote the previous diagnostics to the current session.
581+
tcx.on_disk_query_result_cache
582+
.store_diagnostics(dep_node_index, diagnostics.clone());
583+
584+
for diagnostic in diagnostics {
585+
DiagnosticBuilder::new_diagnostic(handle, diagnostic).emit();
586+
}
587+
}
588+
}
589+
571590
// ... and finally storing a "Green" entry in the color map.
572591
let old_color = data.colors
573592
.borrow_mut()

src/librustc/dep_graph/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,4 @@ pub use self::prev::PreviousDepGraph;
2626
pub use self::query::DepGraphQuery;
2727
pub use self::safe::AssertDepGraphSafe;
2828
pub use self::safe::DepGraphSafe;
29-
pub use self::serialized::SerializedDepGraph;
29+
pub use self::serialized::{SerializedDepGraph, SerializedDepNodeIndex};

src/librustc/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
#![feature(const_fn)]
4747
#![feature(core_intrinsics)]
4848
#![feature(i128_type)]
49+
#![feature(inclusive_range_syntax)]
4950
#![cfg_attr(windows, feature(libc))]
5051
#![feature(never_type)]
5152
#![feature(nonzero)]

src/librustc/ty/context.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -853,6 +853,11 @@ pub struct GlobalCtxt<'tcx> {
853853

854854
pub dep_graph: DepGraph,
855855

856+
/// This provides access to the incr. comp. on-disk cache for query results.
857+
/// Do not access this directly. It is only meant to be used by
858+
/// `DepGraph::try_mark_green()` and the query infrastructure in `ty::maps`.
859+
pub(crate) on_disk_query_result_cache: maps::OnDiskCache<'tcx>,
860+
856861
/// Common types, pre-interned for your convenience.
857862
pub types: CommonTypes<'tcx>,
858863

@@ -1054,6 +1059,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
10541059
resolutions: ty::Resolutions,
10551060
named_region_map: resolve_lifetime::NamedRegionMap,
10561061
hir: hir_map::Map<'tcx>,
1062+
on_disk_query_result_cache: maps::OnDiskCache<'tcx>,
10571063
crate_name: &str,
10581064
tx: mpsc::Sender<Box<Any + Send>>,
10591065
output_filenames: &OutputFilenames,
@@ -1137,6 +1143,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
11371143
global_arenas: arenas,
11381144
global_interners: interners,
11391145
dep_graph: dep_graph.clone(),
1146+
on_disk_query_result_cache,
11401147
types: common_types,
11411148
named_region_map: NamedRegionMap {
11421149
defs,
@@ -1298,6 +1305,15 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
12981305
self.in_scope_traits_map(def_index);
12991306
}
13001307
}
1308+
1309+
pub fn serialize_query_result_cache<E>(self,
1310+
encoder: &mut E)
1311+
-> Result<(), E::Error>
1312+
where E: ::rustc_serialize::Encoder
1313+
{
1314+
self.on_disk_query_result_cache.serialize(encoder)
1315+
}
1316+
13011317
}
13021318

13031319
impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {

src/librustc/ty/maps/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,9 @@ mod config;
7070
pub use self::config::QueryConfig;
7171
use self::config::QueryDescription;
7272

73+
mod on_disk_cache;
74+
pub use self::on_disk_cache::OnDiskCache;
75+
7376
// Each of these maps also corresponds to a method on a
7477
// `Provider` trait for requesting a value of that type,
7578
// and a method on `Maps` itself for doing that in a

src/librustc/ty/maps/on_disk_cache.rs

Lines changed: 204 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
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+
use dep_graph::{DepNodeIndex, SerializedDepNodeIndex};
12+
use rustc_data_structures::fx::FxHashMap;
13+
use rustc_data_structures::indexed_vec::Idx;
14+
use errors::Diagnostic;
15+
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder, opaque,
16+
SpecializedDecoder};
17+
use session::Session;
18+
use std::borrow::Cow;
19+
use std::cell::RefCell;
20+
use std::collections::BTreeMap;
21+
use std::mem;
22+
use syntax::codemap::{CodeMap, StableFilemapId};
23+
use syntax_pos::{BytePos, Span, NO_EXPANSION, DUMMY_SP};
24+
25+
pub struct OnDiskCache<'sess> {
26+
prev_diagnostics: FxHashMap<SerializedDepNodeIndex, Vec<Diagnostic>>,
27+
28+
_prev_filemap_starts: BTreeMap<BytePos, StableFilemapId>,
29+
codemap: &'sess CodeMap,
30+
31+
current_diagnostics: RefCell<FxHashMap<DepNodeIndex, Vec<Diagnostic>>>,
32+
}
33+
34+
#[derive(RustcEncodable, RustcDecodable)]
35+
struct Header {
36+
prev_filemap_starts: BTreeMap<BytePos, StableFilemapId>,
37+
}
38+
39+
#[derive(RustcEncodable, RustcDecodable)]
40+
struct Body {
41+
diagnostics: Vec<(SerializedDepNodeIndex, Vec<Diagnostic>)>,
42+
}
43+
44+
impl<'sess> OnDiskCache<'sess> {
45+
pub fn new_empty(codemap: &'sess CodeMap) -> OnDiskCache<'sess> {
46+
OnDiskCache {
47+
prev_diagnostics: FxHashMap(),
48+
_prev_filemap_starts: BTreeMap::new(),
49+
codemap,
50+
current_diagnostics: RefCell::new(FxHashMap()),
51+
}
52+
}
53+
54+
pub fn new(sess: &'sess Session, data: &[u8]) -> OnDiskCache<'sess> {
55+
debug_assert!(sess.opts.incremental.is_some());
56+
57+
let mut decoder = opaque::Decoder::new(&data[..], 0);
58+
let header = Header::decode(&mut decoder).unwrap();
59+
60+
let prev_diagnostics: FxHashMap<_, _> = {
61+
let mut decoder = CacheDecoder {
62+
opaque: decoder,
63+
codemap: sess.codemap(),
64+
prev_filemap_starts: &header.prev_filemap_starts,
65+
};
66+
let body = Body::decode(&mut decoder).unwrap();
67+
body.diagnostics.into_iter().collect()
68+
};
69+
70+
OnDiskCache {
71+
prev_diagnostics,
72+
_prev_filemap_starts: header.prev_filemap_starts,
73+
codemap: sess.codemap(),
74+
current_diagnostics: RefCell::new(FxHashMap()),
75+
}
76+
}
77+
78+
pub fn serialize<'a, 'tcx, E>(&self,
79+
encoder: &mut E)
80+
-> Result<(), E::Error>
81+
where E: Encoder
82+
{
83+
let prev_filemap_starts: BTreeMap<_, _> = self
84+
.codemap
85+
.files()
86+
.iter()
87+
.map(|fm| (fm.start_pos, StableFilemapId::new(fm)))
88+
.collect();
89+
90+
Header { prev_filemap_starts }.encode(encoder)?;
91+
92+
let diagnostics: Vec<(SerializedDepNodeIndex, Vec<Diagnostic>)> =
93+
self.current_diagnostics
94+
.borrow()
95+
.iter()
96+
.map(|(k, v)| (SerializedDepNodeIndex::new(k.index()), v.clone()))
97+
.collect();
98+
99+
Body { diagnostics }.encode(encoder)?;
100+
101+
Ok(())
102+
}
103+
104+
pub fn load_diagnostics(&self,
105+
dep_node_index: SerializedDepNodeIndex)
106+
-> Vec<Diagnostic> {
107+
self.prev_diagnostics.get(&dep_node_index).cloned().unwrap_or(vec![])
108+
}
109+
110+
pub fn store_diagnostics(&self,
111+
dep_node_index: DepNodeIndex,
112+
diagnostics: Vec<Diagnostic>) {
113+
let mut current_diagnostics = self.current_diagnostics.borrow_mut();
114+
let prev = current_diagnostics.insert(dep_node_index, diagnostics);
115+
debug_assert!(prev.is_none());
116+
}
117+
118+
pub fn store_diagnostics_for_anon_node(&self,
119+
dep_node_index: DepNodeIndex,
120+
mut diagnostics: Vec<Diagnostic>) {
121+
let mut current_diagnostics = self.current_diagnostics.borrow_mut();
122+
123+
let x = current_diagnostics.entry(dep_node_index).or_insert_with(|| {
124+
mem::replace(&mut diagnostics, Vec::new())
125+
});
126+
127+
x.extend(diagnostics.into_iter());
128+
}
129+
}
130+
131+
impl<'a> SpecializedDecoder<Span> for CacheDecoder<'a> {
132+
fn specialized_decode(&mut self) -> Result<Span, Self::Error> {
133+
let lo = BytePos::decode(self)?;
134+
let hi = BytePos::decode(self)?;
135+
136+
if let Some((prev_filemap_start, filemap_id)) = self.find_filemap_prev_bytepos(lo) {
137+
if let Some(current_filemap) = self.codemap.filemap_by_stable_id(filemap_id) {
138+
let lo = (lo + current_filemap.start_pos) - prev_filemap_start;
139+
let hi = (hi + current_filemap.start_pos) - prev_filemap_start;
140+
return Ok(Span::new(lo, hi, NO_EXPANSION));
141+
}
142+
}
143+
144+
Ok(DUMMY_SP)
145+
}
146+
}
147+
148+
struct CacheDecoder<'a> {
149+
opaque: opaque::Decoder<'a>,
150+
codemap: &'a CodeMap,
151+
prev_filemap_starts: &'a BTreeMap<BytePos, StableFilemapId>,
152+
}
153+
154+
impl<'a> CacheDecoder<'a> {
155+
fn find_filemap_prev_bytepos(&self,
156+
prev_bytepos: BytePos)
157+
-> Option<(BytePos, StableFilemapId)> {
158+
for (start, id) in self.prev_filemap_starts.range(BytePos(0) ... prev_bytepos).rev() {
159+
return Some((*start, *id))
160+
}
161+
162+
None
163+
}
164+
}
165+
166+
macro_rules! decoder_methods {
167+
($($name:ident -> $ty:ty;)*) => {
168+
$(fn $name(&mut self) -> Result<$ty, Self::Error> {
169+
self.opaque.$name()
170+
})*
171+
}
172+
}
173+
174+
impl<'sess> Decoder for CacheDecoder<'sess> {
175+
type Error = String;
176+
177+
decoder_methods! {
178+
read_nil -> ();
179+
180+
read_u128 -> u128;
181+
read_u64 -> u64;
182+
read_u32 -> u32;
183+
read_u16 -> u16;
184+
read_u8 -> u8;
185+
read_usize -> usize;
186+
187+
read_i128 -> i128;
188+
read_i64 -> i64;
189+
read_i32 -> i32;
190+
read_i16 -> i16;
191+
read_i8 -> i8;
192+
read_isize -> isize;
193+
194+
read_bool -> bool;
195+
read_f64 -> f64;
196+
read_f32 -> f32;
197+
read_char -> char;
198+
read_str -> Cow<str>;
199+
}
200+
201+
fn error(&mut self, err: &str) -> Self::Error {
202+
self.opaque.error(err)
203+
}
204+
}

0 commit comments

Comments
 (0)