Skip to content

Commit c1cd236

Browse files
committed
Attribute post-monomorphization error notes by emitting thread
1 parent 4a31759 commit c1cd236

2 files changed

Lines changed: 51 additions & 25 deletions

File tree

compiler/rustc_errors/src/lib.rs

Lines changed: 49 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ use std::io::Write;
2424
use std::num::NonZero;
2525
use std::ops::DerefMut;
2626
use std::path::{Path, PathBuf};
27+
use std::thread::ThreadId;
2728
use std::{assert_matches, fmt, panic};
2829

2930
use Level::*;
@@ -297,11 +298,12 @@ impl<'a> std::ops::Deref for DiagCtxtHandle<'a> {
297298
struct DiagCtxtInner {
298299
flags: DiagCtxtFlags,
299300

300-
/// The error guarantees from all emitted errors. The length gives the error count.
301-
err_guars: Vec<ErrorGuaranteed>,
302-
/// The error guarantee from all emitted lint errors. The length gives the
303-
/// lint error count.
304-
lint_err_guars: Vec<ErrorGuaranteed>,
301+
/// The error guarantees from all emitted errors, each paired with the
302+
/// thread that emitted it. The length gives the error count.
303+
err_guars: Vec<(ErrorGuaranteed, ThreadId)>,
304+
/// The error guarantee from all emitted lint errors, each paired with the
305+
/// thread that emitted it. The length gives the lint error count.
306+
lint_err_guars: Vec<(ErrorGuaranteed, ThreadId)>,
305307
/// The delayed bugs and their error guarantees.
306308
delayed_bugs: Vec<(DelayedDiagInner, ErrorGuaranteed)>,
307309

@@ -343,7 +345,7 @@ struct DiagCtxtInner {
343345
/// `emit_stashed_diagnostics` by the time the `DiagCtxtInner` is dropped,
344346
/// otherwise an assertion failure will occur.
345347
stashed_diagnostics:
346-
FxIndexMap<StashKey, FxIndexMap<Span, (DiagInner, Option<ErrorGuaranteed>)>>,
348+
FxIndexMap<StashKey, FxIndexMap<Span, (DiagInner, Option<ErrorGuaranteed>, ThreadId)>>,
347349

348350
future_breakage_diagnostics: Vec<DiagInner>,
349351

@@ -613,7 +615,7 @@ impl<'a> DiagCtxtHandle<'a> {
613615
.stashed_diagnostics
614616
.entry(key)
615617
.or_default()
616-
.insert(span.with_parent(None), (diag, guar));
618+
.insert(span.with_parent(None), (diag, guar, std::thread::current().id()));
617619

618620
guar
619621
}
@@ -623,7 +625,7 @@ impl<'a> DiagCtxtHandle<'a> {
623625
/// error.
624626
pub fn steal_non_err(self, span: Span, key: StashKey) -> Option<Diag<'a, ()>> {
625627
// FIXME(#120456) - is `swap_remove` correct?
626-
let (diag, guar) = self.inner.borrow_mut().stashed_diagnostics.get_mut(&key).and_then(
628+
let (diag, guar, _) = self.inner.borrow_mut().stashed_diagnostics.get_mut(&key).and_then(
627629
|stashed_diagnostics| stashed_diagnostics.swap_remove(&span.with_parent(None)),
628630
)?;
629631
assert!(!diag.is_error());
@@ -648,7 +650,7 @@ impl<'a> DiagCtxtHandle<'a> {
648650
let err = self.inner.borrow_mut().stashed_diagnostics.get_mut(&key).and_then(
649651
|stashed_diagnostics| stashed_diagnostics.swap_remove(&span.with_parent(None)),
650652
);
651-
err.map(|(err, guar)| {
653+
err.map(|(err, guar, _)| {
652654
// The use of `::<ErrorGuaranteed>` is safe because level is `Level::Error`.
653655
assert_eq!(err.level, Error);
654656
assert!(guar.is_some());
@@ -673,7 +675,7 @@ impl<'a> DiagCtxtHandle<'a> {
673675
|stashed_diagnostics| stashed_diagnostics.swap_remove(&span.with_parent(None)),
674676
);
675677
match old_err {
676-
Some((old_err, guar)) => {
678+
Some((old_err, guar, _)) => {
677679
assert_eq!(old_err.level, Error);
678680
assert!(guar.is_some());
679681
// Because `old_err` has already been counted, it can only be
@@ -710,7 +712,27 @@ impl<'a> DiagCtxtHandle<'a> {
710712
+ inner
711713
.stashed_diagnostics
712714
.values()
713-
.map(|a| a.values().filter(|(_, guar)| guar.is_some()).count())
715+
.map(|a| a.values().filter(|(_, guar, _)| guar.is_some()).count())
716+
.sum::<usize>()
717+
}
718+
719+
/// The number of errors that have been emitted on the *current thread*.
720+
///
721+
/// Like [`DiagCtxtHandle::err_count`], but only counts errors whose recorded
722+
/// emitting thread is the calling thread.
723+
pub fn err_count_on_current_thread(&self) -> usize {
724+
let inner = self.inner.borrow();
725+
let current = std::thread::current().id();
726+
inner.err_guars.iter().filter(|(_, thread)| *thread == current).count()
727+
+ inner.lint_err_guars.iter().filter(|(_, thread)| *thread == current).count()
728+
+ inner
729+
.stashed_diagnostics
730+
.values()
731+
.map(|a| {
732+
a.values()
733+
.filter(|(_, guar, thread)| guar.is_some() && *thread == current)
734+
.count()
735+
})
714736
.sum::<usize>()
715737
}
716738

@@ -879,7 +901,8 @@ impl<'a> DiagCtxtHandle<'a> {
879901
// This `unchecked_error_guaranteed` is valid. It is where the
880902
// `ErrorGuaranteed` for unused_extern errors originates.
881903
#[allow(deprecated)]
882-
inner.lint_err_guars.push(ErrorGuaranteed::unchecked_error_guaranteed());
904+
let guar = ErrorGuaranteed::unchecked_error_guaranteed();
905+
inner.lint_err_guars.push((guar, std::thread::current().id()));
883906
inner.panic_if_treat_err_as_bug();
884907
}
885908

@@ -1178,7 +1201,7 @@ impl DiagCtxtInner {
11781201
let mut guar = None;
11791202
let has_errors = !self.err_guars.is_empty();
11801203
for (_, stashed_diagnostics) in std::mem::take(&mut self.stashed_diagnostics).into_iter() {
1181-
for (_, (diag, _guar)) in stashed_diagnostics {
1204+
for (_, (diag, _guar, _thread)) in stashed_diagnostics {
11821205
if !diag.is_error() {
11831206
// Unless they're forced, don't flush stashed warnings when
11841207
// there are errors, to avoid causing warning overload. The
@@ -1347,13 +1370,14 @@ impl DiagCtxtInner {
13471370
// `ErrorGuaranteed` for errors and lint errors originates.
13481371
#[allow(deprecated)]
13491372
let guar = ErrorGuaranteed::unchecked_error_guaranteed();
1373+
let thread = std::thread::current().id();
13501374
if is_lint {
1351-
self.lint_err_guars.push(guar);
1375+
self.lint_err_guars.push((guar, thread));
13521376
} else {
13531377
if let Some(taint) = taint {
13541378
taint.set(Some(guar));
13551379
}
1356-
self.err_guars.push(guar);
1380+
self.err_guars.push((guar, thread));
13571381
}
13581382
self.panic_if_treat_err_as_bug();
13591383
Some(guar)
@@ -1377,12 +1401,12 @@ impl DiagCtxtInner {
13771401
}
13781402

13791403
fn has_errors_excluding_lint_errors(&self) -> Option<ErrorGuaranteed> {
1380-
self.err_guars.get(0).copied().or_else(|| {
1381-
if let Some((_diag, guar)) = self
1404+
self.err_guars.get(0).map(|(guar, _)| *guar).or_else(|| {
1405+
if let Some((_diag, guar, _)) = self
13821406
.stashed_diagnostics
13831407
.values()
13841408
.flat_map(|stashed_diagnostics| stashed_diagnostics.values())
1385-
.find(|(diag, guar)| guar.is_some() && diag.is_lint.is_none())
1409+
.find(|(diag, guar, _)| guar.is_some() && diag.is_lint.is_none())
13861410
{
13871411
*guar
13881412
} else {
@@ -1392,13 +1416,15 @@ impl DiagCtxtInner {
13921416
}
13931417

13941418
fn has_errors(&self) -> Option<ErrorGuaranteed> {
1395-
self.err_guars.get(0).copied().or_else(|| self.lint_err_guars.get(0).copied()).or_else(
1396-
|| {
1419+
self.err_guars
1420+
.get(0)
1421+
.map(|(guar, _)| *guar)
1422+
.or_else(|| self.lint_err_guars.get(0).map(|(guar, _)| *guar))
1423+
.or_else(|| {
13971424
self.stashed_diagnostics.values().find_map(|stashed_diagnostics| {
1398-
stashed_diagnostics.values().find_map(|(_, guar)| *guar)
1425+
stashed_diagnostics.values().find_map(|(_, guar, _)| *guar)
13991426
})
1400-
},
1401-
)
1427+
})
14021428
}
14031429

14041430
fn has_errors_or_delayed_bugs(&self) -> Option<ErrorGuaranteed> {

compiler/rustc_monomorphize/src/collector.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -413,7 +413,7 @@ fn collect_items_rec<'tcx>(
413413
// current step of mono items collection.
414414
//
415415
// FIXME: don't rely on global state, instead bubble up errors. Note: this is very hard to do.
416-
let error_count = tcx.dcx().err_count();
416+
let error_count = tcx.dcx().err_count_on_current_thread();
417417

418418
// In `mentioned_items` we collect items that were mentioned in this MIR but possibly do not
419419
// need to be monomorphized. This is done to ensure that optimizing away function calls does not
@@ -538,7 +538,7 @@ fn collect_items_rec<'tcx>(
538538

539539
// Check for PMEs and emit a diagnostic if one happened. To try to show relevant edges of the
540540
// mono item graph.
541-
if tcx.dcx().err_count() > error_count
541+
if tcx.dcx().err_count_on_current_thread() > error_count
542542
&& starting_item.node.is_generic_fn()
543543
&& starting_item.node.is_user_defined()
544544
{

0 commit comments

Comments
 (0)