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