Skip to content

Commit 2aeb593

Browse files
committed
Auto merge of #44046 - alexcrichton:capture-diagnostics, r=michaelwoerister
rustc: Capture diagnostics from all queries This commit alters the `rustc::ty::maps` implementation to ensure that all output diagnostics from the compiler are tracked for the duration of each query. These are then intended to be replayed back the first time a cached value is loaded, and otherwise the cache should operate the same as it does today. Closes #42513
2 parents a1c3365 + 8e95b3a commit 2aeb593

File tree

3 files changed

+90
-28
lines changed

3 files changed

+90
-28
lines changed

src/librustc/ty/maps.rs

+60-22
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
// except according to those terms.
1010

1111
use dep_graph::{DepConstructor, DepNode, DepNodeIndex};
12+
use errors::{Diagnostic, DiagnosticBuilder};
1213
use hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
1314
use hir::def::Def;
1415
use hir;
@@ -32,7 +33,7 @@ use util::common::{profq_msg, ProfileQueriesMsg};
3233

3334
use rustc_data_structures::indexed_vec::IndexVec;
3435
use rustc_data_structures::fx::FxHashMap;
35-
use std::cell::{RefCell, RefMut};
36+
use std::cell::{RefCell, RefMut, Cell};
3637
use std::fmt::Debug;
3738
use std::hash::Hash;
3839
use std::marker::PhantomData;
@@ -188,7 +189,18 @@ impl<'tcx> Value<'tcx> for ty::SymbolName {
188189

189190
struct QueryMap<D: QueryDescription> {
190191
phantom: PhantomData<D>,
191-
map: FxHashMap<D::Key, (D::Value, DepNodeIndex)>,
192+
map: FxHashMap<D::Key, QueryValue<D::Value>>,
193+
}
194+
195+
struct QueryValue<T> {
196+
value: T,
197+
index: DepNodeIndex,
198+
diagnostics: Option<Box<QueryDiagnostics>>,
199+
}
200+
201+
struct QueryDiagnostics {
202+
diagnostics: Vec<Diagnostic>,
203+
emitted_diagnostics: Cell<bool>,
192204
}
193205

194206
impl<M: QueryDescription> QueryMap<M> {
@@ -618,10 +630,20 @@ macro_rules! define_maps {
618630
)
619631
);
620632

621-
if let Some(&(ref result, dep_node_index)) = tcx.maps.$name.borrow().map.get(&key) {
622-
tcx.dep_graph.read_index(dep_node_index);
633+
if let Some(value) = tcx.maps.$name.borrow().map.get(&key) {
634+
if let Some(ref d) = value.diagnostics {
635+
if !d.emitted_diagnostics.get() {
636+
d.emitted_diagnostics.set(true);
637+
let handle = tcx.sess.diagnostic();
638+
for diagnostic in d.diagnostics.iter() {
639+
DiagnosticBuilder::new_diagnostic(handle, diagnostic.clone())
640+
.emit();
641+
}
642+
}
643+
}
623644
profq_msg!(tcx, ProfileQueriesMsg::CacheHit);
624-
return Ok(f(result));
645+
tcx.dep_graph.read_index(value.index);
646+
return Ok(f(&value.value));
625647
}
626648
// else, we are going to run the provider:
627649
profq_msg!(tcx, ProfileQueriesMsg::ProviderBegin);
@@ -633,36 +655,52 @@ macro_rules! define_maps {
633655
span = key.default_span(tcx)
634656
}
635657

636-
let (result, dep_node_index) = tcx.cycle_check(span, Query::$name(key), || {
658+
let res = tcx.cycle_check(span, Query::$name(key), || {
637659
let dep_node = Self::to_dep_node(tcx, &key);
638660

639-
if dep_node.kind.is_anon() {
640-
tcx.dep_graph.with_anon_task(dep_node.kind, || {
641-
let provider = tcx.maps.providers[key.map_crate()].$name;
642-
provider(tcx.global_tcx(), key)
643-
})
644-
} else {
645-
fn run_provider<'a, 'tcx, 'lcx>(tcx: TyCtxt<'a, 'tcx, 'lcx>,
646-
key: $K)
647-
-> $V {
648-
let provider = tcx.maps.providers[key.map_crate()].$name;
649-
provider(tcx.global_tcx(), key)
661+
tcx.sess.diagnostic().track_diagnostics(|| {
662+
if dep_node.kind.is_anon() {
663+
tcx.dep_graph.with_anon_task(dep_node.kind, || {
664+
let provider = tcx.maps.providers[key.map_crate()].$name;
665+
provider(tcx.global_tcx(), key)
666+
})
667+
} else {
668+
fn run_provider<'a, 'tcx, 'lcx>(tcx: TyCtxt<'a, 'tcx, 'lcx>,
669+
key: $K)
670+
-> $V {
671+
let provider = tcx.maps.providers[key.map_crate()].$name;
672+
provider(tcx.global_tcx(), key)
673+
}
674+
675+
tcx.dep_graph.with_task(dep_node, tcx, key, run_provider)
650676
}
651-
652-
tcx.dep_graph.with_task(dep_node, tcx, key, run_provider)
653-
}
677+
})
654678
})?;
655679
profq_msg!(tcx, ProfileQueriesMsg::ProviderEnd);
680+
let ((result, dep_node_index), diagnostics) = res;
656681

657682
tcx.dep_graph.read_index(dep_node_index);
658683

684+
let value = QueryValue {
685+
value: result,
686+
index: dep_node_index,
687+
diagnostics: if diagnostics.len() == 0 {
688+
None
689+
} else {
690+
Some(Box::new(QueryDiagnostics {
691+
diagnostics,
692+
emitted_diagnostics: Cell::new(true),
693+
}))
694+
},
695+
};
696+
659697
Ok(f(&tcx.maps
660698
.$name
661699
.borrow_mut()
662700
.map
663701
.entry(key)
664-
.or_insert((result, dep_node_index))
665-
.0))
702+
.or_insert(value)
703+
.value))
666704
}
667705

668706
pub fn try_get(tcx: TyCtxt<'a, $tcx, 'lcx>, span: Span, key: $K)

src/librustc_errors/diagnostic_builder.rs

+8-5
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ impl<'a> DiagnosticBuilder<'a> {
9898
}
9999
};
100100

101-
self.handler.emitter.borrow_mut().emit(&self);
101+
self.handler.emit_db(&self);
102102
self.cancel();
103103

104104
if is_error {
@@ -178,10 +178,13 @@ impl<'a> DiagnosticBuilder<'a> {
178178
code: Option<String>,
179179
message: &str)
180180
-> DiagnosticBuilder<'a> {
181-
DiagnosticBuilder {
182-
handler,
183-
diagnostic: Diagnostic::new_with_code(level, code, message)
184-
}
181+
let diagnostic = Diagnostic::new_with_code(level, code, message);
182+
DiagnosticBuilder::new_diagnostic(handler, diagnostic)
183+
}
184+
185+
/// Creates a new `DiagnosticBuilder` with an already constructed diagnostic.
186+
pub fn new_diagnostic(handler: &'a Handler, diagnostic: Diagnostic) -> DiagnosticBuilder<'a> {
187+
DiagnosticBuilder { handler, diagnostic }
185188
}
186189
}
187190

src/librustc_errors/lib.rs

+22-1
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,9 @@ use emitter::{Emitter, EmitterWriter};
3535

3636
use std::borrow::Cow;
3737
use std::cell::{RefCell, Cell};
38-
use std::{error, fmt};
38+
use std::mem;
3939
use std::rc::Rc;
40+
use std::{error, fmt};
4041

4142
mod diagnostic;
4243
mod diagnostic_builder;
@@ -275,6 +276,7 @@ pub struct Handler {
275276
treat_err_as_bug: bool,
276277
continue_after_error: Cell<bool>,
277278
delayed_span_bug: RefCell<Option<(MultiSpan, String)>>,
279+
tracked_diagnostics: RefCell<Option<Vec<Diagnostic>>>,
278280
}
279281

280282
impl Handler {
@@ -298,6 +300,7 @@ impl Handler {
298300
treat_err_as_bug,
299301
continue_after_error: Cell::new(true),
300302
delayed_span_bug: RefCell::new(None),
303+
tracked_diagnostics: RefCell::new(None),
301304
}
302305
}
303306

@@ -547,6 +550,24 @@ impl Handler {
547550
self.abort_if_errors();
548551
}
549552
}
553+
554+
pub fn track_diagnostics<F, R>(&self, f: F) -> (R, Vec<Diagnostic>)
555+
where F: FnOnce() -> R
556+
{
557+
let prev = mem::replace(&mut *self.tracked_diagnostics.borrow_mut(),
558+
Some(Vec::new()));
559+
let ret = f();
560+
let diagnostics = mem::replace(&mut *self.tracked_diagnostics.borrow_mut(), prev)
561+
.unwrap();
562+
(ret, diagnostics)
563+
}
564+
565+
fn emit_db(&self, db: &DiagnosticBuilder) {
566+
if let Some(ref mut list) = *self.tracked_diagnostics.borrow_mut() {
567+
list.push((**db).clone());
568+
}
569+
self.emitter.borrow_mut().emit(db);
570+
}
550571
}
551572

552573

0 commit comments

Comments
 (0)