rustc_next_trait_solver/solve/eval_ctxt/
probe.rs

1use std::marker::PhantomData;
2
3use rustc_type_ir::{InferCtxtLike, Interner};
4use tracing::instrument;
5
6use crate::delegate::SolverDelegate;
7use crate::solve::assembly::Candidate;
8use crate::solve::{
9    BuiltinImplSource, CandidateSource, EvalCtxt, NoSolution, QueryResult, inspect,
10};
11
12pub(in crate::solve) struct ProbeCtxt<'me, 'a, D, I, F, T>
13where
14    D: SolverDelegate<Interner = I>,
15    I: Interner,
16{
17    ecx: &'me mut EvalCtxt<'a, D, I>,
18    probe_kind: F,
19    _result: PhantomData<T>,
20}
21
22impl<D, I, F, T> ProbeCtxt<'_, '_, D, I, F, T>
23where
24    F: FnOnce(&T) -> inspect::ProbeKind<I>,
25    D: SolverDelegate<Interner = I>,
26    I: Interner,
27{
28    pub(in crate::solve) fn enter(self, f: impl FnOnce(&mut EvalCtxt<'_, D>) -> T) -> T {
29        let ProbeCtxt { ecx: outer, probe_kind, _result } = self;
30
31        let delegate = outer.delegate;
32        let max_input_universe = outer.max_input_universe;
33        let mut nested = EvalCtxt {
34            delegate,
35            variables: outer.variables,
36            var_values: outer.var_values,
37            current_goal_kind: outer.current_goal_kind,
38            max_input_universe,
39            initial_opaque_types_storage_num_entries: outer
40                .initial_opaque_types_storage_num_entries,
41            search_graph: outer.search_graph,
42            nested_goals: outer.nested_goals.clone(),
43            origin_span: outer.origin_span,
44            tainted: outer.tainted,
45            inspect: outer.inspect.take_and_enter_probe(),
46        };
47        let r = nested.delegate.probe(|| {
48            let r = f(&mut nested);
49            nested.inspect.probe_final_state(delegate, max_input_universe);
50            r
51        });
52        if !nested.inspect.is_noop() {
53            let probe_kind = probe_kind(&r);
54            nested.inspect.probe_kind(probe_kind);
55            outer.inspect = nested.inspect.finish_probe();
56        }
57        r
58    }
59}
60
61pub(in crate::solve) struct TraitProbeCtxt<'me, 'a, D, I, F>
62where
63    D: SolverDelegate<Interner = I>,
64    I: Interner,
65{
66    cx: ProbeCtxt<'me, 'a, D, I, F, QueryResult<I>>,
67    source: CandidateSource<I>,
68}
69
70impl<D, I, F> TraitProbeCtxt<'_, '_, D, I, F>
71where
72    D: SolverDelegate<Interner = I>,
73    I: Interner,
74    F: FnOnce(&QueryResult<I>) -> inspect::ProbeKind<I>,
75{
76    #[instrument(level = "debug", skip_all, fields(source = ?self.source))]
77    pub(in crate::solve) fn enter(
78        self,
79        f: impl FnOnce(&mut EvalCtxt<'_, D>) -> QueryResult<I>,
80    ) -> Result<Candidate<I>, NoSolution> {
81        self.cx.enter(|ecx| f(ecx)).map(|result| Candidate { source: self.source, result })
82    }
83}
84
85impl<'a, D, I> EvalCtxt<'a, D, I>
86where
87    D: SolverDelegate<Interner = I>,
88    I: Interner,
89{
90    /// `probe_kind` is only called when proof tree building is enabled so it can be
91    /// as expensive as necessary to output the desired information.
92    pub(in crate::solve) fn probe<F, T>(&mut self, probe_kind: F) -> ProbeCtxt<'_, 'a, D, I, F, T>
93    where
94        F: FnOnce(&T) -> inspect::ProbeKind<I>,
95    {
96        ProbeCtxt { ecx: self, probe_kind, _result: PhantomData }
97    }
98
99    pub(in crate::solve) fn probe_builtin_trait_candidate(
100        &mut self,
101        source: BuiltinImplSource,
102    ) -> TraitProbeCtxt<'_, 'a, D, I, impl FnOnce(&QueryResult<I>) -> inspect::ProbeKind<I>> {
103        self.probe_trait_candidate(CandidateSource::BuiltinImpl(source))
104    }
105
106    pub(in crate::solve) fn probe_trait_candidate(
107        &mut self,
108        source: CandidateSource<I>,
109    ) -> TraitProbeCtxt<'_, 'a, D, I, impl FnOnce(&QueryResult<I>) -> inspect::ProbeKind<I>> {
110        TraitProbeCtxt {
111            cx: ProbeCtxt {
112                ecx: self,
113                probe_kind: move |result: &QueryResult<I>| inspect::ProbeKind::TraitCandidate {
114                    source,
115                    result: *result,
116                },
117                _result: PhantomData,
118            },
119            source,
120        }
121    }
122}