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, Goal, GoalSource, GoalStalledOn, NoSolution,
11 QueryResult, inspect,
12};
13
14pub(in crate::solve) struct ProbeCtxt<'me, 'a, D, I, F, T>
15where
16 D: SolverDelegate<Interner = I>,
17 I: Interner,
18{
19 ecx: &'me mut EvalCtxt<'a, D, I>,
20 probe_kind: F,
21 _result: PhantomData<T>,
22}
23
24impl<D, I, F, T> ProbeCtxt<'_, '_, D, I, F, T>
25where
26 F: FnOnce(&T) -> inspect::ProbeKind<I>,
27 D: SolverDelegate<Interner = I>,
28 I: Interner,
29{
30 pub(in crate::solve) fn enter_single_candidate(
31 self,
32 f: impl FnOnce(&mut EvalCtxt<'_, D>) -> T,
33 ) -> (T, CandidateHeadUsages) {
34 self.ecx.search_graph.enter_single_candidate();
35 let mut candidate_usages = CandidateHeadUsages::default();
36 let result = self.enter(|ecx| {
37 let result = f(ecx);
38 candidate_usages = ecx.search_graph.finish_single_candidate();
39 result
40 });
41 (result, candidate_usages)
42 }
43
44 pub(in crate::solve) fn enter(self, f: impl FnOnce(&mut EvalCtxt<'_, D>) -> T) -> T {
45 let nested_goals = self.ecx.nested_goals.clone();
46 self.enter_inner(f, nested_goals)
47 }
48
49 pub(in crate::solve) fn enter_without_propagated_nested_goals(
50 self,
51 f: impl FnOnce(&mut EvalCtxt<'_, D>) -> T,
52 ) -> T {
53 self.enter_inner(f, Default::default())
54 }
55
56 fn enter_inner(
57 self,
58 f: impl FnOnce(&mut EvalCtxt<'_, D>) -> T,
59 propagated_nested_goals: Vec<(GoalSource, Goal<I, I::Predicate>, Option<GoalStalledOn<I>>)>,
60 ) -> T {
61 let ProbeCtxt { ecx: outer, probe_kind, _result } = self;
62
63 let delegate = outer.delegate;
64 let max_input_universe = outer.max_input_universe;
65 let mut nested = EvalCtxt {
66 delegate,
67 var_kinds: outer.var_kinds,
68 var_values: outer.var_values,
69 current_goal_kind: outer.current_goal_kind,
70 max_input_universe,
71 initial_opaque_types_storage_num_entries: outer
72 .initial_opaque_types_storage_num_entries,
73 search_graph: outer.search_graph,
74 nested_goals: propagated_nested_goals,
75 origin_span: outer.origin_span,
76 tainted: outer.tainted,
77 inspect: outer.inspect.take_and_enter_probe(),
78 };
79 let r = nested.delegate.probe(|| {
80 let r = f(&mut nested);
81 nested.inspect.probe_final_state(delegate, max_input_universe);
82 r
83 });
84 if !nested.inspect.is_noop() {
85 let probe_kind = probe_kind(&r);
86 nested.inspect.probe_kind(probe_kind);
87 outer.inspect = nested.inspect.finish_probe();
88 }
89 r
90 }
91}
92
93pub(in crate::solve) struct TraitProbeCtxt<'me, 'a, D, I, F>
94where
95 D: SolverDelegate<Interner = I>,
96 I: Interner,
97{
98 cx: ProbeCtxt<'me, 'a, D, I, F, QueryResult<I>>,
99 source: CandidateSource<I>,
100}
101
102impl<D, I, F> TraitProbeCtxt<'_, '_, D, I, F>
103where
104 D: SolverDelegate<Interner = I>,
105 I: Interner,
106 F: FnOnce(&QueryResult<I>) -> inspect::ProbeKind<I>,
107{
108 #[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("enter",
"rustc_next_trait_solver::solve::eval_ctxt::probe",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_next_trait_solver/src/solve/eval_ctxt/probe.rs"),
::tracing_core::__macro_support::Option::Some(108u32),
::tracing_core::__macro_support::Option::Some("rustc_next_trait_solver::solve::eval_ctxt::probe"),
::tracing_core::field::FieldSet::new(&["source"],
::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.source)
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: Result<Candidate<I>, NoSolution> =
loop {};
return __tracing_attr_fake_return;
}
{
let (result, head_usages) = self.cx.enter_single_candidate(f);
result.map(|result|
Candidate { source: self.source, result, head_usages })
}
}
}#[instrument(level = "debug", skip_all, fields(source = ?self.source))]
109 pub(in crate::solve) fn enter(
110 self,
111 f: impl FnOnce(&mut EvalCtxt<'_, D>) -> QueryResult<I>,
112 ) -> Result<Candidate<I>, NoSolution> {
113 let (result, head_usages) = self.cx.enter_single_candidate(f);
114 result.map(|result| Candidate { source: self.source, result, head_usages })
115 }
116}
117
118impl<'a, D, I> EvalCtxt<'a, D, I>
119where
120 D: SolverDelegate<Interner = I>,
121 I: Interner,
122{
123 pub(in crate::solve) fn probe<F, T>(&mut self, probe_kind: F) -> ProbeCtxt<'_, 'a, D, I, F, T>
126 where
127 F: FnOnce(&T) -> inspect::ProbeKind<I>,
128 {
129 ProbeCtxt { ecx: self, probe_kind, _result: PhantomData }
130 }
131
132 pub(in crate::solve) fn probe_builtin_trait_candidate(
133 &mut self,
134 source: BuiltinImplSource,
135 ) -> TraitProbeCtxt<'_, 'a, D, I, impl FnOnce(&QueryResult<I>) -> inspect::ProbeKind<I>> {
136 self.probe_trait_candidate(CandidateSource::BuiltinImpl(source))
137 }
138
139 pub(in crate::solve) fn probe_trait_candidate(
140 &mut self,
141 source: CandidateSource<I>,
142 ) -> TraitProbeCtxt<'_, 'a, D, I, impl FnOnce(&QueryResult<I>) -> inspect::ProbeKind<I>> {
143 TraitProbeCtxt {
144 cx: ProbeCtxt {
145 ecx: self,
146 probe_kind: move |result: &QueryResult<I>| inspect::ProbeKind::TraitCandidate {
147 source,
148 result: *result,
149 },
150 _result: PhantomData,
151 },
152 source,
153 }
154 }
155}