Skip to content

Commit 44f0043

Browse files
committed
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 #121812 identified a second case, and it's possible there are more. Fixes #121812.
1 parent 721c741 commit 44f0043

File tree

4 files changed

+44
-21
lines changed

4 files changed

+44
-21
lines changed

compiler/rustc_errors/src/lib.rs

+25-11
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

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)