Restrict diagnostic context lifetime of InferCtxt to itself instead of TyCtxt

This commit is contained in:
Oli Scherer 2024-06-26 10:52:57 +00:00
parent 79ac8982ca
commit 5988078aa2
12 changed files with 79 additions and 53 deletions

View File

@ -149,13 +149,13 @@ trait TypeOpInfo<'tcx> {
fn base_universe(&self) -> ty::UniverseIndex;
fn nice_error(
fn nice_error<'cx>(
&self,
mbcx: &mut MirBorrowckCtxt<'_, '_, '_, 'tcx>,
mbcx: &mut MirBorrowckCtxt<'_, '_, 'cx, 'tcx>,
cause: ObligationCause<'tcx>,
placeholder_region: ty::Region<'tcx>,
error_region: Option<ty::Region<'tcx>>,
) -> Option<Diag<'tcx>>;
) -> Option<Diag<'cx>>;
#[instrument(level = "debug", skip(self, mbcx))]
fn report_error(
@ -231,18 +231,25 @@ impl<'tcx> TypeOpInfo<'tcx> for PredicateQuery<'tcx> {
self.base_universe
}
fn nice_error(
fn nice_error<'cx>(
&self,
mbcx: &mut MirBorrowckCtxt<'_, '_, '_, 'tcx>,
mbcx: &mut MirBorrowckCtxt<'_, '_, 'cx, 'tcx>,
cause: ObligationCause<'tcx>,
placeholder_region: ty::Region<'tcx>,
error_region: Option<ty::Region<'tcx>>,
) -> Option<Diag<'tcx>> {
) -> Option<Diag<'cx>> {
let (infcx, key, _) =
mbcx.infcx.tcx.infer_ctxt().build_with_canonical(cause.span, &self.canonical_query);
let ocx = ObligationCtxt::new(&infcx);
type_op_prove_predicate_with_cause(&ocx, key, cause);
try_extract_error_from_fulfill_cx(&ocx, mbcx.mir_def_id(), placeholder_region, error_region)
let diag = try_extract_error_from_fulfill_cx(
&ocx,
mbcx.mir_def_id(),
placeholder_region,
error_region,
)?
.with_dcx(mbcx.dcx());
Some(diag)
}
}
@ -268,13 +275,13 @@ where
self.base_universe
}
fn nice_error(
fn nice_error<'cx>(
&self,
mbcx: &mut MirBorrowckCtxt<'_, '_, '_, 'tcx>,
mbcx: &mut MirBorrowckCtxt<'_, '_, 'cx, 'tcx>,
cause: ObligationCause<'tcx>,
placeholder_region: ty::Region<'tcx>,
error_region: Option<ty::Region<'tcx>>,
) -> Option<Diag<'tcx>> {
) -> Option<Diag<'cx>> {
let (infcx, key, _) =
mbcx.infcx.tcx.infer_ctxt().build_with_canonical(cause.span, &self.canonical_query);
let ocx = ObligationCtxt::new(&infcx);
@ -288,7 +295,14 @@ where
let (param_env, value) = key.into_parts();
let _ = ocx.normalize(&cause, param_env, value.value);
try_extract_error_from_fulfill_cx(&ocx, mbcx.mir_def_id(), placeholder_region, error_region)
let diag = try_extract_error_from_fulfill_cx(
&ocx,
mbcx.mir_def_id(),
placeholder_region,
error_region,
)?
.with_dcx(mbcx.dcx());
Some(diag)
}
}
@ -308,18 +322,25 @@ impl<'tcx> TypeOpInfo<'tcx> for AscribeUserTypeQuery<'tcx> {
self.base_universe
}
fn nice_error(
fn nice_error<'cx>(
&self,
mbcx: &mut MirBorrowckCtxt<'_, '_, '_, 'tcx>,
mbcx: &mut MirBorrowckCtxt<'_, '_, 'cx, 'tcx>,
cause: ObligationCause<'tcx>,
placeholder_region: ty::Region<'tcx>,
error_region: Option<ty::Region<'tcx>>,
) -> Option<Diag<'tcx>> {
) -> Option<Diag<'cx>> {
let (infcx, key, _) =
mbcx.infcx.tcx.infer_ctxt().build_with_canonical(cause.span, &self.canonical_query);
let ocx = ObligationCtxt::new(&infcx);
type_op_ascribe_user_type_with_span(&ocx, key, Some(cause.span)).ok()?;
try_extract_error_from_fulfill_cx(&ocx, mbcx.mir_def_id(), placeholder_region, error_region)
let diag = try_extract_error_from_fulfill_cx(
&ocx,
mbcx.mir_def_id(),
placeholder_region,
error_region,
)?
.with_dcx(mbcx.dcx());
Some(diag)
}
}
@ -334,13 +355,13 @@ impl<'tcx> TypeOpInfo<'tcx> for crate::type_check::InstantiateOpaqueType<'tcx> {
self.base_universe.unwrap()
}
fn nice_error(
fn nice_error<'cx>(
&self,
mbcx: &mut MirBorrowckCtxt<'_, '_, '_, 'tcx>,
mbcx: &mut MirBorrowckCtxt<'_, '_, 'cx, 'tcx>,
_cause: ObligationCause<'tcx>,
placeholder_region: ty::Region<'tcx>,
error_region: Option<ty::Region<'tcx>>,
) -> Option<Diag<'tcx>> {
) -> Option<Diag<'cx>> {
try_extract_error_from_region_constraints(
mbcx.infcx,
mbcx.mir_def_id(),
@ -358,12 +379,12 @@ impl<'tcx> TypeOpInfo<'tcx> for crate::type_check::InstantiateOpaqueType<'tcx> {
}
#[instrument(skip(ocx), level = "debug")]
fn try_extract_error_from_fulfill_cx<'tcx>(
ocx: &ObligationCtxt<'_, 'tcx>,
fn try_extract_error_from_fulfill_cx<'a, 'tcx>(
ocx: &ObligationCtxt<'a, 'tcx>,
generic_param_scope: LocalDefId,
placeholder_region: ty::Region<'tcx>,
error_region: Option<ty::Region<'tcx>>,
) -> Option<Diag<'tcx>> {
) -> Option<Diag<'a>> {
// We generally shouldn't have errors here because the query was
// already run, but there's no point using `span_delayed_bug`
// when we're going to emit an error here anyway.
@ -381,15 +402,15 @@ fn try_extract_error_from_fulfill_cx<'tcx>(
}
#[instrument(level = "debug", skip(infcx, region_var_origin, universe_of_region))]
fn try_extract_error_from_region_constraints<'tcx>(
infcx: &InferCtxt<'tcx>,
fn try_extract_error_from_region_constraints<'a, 'tcx>(
infcx: &'a InferCtxt<'tcx>,
generic_param_scope: LocalDefId,
placeholder_region: ty::Region<'tcx>,
error_region: Option<ty::Region<'tcx>>,
region_constraints: &RegionConstraintData<'tcx>,
mut region_var_origin: impl FnMut(RegionVid) -> RegionVariableOrigin,
mut universe_of_region: impl FnMut(RegionVid) -> UniverseIndex,
) -> Option<Diag<'tcx>> {
) -> Option<Diag<'a>> {
let placeholder_universe = match placeholder_region.kind() {
ty::RePlaceholder(p) => p.universe,
ty::ReVar(vid) => universe_of_region(vid),

View File

@ -582,6 +582,11 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
Self::new_diagnostic(dcx, DiagInner::new(level, message))
}
/// Allow moving diagnostics between different error tainting contexts
pub fn with_dcx(mut self, dcx: DiagCtxtHandle<'_>) -> Diag<'_, G> {
Diag { dcx, diag: self.diag.take(), _marker: PhantomData }
}
/// Creates a new `Diag` with an already constructed diagnostic.
#[track_caller]
pub(crate) fn new_diagnostic(dcx: DiagCtxtHandle<'a>, diag: DiagInner) -> Self {

View File

@ -1797,16 +1797,16 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
err.subdiagnostic(SuggestBoxingForReturnImplTrait::BoxReturnExpr { starts, ends });
}
fn report_return_mismatched_types<'a>(
fn report_return_mismatched_types<'cx>(
&self,
cause: &ObligationCause<'tcx>,
expected: Ty<'tcx>,
found: Ty<'tcx>,
ty_err: TypeError<'tcx>,
fcx: &FnCtxt<'a, 'tcx>,
fcx: &'cx FnCtxt<'_, 'tcx>,
block_or_return_id: hir::HirId,
expression: Option<&'tcx hir::Expr<'tcx>>,
) -> Diag<'a> {
) -> Diag<'cx> {
let mut err = fcx.err_ctxt().report_mismatched_types(cause, expected, found, ty_err);
let due_to_block = matches!(fcx.tcx.hir_node(block_or_return_id), hir::Node::Block(..));

View File

@ -172,21 +172,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
pub fn demand_suptype_diag(
&self,
&'a self,
sp: Span,
expected: Ty<'tcx>,
actual: Ty<'tcx>,
) -> Result<(), Diag<'tcx>> {
) -> Result<(), Diag<'a>> {
self.demand_suptype_with_origin(&self.misc(sp), expected, actual)
}
#[instrument(skip(self), level = "debug")]
pub fn demand_suptype_with_origin(
&self,
&'a self,
cause: &ObligationCause<'tcx>,
expected: Ty<'tcx>,
actual: Ty<'tcx>,
) -> Result<(), Diag<'tcx>> {
) -> Result<(), Diag<'a>> {
self.at(cause, self.param_env)
.sup(DefineOpaqueTypes::Yes, expected, actual)
.map(|infer_ok| self.register_infer_ok_obligations(infer_ok))
@ -200,20 +200,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
pub fn demand_eqtype_diag(
&self,
&'a self,
sp: Span,
expected: Ty<'tcx>,
actual: Ty<'tcx>,
) -> Result<(), Diag<'tcx>> {
) -> Result<(), Diag<'a>> {
self.demand_eqtype_with_origin(&self.misc(sp), expected, actual)
}
pub fn demand_eqtype_with_origin(
&self,
&'a self,
cause: &ObligationCause<'tcx>,
expected: Ty<'tcx>,
actual: Ty<'tcx>,
) -> Result<(), Diag<'tcx>> {
) -> Result<(), Diag<'a>> {
self.at(cause, self.param_env)
.eq(DefineOpaqueTypes::Yes, expected, actual)
.map(|infer_ok| self.register_infer_ok_obligations(infer_ok))
@ -247,13 +247,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
/// will be permitted if the diverges flag is currently "always".
#[instrument(level = "debug", skip(self, expr, expected_ty_expr, allow_two_phase))]
pub fn demand_coerce_diag(
&self,
&'a self,
mut expr: &'tcx hir::Expr<'tcx>,
checked_ty: Ty<'tcx>,
expected: Ty<'tcx>,
mut expected_ty_expr: Option<&'tcx hir::Expr<'tcx>>,
allow_two_phase: AllowTwoPhase,
) -> Result<Ty<'tcx>, Diag<'tcx>> {
) -> Result<Ty<'tcx>, Diag<'a>> {
let expected = self.resolve_vars_with_obligations(expected);
let e = match self.coerce(expr, checked_ty, expected, allow_two_phase, None) {

View File

@ -1424,7 +1424,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
expected_ty: Ty<'tcx>,
provided_ty: Ty<'tcx>,
arg: &hir::Expr<'tcx>,
err: &mut Diag<'tcx>,
err: &mut Diag<'_>,
) {
if let ty::RawPtr(_, hir::Mutability::Mut) = expected_ty.kind()
&& let ty::RawPtr(_, hir::Mutability::Not) = provided_ty.kind()

View File

@ -145,7 +145,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
pub(crate) fn dcx(&self) -> DiagCtxtHandle<'a> {
self.infcx.dcx()
self.root_ctxt.infcx.dcx()
}
pub fn cause(&self, span: Span, code: ObligationCauseCode<'tcx>) -> ObligationCause<'tcx> {

View File

@ -89,7 +89,7 @@ struct PatInfo<'tcx, 'a> {
current_depth: u32,
}
impl<'tcx> FnCtxt<'_, 'tcx> {
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
fn pattern_cause(&self, ti: &TopInfo<'tcx>, cause_span: Span) -> ObligationCause<'tcx> {
let code = ObligationCauseCode::Pattern {
span: ti.span,
@ -100,12 +100,12 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
}
fn demand_eqtype_pat_diag(
&self,
&'a self,
cause_span: Span,
expected: Ty<'tcx>,
actual: Ty<'tcx>,
ti: &TopInfo<'tcx>,
) -> Result<(), Diag<'tcx>> {
) -> Result<(), Diag<'a>> {
self.demand_eqtype_with_origin(&self.pattern_cause(ti, cause_span), expected, actual)
.map_err(|mut diag| {
if let Some(expr) = ti.origin_expr {

View File

@ -436,7 +436,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 +2206,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();

View File

@ -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;
@ -453,7 +453,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, '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<'a, 'tcx> TypeErrCtxt<'a, '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);

View File

@ -684,7 +684,7 @@ impl<'tcx> InferOk<'tcx, ()> {
}
impl<'tcx> InferCtxt<'tcx> {
pub fn dcx(&self) -> DiagCtxtHandle<'tcx> {
pub fn dcx(&self) -> DiagCtxtHandle<'_> {
self.tcx.dcx()
}
@ -1646,7 +1646,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, '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 +1656,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, '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)
}
}

View File

@ -88,7 +88,7 @@ impl<'tcx> InferCtxt<'tcx> {
found_args: Vec<ArgKind>,
is_closure: bool,
closure_arg_span: Option<Span>,
) -> Diag<'tcx> {
) -> Diag<'_> {
let kind = if is_closure { "closure" } else { "function" };
let args_str = |arguments: &[ArgKind], other: &[ArgKind]| {

View File

@ -3422,7 +3422,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
found_trait_ref: ty::TraitRef<'tcx>,
expected_trait_ref: ty::TraitRef<'tcx>,
terr: TypeError<'tcx>,
) -> Diag<'tcx> {
) -> Diag<'a> {
let self_ty = found_trait_ref.self_ty();
let (cause, terr) = if let ty::Closure(def_id, _) = self_ty.kind() {
(
@ -3553,7 +3553,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
})
.unwrap_or((found_span, None, found));
self.report_arg_count_mismatch(
self.infcx.report_arg_count_mismatch(
span,
closure_span,
expected,