Make proof tree probing generic

This commit is contained in:
Michael Goulet 2024-06-14 16:04:45 -04:00
parent 8a8bbc0c17
commit c2e416c471
3 changed files with 51 additions and 38 deletions

View file

@ -471,6 +471,10 @@ impl<'tcx> ty::InferCtxtLike for InferCtxt<'tcx> {
{ {
self.resolve_vars_if_possible(value) self.resolve_vars_if_possible(value)
} }
fn probe<T>(&self, probe: impl FnOnce() -> T) -> T {
self.probe(|_| probe())
}
} }
/// See the `error_reporting` module for more details. /// See the `error_reporting` module for more details.

View file

@ -1,27 +1,29 @@
use crate::solve::assembly::Candidate; use crate::solve::assembly::Candidate;
use super::EvalCtxt; use super::EvalCtxt;
use rustc_infer::infer::InferCtxt; use rustc_next_trait_solver::solve::{
use rustc_infer::traits::BuiltinImplSource; inspect, BuiltinImplSource, CandidateSource, NoSolution, QueryResult,
use rustc_middle::traits::query::NoSolution; };
use rustc_middle::traits::solve::{inspect, CandidateSource, QueryResult}; use rustc_type_ir::{InferCtxtLike, Interner};
use rustc_middle::ty::TyCtxt;
use std::marker::PhantomData; use std::marker::PhantomData;
pub(in crate::solve) struct ProbeCtxt<'me, 'a, 'tcx, F, T> { pub(in crate::solve) struct ProbeCtxt<'me, 'a, Infcx, I, F, T>
ecx: &'me mut EvalCtxt<'a, InferCtxt<'tcx>>, where
Infcx: InferCtxtLike<Interner = I>,
I: Interner,
{
ecx: &'me mut EvalCtxt<'a, Infcx, I>,
probe_kind: F, probe_kind: F,
_result: PhantomData<T>, _result: PhantomData<T>,
} }
impl<'tcx, F, T> ProbeCtxt<'_, '_, 'tcx, F, T> impl<Infcx, I, F, T> ProbeCtxt<'_, '_, Infcx, I, F, T>
where where
F: FnOnce(&T) -> inspect::ProbeKind<TyCtxt<'tcx>>, F: FnOnce(&T) -> inspect::ProbeKind<I>,
Infcx: InferCtxtLike<Interner = I>,
I: Interner,
{ {
pub(in crate::solve) fn enter( pub(in crate::solve) fn enter(self, f: impl FnOnce(&mut EvalCtxt<'_, Infcx>) -> T) -> T {
self,
f: impl FnOnce(&mut EvalCtxt<'_, InferCtxt<'tcx>>) -> T,
) -> T {
let ProbeCtxt { ecx: outer_ecx, probe_kind, _result } = self; let ProbeCtxt { ecx: outer_ecx, probe_kind, _result } = self;
let infcx = outer_ecx.infcx; let infcx = outer_ecx.infcx;
@ -38,7 +40,7 @@ where
tainted: outer_ecx.tainted, tainted: outer_ecx.tainted,
inspect: outer_ecx.inspect.take_and_enter_probe(), inspect: outer_ecx.inspect.take_and_enter_probe(),
}; };
let r = nested_ecx.infcx.probe(|_| { let r = nested_ecx.infcx.probe(|| {
let r = f(&mut nested_ecx); let r = f(&mut nested_ecx);
nested_ecx.inspect.probe_final_state(infcx, max_input_universe); nested_ecx.inspect.probe_final_state(infcx, max_input_universe);
r r
@ -52,30 +54,43 @@ where
} }
} }
pub(in crate::solve) struct TraitProbeCtxt<'me, 'a, 'tcx, F> { pub(in crate::solve) struct TraitProbeCtxt<'me, 'a, Infcx, I, F>
cx: ProbeCtxt<'me, 'a, 'tcx, F, QueryResult<'tcx>>, where
source: CandidateSource<'tcx>, Infcx: InferCtxtLike<Interner = I>,
I: Interner,
{
cx: ProbeCtxt<'me, 'a, Infcx, I, F, QueryResult<I>>,
source: CandidateSource<I>,
} }
impl<'tcx, F> TraitProbeCtxt<'_, '_, 'tcx, F> impl<Infcx, I, F> TraitProbeCtxt<'_, '_, Infcx, I, F>
where where
F: FnOnce(&QueryResult<'tcx>) -> inspect::ProbeKind<TyCtxt<'tcx>>, Infcx: InferCtxtLike<Interner = I>,
I: Interner,
F: FnOnce(&QueryResult<I>) -> inspect::ProbeKind<I>,
{ {
#[instrument(level = "debug", skip_all, fields(source = ?self.source))] #[instrument(level = "debug", skip_all, fields(source = ?self.source))]
pub(in crate::solve) fn enter( pub(in crate::solve) fn enter(
self, self,
f: impl FnOnce(&mut EvalCtxt<'_, InferCtxt<'tcx>>) -> QueryResult<'tcx>, f: impl FnOnce(&mut EvalCtxt<'_, Infcx>) -> QueryResult<I>,
) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution> { ) -> Result<Candidate<I>, NoSolution> {
self.cx.enter(|ecx| f(ecx)).map(|result| Candidate { source: self.source, result }) self.cx.enter(|ecx| f(ecx)).map(|result| Candidate { source: self.source, result })
} }
} }
impl<'a, 'tcx> EvalCtxt<'a, InferCtxt<'tcx>> { impl<'a, Infcx, I> EvalCtxt<'a, Infcx, I>
where
Infcx: InferCtxtLike<Interner = I>,
I: Interner,
{
/// `probe_kind` is only called when proof tree building is enabled so it can be /// `probe_kind` is only called when proof tree building is enabled so it can be
/// as expensive as necessary to output the desired information. /// as expensive as necessary to output the desired information.
pub(in crate::solve) fn probe<F, T>(&mut self, probe_kind: F) -> ProbeCtxt<'_, 'a, 'tcx, F, T> pub(in crate::solve) fn probe<F, T>(
&mut self,
probe_kind: F,
) -> ProbeCtxt<'_, 'a, Infcx, I, F, T>
where where
F: FnOnce(&T) -> inspect::ProbeKind<TyCtxt<'tcx>>, F: FnOnce(&T) -> inspect::ProbeKind<I>,
{ {
ProbeCtxt { ecx: self, probe_kind, _result: PhantomData } ProbeCtxt { ecx: self, probe_kind, _result: PhantomData }
} }
@ -83,28 +98,20 @@ impl<'a, 'tcx> EvalCtxt<'a, InferCtxt<'tcx>> {
pub(in crate::solve) fn probe_builtin_trait_candidate( pub(in crate::solve) fn probe_builtin_trait_candidate(
&mut self, &mut self,
source: BuiltinImplSource, source: BuiltinImplSource,
) -> TraitProbeCtxt< ) -> TraitProbeCtxt<'_, 'a, Infcx, I, impl FnOnce(&QueryResult<I>) -> inspect::ProbeKind<I>>
'_, {
'a,
'tcx,
impl FnOnce(&QueryResult<'tcx>) -> inspect::ProbeKind<TyCtxt<'tcx>>,
> {
self.probe_trait_candidate(CandidateSource::BuiltinImpl(source)) self.probe_trait_candidate(CandidateSource::BuiltinImpl(source))
} }
pub(in crate::solve) fn probe_trait_candidate( pub(in crate::solve) fn probe_trait_candidate(
&mut self, &mut self,
source: CandidateSource<'tcx>, source: CandidateSource<I>,
) -> TraitProbeCtxt< ) -> TraitProbeCtxt<'_, 'a, Infcx, I, impl FnOnce(&QueryResult<I>) -> inspect::ProbeKind<I>>
'_, {
'a,
'tcx,
impl FnOnce(&QueryResult<'tcx>) -> inspect::ProbeKind<TyCtxt<'tcx>>,
> {
TraitProbeCtxt { TraitProbeCtxt {
cx: ProbeCtxt { cx: ProbeCtxt {
ecx: self, ecx: self,
probe_kind: move |result: &QueryResult<'tcx>| inspect::ProbeKind::TraitCandidate { probe_kind: move |result: &QueryResult<I>| inspect::ProbeKind::TraitCandidate {
source, source,
result: *result, result: *result,
}, },

View file

@ -72,4 +72,6 @@ pub trait InferCtxtLike: Sized {
fn resolve_vars_if_possible<T>(&self, value: T) -> T fn resolve_vars_if_possible<T>(&self, value: T) -> T
where where
T: TypeFoldable<Self::Interner>; T: TypeFoldable<Self::Interner>;
fn probe<T>(&self, probe: impl FnOnce() -> T) -> T;
} }