rustc_next_trait_solver/canonical/
mod.rs1use std::iter;
13
14use canonicalizer::Canonicalizer;
15use rustc_index::IndexVec;
16use rustc_type_ir::inherent::*;
17use rustc_type_ir::relate::solver_relating::RelateExt;
18use rustc_type_ir::{
19 self as ty, Canonical, CanonicalVarKind, CanonicalVarValues, InferCtxtLike, Interner,
20 TypeFoldable,
21};
22use tracing::instrument;
23
24use crate::delegate::SolverDelegate;
25use crate::resolve::eager_resolve_vars;
26use crate::solve::{
27 CanonicalInput, CanonicalResponse, Certainty, ExternalConstraintsData, Goal,
28 NestedNormalizationGoals, PredefinedOpaquesData, QueryInput, Response, inspect,
29};
30
31pub mod canonicalizer;
32
33trait ResponseT<I: Interner> {
34 fn var_values(&self) -> CanonicalVarValues<I>;
35}
36
37impl<I: Interner> ResponseT<I> for Response<I> {
38 fn var_values(&self) -> CanonicalVarValues<I> {
39 self.var_values
40 }
41}
42
43impl<I: Interner, T> ResponseT<I> for inspect::State<I, T> {
44 fn var_values(&self) -> CanonicalVarValues<I> {
45 self.var_values
46 }
47}
48
49pub(super) fn canonicalize_goal<D, I>(
54 delegate: &D,
55 goal: Goal<I, I::Predicate>,
56 opaque_types: Vec<(ty::OpaqueTypeKey<I>, I::Ty)>,
57) -> (Vec<I::GenericArg>, CanonicalInput<I, I::Predicate>)
58where
59 D: SolverDelegate<Interner = I>,
60 I: Interner,
61{
62 let mut orig_values = Default::default();
63 let canonical = Canonicalizer::canonicalize_input(
64 delegate,
65 &mut orig_values,
66 QueryInput {
67 goal,
68 predefined_opaques_in_body: delegate
69 .cx()
70 .mk_predefined_opaques_in_body(PredefinedOpaquesData { opaque_types }),
71 },
72 );
73 let query_input = ty::CanonicalQueryInput { canonical, typing_mode: delegate.typing_mode() };
74 (orig_values, query_input)
75}
76
77pub(super) fn canonicalize_response<D, I, T>(
78 delegate: &D,
79 max_input_universe: ty::UniverseIndex,
80 value: T,
81) -> ty::Canonical<I, T>
82where
83 D: SolverDelegate<Interner = I>,
84 I: Interner,
85 T: TypeFoldable<I>,
86{
87 let mut orig_values = Default::default();
88 let canonical =
89 Canonicalizer::canonicalize_response(delegate, max_input_universe, &mut orig_values, value);
90 canonical
91}
92
93pub(super) fn instantiate_and_apply_query_response<D, I>(
102 delegate: &D,
103 param_env: I::ParamEnv,
104 original_values: &[I::GenericArg],
105 response: CanonicalResponse<I>,
106 span: I::Span,
107) -> (NestedNormalizationGoals<I>, Certainty)
108where
109 D: SolverDelegate<Interner = I>,
110 I: Interner,
111{
112 let instantiation =
113 compute_query_response_instantiation_values(delegate, &original_values, &response, span);
114
115 let Response { var_values, external_constraints, certainty } =
116 delegate.instantiate_canonical(response, instantiation);
117
118 unify_query_var_values(delegate, param_env, &original_values, var_values, span);
119
120 let ExternalConstraintsData { region_constraints, opaque_types, normalization_nested_goals } =
121 &*external_constraints;
122
123 register_region_constraints(delegate, region_constraints, span);
124 register_new_opaque_types(delegate, opaque_types, span);
125
126 (normalization_nested_goals.clone(), certainty)
127}
128
129fn compute_query_response_instantiation_values<D, I, T>(
133 delegate: &D,
134 original_values: &[I::GenericArg],
135 response: &Canonical<I, T>,
136 span: I::Span,
137) -> CanonicalVarValues<I>
138where
139 D: SolverDelegate<Interner = I>,
140 I: Interner,
141 T: ResponseT<I>,
142{
143 let prev_universe = delegate.universe();
147 let universes_created_in_query = response.max_universe.index();
148 for _ in 0..universes_created_in_query {
149 delegate.create_next_universe();
150 }
151
152 let var_values = response.value.var_values();
153 assert_eq!(original_values.len(), var_values.len());
154
155 let mut opt_values = IndexVec::from_elem_n(None, response.variables.len());
163 for (original_value, result_value) in iter::zip(original_values, var_values.var_values.iter()) {
164 match result_value.kind() {
165 ty::GenericArgKind::Type(t) => {
166 if let ty::Bound(debruijn, b) = t.kind()
171 && !matches!(
172 response.variables.get(b.var().as_usize()).unwrap(),
173 CanonicalVarKind::Ty { .. }
174 )
175 {
176 assert_eq!(debruijn, ty::INNERMOST);
177 opt_values[b.var()] = Some(*original_value);
178 }
179 }
180 ty::GenericArgKind::Lifetime(r) => {
181 if let ty::ReBound(debruijn, br) = r.kind() {
182 assert_eq!(debruijn, ty::INNERMOST);
183 opt_values[br.var()] = Some(*original_value);
184 }
185 }
186 ty::GenericArgKind::Const(c) => {
187 if let ty::ConstKind::Bound(debruijn, bv) = c.kind() {
188 assert_eq!(debruijn, ty::INNERMOST);
189 opt_values[bv.var()] = Some(*original_value);
190 }
191 }
192 }
193 }
194 CanonicalVarValues::instantiate(delegate.cx(), response.variables, |var_values, kind| {
195 if kind.universe() != ty::UniverseIndex::ROOT {
196 delegate.instantiate_canonical_var(kind, span, &var_values, |idx| {
200 prev_universe + idx.index()
201 })
202 } else if kind.is_existential() {
203 if let Some(v) = opt_values[ty::BoundVar::from_usize(var_values.len())] {
211 v
212 } else {
213 delegate.instantiate_canonical_var(kind, span, &var_values, |_| prev_universe)
214 }
215 } else {
216 original_values[kind.expect_placeholder_index()]
219 }
220 })
221}
222
223#[instrument(level = "trace", skip(delegate))]
236fn unify_query_var_values<D, I>(
237 delegate: &D,
238 param_env: I::ParamEnv,
239 original_values: &[I::GenericArg],
240 var_values: CanonicalVarValues<I>,
241 span: I::Span,
242) where
243 D: SolverDelegate<Interner = I>,
244 I: Interner,
245{
246 assert_eq!(original_values.len(), var_values.len());
247
248 for (&orig, response) in iter::zip(original_values, var_values.var_values.iter()) {
249 let goals =
250 delegate.eq_structurally_relating_aliases(param_env, orig, response, span).unwrap();
251 assert!(goals.is_empty());
252 }
253}
254
255fn register_region_constraints<D, I>(
256 delegate: &D,
257 outlives: &[ty::OutlivesPredicate<I, I::GenericArg>],
258 span: I::Span,
259) where
260 D: SolverDelegate<Interner = I>,
261 I: Interner,
262{
263 for &ty::OutlivesPredicate(lhs, rhs) in outlives {
264 match lhs.kind() {
265 ty::GenericArgKind::Lifetime(lhs) => delegate.sub_regions(rhs, lhs, span),
266 ty::GenericArgKind::Type(lhs) => delegate.register_ty_outlives(lhs, rhs, span),
267 ty::GenericArgKind::Const(_) => panic!("const outlives: {lhs:?}: {rhs:?}"),
268 }
269 }
270}
271
272fn register_new_opaque_types<D, I>(
273 delegate: &D,
274 opaque_types: &[(ty::OpaqueTypeKey<I>, I::Ty)],
275 span: I::Span,
276) where
277 D: SolverDelegate<Interner = I>,
278 I: Interner,
279{
280 for &(key, ty) in opaque_types {
281 let prev = delegate.register_hidden_type_in_storage(key, ty, span);
282 if let Some(prev) = prev {
290 delegate.add_duplicate_opaque_type(key, prev, span);
291 }
292 }
293}
294
295pub fn make_canonical_state<D, I, T>(
300 delegate: &D,
301 var_values: &[I::GenericArg],
302 max_input_universe: ty::UniverseIndex,
303 data: T,
304) -> inspect::CanonicalState<I, T>
305where
306 D: SolverDelegate<Interner = I>,
307 I: Interner,
308 T: TypeFoldable<I>,
309{
310 let var_values = CanonicalVarValues { var_values: delegate.cx().mk_args(var_values) };
311 let state = inspect::State { var_values, data };
312 let state = eager_resolve_vars(delegate, state);
313 Canonicalizer::canonicalize_response(delegate, max_input_universe, &mut vec![], state)
314}
315
316pub fn instantiate_canonical_state<D, I, T>(
319 delegate: &D,
320 span: I::Span,
321 param_env: I::ParamEnv,
322 orig_values: &mut Vec<I::GenericArg>,
323 state: inspect::CanonicalState<I, T>,
324) -> T
325where
326 D: SolverDelegate<Interner = I>,
327 I: Interner,
328 T: TypeFoldable<I>,
329{
330 orig_values.extend(
333 state.value.var_values.var_values.as_slice()[orig_values.len()..]
334 .iter()
335 .map(|&arg| delegate.fresh_var_for_kind_with_span(arg, span)),
336 );
337
338 let instantiation =
339 compute_query_response_instantiation_values(delegate, orig_values, &state, span);
340
341 let inspect::State { var_values, data } = delegate.instantiate_canonical(state, instantiation);
342
343 unify_query_var_values(delegate, param_env, orig_values, var_values, span);
344 data
345}
346
347pub fn response_no_constraints_raw<I: Interner>(
348 cx: I,
349 max_universe: ty::UniverseIndex,
350 variables: I::CanonicalVarKinds,
351 certainty: Certainty,
352) -> CanonicalResponse<I> {
353 ty::Canonical {
354 max_universe,
355 variables,
356 value: Response {
357 var_values: ty::CanonicalVarValues::make_identity(cx, variables),
358 external_constraints: cx.mk_external_constraints(ExternalConstraintsData::default()),
361 certainty,
362 },
363 }
364}