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::{
16 Certainty, GenerateProofTree, Goal, GoalEvaluationKind, GoalSource, QueryResult, inspect,
17};
18
19pub(crate) struct ProofTreeBuilder<D, I = <D as SolverDelegate>::Interner>
40where
41 D: SolverDelegate<Interner = I>,
42 I: Interner,
43{
44 _infcx: PhantomData<D>,
45 state: Option<Box<DebugSolver<I>>>,
46}
47
48#[derive_where(Debug; I: Interner)]
53enum DebugSolver<I: Interner> {
54 Root,
55 GoalEvaluation(WipGoalEvaluation<I>),
56 CanonicalGoalEvaluationStep(WipCanonicalGoalEvaluationStep<I>),
57}
58
59impl<I: Interner> From<WipGoalEvaluation<I>> for DebugSolver<I> {
60 fn from(g: WipGoalEvaluation<I>) -> DebugSolver<I> {
61 DebugSolver::GoalEvaluation(g)
62 }
63}
64
65impl<I: Interner> From<WipCanonicalGoalEvaluationStep<I>> for DebugSolver<I> {
66 fn from(g: WipCanonicalGoalEvaluationStep<I>) -> DebugSolver<I> {
67 DebugSolver::CanonicalGoalEvaluationStep(g)
68 }
69}
70
71#[derive_where(PartialEq, Debug; I: Interner)]
72struct WipGoalEvaluation<I: Interner> {
73 pub uncanonicalized_goal: Goal<I, I::Predicate>,
74 pub orig_values: Vec<I::GenericArg>,
75 pub encountered_overflow: bool,
76 pub final_revision: Option<WipCanonicalGoalEvaluationStep<I>>,
78 pub result: Option<QueryResult<I>>,
79}
80
81impl<I: Interner> Eq for WipGoalEvaluation<I> {}
82
83impl<I: Interner> WipGoalEvaluation<I> {
84 fn finalize(self) -> inspect::GoalEvaluation<I> {
85 inspect::GoalEvaluation {
86 uncanonicalized_goal: self.uncanonicalized_goal,
87 orig_values: self.orig_values,
88 kind: if self.encountered_overflow {
89 assert!(self.final_revision.is_none());
90 inspect::GoalEvaluationKind::Overflow
91 } else {
92 let final_revision = self.final_revision.unwrap().finalize();
93 inspect::GoalEvaluationKind::Evaluation { final_revision }
94 },
95 result: self.result.unwrap(),
96 }
97 }
98}
99
100#[derive_where(PartialEq, Debug; I: Interner)]
104struct WipCanonicalGoalEvaluationStep<I: Interner> {
105 var_values: Vec<I::GenericArg>,
112 probe_depth: usize,
113 evaluation: WipProbe<I>,
114}
115
116impl<I: Interner> Eq for WipCanonicalGoalEvaluationStep<I> {}
117
118impl<I: Interner> WipCanonicalGoalEvaluationStep<I> {
119 fn current_evaluation_scope(&mut self) -> &mut WipProbe<I> {
120 let mut current = &mut self.evaluation;
121 for _ in 0..self.probe_depth {
122 match current.steps.last_mut() {
123 Some(WipProbeStep::NestedProbe(p)) => current = p,
124 _ => panic!(),
125 }
126 }
127 current
128 }
129
130 fn finalize(self) -> inspect::Probe<I> {
131 let evaluation = self.evaluation.finalize();
132 match evaluation.kind {
133 inspect::ProbeKind::Root { .. } => evaluation,
134 _ => unreachable!("unexpected root evaluation: {evaluation:?}"),
135 }
136 }
137}
138
139#[derive_where(PartialEq, Debug; I: Interner)]
140struct WipProbe<I: Interner> {
141 initial_num_var_values: usize,
142 steps: Vec<WipProbeStep<I>>,
143 kind: Option<inspect::ProbeKind<I>>,
144 final_state: Option<inspect::CanonicalState<I, ()>>,
145}
146
147impl<I: Interner> Eq for WipProbe<I> {}
148
149impl<I: Interner> WipProbe<I> {
150 fn finalize(self) -> inspect::Probe<I> {
151 inspect::Probe {
152 steps: self.steps.into_iter().map(WipProbeStep::finalize).collect(),
153 kind: self.kind.unwrap(),
154 final_state: self.final_state.unwrap(),
155 }
156 }
157}
158
159#[derive_where(PartialEq, Debug; I: Interner)]
160enum WipProbeStep<I: Interner> {
161 AddGoal(GoalSource, inspect::CanonicalState<I, Goal<I, I::Predicate>>),
162 NestedProbe(WipProbe<I>),
163 MakeCanonicalResponse { shallow_certainty: Certainty },
164 RecordImplArgs { impl_args: inspect::CanonicalState<I, I::GenericArgs> },
165}
166
167impl<I: Interner> Eq for WipProbeStep<I> {}
168
169impl<I: Interner> WipProbeStep<I> {
170 fn finalize(self) -> inspect::ProbeStep<I> {
171 match self {
172 WipProbeStep::AddGoal(source, goal) => inspect::ProbeStep::AddGoal(source, goal),
173 WipProbeStep::NestedProbe(probe) => inspect::ProbeStep::NestedProbe(probe.finalize()),
174 WipProbeStep::RecordImplArgs { impl_args } => {
175 inspect::ProbeStep::RecordImplArgs { impl_args }
176 }
177 WipProbeStep::MakeCanonicalResponse { shallow_certainty } => {
178 inspect::ProbeStep::MakeCanonicalResponse { shallow_certainty }
179 }
180 }
181 }
182}
183
184impl<D: SolverDelegate<Interner = I>, I: Interner> ProofTreeBuilder<D> {
185 fn new(state: impl Into<DebugSolver<I>>) -> ProofTreeBuilder<D> {
186 ProofTreeBuilder { state: Some(Box::new(state.into())), _infcx: PhantomData }
187 }
188
189 fn opt_nested<T: Into<DebugSolver<I>>>(&self, state: impl FnOnce() -> Option<T>) -> Self {
190 ProofTreeBuilder {
191 state: self.state.as_ref().and_then(|_| Some(state()?.into())).map(Box::new),
192 _infcx: PhantomData,
193 }
194 }
195
196 fn nested<T: Into<DebugSolver<I>>>(&self, state: impl FnOnce() -> T) -> Self {
197 ProofTreeBuilder {
198 state: self.state.as_ref().map(|_| Box::new(state().into())),
199 _infcx: PhantomData,
200 }
201 }
202
203 fn as_mut(&mut self) -> Option<&mut DebugSolver<I>> {
204 self.state.as_deref_mut()
205 }
206
207 pub(crate) fn take_and_enter_probe(&mut self) -> ProofTreeBuilder<D> {
208 let mut nested = ProofTreeBuilder { state: self.state.take(), _infcx: PhantomData };
209 nested.enter_probe();
210 nested
211 }
212
213 pub(crate) fn finalize(self) -> Option<inspect::GoalEvaluation<I>> {
214 match *self.state? {
215 DebugSolver::GoalEvaluation(wip_goal_evaluation) => {
216 Some(wip_goal_evaluation.finalize())
217 }
218 root => unreachable!("unexpected proof tree builder root node: {:?}", root),
219 }
220 }
221
222 pub(crate) fn new_maybe_root(generate_proof_tree: GenerateProofTree) -> ProofTreeBuilder<D> {
223 match generate_proof_tree {
224 GenerateProofTree::No => ProofTreeBuilder::new_noop(),
225 GenerateProofTree::Yes => ProofTreeBuilder::new_root(),
226 }
227 }
228
229 fn new_root() -> ProofTreeBuilder<D> {
230 ProofTreeBuilder::new(DebugSolver::Root)
231 }
232
233 fn new_noop() -> ProofTreeBuilder<D> {
234 ProofTreeBuilder { state: None, _infcx: PhantomData }
235 }
236
237 pub(crate) fn is_noop(&self) -> bool {
238 self.state.is_none()
239 }
240
241 pub(in crate::solve) fn new_goal_evaluation(
242 &mut self,
243 uncanonicalized_goal: Goal<I, I::Predicate>,
244 orig_values: &[I::GenericArg],
245 kind: GoalEvaluationKind,
246 ) -> ProofTreeBuilder<D> {
247 self.opt_nested(|| match kind {
248 GoalEvaluationKind::Root => Some(WipGoalEvaluation {
249 uncanonicalized_goal,
250 orig_values: orig_values.to_vec(),
251 encountered_overflow: false,
252 final_revision: None,
253 result: None,
254 }),
255 GoalEvaluationKind::Nested => None,
256 })
257 }
258
259 pub(crate) fn canonical_goal_evaluation_overflow(&mut self) {
260 if let Some(this) = self.as_mut() {
261 match this {
262 DebugSolver::GoalEvaluation(goal_evaluation) => {
263 goal_evaluation.encountered_overflow = true;
264 }
265 _ => unreachable!(),
266 };
267 }
268 }
269
270 pub(crate) fn goal_evaluation(&mut self, goal_evaluation: ProofTreeBuilder<D>) {
271 if let Some(this) = self.as_mut() {
272 match this {
273 DebugSolver::Root => *this = *goal_evaluation.state.unwrap(),
274 DebugSolver::CanonicalGoalEvaluationStep(_) => {
275 assert!(goal_evaluation.state.is_none())
276 }
277 _ => unreachable!(),
278 }
279 }
280 }
281
282 pub(crate) fn new_goal_evaluation_step(
283 &mut self,
284 var_values: ty::CanonicalVarValues<I>,
285 ) -> ProofTreeBuilder<D> {
286 self.nested(|| WipCanonicalGoalEvaluationStep {
287 var_values: var_values.var_values.to_vec(),
288 evaluation: WipProbe {
289 initial_num_var_values: var_values.len(),
290 steps: vec![],
291 kind: None,
292 final_state: None,
293 },
294 probe_depth: 0,
295 })
296 }
297
298 pub(crate) fn goal_evaluation_step(&mut self, goal_evaluation_step: ProofTreeBuilder<D>) {
299 if let Some(this) = self.as_mut() {
300 match (this, *goal_evaluation_step.state.unwrap()) {
301 (
302 DebugSolver::GoalEvaluation(goal_evaluation),
303 DebugSolver::CanonicalGoalEvaluationStep(goal_evaluation_step),
304 ) => {
305 goal_evaluation.final_revision = Some(goal_evaluation_step);
306 }
307 _ => unreachable!(),
308 }
309 }
310 }
311
312 pub(crate) fn add_var_value<T: Into<I::GenericArg>>(&mut self, arg: T) {
313 match self.as_mut() {
314 None => {}
315 Some(DebugSolver::CanonicalGoalEvaluationStep(state)) => {
316 state.var_values.push(arg.into());
317 }
318 Some(s) => panic!("tried to add var values to {s:?}"),
319 }
320 }
321
322 fn enter_probe(&mut self) {
323 match self.as_mut() {
324 None => {}
325 Some(DebugSolver::CanonicalGoalEvaluationStep(state)) => {
326 let initial_num_var_values = state.var_values.len();
327 state.current_evaluation_scope().steps.push(WipProbeStep::NestedProbe(WipProbe {
328 initial_num_var_values,
329 steps: vec![],
330 kind: None,
331 final_state: None,
332 }));
333 state.probe_depth += 1;
334 }
335 Some(s) => panic!("tried to start probe to {s:?}"),
336 }
337 }
338
339 pub(crate) fn probe_kind(&mut self, probe_kind: inspect::ProbeKind<I>) {
340 match self.as_mut() {
341 None => {}
342 Some(DebugSolver::CanonicalGoalEvaluationStep(state)) => {
343 let prev = state.current_evaluation_scope().kind.replace(probe_kind);
344 assert_eq!(prev, None);
345 }
346 _ => panic!(),
347 }
348 }
349
350 pub(crate) fn probe_final_state(
351 &mut self,
352 delegate: &D,
353 max_input_universe: ty::UniverseIndex,
354 ) {
355 match self.as_mut() {
356 None => {}
357 Some(DebugSolver::CanonicalGoalEvaluationStep(state)) => {
358 let final_state = canonical::make_canonical_state(
359 delegate,
360 &state.var_values,
361 max_input_universe,
362 (),
363 );
364 let prev = state.current_evaluation_scope().final_state.replace(final_state);
365 assert_eq!(prev, None);
366 }
367 _ => panic!(),
368 }
369 }
370
371 pub(crate) fn add_goal(
372 &mut self,
373 delegate: &D,
374 max_input_universe: ty::UniverseIndex,
375 source: GoalSource,
376 goal: Goal<I, I::Predicate>,
377 ) {
378 match self.as_mut() {
379 None => {}
380 Some(DebugSolver::CanonicalGoalEvaluationStep(state)) => {
381 let goal = canonical::make_canonical_state(
382 delegate,
383 &state.var_values,
384 max_input_universe,
385 goal,
386 );
387 state.current_evaluation_scope().steps.push(WipProbeStep::AddGoal(source, goal))
388 }
389 _ => panic!(),
390 }
391 }
392
393 pub(crate) fn record_impl_args(
394 &mut self,
395 delegate: &D,
396 max_input_universe: ty::UniverseIndex,
397 impl_args: I::GenericArgs,
398 ) {
399 match self.as_mut() {
400 Some(DebugSolver::CanonicalGoalEvaluationStep(state)) => {
401 let impl_args = canonical::make_canonical_state(
402 delegate,
403 &state.var_values,
404 max_input_universe,
405 impl_args,
406 );
407 state
408 .current_evaluation_scope()
409 .steps
410 .push(WipProbeStep::RecordImplArgs { impl_args });
411 }
412 None => {}
413 _ => panic!(),
414 }
415 }
416
417 pub(crate) fn make_canonical_response(&mut self, shallow_certainty: Certainty) {
418 match self.as_mut() {
419 Some(DebugSolver::CanonicalGoalEvaluationStep(state)) => {
420 state
421 .current_evaluation_scope()
422 .steps
423 .push(WipProbeStep::MakeCanonicalResponse { shallow_certainty });
424 }
425 None => {}
426 _ => panic!(),
427 }
428 }
429
430 pub(crate) fn finish_probe(mut self) -> ProofTreeBuilder<D> {
431 match self.as_mut() {
432 None => {}
433 Some(DebugSolver::CanonicalGoalEvaluationStep(state)) => {
434 assert_ne!(state.probe_depth, 0);
435 let num_var_values = state.current_evaluation_scope().initial_num_var_values;
436 state.var_values.truncate(num_var_values);
437 state.probe_depth -= 1;
438 }
439 _ => panic!(),
440 }
441
442 self
443 }
444
445 pub(crate) fn query_result(&mut self, result: QueryResult<I>) {
446 if let Some(this) = self.as_mut() {
447 match this {
448 DebugSolver::GoalEvaluation(goal_evaluation) => {
449 assert_eq!(goal_evaluation.result.replace(result), None);
450 }
451 DebugSolver::CanonicalGoalEvaluationStep(evaluation_step) => {
452 assert_eq!(
453 evaluation_step
454 .evaluation
455 .kind
456 .replace(inspect::ProbeKind::Root { result }),
457 None
458 );
459 }
460 _ => unreachable!(),
461 }
462 }
463 }
464}