Auto merge of #126996 - oli-obk:do_not_count_errors, r=nnethercote
Automatically taint InferCtxt when errors are emitted r? `@nnethercote` Basically `InferCtxt::dcx` now returns a `DiagCtxt` that refers back to the `Cell<Option<ErrorGuaranteed>>` of the `InferCtxt` and thus when invoking `Diag::emit`, and the diagnostic is an error, we taint the `InferCtxt` directly. That change on its own has no effect at all, because `InferCtxt` already tracks whether errors have been emitted by recording the global error count when it gets opened, and checking at the end whether the count changed. So I removed that error count check, which had a bit of fallout that I immediately fixed by invoking `InferCtxt::dcx` instead of `TyCtxt::dcx` in a bunch of places. The remaining new errors are because an error was reported in another query, and never bubbled up. I think they are minor enough for this to be ok, and sometimes it actually improves diagnostics, by not silencing useful diagnostics anymore. fixes #126485 (cc `@olafes)` There are more improvements we can do (like tainting in hir ty lowering), but I would rather do that in follow up PRs, because it requires some refactorings.
This commit is contained in:
commit
7b21c18fe4
77 changed files with 899 additions and 829 deletions
|
@ -139,7 +139,7 @@ pub struct TypeErrCtxt<'a, 'tcx> {
|
|||
}
|
||||
|
||||
impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||
pub fn dcx(&self) -> DiagCtxtHandle<'tcx> {
|
||||
pub fn dcx(&self) -> DiagCtxtHandle<'a> {
|
||||
self.infcx.dcx()
|
||||
}
|
||||
|
||||
|
@ -305,16 +305,17 @@ fn label_msg_span(
|
|||
}
|
||||
}
|
||||
|
||||
#[instrument(level = "trace", skip(tcx))]
|
||||
pub fn unexpected_hidden_region_diagnostic<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
#[instrument(level = "trace", skip(infcx))]
|
||||
pub fn unexpected_hidden_region_diagnostic<'a, 'tcx>(
|
||||
infcx: &'a InferCtxt<'tcx>,
|
||||
generic_param_scope: LocalDefId,
|
||||
span: Span,
|
||||
hidden_ty: Ty<'tcx>,
|
||||
hidden_region: ty::Region<'tcx>,
|
||||
opaque_ty_key: ty::OpaqueTypeKey<'tcx>,
|
||||
) -> Diag<'tcx> {
|
||||
let mut err = tcx.dcx().create_err(errors::OpaqueCapturesLifetime {
|
||||
) -> Diag<'a> {
|
||||
let tcx = infcx.tcx;
|
||||
let mut err = infcx.dcx().create_err(errors::OpaqueCapturesLifetime {
|
||||
span,
|
||||
opaque_ty: Ty::new_opaque(tcx, opaque_ty_key.def_id.to_def_id(), opaque_ty_key.args),
|
||||
opaque_ty_span: tcx.def_span(opaque_ty_key.def_id),
|
||||
|
@ -436,7 +437,7 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
||||
impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||
pub fn report_region_errors(
|
||||
&self,
|
||||
generic_param_scope: LocalDefId,
|
||||
|
@ -2206,7 +2207,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||
&self,
|
||||
trace: TypeTrace<'tcx>,
|
||||
terr: TypeError<'tcx>,
|
||||
) -> Diag<'tcx> {
|
||||
) -> Diag<'a> {
|
||||
debug!("report_and_explain_type_error(trace={:?}, terr={:?})", trace, terr);
|
||||
|
||||
let span = trace.cause.span();
|
||||
|
@ -2215,7 +2216,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||
span,
|
||||
self.type_error_additional_suggestions(&trace, terr),
|
||||
);
|
||||
let mut diag = self.tcx.dcx().create_err(failure_code);
|
||||
let mut diag = self.dcx().create_err(failure_code);
|
||||
self.note_type_err(&mut diag, &trace.cause, None, Some(trace.values), terr, false, false);
|
||||
diag
|
||||
}
|
||||
|
@ -2357,14 +2358,14 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||
origin: Option<SubregionOrigin<'tcx>>,
|
||||
bound_kind: GenericKind<'tcx>,
|
||||
sub: Region<'tcx>,
|
||||
) -> Diag<'tcx> {
|
||||
) -> Diag<'a> {
|
||||
if let Some(SubregionOrigin::CompareImplItemObligation {
|
||||
span,
|
||||
impl_item_def_id,
|
||||
trait_item_def_id,
|
||||
}) = origin
|
||||
{
|
||||
return self.report_extra_impl_obligation(
|
||||
return self.infcx.report_extra_impl_obligation(
|
||||
span,
|
||||
impl_item_def_id,
|
||||
trait_item_def_id,
|
||||
|
@ -2790,7 +2791,7 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for SameTypeModuloInfer<'_, 'tcx> {
|
|||
}
|
||||
|
||||
impl<'tcx> InferCtxt<'tcx> {
|
||||
fn report_inference_failure(&self, var_origin: RegionVariableOrigin) -> Diag<'tcx> {
|
||||
fn report_inference_failure(&self, var_origin: RegionVariableOrigin) -> Diag<'_> {
|
||||
let br_string = |br: ty::BoundRegionKind| {
|
||||
let mut s = match br {
|
||||
ty::BrNamed(_, name) => name.to_string(),
|
||||
|
@ -2829,7 +2830,7 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||
};
|
||||
|
||||
struct_span_code_err!(
|
||||
self.tcx.dcx(),
|
||||
self.dcx(),
|
||||
var_origin.span(),
|
||||
E0495,
|
||||
"cannot infer an appropriate lifetime{} due to conflicting requirements",
|
||||
|
|
|
@ -391,7 +391,7 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||
span: Span,
|
||||
arg_data: InferenceDiagnosticsData,
|
||||
error_code: TypeAnnotationNeeded,
|
||||
) -> Diag<'tcx> {
|
||||
) -> Diag<'_> {
|
||||
let source_kind = "other";
|
||||
let source_name = "";
|
||||
let failure_span = None;
|
||||
|
@ -436,7 +436,7 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
||||
impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||
#[instrument(level = "debug", skip(self, error_code))]
|
||||
pub fn emit_inference_failure_err(
|
||||
&self,
|
||||
|
@ -445,7 +445,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||
arg: GenericArg<'tcx>,
|
||||
error_code: TypeAnnotationNeeded,
|
||||
should_label_span: bool,
|
||||
) -> Diag<'tcx> {
|
||||
) -> Diag<'a> {
|
||||
let arg = self.resolve_vars_if_possible(arg);
|
||||
let arg_data = self.extract_inference_diagnostics_data(arg, None);
|
||||
|
||||
|
@ -453,7 +453,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||
// If we don't have any typeck results we're outside
|
||||
// of a body, so we won't be able to get better info
|
||||
// here.
|
||||
return self.bad_inference_failure_err(failure_span, arg_data, error_code);
|
||||
return self.infcx.bad_inference_failure_err(failure_span, arg_data, error_code);
|
||||
};
|
||||
|
||||
let mut local_visitor = FindInferSourceVisitor::new(self, typeck_results, arg);
|
||||
|
@ -465,7 +465,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||
}
|
||||
|
||||
let Some(InferSource { span, kind }) = local_visitor.infer_source else {
|
||||
return self.bad_inference_failure_err(failure_span, arg_data, error_code);
|
||||
return self.infcx.bad_inference_failure_err(failure_span, arg_data, error_code);
|
||||
};
|
||||
|
||||
let (source_kind, name, path) = kind.ty_localized_msg(self);
|
||||
|
|
|
@ -14,7 +14,7 @@ use rustc_span::symbol::kw;
|
|||
|
||||
use super::ObligationCauseAsDiagArg;
|
||||
|
||||
impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
||||
impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||
pub(super) fn note_region_origin(&self, err: &mut Diag<'_>, origin: &SubregionOrigin<'tcx>) {
|
||||
match *origin {
|
||||
infer::Subtype(ref trace) => RegionOriginNote::WithRequirement {
|
||||
|
@ -79,7 +79,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||
origin: SubregionOrigin<'tcx>,
|
||||
sub: Region<'tcx>,
|
||||
sup: Region<'tcx>,
|
||||
) -> Diag<'tcx> {
|
||||
) -> Diag<'a> {
|
||||
let mut err = match origin {
|
||||
infer::Subtype(box trace) => {
|
||||
let terr = TypeError::RegionsDoesNotOutlive(sup, sub);
|
||||
|
@ -245,7 +245,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||
})
|
||||
}
|
||||
infer::CompareImplItemObligation { span, impl_item_def_id, trait_item_def_id } => {
|
||||
let mut err = self.report_extra_impl_obligation(
|
||||
let mut err = self.infcx.report_extra_impl_obligation(
|
||||
span,
|
||||
impl_item_def_id,
|
||||
trait_item_def_id,
|
||||
|
@ -378,7 +378,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||
placeholder_origin: SubregionOrigin<'tcx>,
|
||||
sub: Region<'tcx>,
|
||||
sup: Region<'tcx>,
|
||||
) -> Diag<'tcx> {
|
||||
) -> Diag<'a> {
|
||||
// I can't think how to do better than this right now. -nikomatsakis
|
||||
debug!(?placeholder_origin, ?sub, ?sup, "report_placeholder_failure");
|
||||
match placeholder_origin {
|
||||
|
|
|
@ -684,8 +684,8 @@ impl<'tcx> InferOk<'tcx, ()> {
|
|||
}
|
||||
|
||||
impl<'tcx> InferCtxt<'tcx> {
|
||||
pub fn dcx(&self) -> DiagCtxtHandle<'tcx> {
|
||||
self.tcx.dcx()
|
||||
pub fn dcx(&self) -> DiagCtxtHandle<'_> {
|
||||
self.tcx.dcx().taintable_handle(&self.tainted_by_errors)
|
||||
}
|
||||
|
||||
pub fn defining_opaque_types(&self) -> &'tcx ty::List<LocalDefId> {
|
||||
|
@ -1089,19 +1089,7 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||
/// inference variables, regionck errors).
|
||||
#[must_use = "this method does not have any side effects"]
|
||||
pub fn tainted_by_errors(&self) -> Option<ErrorGuaranteed> {
|
||||
if let Some(guar) = self.tainted_by_errors.get() {
|
||||
Some(guar)
|
||||
} else if self.dcx().err_count_excluding_lint_errs() > self.err_count_on_creation {
|
||||
// Errors reported since this infcx was made. Lint errors are
|
||||
// excluded to avoid some being swallowed in the presence of
|
||||
// non-lint errors. (It's arguable whether or not this exclusion is
|
||||
// important.)
|
||||
let guar = self.dcx().has_errors().unwrap();
|
||||
self.set_tainted_by_errors(guar);
|
||||
Some(guar)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
self.tainted_by_errors.get()
|
||||
}
|
||||
|
||||
/// Set the "tainted by errors" flag to true. We call this when we
|
||||
|
@ -1328,8 +1316,7 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||
bug!("`{value:?}` is not fully resolved");
|
||||
}
|
||||
if value.has_infer_regions() {
|
||||
let guar =
|
||||
self.tcx.dcx().delayed_bug(format!("`{value:?}` is not fully resolved"));
|
||||
let guar = self.dcx().delayed_bug(format!("`{value:?}` is not fully resolved"));
|
||||
Ok(self.tcx.fold_regions(value, |re, _| {
|
||||
if re.is_var() { ty::Region::new_error(self.tcx, guar) } else { re }
|
||||
}))
|
||||
|
@ -1607,7 +1594,7 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
||||
impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||
// [Note-Type-error-reporting]
|
||||
// An invariant is that anytime the expected or actual type is Error (the special
|
||||
// error type, meaning that an error occurred when typechecking this expression),
|
||||
|
@ -1623,9 +1610,9 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||
sp: Span,
|
||||
mk_diag: M,
|
||||
actual_ty: Ty<'tcx>,
|
||||
) -> Diag<'tcx>
|
||||
) -> Diag<'a>
|
||||
where
|
||||
M: FnOnce(String) -> Diag<'tcx>,
|
||||
M: FnOnce(String) -> Diag<'a>,
|
||||
{
|
||||
let actual_ty = self.resolve_vars_if_possible(actual_ty);
|
||||
debug!("type_error_struct_with_diag({:?}, {:?})", sp, actual_ty);
|
||||
|
@ -1646,7 +1633,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||
expected: Ty<'tcx>,
|
||||
actual: Ty<'tcx>,
|
||||
err: TypeError<'tcx>,
|
||||
) -> Diag<'tcx> {
|
||||
) -> Diag<'a> {
|
||||
self.report_and_explain_type_error(TypeTrace::types(cause, true, expected, actual), err)
|
||||
}
|
||||
|
||||
|
@ -1656,7 +1643,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||
expected: ty::Const<'tcx>,
|
||||
actual: ty::Const<'tcx>,
|
||||
err: TypeError<'tcx>,
|
||||
) -> Diag<'tcx> {
|
||||
) -> Diag<'a> {
|
||||
self.report_and_explain_type_error(TypeTrace::consts(cause, true, expected, actual), err)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -156,7 +156,7 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||
if self.can_define_opaque_ty(b_def_id)
|
||||
&& self.tcx.is_type_alias_impl_trait(b_def_id)
|
||||
{
|
||||
self.tcx.dcx().emit_err(OpaqueHiddenTypeDiag {
|
||||
self.dcx().emit_err(OpaqueHiddenTypeDiag {
|
||||
span,
|
||||
hidden_type: self.tcx.def_span(b_def_id),
|
||||
opaque_type: self.tcx.def_span(def_id),
|
||||
|
|
|
@ -12,15 +12,15 @@ use std::fmt;
|
|||
use std::iter;
|
||||
|
||||
impl<'tcx> InferCtxt<'tcx> {
|
||||
pub fn report_extra_impl_obligation(
|
||||
&self,
|
||||
pub fn report_extra_impl_obligation<'a>(
|
||||
&'a self,
|
||||
error_span: Span,
|
||||
impl_item_def_id: LocalDefId,
|
||||
trait_item_def_id: DefId,
|
||||
requirement: &dyn fmt::Display,
|
||||
) -> Diag<'tcx> {
|
||||
) -> Diag<'a> {
|
||||
let mut err = struct_span_code_err!(
|
||||
self.tcx.dcx(),
|
||||
self.dcx(),
|
||||
error_span,
|
||||
E0276,
|
||||
"impl has stricter requirements than trait"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue