rustc_next_trait_solver/solve/
search_graph.rs1use std::convert::Infallible;
2use std::marker::PhantomData;
3
4use rustc_type_ir::search_graph::{self, PathKind};
5use rustc_type_ir::solve::{AccessedOpaques, Certainty, NoSolution, QueryResult, RerunResultExt};
6use rustc_type_ir::{Interner, MayBeErased, TypingMode};
7
8use crate::canonical::response_no_constraints_raw;
9use crate::delegate::SolverDelegate;
10use crate::solve::{
11 EvalCtxt, FIXPOINT_STEP_LIMIT, has_no_inference_or_external_constraints, inspect,
12};
13
14pub(super) struct SearchGraphDelegate<D: SolverDelegate> {
17 _marker: PhantomData<D>,
18}
19pub(super) type SearchGraph<D> = search_graph::SearchGraph<SearchGraphDelegate<D>>;
20impl<D, I> search_graph::Delegate for SearchGraphDelegate<D>
21where
22 D: SolverDelegate<Interner = I>,
23 I: Interner,
24{
25 type Cx = D::Interner;
26
27 const ENABLE_PROVISIONAL_CACHE: bool = true;
28 type ValidationScope = Infallible;
29 fn enter_validation_scope(
30 _cx: Self::Cx,
31 _input: I::CanonicalInput,
32 ) -> Option<Self::ValidationScope> {
33 None
34 }
35
36 const FIXPOINT_STEP_LIMIT: usize = FIXPOINT_STEP_LIMIT;
37
38 type ProofTreeBuilder = inspect::ProofTreeBuilder<D>;
39 fn inspect_is_noop(inspect: &mut Self::ProofTreeBuilder) -> bool {
40 inspect.is_noop()
41 }
42
43 const DIVIDE_AVAILABLE_DEPTH_ON_OVERFLOW: usize = 4;
44
45 fn initial_provisional_result(
46 cx: I,
47 kind: PathKind,
48 input: I::CanonicalInput,
49 ) -> (QueryResult<I>, AccessedOpaques<I>) {
50 match kind {
51 PathKind::Coinductive => response_no_constraints(cx, input, Certainty::Yes),
52 PathKind::Unknown | PathKind::ForcedAmbiguity => {
53 response_no_constraints(cx, input, Certainty::overflow(false))
54 }
55 PathKind::Inductive => match input.typing_mode.0 {
65 TypingMode::Coherence => {
66 response_no_constraints(cx, input, Certainty::overflow(false))
67 }
68 TypingMode::Typeck { .. }
69 | TypingMode::PostTypeckUntilBorrowck { .. }
70 | TypingMode::Reflection
71 | TypingMode::PostBorrowck { .. }
72 | TypingMode::PostAnalysis
73 | TypingMode::Codegen
74 | TypingMode::ErasedNotCoherence(MayBeErased) => {
75 (Err(NoSolution), AccessedOpaques::default())
76 }
77 },
78 }
79 }
80
81 fn is_initial_provisional_result(
82 result: (QueryResult<I>, AccessedOpaques<I>),
83 ) -> Option<PathKind> {
84 match result.0 {
85 Ok(response) => {
86 if has_no_inference_or_external_constraints(response) {
87 if response.value.certainty == Certainty::Yes {
88 return Some(PathKind::Coinductive);
89 } else if response.value.certainty == Certainty::overflow(false) {
90 return Some(PathKind::Unknown);
91 }
92 }
93
94 None
95 }
96 Err(NoSolution) => Some(PathKind::Inductive),
97 }
98 }
99
100 fn stack_overflow_result(
101 cx: I,
102 input: I::CanonicalInput,
103 ) -> (QueryResult<I>, AccessedOpaques<I>) {
104 response_no_constraints(cx, input, Certainty::overflow(true))
105 }
106
107 const FIXPOINT_OVERFLOW_AMBIGUITY_KIND: Certainty = Certainty::overflow(false);
108 fn fixpoint_overflow_result(
109 cx: I,
110 input: I::CanonicalInput,
111 ) -> (QueryResult<I>, AccessedOpaques<I>) {
112 response_no_constraints(cx, input, Certainty::overflow(false))
113 }
114
115 fn is_ambiguous_result(result: (QueryResult<I>, AccessedOpaques<I>)) -> Option<Certainty> {
116 result.0.ok().and_then(|response| {
117 if has_no_inference_or_external_constraints(response)
118 && #[allow(non_exhaustive_omitted_patterns)] match response.value.certainty {
Certainty::Maybe { .. } => true,
_ => false,
}matches!(response.value.certainty, Certainty::Maybe { .. })
119 {
120 Some(response.value.certainty)
121 } else {
122 None
123 }
124 })
125 }
126
127 fn compute_goal(
128 search_graph: &mut SearchGraph<D>,
129 cx: I,
130 input: I::CanonicalInput,
131 inspect: &mut Self::ProofTreeBuilder,
132 ) -> (QueryResult<I>, AccessedOpaques<I>) {
133 EvalCtxt::enter_canonical(cx, search_graph, input, inspect, |ecx, goal| {
134 let result = ecx.compute_goal(goal).map_err_to_rerun()?;
136
137 ecx.inspect.query_result(result);
138 result.map_err(Into::into)
139 })
140 }
141}
142
143fn response_no_constraints<I: Interner>(
144 cx: I,
145 input: I::CanonicalInput,
146 certainty: Certainty,
147) -> (QueryResult<I>, AccessedOpaques<I>) {
148 (
149 Ok(response_no_constraints_raw(
150 cx,
151 input.canonical.max_universe,
152 input.canonical.var_kinds,
153 certainty,
154 )),
155 AccessedOpaques::default(),
156 )
157}