rustc_next_trait_solver/solve/inspect/
build.rs1use std::marker::PhantomData;
8
9use derive_where::derive_where;
10use rustc_type_ir::inherent::*;
11use rustc_type_ir::{self as ty, Interner};
12
13use crate::delegate::SolverDelegate;
14use crate::solve::eval_ctxt::canonical;
15use crate::solve::{Certainty, Goal, GoalSource, QueryResult, inspect};
16
17pub(crate) struct ProofTreeBuilder<D, I = <D as SolverDelegate>::Interner>
26where
27 D: SolverDelegate<Interner = I>,
28 I: Interner,
29{
30 state: Option<Box<Option<inspect::Probe<I>>>>,
31 _infcx: PhantomData<D>,
32}
33
34impl<D: SolverDelegate<Interner = I>, I: Interner> ProofTreeBuilder<D> {
35 pub(crate) fn new() -> ProofTreeBuilder<D> {
36 ProofTreeBuilder { state: Some(Box::new(None)), _infcx: PhantomData }
37 }
38
39 pub(crate) fn new_noop() -> ProofTreeBuilder<D> {
40 ProofTreeBuilder { state: None, _infcx: PhantomData }
41 }
42
43 pub(crate) fn is_noop(&self) -> bool {
44 self.state.is_none()
45 }
46
47 pub(crate) fn new_evaluation_step(
48 &mut self,
49 var_values: ty::CanonicalVarValues<I>,
50 ) -> EvaluationStepBuilder<D> {
51 if self.is_noop() {
52 EvaluationStepBuilder { state: None, _infcx: PhantomData }
53 } else {
54 EvaluationStepBuilder {
55 state: Some(Box::new(WipEvaluationStep {
56 var_values: var_values.var_values.to_vec(),
57 evaluation: WipProbe {
58 initial_num_var_values: var_values.len(),
59 steps: vec![],
60 kind: None,
61 final_state: None,
62 },
63 probe_depth: 0,
64 })),
65 _infcx: PhantomData,
66 }
67 }
68 }
69
70 pub(crate) fn finish_evaluation_step(
71 &mut self,
72 goal_evaluation_step: EvaluationStepBuilder<D>,
73 ) {
74 if let Some(this) = self.state.as_deref_mut() {
75 *this = Some(goal_evaluation_step.state.unwrap().finalize());
76 }
77 }
78
79 pub(crate) fn unwrap(self) -> inspect::Probe<I> {
80 self.state.unwrap().unwrap()
81 }
82}
83
84pub(crate) struct EvaluationStepBuilder<D, I = <D as SolverDelegate>::Interner>
85where
86 D: SolverDelegate<Interner = I>,
87 I: Interner,
88{
89 state: Option<Box<WipEvaluationStep<I>>>,
90 _infcx: PhantomData<D>,
91}
92
93#[derive_where(PartialEq, Eq, Debug; I: Interner)]
94struct WipEvaluationStep<I: Interner> {
95 var_values: Vec<I::GenericArg>,
102 probe_depth: usize,
103 evaluation: WipProbe<I>,
104}
105
106impl<I: Interner> WipEvaluationStep<I> {
107 fn current_evaluation_scope(&mut self) -> &mut WipProbe<I> {
108 let mut current = &mut self.evaluation;
109 for _ in 0..self.probe_depth {
110 match current.steps.last_mut() {
111 Some(WipProbeStep::NestedProbe(p)) => current = p,
112 _ => panic!(),
113 }
114 }
115 current
116 }
117
118 fn finalize(self) -> inspect::Probe<I> {
119 let evaluation = self.evaluation.finalize();
120 match evaluation.kind {
121 inspect::ProbeKind::Root { .. } => evaluation,
122 _ => unreachable!("unexpected root evaluation: {evaluation:?}"),
123 }
124 }
125}
126
127#[derive_where(PartialEq, Debug; I: Interner)]
128struct WipProbe<I: Interner> {
129 initial_num_var_values: usize,
130 steps: Vec<WipProbeStep<I>>,
131 kind: Option<inspect::ProbeKind<I>>,
132 final_state: Option<inspect::CanonicalState<I, ()>>,
133}
134
135impl<I: Interner> Eq for WipProbe<I> {}
136
137impl<I: Interner> WipProbe<I> {
138 fn finalize(self) -> inspect::Probe<I> {
139 inspect::Probe {
140 steps: self.steps.into_iter().map(WipProbeStep::finalize).collect(),
141 kind: self.kind.unwrap(),
142 final_state: self.final_state.unwrap(),
143 }
144 }
145}
146
147#[derive_where(PartialEq, Debug; I: Interner)]
148enum WipProbeStep<I: Interner> {
149 AddGoal(GoalSource, inspect::CanonicalState<I, Goal<I, I::Predicate>>),
150 NestedProbe(WipProbe<I>),
151 MakeCanonicalResponse { shallow_certainty: Certainty },
152 RecordImplArgs { impl_args: inspect::CanonicalState<I, I::GenericArgs> },
153}
154
155impl<I: Interner> Eq for WipProbeStep<I> {}
156
157impl<I: Interner> WipProbeStep<I> {
158 fn finalize(self) -> inspect::ProbeStep<I> {
159 match self {
160 WipProbeStep::AddGoal(source, goal) => inspect::ProbeStep::AddGoal(source, goal),
161 WipProbeStep::NestedProbe(probe) => inspect::ProbeStep::NestedProbe(probe.finalize()),
162 WipProbeStep::RecordImplArgs { impl_args } => {
163 inspect::ProbeStep::RecordImplArgs { impl_args }
164 }
165 WipProbeStep::MakeCanonicalResponse { shallow_certainty } => {
166 inspect::ProbeStep::MakeCanonicalResponse { shallow_certainty }
167 }
168 }
169 }
170}
171
172impl<D: SolverDelegate<Interner = I>, I: Interner> EvaluationStepBuilder<D> {
173 pub(crate) fn new_noop() -> EvaluationStepBuilder<D> {
174 EvaluationStepBuilder { state: None, _infcx: PhantomData }
175 }
176
177 pub(crate) fn is_noop(&self) -> bool {
178 self.state.is_none()
179 }
180
181 fn as_mut(&mut self) -> Option<&mut WipEvaluationStep<I>> {
182 self.state.as_deref_mut()
183 }
184
185 pub(crate) fn take_and_enter_probe(&mut self) -> EvaluationStepBuilder<D> {
186 let mut nested = EvaluationStepBuilder { state: self.state.take(), _infcx: PhantomData };
187 nested.enter_probe();
188 nested
189 }
190
191 pub(crate) fn add_var_value<T: Into<I::GenericArg>>(&mut self, arg: T) {
192 if let Some(this) = self.as_mut() {
193 this.var_values.push(arg.into());
194 }
195 }
196
197 fn enter_probe(&mut self) {
198 if let Some(this) = self.as_mut() {
199 let initial_num_var_values = this.var_values.len();
200 this.current_evaluation_scope().steps.push(WipProbeStep::NestedProbe(WipProbe {
201 initial_num_var_values,
202 steps: vec![],
203 kind: None,
204 final_state: None,
205 }));
206 this.probe_depth += 1;
207 }
208 }
209
210 pub(crate) fn probe_kind(&mut self, probe_kind: inspect::ProbeKind<I>) {
211 if let Some(this) = self.as_mut() {
212 let prev = this.current_evaluation_scope().kind.replace(probe_kind);
213 assert_eq!(prev, None);
214 }
215 }
216
217 pub(crate) fn probe_final_state(
218 &mut self,
219 delegate: &D,
220 max_input_universe: ty::UniverseIndex,
221 ) {
222 if let Some(this) = self.as_mut() {
223 let final_state =
224 canonical::make_canonical_state(delegate, &this.var_values, max_input_universe, ());
225 let prev = this.current_evaluation_scope().final_state.replace(final_state);
226 assert_eq!(prev, None);
227 }
228 }
229
230 pub(crate) fn add_goal(
231 &mut self,
232 delegate: &D,
233 max_input_universe: ty::UniverseIndex,
234 source: GoalSource,
235 goal: Goal<I, I::Predicate>,
236 ) {
237 if let Some(this) = self.as_mut() {
238 let goal = canonical::make_canonical_state(
239 delegate,
240 &this.var_values,
241 max_input_universe,
242 goal,
243 );
244 this.current_evaluation_scope().steps.push(WipProbeStep::AddGoal(source, goal))
245 }
246 }
247
248 pub(crate) fn record_impl_args(
249 &mut self,
250 delegate: &D,
251 max_input_universe: ty::UniverseIndex,
252 impl_args: I::GenericArgs,
253 ) {
254 if let Some(this) = self.as_mut() {
255 let impl_args = canonical::make_canonical_state(
256 delegate,
257 &this.var_values,
258 max_input_universe,
259 impl_args,
260 );
261 this.current_evaluation_scope().steps.push(WipProbeStep::RecordImplArgs { impl_args });
262 }
263 }
264
265 pub(crate) fn make_canonical_response(&mut self, shallow_certainty: Certainty) {
266 if let Some(this) = self.as_mut() {
267 this.current_evaluation_scope()
268 .steps
269 .push(WipProbeStep::MakeCanonicalResponse { shallow_certainty });
270 }
271 }
272
273 pub(crate) fn finish_probe(mut self) -> EvaluationStepBuilder<D> {
274 if let Some(this) = self.as_mut() {
275 assert_ne!(this.probe_depth, 0);
276 let num_var_values = this.current_evaluation_scope().initial_num_var_values;
277 this.var_values.truncate(num_var_values);
278 this.probe_depth -= 1;
279 }
280
281 self
282 }
283
284 pub(crate) fn query_result(&mut self, result: QueryResult<I>) {
285 if let Some(this) = self.as_mut() {
286 assert_eq!(this.evaluation.kind.replace(inspect::ProbeKind::Root { result }), None);
287 }
288 }
289}