Skip to content

Commit c90b8cf

Browse files
authored
Rollup merge of rust-lang#121819 - nnethercote:fix-121812, r=oli-obk
Handle stashing of delayed bugs By just emitting them immediately, because it does happen in practice, when errors are downgraded to delayed bugs. We already had one case in `lint.rs` where we handled this at the callsite. This commit changes things so it's handled within `stash_diagnostic` instead, because rust-lang#121812 identified a second case, and it's possible there are more. Fixes rust-lang#121812. r? ```@oli-obk```
2 parents 4e5b4c5 + 44f0043 commit c90b8cf

File tree

4 files changed

+51
-28
lines changed

4 files changed

+51
-28
lines changed

compiler/rustc_errors/src/lib.rs

+32-18
Original file line numberDiff line numberDiff line change
@@ -712,33 +712,47 @@ impl DiagCtxt {
712712
/// Stashes a diagnostic for possible later improvement in a different,
713713
/// later stage of the compiler. Possible actions depend on the diagnostic
714714
/// level:
715+
/// - Level::Bug, Level:Fatal: not allowed, will trigger a panic.
715716
/// - Level::Error: immediately counted as an error that has occurred, because it
716717
/// is guaranteed to be emitted eventually. Can be later accessed with the
717718
/// provided `span` and `key` through
718719
/// [`DiagCtxt::try_steal_modify_and_emit_err`] or
719720
/// [`DiagCtxt::try_steal_replace_and_emit_err`]. These do not allow
720721
/// cancellation or downgrading of the error. Returns
721722
/// `Some(ErrorGuaranteed)`.
723+
/// - Level::DelayedBug: this does happen occasionally with errors that are
724+
/// downgraded to delayed bugs. It is not stashed, but immediately
725+
/// emitted as a delayed bug. This is because stashing it would cause it
726+
/// to be counted by `err_count` which we don't want. It doesn't matter
727+
/// that we cannot steal and improve it later, because it's not a
728+
/// user-facing error. Returns `Some(ErrorGuaranteed)` as is normal for
729+
/// delayed bugs.
722730
/// - Level::Warning and lower (i.e. !is_error()): can be accessed with the
723731
/// provided `span` and `key` through [`DiagCtxt::steal_non_err()`]. This
724732
/// allows cancelling and downgrading of the diagnostic. Returns `None`.
725-
/// - Others: not allowed, will trigger a panic.
726733
pub fn stash_diagnostic(
727734
&self,
728735
span: Span,
729736
key: StashKey,
730737
diag: DiagInner,
731738
) -> Option<ErrorGuaranteed> {
732-
let guar = if diag.level() == Level::Error {
733-
// This `unchecked_error_guaranteed` is valid. It is where the
734-
// `ErrorGuaranteed` for stashed errors originates. See
735-
// `DiagCtxtInner::drop`.
736-
#[allow(deprecated)]
737-
Some(ErrorGuaranteed::unchecked_error_guaranteed())
738-
} else if !diag.is_error() {
739-
None
740-
} else {
741-
self.span_bug(span, format!("invalid level in `stash_diagnostic`: {}", diag.level));
739+
let guar = match diag.level {
740+
Bug | Fatal => {
741+
self.span_bug(
742+
span,
743+
format!("invalid level in `stash_diagnostic`: {:?}", diag.level),
744+
);
745+
}
746+
Error => {
747+
// This `unchecked_error_guaranteed` is valid. It is where the
748+
// `ErrorGuaranteed` for stashed errors originates. See
749+
// `DiagCtxtInner::drop`.
750+
#[allow(deprecated)]
751+
Some(ErrorGuaranteed::unchecked_error_guaranteed())
752+
}
753+
DelayedBug => return self.inner.borrow_mut().emit_diagnostic(diag),
754+
ForceWarning(_) | Warning | Note | OnceNote | Help | OnceHelp | FailureNote | Allow
755+
| Expect(_) => None,
742756
};
743757

744758
// FIXME(Centril, #69537): Consider reintroducing panic on overwriting a stashed diagnostic
@@ -780,11 +794,11 @@ impl DiagCtxt {
780794
let err = self.inner.borrow_mut().stashed_diagnostics.swap_remove(&key);
781795
err.map(|(err, guar)| {
782796
// The use of `::<ErrorGuaranteed>` is safe because level is `Level::Error`.
783-
assert_eq!(err.level, Level::Error);
797+
assert_eq!(err.level, Error);
784798
assert!(guar.is_some());
785799
let mut err = Diag::<ErrorGuaranteed>::new_diagnostic(self, err);
786800
modify_err(&mut err);
787-
assert_eq!(err.level, Level::Error);
801+
assert_eq!(err.level, Error);
788802
err.emit()
789803
})
790804
}
@@ -803,7 +817,7 @@ impl DiagCtxt {
803817
let old_err = self.inner.borrow_mut().stashed_diagnostics.swap_remove(&key);
804818
match old_err {
805819
Some((old_err, guar)) => {
806-
assert_eq!(old_err.level, Level::Error);
820+
assert_eq!(old_err.level, Error);
807821
assert!(guar.is_some());
808822
// Because `old_err` has already been counted, it can only be
809823
// safely cancelled because the `new_err` supplants it.
@@ -1367,7 +1381,7 @@ impl DiagCtxtInner {
13671381
}
13681382

13691383
if diagnostic.has_future_breakage() {
1370-
// Future breakages aren't emitted if they're Level::Allow,
1384+
// Future breakages aren't emitted if they're `Level::Allow`,
13711385
// but they still need to be constructed and stashed below,
13721386
// so they'll trigger the must_produce_diag check.
13731387
self.suppressed_expected_diag = true;
@@ -1453,7 +1467,7 @@ impl DiagCtxtInner {
14531467
diagnostic.children.extract_if(already_emitted_sub).for_each(|_| {});
14541468
if already_emitted {
14551469
let msg = "duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`";
1456-
diagnostic.sub(Level::Note, msg, MultiSpan::new());
1470+
diagnostic.sub(Note, msg, MultiSpan::new());
14571471
}
14581472

14591473
if is_error {
@@ -1623,7 +1637,7 @@ impl DiagCtxtInner {
16231637
bug.arg("level", bug.level);
16241638
let msg = crate::fluent_generated::errors_invalid_flushed_delayed_diagnostic_level;
16251639
let msg = self.eagerly_translate_for_subdiag(&bug, msg); // after the `arg` call
1626-
bug.sub(Level::Note, msg, bug.span.primary_span().unwrap().into());
1640+
bug.sub(Note, msg, bug.span.primary_span().unwrap().into());
16271641
}
16281642
bug.level = Bug;
16291643

@@ -1671,7 +1685,7 @@ impl DelayedDiagInner {
16711685
diag.arg("emitted_at", diag.emitted_at.clone());
16721686
diag.arg("note", self.note);
16731687
let msg = dcx.eagerly_translate_for_subdiag(&diag, msg); // after the `arg` calls
1674-
diag.sub(Level::Note, msg, diag.span.primary_span().unwrap_or(DUMMY_SP).into());
1688+
diag.sub(Note, msg, diag.span.primary_span().unwrap_or(DUMMY_SP).into());
16751689
diag
16761690
}
16771691
}

compiler/rustc_hir_analysis/src/astconv/lint.rs

+2-10
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use rustc_ast::TraitObjectSyntax;
2-
use rustc_errors::{codes::*, Diag, EmissionGuarantee, Level, StashKey};
2+
use rustc_errors::{codes::*, Diag, EmissionGuarantee, StashKey};
33
use rustc_hir as hir;
44
use rustc_hir::def::{DefKind, Res};
55
use rustc_lint_defs::{builtin::BARE_TRAIT_OBJECTS, Applicability};
@@ -237,15 +237,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
237237
}
238238
// check if the impl trait that we are considering is a impl of a local trait
239239
self.maybe_lint_blanket_trait_impl(self_ty, &mut diag);
240-
match diag.level() {
241-
Level::Error => {
242-
diag.stash(self_ty.span, StashKey::TraitMissingMethod);
243-
}
244-
Level::DelayedBug => {
245-
diag.emit();
246-
}
247-
_ => unreachable!(),
248-
}
240+
diag.stash(self_ty.span, StashKey::TraitMissingMethod);
249241
} else {
250242
let msg = "trait objects without an explicit `dyn` are deprecated";
251243
tcx.node_span_lint(BARE_TRAIT_OBJECTS, self_ty.hir_id, self_ty.span, msg, |lint| {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
union U {
2+
a: u16,
3+
b: [u8; 3],
4+
}
5+
6+
fn main() {
7+
_ = U { b: [()] }; //~ ERROR mismatched types
8+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
error[E0308]: mismatched types
2+
--> $DIR/invalid-stashed-level-issue-121812.rs:7:17
3+
|
4+
LL | _ = U { b: [()] };
5+
| ^^ expected `u8`, found `()`
6+
7+
error: aborting due to 1 previous error
8+
9+
For more information about this error, try `rustc --explain E0308`.

0 commit comments

Comments
 (0)