Rollup merge of #121669 - nnethercote:count-stashed-errs-again, r=estebank

Count stashed errors again

Stashed diagnostics are such a pain. Their "might be emitted, might not" semantics messes with lots of things.

#120828 and #121206 made some big changes to how they work, improving some things, but still leaving some problems, as seen by the issues caused by #121206. This PR aims to fix all of them by restricting them in a way that eliminates the "might be emitted, might not" semantics while still allowing 98% of their benefit. Details in the individual commit logs.

r? `@oli-obk`
This commit is contained in:
Guillaume Gomez 2024-02-29 17:08:38 +01:00 committed by GitHub
commit a5945b5d8d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
40 changed files with 476 additions and 343 deletions

View file

@ -1,5 +1,5 @@
use rustc_ast::TraitObjectSyntax;
use rustc_errors::{codes::*, Diag, EmissionGuarantee, StashKey};
use rustc_errors::{codes::*, Diag, EmissionGuarantee, Level, StashKey};
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
use rustc_lint_defs::{builtin::BARE_TRAIT_OBJECTS, Applicability};
@ -237,7 +237,15 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
}
// 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);
diag.stash(self_ty.span, StashKey::TraitMissingMethod);
match diag.level() {
Level::Error => {
diag.stash(self_ty.span, StashKey::TraitMissingMethod);
}
Level::DelayedBug => {
diag.emit();
}
_ => unreachable!(),
}
} else {
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| {

View file

@ -1350,8 +1350,7 @@ fn check_type_alias_type_params_are_used<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalD
let ty = tcx.type_of(def_id).instantiate_identity();
if ty.references_error() {
// If there is already another error, do not emit an error for not using a type parameter.
// Without the `stashed_err_count` part this can fail (#120856).
assert!(tcx.dcx().has_errors().is_some() || tcx.dcx().stashed_err_count() > 0);
assert!(tcx.dcx().has_errors().is_some());
return;
}

View file

@ -596,10 +596,11 @@ fn infer_placeholder_type<'a>(
// then the user may have written e.g. `const A = 42;`.
// In this case, the parser has stashed a diagnostic for
// us to improve in typeck so we do that now.
match tcx.dcx().steal_diagnostic(span, StashKey::ItemNoType) {
Some(mut err) => {
let guar = tcx
.dcx()
.try_steal_modify_and_emit_err(span, StashKey::ItemNoType, |err| {
if !ty.references_error() {
// Only suggest adding `:` if it was missing (and suggested by parsing diagnostic)
// Only suggest adding `:` if it was missing (and suggested by parsing diagnostic).
let colon = if span == item_ident.span.shrink_to_hi() { ":" } else { "" };
// The parser provided a sub-optimal `HasPlaceholders` suggestion for the type.
@ -622,12 +623,8 @@ fn infer_placeholder_type<'a>(
));
}
}
err.emit();
// diagnostic stashing loses the information of whether something is a hard error.
Ty::new_error_with_message(tcx, span, "ItemNoType is a hard error")
}
None => {
})
.unwrap_or_else(|| {
let mut diag = bad_placeholder(tcx, vec![span], kind);
if !ty.references_error() {
@ -645,10 +642,9 @@ fn infer_placeholder_type<'a>(
));
}
}
Ty::new_error(tcx, diag.emit())
}
}
diag.emit()
});
Ty::new_error(tcx, guar)
}
fn check_feature_inherent_assoc_ty(tcx: TyCtxt<'_>, span: Span) {