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.
This commit is contained in:
parent
721c741756
commit
44f0043e82
4 changed files with 44 additions and 21 deletions
|
@ -712,6 +712,7 @@ impl DiagCtxt {
|
||||||
/// Stashes a diagnostic for possible later improvement in a different,
|
/// Stashes a diagnostic for possible later improvement in a different,
|
||||||
/// later stage of the compiler. Possible actions depend on the diagnostic
|
/// later stage of the compiler. Possible actions depend on the diagnostic
|
||||||
/// level:
|
/// level:
|
||||||
|
/// - Level::Bug, Level:Fatal: not allowed, will trigger a panic.
|
||||||
/// - Level::Error: immediately counted as an error that has occurred, because it
|
/// - Level::Error: immediately counted as an error that has occurred, because it
|
||||||
/// is guaranteed to be emitted eventually. Can be later accessed with the
|
/// is guaranteed to be emitted eventually. Can be later accessed with the
|
||||||
/// provided `span` and `key` through
|
/// provided `span` and `key` through
|
||||||
|
@ -719,26 +720,39 @@ impl DiagCtxt {
|
||||||
/// [`DiagCtxt::try_steal_replace_and_emit_err`]. These do not allow
|
/// [`DiagCtxt::try_steal_replace_and_emit_err`]. These do not allow
|
||||||
/// cancellation or downgrading of the error. Returns
|
/// cancellation or downgrading of the error. Returns
|
||||||
/// `Some(ErrorGuaranteed)`.
|
/// `Some(ErrorGuaranteed)`.
|
||||||
|
/// - Level::DelayedBug: this does happen occasionally with errors that are
|
||||||
|
/// downgraded to delayed bugs. It is not stashed, but immediately
|
||||||
|
/// emitted as a delayed bug. This is because stashing it would cause it
|
||||||
|
/// to be counted by `err_count` which we don't want. It doesn't matter
|
||||||
|
/// that we cannot steal and improve it later, because it's not a
|
||||||
|
/// user-facing error. Returns `Some(ErrorGuaranteed)` as is normal for
|
||||||
|
/// delayed bugs.
|
||||||
/// - Level::Warning and lower (i.e. !is_error()): can be accessed with the
|
/// - Level::Warning and lower (i.e. !is_error()): can be accessed with the
|
||||||
/// provided `span` and `key` through [`DiagCtxt::steal_non_err()`]. This
|
/// provided `span` and `key` through [`DiagCtxt::steal_non_err()`]. This
|
||||||
/// allows cancelling and downgrading of the diagnostic. Returns `None`.
|
/// allows cancelling and downgrading of the diagnostic. Returns `None`.
|
||||||
/// - Others: not allowed, will trigger a panic.
|
|
||||||
pub fn stash_diagnostic(
|
pub fn stash_diagnostic(
|
||||||
&self,
|
&self,
|
||||||
span: Span,
|
span: Span,
|
||||||
key: StashKey,
|
key: StashKey,
|
||||||
diag: DiagInner,
|
diag: DiagInner,
|
||||||
) -> Option<ErrorGuaranteed> {
|
) -> Option<ErrorGuaranteed> {
|
||||||
let guar = if diag.level() == Level::Error {
|
let guar = match diag.level {
|
||||||
|
Bug | Fatal => {
|
||||||
|
self.span_bug(
|
||||||
|
span,
|
||||||
|
format!("invalid level in `stash_diagnostic`: {:?}", diag.level),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Error => {
|
||||||
// This `unchecked_error_guaranteed` is valid. It is where the
|
// This `unchecked_error_guaranteed` is valid. It is where the
|
||||||
// `ErrorGuaranteed` for stashed errors originates. See
|
// `ErrorGuaranteed` for stashed errors originates. See
|
||||||
// `DiagCtxtInner::drop`.
|
// `DiagCtxtInner::drop`.
|
||||||
#[allow(deprecated)]
|
#[allow(deprecated)]
|
||||||
Some(ErrorGuaranteed::unchecked_error_guaranteed())
|
Some(ErrorGuaranteed::unchecked_error_guaranteed())
|
||||||
} else if !diag.is_error() {
|
}
|
||||||
None
|
DelayedBug => return self.inner.borrow_mut().emit_diagnostic(diag),
|
||||||
} else {
|
ForceWarning(_) | Warning | Note | OnceNote | Help | OnceHelp | FailureNote | Allow
|
||||||
self.span_bug(span, format!("invalid level in `stash_diagnostic`: {}", diag.level));
|
| Expect(_) => None,
|
||||||
};
|
};
|
||||||
|
|
||||||
// FIXME(Centril, #69537): Consider reintroducing panic on overwriting a stashed diagnostic
|
// FIXME(Centril, #69537): Consider reintroducing panic on overwriting a stashed diagnostic
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use rustc_ast::TraitObjectSyntax;
|
use rustc_ast::TraitObjectSyntax;
|
||||||
use rustc_errors::{codes::*, Diag, EmissionGuarantee, Level, StashKey};
|
use rustc_errors::{codes::*, Diag, EmissionGuarantee, StashKey};
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::def::{DefKind, Res};
|
use rustc_hir::def::{DefKind, Res};
|
||||||
use rustc_lint_defs::{builtin::BARE_TRAIT_OBJECTS, Applicability};
|
use rustc_lint_defs::{builtin::BARE_TRAIT_OBJECTS, Applicability};
|
||||||
|
@ -237,15 +237,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||||
}
|
}
|
||||||
// check if the impl trait that we are considering is a impl of a local trait
|
// check if the impl trait that we are considering is a impl of a local trait
|
||||||
self.maybe_lint_blanket_trait_impl(self_ty, &mut diag);
|
self.maybe_lint_blanket_trait_impl(self_ty, &mut diag);
|
||||||
match diag.level() {
|
|
||||||
Level::Error => {
|
|
||||||
diag.stash(self_ty.span, StashKey::TraitMissingMethod);
|
diag.stash(self_ty.span, StashKey::TraitMissingMethod);
|
||||||
}
|
|
||||||
Level::DelayedBug => {
|
|
||||||
diag.emit();
|
|
||||||
}
|
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
let msg = "trait objects without an explicit `dyn` are deprecated";
|
let msg = "trait objects without an explicit `dyn` are deprecated";
|
||||||
tcx.node_span_lint(BARE_TRAIT_OBJECTS, self_ty.hir_id, self_ty.span, msg, |lint| {
|
tcx.node_span_lint(BARE_TRAIT_OBJECTS, self_ty.hir_id, self_ty.span, msg, |lint| {
|
||||||
|
|
8
tests/ui/typeck/invalid-stashed-level-issue-121812.rs
Normal file
8
tests/ui/typeck/invalid-stashed-level-issue-121812.rs
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
union U {
|
||||||
|
a: u16,
|
||||||
|
b: [u8; 3],
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
_ = U { b: [()] }; //~ ERROR mismatched types
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/invalid-stashed-level-issue-121812.rs:7:17
|
||||||
|
|
|
||||||
|
LL | _ = U { b: [()] };
|
||||||
|
| ^^ expected `u8`, found `()`
|
||||||
|
|
||||||
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0308`.
|
Loading…
Add table
Add a link
Reference in a new issue