rustc_next_trait_solver/solve/eval_ctxt/
probe.rs1use 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 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}