Overhaul how stashed diagnostics work, again.
Stashed errors used to be counted as errors, but could then be cancelled, leading to `ErrorGuaranteed` soundness holes. #120828 changed that, closing the soundness hole. But it introduced other difficulties because you sometimes have to account for pending stashed errors when making decisions about whether errors have occured/will occur and it's easy to overlook these. This commit aims for a middle ground. - Stashed errors (not warnings) are counted immediately as emitted errors, avoiding the possibility of forgetting to consider them. - The ability to cancel (or downgrade) stashed errors is eliminated, by disallowing the use of `steal_diagnostic` with errors, and introducing the more restrictive methods `try_steal_{modify,replace}_and_emit_err` that can be used instead. Other things: - `DiagnosticBuilder::stash` and `DiagCtxt::stash_diagnostic` now both return `Option<ErrorGuaranteed>`, which enables the removal of two `delayed_bug` calls and one `Ty::new_error_with_message` call. This is possible because we store error guarantees in `DiagCtxt::stashed_diagnostics`. - Storing the guarantees also saves us having to maintain a counter. - Calls to the `stashed_err_count` method are no longer necessary alongside calls to `has_errors`, which is a nice simplification, and eliminates two more `span_delayed_bug` calls and one FIXME comment. - Tests are added for three of the four fixed PRs mentioned below. - `issue-121108.rs`'s output improved slightly, omitting a non-useful error message. Fixes #121451. Fixes #121477. Fixes #121504. Fixes #121508.
This commit is contained in:
parent
ec25d6db53
commit
260ae70140
29 changed files with 406 additions and 295 deletions
|
@ -1762,24 +1762,25 @@ impl<'a> Parser<'a> {
|
|||
err: impl FnOnce(&Self) -> Diag<'a>,
|
||||
) -> L {
|
||||
assert!(could_be_unclosed_char_literal(ident));
|
||||
if let Some(diag) = self.dcx().steal_diagnostic(ident.span, StashKey::LifetimeIsChar) {
|
||||
diag.with_span_suggestion_verbose(
|
||||
ident.span.shrink_to_hi(),
|
||||
"add `'` to close the char literal",
|
||||
"'",
|
||||
Applicability::MaybeIncorrect,
|
||||
)
|
||||
.emit();
|
||||
} else {
|
||||
err(self)
|
||||
.with_span_suggestion_verbose(
|
||||
self.dcx()
|
||||
.try_steal_modify_and_emit_err(ident.span, StashKey::LifetimeIsChar, |err| {
|
||||
err.span_suggestion_verbose(
|
||||
ident.span.shrink_to_hi(),
|
||||
"add `'` to close the char literal",
|
||||
"'",
|
||||
Applicability::MaybeIncorrect,
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
);
|
||||
})
|
||||
.unwrap_or_else(|| {
|
||||
err(self)
|
||||
.with_span_suggestion_verbose(
|
||||
ident.span.shrink_to_hi(),
|
||||
"add `'` to close the char literal",
|
||||
"'",
|
||||
Applicability::MaybeIncorrect,
|
||||
)
|
||||
.emit()
|
||||
});
|
||||
let name = ident.without_first_quote().name;
|
||||
mk_lit_char(name, ident.span)
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue