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_ecx, probe_kind, _result } = self;
30
31 let delegate = outer_ecx.delegate;
32 let max_input_universe = outer_ecx.max_input_universe;
33 let mut nested_ecx = EvalCtxt {
34 delegate,
35 variables: outer_ecx.variables,
36 var_values: outer_ecx.var_values,
37 is_normalizes_to_goal: outer_ecx.is_normalizes_to_goal,
38 predefined_opaques_in_body: outer_ecx.predefined_opaques_in_body,
39 max_input_universe,
40 search_graph: outer_ecx.search_graph,
41 nested_goals: outer_ecx.nested_goals.clone(),
42 origin_span: outer_ecx.origin_span,
43 tainted: outer_ecx.tainted,
44 inspect: outer_ecx.inspect.take_and_enter_probe(),
45 };
46 let r = nested_ecx.delegate.probe(|| {
47 let r = f(&mut nested_ecx);
48 nested_ecx.inspect.probe_final_state(delegate, max_input_universe);
49 r
50 });
51 if !nested_ecx.inspect.is_noop() {
52 let probe_kind = probe_kind(&r);
53 nested_ecx.inspect.probe_kind(probe_kind);
54 outer_ecx.inspect = nested_ecx.inspect.finish_probe();
55 }
56 r
57 }
58}
59
60pub(in crate::solve) struct TraitProbeCtxt<'me, 'a, D, I, F>
61where
62 D: SolverDelegate<Interner = I>,
63 I: Interner,
64{
65 cx: ProbeCtxt<'me, 'a, D, I, F, QueryResult<I>>,
66 source: CandidateSource<I>,
67}
68
69impl<D, I, F> TraitProbeCtxt<'_, '_, D, I, F>
70where
71 D: SolverDelegate<Interner = I>,
72 I: Interner,
73 F: FnOnce(&QueryResult<I>) -> inspect::ProbeKind<I>,
74{
75 #[instrument(level = "debug", skip_all, fields(source = ?self.source))]
76 pub(in crate::solve) fn enter(
77 self,
78 f: impl FnOnce(&mut EvalCtxt<'_, D>) -> QueryResult<I>,
79 ) -> Result<Candidate<I>, NoSolution> {
80 self.cx.enter(|ecx| f(ecx)).map(|result| Candidate { source: self.source, result })
81 }
82}
83
84impl<'a, D, I> EvalCtxt<'a, D, I>
85where
86 D: SolverDelegate<Interner = I>,
87 I: Interner,
88{
89 pub(in crate::solve) fn probe<F, T>(&mut self, probe_kind: F) -> ProbeCtxt<'_, 'a, D, I, F, T>
92 where
93 F: FnOnce(&T) -> inspect::ProbeKind<I>,
94 {
95 ProbeCtxt { ecx: self, probe_kind, _result: PhantomData }
96 }
97
98 pub(in crate::solve) fn probe_builtin_trait_candidate(
99 &mut self,
100 source: BuiltinImplSource,
101 ) -> TraitProbeCtxt<'_, 'a, D, I, impl FnOnce(&QueryResult<I>) -> inspect::ProbeKind<I>> {
102 self.probe_trait_candidate(CandidateSource::BuiltinImpl(source))
103 }
104
105 pub(in crate::solve) fn probe_trait_candidate(
106 &mut self,
107 source: CandidateSource<I>,
108 ) -> TraitProbeCtxt<'_, 'a, D, I, impl FnOnce(&QueryResult<I>) -> inspect::ProbeKind<I>> {
109 TraitProbeCtxt {
110 cx: ProbeCtxt {
111 ecx: self,
112 probe_kind: move |result: &QueryResult<I>| inspect::ProbeKind::TraitCandidate {
113 source,
114 result: *result,
115 },
116 _result: PhantomData,
117 },
118 source,
119 }
120 }
121}