Ignore span references from diagnostics.

The diagnostics are replayed at the correct place anyway.
This commit is contained in:
Camille GILLOT 2021-04-30 19:38:06 +02:00
parent 40c8165395
commit 4719cb3036
3 changed files with 65 additions and 50 deletions

View File

@ -473,10 +473,12 @@ pub enum StashKey {
CallAssocMethod,
}
fn default_track_diagnostic(_: &Diagnostic) {}
fn default_track_diagnostic(d: &mut Diagnostic, f: &mut dyn FnMut(&mut Diagnostic)) {
(*f)(d)
}
pub static TRACK_DIAGNOSTICS: AtomicRef<fn(&Diagnostic)> =
AtomicRef::new(&(default_track_diagnostic as fn(&_)));
pub static TRACK_DIAGNOSTICS: AtomicRef<fn(&mut Diagnostic, &mut dyn FnMut(&mut Diagnostic))> =
AtomicRef::new(&(default_track_diagnostic as _));
#[derive(Copy, Clone, Default)]
pub struct HandlerFlags {
@ -1290,67 +1292,69 @@ impl HandlerInner {
&& !diagnostic.is_force_warn()
{
if diagnostic.has_future_breakage() {
(*TRACK_DIAGNOSTICS)(diagnostic);
(*TRACK_DIAGNOSTICS)(diagnostic, &mut |_| {});
}
return None;
}
(*TRACK_DIAGNOSTICS)(diagnostic);
if matches!(diagnostic.level, Level::Expect(_) | Level::Allow) {
(*TRACK_DIAGNOSTICS)(diagnostic, &mut |_| {});
return None;
}
if let Some(ref code) = diagnostic.code {
self.emitted_diagnostic_codes.insert(code.clone());
}
let mut guaranteed = None;
(*TRACK_DIAGNOSTICS)(diagnostic, &mut |diagnostic| {
if let Some(ref code) = diagnostic.code {
self.emitted_diagnostic_codes.insert(code.clone());
}
let already_emitted = |this: &mut Self| {
let mut hasher = StableHasher::new();
diagnostic.hash(&mut hasher);
let diagnostic_hash = hasher.finish();
!this.emitted_diagnostics.insert(diagnostic_hash)
};
// Only emit the diagnostic if we've been asked to deduplicate or
// haven't already emitted an equivalent diagnostic.
if !(self.flags.deduplicate_diagnostics && already_emitted(self)) {
debug!(?diagnostic);
debug!(?self.emitted_diagnostics);
let already_emitted_sub = |sub: &mut SubDiagnostic| {
debug!(?sub);
if sub.level != Level::OnceNote {
return false;
}
let already_emitted = |this: &mut Self| {
let mut hasher = StableHasher::new();
sub.hash(&mut hasher);
diagnostic.hash(&mut hasher);
let diagnostic_hash = hasher.finish();
debug!(?diagnostic_hash);
!self.emitted_diagnostics.insert(diagnostic_hash)
!this.emitted_diagnostics.insert(diagnostic_hash)
};
diagnostic.children.drain_filter(already_emitted_sub).for_each(|_| {});
// Only emit the diagnostic if we've been asked to deduplicate or
// haven't already emitted an equivalent diagnostic.
if !(self.flags.deduplicate_diagnostics && already_emitted(self)) {
debug!(?diagnostic);
debug!(?self.emitted_diagnostics);
let already_emitted_sub = |sub: &mut SubDiagnostic| {
debug!(?sub);
if sub.level != Level::OnceNote {
return false;
}
let mut hasher = StableHasher::new();
sub.hash(&mut hasher);
let diagnostic_hash = hasher.finish();
debug!(?diagnostic_hash);
!self.emitted_diagnostics.insert(diagnostic_hash)
};
self.emitter.emit_diagnostic(diagnostic);
diagnostic.children.drain_filter(already_emitted_sub).for_each(|_| {});
self.emitter.emit_diagnostic(diagnostic);
if diagnostic.is_error() {
self.deduplicated_err_count += 1;
} else if let Warning(_) = diagnostic.level {
self.deduplicated_warn_count += 1;
}
}
if diagnostic.is_error() {
self.deduplicated_err_count += 1;
} else if let Warning(_) = diagnostic.level {
self.deduplicated_warn_count += 1;
}
}
if diagnostic.is_error() {
if matches!(diagnostic.level, Level::Error { lint: true }) {
self.bump_lint_err_count();
if matches!(diagnostic.level, Level::Error { lint: true }) {
self.bump_lint_err_count();
} else {
self.bump_err_count();
}
guaranteed = Some(ErrorGuaranteed::unchecked_claim_error_was_emitted());
} else {
self.bump_err_count();
self.bump_warn_count();
}
});
Some(ErrorGuaranteed::unchecked_claim_error_was_emitted())
} else {
self.bump_warn_count();
None
}
guaranteed
}
fn emit_artifact_notification(&mut self, path: &Path, artifact_type: &str) {

View File

@ -10,6 +10,7 @@
//! origin crate when the `TyCtxt` is not present in TLS.
use rustc_errors::{Diagnostic, TRACK_DIAGNOSTICS};
use rustc_middle::dep_graph::TaskDepsRef;
use rustc_middle::ty::tls;
use std::fmt;
@ -26,14 +27,22 @@ fn track_span_parent(def_id: rustc_span::def_id::LocalDefId) {
/// This is a callback from `rustc_ast` as it cannot access the implicit state
/// in `rustc_middle` otherwise. It is used when diagnostic messages are
/// emitted and stores them in the current query, if there is one.
fn track_diagnostic(diagnostic: &Diagnostic) {
fn track_diagnostic(diagnostic: &mut Diagnostic, f: &mut dyn FnMut(&mut Diagnostic)) {
tls::with_context_opt(|icx| {
if let Some(icx) = icx {
if let Some(diagnostics) = icx.diagnostics {
let mut diagnostics = diagnostics.lock();
diagnostics.extend(Some(diagnostic.clone()));
std::mem::drop(diagnostics);
}
// Diagnostics are tracked, we can ignore the dependency.
let icx = tls::ImplicitCtxt { task_deps: TaskDepsRef::Ignore, ..icx.clone() };
return tls::enter_context(&icx, move |_| (*f)(diagnostic));
}
// In any other case, invoke diagnostics anyway.
(*f)(diagnostic);
})
}
@ -55,5 +64,5 @@ fn def_id_debug(def_id: rustc_hir::def_id::DefId, f: &mut fmt::Formatter<'_>) ->
pub fn setup_callbacks() {
rustc_span::SPAN_TRACK.swap(&(track_span_parent as fn(_)));
rustc_hir::def_id::DEF_ID_DEBUG.swap(&(def_id_debug as fn(_, &mut fmt::Formatter<'_>) -> _));
TRACK_DIAGNOSTICS.swap(&(track_diagnostic as fn(&_)));
TRACK_DIAGNOSTICS.swap(&(track_diagnostic as _));
}

View File

@ -634,7 +634,7 @@ impl<K: DepKind> DepGraph<K> {
if dep_node_debug.borrow().contains_key(&dep_node) {
return;
}
let debug_str = debug_str_gen();
let debug_str = self.with_ignore(debug_str_gen);
dep_node_debug.borrow_mut().insert(dep_node, debug_str);
}
@ -829,7 +829,9 @@ impl<K: DepKind> DepGraph<K> {
);
if !side_effects.is_empty() {
self.emit_side_effects(qcx, data, dep_node_index, side_effects);
self.with_query_deserialization(|| {
self.emit_side_effects(qcx, data, dep_node_index, side_effects)
});
}
// ... and finally storing a "Green" entry in the color map.