1use rustc_data_structures::assert_matches;
13use rustc_infer::infer::InferCtxt;
14use rustc_infer::traits::Obligation;
15use rustc_macros::extension;
16use rustc_middle::traits::ObligationCause;
17use rustc_middle::traits::solve::{Certainty, Goal, GoalSource, NoSolution, QueryResult};
18use rustc_middle::ty::{TyCtxt, VisitorResult, try_visit};
19use rustc_middle::{bug, ty};
20use rustc_next_trait_solver::canonical::instantiate_canonical_state;
21use rustc_next_trait_solver::resolve::eager_resolve_vars;
22use rustc_next_trait_solver::solve::{MaybeCause, SolverDelegateEvalExt as _, inspect};
23use rustc_span::Span;
24use tracing::instrument;
25
26use crate::solve::delegate::SolverDelegate;
27use crate::traits::ObligationCtxt;
28
29pub struct InspectConfig {
30 pub max_depth: usize,
31}
32
33pub struct InspectGoal<'a, 'tcx> {
34 infcx: &'a SolverDelegate<'tcx>,
35 depth: usize,
36 orig_values: Vec<ty::GenericArg<'tcx>>,
37 goal: Goal<'tcx, ty::Predicate<'tcx>>,
38 result: Result<Certainty, NoSolution>,
39 final_revision: &'tcx inspect::Probe<TyCtxt<'tcx>>,
40 normalizes_to_term_hack: Option<NormalizesToTermHack<'tcx>>,
41 source: GoalSource,
42}
43
44#[derive(#[automatically_derived]
impl<'tcx> ::core::marker::Copy for NormalizesToTermHack<'tcx> { }Copy, #[automatically_derived]
impl<'tcx> ::core::clone::Clone for NormalizesToTermHack<'tcx> {
#[inline]
fn clone(&self) -> NormalizesToTermHack<'tcx> {
let _: ::core::clone::AssertParamIsClone<ty::Term<'tcx>>;
let _: ::core::clone::AssertParamIsClone<ty::Term<'tcx>>;
*self
}
}Clone)]
54struct NormalizesToTermHack<'tcx> {
55 term: ty::Term<'tcx>,
56 unconstrained_term: ty::Term<'tcx>,
57}
58
59impl<'tcx> NormalizesToTermHack<'tcx> {
60 fn constrain_and(
64 &self,
65 infcx: &InferCtxt<'tcx>,
66 span: Span,
67 param_env: ty::ParamEnv<'tcx>,
68 f: impl FnOnce(&ObligationCtxt<'_, 'tcx>),
69 ) -> Result<Certainty, NoSolution> {
70 let ocx = ObligationCtxt::new(infcx);
71 ocx.eq(
72 &ObligationCause::dummy_with_span(span),
73 param_env,
74 self.term,
75 self.unconstrained_term,
76 )?;
77 f(&ocx);
78 let errors = ocx.evaluate_obligations_error_on_ambiguity();
79 if errors.is_empty() {
80 Ok(Certainty::Yes)
81 } else if errors.iter().all(|e| !e.is_true_error()) {
82 Ok(Certainty::AMBIGUOUS)
83 } else {
84 Err(NoSolution)
85 }
86 }
87}
88
89pub struct InspectCandidate<'a, 'tcx> {
90 goal: &'a InspectGoal<'a, 'tcx>,
91 kind: inspect::ProbeKind<TyCtxt<'tcx>>,
92 steps: Vec<&'a inspect::ProbeStep<TyCtxt<'tcx>>>,
93 final_state: inspect::CanonicalState<TyCtxt<'tcx>, ()>,
94 result: QueryResult<'tcx>,
95 shallow_certainty: Certainty,
96}
97
98impl<'a, 'tcx> InspectCandidate<'a, 'tcx> {
99 pub fn kind(&self) -> inspect::ProbeKind<TyCtxt<'tcx>> {
100 self.kind
101 }
102
103 pub fn result(&self) -> Result<Certainty, NoSolution> {
104 self.result.map(|c| c.value.certainty)
105 }
106
107 pub fn goal(&self) -> &'a InspectGoal<'a, 'tcx> {
108 self.goal
109 }
110
111 pub fn shallow_certainty(&self) -> Certainty {
120 self.shallow_certainty
121 }
122
123 pub fn visit_nested_no_probe<V: ProofTreeVisitor<'tcx>>(&self, visitor: &mut V) -> V::Result {
127 for goal in self.instantiate_nested_goals(visitor.span()) {
128 match ::rustc_ast_ir::visit::VisitorResult::branch(goal.visit_with(visitor)) {
core::ops::ControlFlow::Continue(()) =>
(),
#[allow(unreachable_code)]
core::ops::ControlFlow::Break(r) => {
return ::rustc_ast_ir::visit::VisitorResult::from_residual(r);
}
};try_visit!(goal.visit_with(visitor));
129 }
130
131 V::Result::output()
132 }
133
134 #[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("instantiate_nested_goals",
"rustc_trait_selection::solve::inspect::analyse",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/solve/inspect/analyse.rs"),
::tracing_core::__macro_support::Option::Some(138u32),
::tracing_core::__macro_support::Option::Some("rustc_trait_selection::solve::inspect::analyse"),
::tracing_core::field::FieldSet::new(&["goal", "steps"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = meta.fields().iter();
meta.fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&self.goal.goal)
as &dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&self.steps)
as &dyn Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy ::
needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: Vec<InspectGoal<'a, 'tcx>> =
loop {};
return __tracing_attr_fake_return;
}
{
let infcx = self.goal.infcx;
let param_env = self.goal.goal.param_env;
let mut orig_values = self.goal.orig_values.clone();
let mut instantiated_goals = ::alloc::vec::Vec::new();
for step in &self.steps {
match **step {
inspect::ProbeStep::AddGoal(source, goal) =>
instantiated_goals.push((source,
instantiate_canonical_state(infcx, span, param_env,
&mut orig_values, goal))),
inspect::ProbeStep::RecordImplArgs { .. } => {}
inspect::ProbeStep::MakeCanonicalResponse { .. } |
inspect::ProbeStep::NestedProbe(_) =>
::core::panicking::panic("internal error: entered unreachable code"),
}
}
let () =
instantiate_canonical_state(infcx, span, param_env,
&mut orig_values, self.final_state);
if let Some(term_hack) = &self.goal.normalizes_to_term_hack {
let _ =
term_hack.constrain_and(infcx, span, param_env, |_| {});
}
instantiated_goals.into_iter().map(|(source, goal)|
self.instantiate_proof_tree_for_nested_goal(source, goal,
span)).collect()
}
}
}#[instrument(
139 level = "debug",
140 skip_all,
141 fields(goal = ?self.goal.goal, steps = ?self.steps)
142 )]
143 pub fn instantiate_nested_goals(&self, span: Span) -> Vec<InspectGoal<'a, 'tcx>> {
144 let infcx = self.goal.infcx;
145 let param_env = self.goal.goal.param_env;
146 let mut orig_values = self.goal.orig_values.clone();
147
148 let mut instantiated_goals = vec![];
149 for step in &self.steps {
150 match **step {
151 inspect::ProbeStep::AddGoal(source, goal) => instantiated_goals.push((
152 source,
153 instantiate_canonical_state(infcx, span, param_env, &mut orig_values, goal),
154 )),
155 inspect::ProbeStep::RecordImplArgs { .. } => {}
156 inspect::ProbeStep::MakeCanonicalResponse { .. }
157 | inspect::ProbeStep::NestedProbe(_) => unreachable!(),
158 }
159 }
160
161 let () =
162 instantiate_canonical_state(infcx, span, param_env, &mut orig_values, self.final_state);
163
164 if let Some(term_hack) = &self.goal.normalizes_to_term_hack {
165 let _ = term_hack.constrain_and(infcx, span, param_env, |_| {});
169 }
170
171 instantiated_goals
172 .into_iter()
173 .map(|(source, goal)| self.instantiate_proof_tree_for_nested_goal(source, goal, span))
174 .collect()
175 }
176
177 #[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("instantiate_impl_args",
"rustc_trait_selection::solve::inspect::analyse",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/solve/inspect/analyse.rs"),
::tracing_core::__macro_support::Option::Some(180u32),
::tracing_core::__macro_support::Option::Some("rustc_trait_selection::solve::inspect::analyse"),
::tracing_core::field::FieldSet::new(&["goal", "steps"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = meta.fields().iter();
meta.fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&self.goal.goal)
as &dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&self.steps)
as &dyn Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy ::
needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: ty::GenericArgsRef<'tcx> =
loop {};
return __tracing_attr_fake_return;
}
{
let infcx = self.goal.infcx;
let param_env = self.goal.goal.param_env;
let mut orig_values = self.goal.orig_values.clone();
for step in &self.steps {
match **step {
inspect::ProbeStep::RecordImplArgs { impl_args } => {
let impl_args =
instantiate_canonical_state(infcx, span, param_env,
&mut orig_values, impl_args);
let () =
instantiate_canonical_state(infcx, span, param_env,
&mut orig_values, self.final_state);
if !self.goal.normalizes_to_term_hack.is_none() {
{
::core::panicking::panic_fmt(format_args!("cannot use `instantiate_impl_args` with a `NormalizesTo` goal"));
}
};
return eager_resolve_vars(infcx, impl_args);
}
inspect::ProbeStep::AddGoal(..) => {}
inspect::ProbeStep::MakeCanonicalResponse { .. } |
inspect::ProbeStep::NestedProbe(_) =>
::core::panicking::panic("internal error: entered unreachable code"),
}
}
::rustc_middle::util::bug::bug_fmt(format_args!("expected impl args probe step for `instantiate_impl_args`"));
}
}
}#[instrument(
181 level = "debug",
182 skip_all,
183 fields(goal = ?self.goal.goal, steps = ?self.steps)
184 )]
185 pub fn instantiate_impl_args(&self, span: Span) -> ty::GenericArgsRef<'tcx> {
186 let infcx = self.goal.infcx;
187 let param_env = self.goal.goal.param_env;
188 let mut orig_values = self.goal.orig_values.clone();
189
190 for step in &self.steps {
191 match **step {
192 inspect::ProbeStep::RecordImplArgs { impl_args } => {
193 let impl_args = instantiate_canonical_state(
194 infcx,
195 span,
196 param_env,
197 &mut orig_values,
198 impl_args,
199 );
200
201 let () = instantiate_canonical_state(
202 infcx,
203 span,
204 param_env,
205 &mut orig_values,
206 self.final_state,
207 );
208
209 assert!(
211 self.goal.normalizes_to_term_hack.is_none(),
212 "cannot use `instantiate_impl_args` with a `NormalizesTo` goal"
213 );
214
215 return eager_resolve_vars(infcx, impl_args);
216 }
217 inspect::ProbeStep::AddGoal(..) => {}
218 inspect::ProbeStep::MakeCanonicalResponse { .. }
219 | inspect::ProbeStep::NestedProbe(_) => unreachable!(),
220 }
221 }
222
223 bug!("expected impl args probe step for `instantiate_impl_args`");
224 }
225
226 pub fn instantiate_proof_tree_for_nested_goal(
227 &self,
228 source: GoalSource,
229 goal: Goal<'tcx, ty::Predicate<'tcx>>,
230 span: Span,
231 ) -> InspectGoal<'a, 'tcx> {
232 let infcx = self.goal.infcx;
233 match goal.predicate.kind().no_bound_vars() {
234 Some(ty::PredicateKind::NormalizesTo(ty::NormalizesTo { alias, term })) => {
235 let unconstrained_term = infcx.next_term_var_of_kind(term, span);
236 let goal =
237 goal.with(infcx.tcx, ty::NormalizesTo { alias, term: unconstrained_term });
238 let normalizes_to_term_hack = NormalizesToTermHack { term, unconstrained_term };
245 let (proof_tree, nested_goals_result) = infcx.probe(|_| {
246 let (nested, proof_tree) = infcx.evaluate_root_goal_for_proof_tree(goal, span);
251 let nested_goals_result = nested.and_then(|nested| {
252 normalizes_to_term_hack.constrain_and(
253 infcx,
254 span,
255 proof_tree.uncanonicalized_goal.param_env,
256 |ocx| {
257 ocx.register_obligations(nested.0.into_iter().map(|(_, goal)| {
258 Obligation::new(
259 infcx.tcx,
260 ObligationCause::dummy_with_span(span),
261 goal.param_env,
262 goal.predicate,
263 )
264 }));
265 },
266 )
267 });
268 (proof_tree, nested_goals_result)
269 });
270 InspectGoal::new(
271 infcx,
272 self.goal.depth + 1,
273 proof_tree,
274 Some((normalizes_to_term_hack, nested_goals_result)),
275 source,
276 )
277 }
278 _ => {
279 let proof_tree =
285 infcx.probe(|_| infcx.evaluate_root_goal_for_proof_tree(goal, span).1);
286 InspectGoal::new(infcx, self.goal.depth + 1, proof_tree, None, source)
287 }
288 }
289 }
290
291 pub fn visit_nested_in_probe<V: ProofTreeVisitor<'tcx>>(&self, visitor: &mut V) -> V::Result {
294 self.goal.infcx.probe(|_| self.visit_nested_no_probe(visitor))
295 }
296}
297
298impl<'a, 'tcx> InspectGoal<'a, 'tcx> {
299 pub fn infcx(&self) -> &'a InferCtxt<'tcx> {
300 self.infcx
301 }
302
303 pub fn goal(&self) -> Goal<'tcx, ty::Predicate<'tcx>> {
304 self.goal
305 }
306
307 pub fn result(&self) -> Result<Certainty, NoSolution> {
308 self.result
309 }
310
311 pub fn source(&self) -> GoalSource {
312 self.source
313 }
314
315 pub fn depth(&self) -> usize {
316 self.depth
317 }
318
319 fn candidates_recur(
320 &'a self,
321 candidates: &mut Vec<InspectCandidate<'a, 'tcx>>,
322 steps: &mut Vec<&'a inspect::ProbeStep<TyCtxt<'tcx>>>,
323 probe: &'a inspect::Probe<TyCtxt<'tcx>>,
324 ) {
325 let mut shallow_certainty = None;
326 for step in &probe.steps {
327 match *step {
328 inspect::ProbeStep::AddGoal(..) | inspect::ProbeStep::RecordImplArgs { .. } => {
329 steps.push(step)
330 }
331 inspect::ProbeStep::MakeCanonicalResponse { shallow_certainty: c } => {
332 match shallow_certainty.replace(c) {
None | Some(Certainty::Maybe { cause: MaybeCause::Ambiguity, .. }) => {}
ref left_val => {
::core::panicking::assert_matches_failed(left_val,
"None | Some(Certainty::Maybe { cause: MaybeCause::Ambiguity, .. })",
::core::option::Option::None);
}
};assert_matches!(
333 shallow_certainty.replace(c),
334 None | Some(Certainty::Maybe { cause: MaybeCause::Ambiguity, .. })
335 );
336 }
337 inspect::ProbeStep::NestedProbe(ref probe) => {
338 match probe.kind {
339 inspect::ProbeKind::ProjectionCompatibility
341 | inspect::ProbeKind::ShadowedEnvProbing => continue,
342
343 inspect::ProbeKind::NormalizedSelfTyAssembly
344 | inspect::ProbeKind::UnsizeAssembly
345 | inspect::ProbeKind::Root { .. }
346 | inspect::ProbeKind::TraitCandidate { .. }
347 | inspect::ProbeKind::OpaqueTypeStorageLookup { .. }
348 | inspect::ProbeKind::RigidAlias { .. } => {
349 let num_steps = steps.len();
353 self.candidates_recur(candidates, steps, probe);
354 steps.truncate(num_steps);
355 }
356 }
357 }
358 }
359 }
360
361 match probe.kind {
362 inspect::ProbeKind::ProjectionCompatibility
363 | inspect::ProbeKind::ShadowedEnvProbing => {
364 ::rustc_middle::util::bug::bug_fmt(format_args!("impossible case reached"))bug!()
365 }
366
367 inspect::ProbeKind::NormalizedSelfTyAssembly | inspect::ProbeKind::UnsizeAssembly => {}
368
369 inspect::ProbeKind::Root { result }
372 | inspect::ProbeKind::TraitCandidate { source: _, result }
373 | inspect::ProbeKind::OpaqueTypeStorageLookup { result }
374 | inspect::ProbeKind::RigidAlias { result } => {
375 if let Some(shallow_certainty) = shallow_certainty {
378 candidates.push(InspectCandidate {
379 goal: self,
380 kind: probe.kind,
381 steps: steps.clone(),
382 final_state: probe.final_state,
383 shallow_certainty,
384 result,
385 });
386 }
387 }
388 }
389 }
390
391 pub fn candidates(&'a self) -> Vec<InspectCandidate<'a, 'tcx>> {
392 let mut candidates = ::alloc::vec::Vec::new()vec![];
393 let mut nested_goals = ::alloc::vec::Vec::new()vec![];
394 self.candidates_recur(&mut candidates, &mut nested_goals, &self.final_revision);
395 candidates
396 }
397
398 pub fn unique_applicable_candidate(&'a self) -> Option<InspectCandidate<'a, 'tcx>> {
402 let mut candidates = self.candidates();
405 candidates.retain(|c| c.result().is_ok());
406 candidates.pop().filter(|_| candidates.is_empty())
407 }
408
409 fn new(
410 infcx: &'a InferCtxt<'tcx>,
411 depth: usize,
412 root: inspect::GoalEvaluation<TyCtxt<'tcx>>,
413 term_hack_and_nested_certainty: Option<(
414 NormalizesToTermHack<'tcx>,
415 Result<Certainty, NoSolution>,
416 )>,
417 source: GoalSource,
418 ) -> Self {
419 let infcx = <&SolverDelegate<'tcx>>::from(infcx);
420
421 let inspect::GoalEvaluation { uncanonicalized_goal, orig_values, final_revision, result } =
422 root;
423 let result = result.and_then(|ok| {
426 let nested_goals_certainty =
427 term_hack_and_nested_certainty.map_or(Ok(Certainty::Yes), |(_, c)| c)?;
428 Ok(ok.value.certainty.and(nested_goals_certainty))
429 });
430
431 InspectGoal {
432 infcx,
433 depth,
434 orig_values,
435 goal: eager_resolve_vars(infcx, uncanonicalized_goal),
436 result,
437 final_revision,
438 normalizes_to_term_hack: term_hack_and_nested_certainty.map(|(n, _)| n),
439 source,
440 }
441 }
442
443 pub(crate) fn visit_with<V: ProofTreeVisitor<'tcx>>(&self, visitor: &mut V) -> V::Result {
444 if self.depth < visitor.config().max_depth {
445 match ::rustc_ast_ir::visit::VisitorResult::branch(visitor.visit_goal(self)) {
core::ops::ControlFlow::Continue(()) =>
(),
#[allow(unreachable_code)]
core::ops::ControlFlow::Break(r) => {
return ::rustc_ast_ir::visit::VisitorResult::from_residual(r);
}
};try_visit!(visitor.visit_goal(self));
446 }
447
448 V::Result::output()
449 }
450}
451
452pub trait ProofTreeVisitor<'tcx> {
454 type Result: VisitorResult = ();
455
456 fn span(&self) -> Span;
457
458 fn config(&self) -> InspectConfig {
459 InspectConfig { max_depth: 10 }
460 }
461
462 fn visit_goal(&mut self, goal: &InspectGoal<'_, 'tcx>) -> Self::Result;
463}
464
465impl<'tcx> InferCtxtProofTreeExt<'tcx> for InferCtxt<'tcx> {
fn visit_proof_tree<V: ProofTreeVisitor<'tcx>>(&self,
goal: Goal<'tcx, ty::Predicate<'tcx>>, visitor: &mut V) -> V::Result {
self.visit_proof_tree_at_depth(goal, 0, visitor)
}
fn visit_proof_tree_at_depth<V: ProofTreeVisitor<'tcx>>(&self,
goal: Goal<'tcx, ty::Predicate<'tcx>>, depth: usize, visitor: &mut V)
-> V::Result {
let (_, proof_tree) =
<&SolverDelegate<'tcx>>::from(self).evaluate_root_goal_for_proof_tree(goal,
visitor.span());
visitor.visit_goal(&InspectGoal::new(self, depth, proof_tree, None,
GoalSource::Misc))
}
}#[extension(pub trait InferCtxtProofTreeExt<'tcx>)]
466impl<'tcx> InferCtxt<'tcx> {
467 fn visit_proof_tree<V: ProofTreeVisitor<'tcx>>(
468 &self,
469 goal: Goal<'tcx, ty::Predicate<'tcx>>,
470 visitor: &mut V,
471 ) -> V::Result {
472 self.visit_proof_tree_at_depth(goal, 0, visitor)
473 }
474
475 fn visit_proof_tree_at_depth<V: ProofTreeVisitor<'tcx>>(
476 &self,
477 goal: Goal<'tcx, ty::Predicate<'tcx>>,
478 depth: usize,
479 visitor: &mut V,
480 ) -> V::Result {
481 let (_, proof_tree) = <&SolverDelegate<'tcx>>::from(self)
482 .evaluate_root_goal_for_proof_tree(goal, visitor.span());
483 visitor.visit_goal(&InspectGoal::new(self, depth, proof_tree, None, GoalSource::Misc))
484 }
485}