rustc_infer/infer/canonical/
query_response.rs

1//! This module contains the code to instantiate a "query result", and
2//! in particular to extract out the resulting region obligations and
3//! encode them therein.
4//!
5//! For an overview of what canonicalization is and how it fits into
6//! rustc, check out the [chapter in the rustc dev guide][c].
7//!
8//! [c]: https://rust-lang.github.io/chalk/book/canonical_queries/canonicalization.html
9
10use std::fmt::Debug;
11use std::iter;
12
13use rustc_index::{Idx, IndexVec};
14use rustc_middle::arena::ArenaAllocatable;
15use rustc_middle::mir::ConstraintCategory;
16use rustc_middle::ty::{self, BoundVar, GenericArg, GenericArgKind, Ty, TyCtxt, TypeFoldable};
17use rustc_middle::{bug, span_bug};
18use tracing::{debug, instrument};
19
20use crate::infer::canonical::instantiate::{CanonicalExt, instantiate_value};
21use crate::infer::canonical::{
22    Canonical, CanonicalQueryResponse, CanonicalVarValues, Certainty, OriginalQueryValues,
23    QueryOutlivesConstraint, QueryRegionConstraints, QueryResponse,
24};
25use crate::infer::region_constraints::{Constraint, RegionConstraintData};
26use crate::infer::{DefineOpaqueTypes, InferCtxt, InferOk, InferResult};
27use crate::traits::query::NoSolution;
28use crate::traits::{
29    Obligation, ObligationCause, PredicateObligation, PredicateObligations, ScrubbedTraitError,
30    TraitEngine,
31};
32
33impl<'tcx> InferCtxt<'tcx> {
34    /// This method is meant to be invoked as the final step of a canonical query
35    /// implementation. It is given:
36    ///
37    /// - the instantiated variables `inference_vars` created from the query key
38    /// - the result `answer` of the query
39    /// - a fulfillment context `fulfill_cx` that may contain various obligations which
40    ///   have yet to be proven.
41    ///
42    /// Given this, the function will process the obligations pending
43    /// in `fulfill_cx`:
44    ///
45    /// - If all the obligations can be proven successfully, it will
46    ///   package up any resulting region obligations (extracted from
47    ///   `infcx`) along with the fully resolved value `answer` into a
48    ///   query result (which is then itself canonicalized).
49    /// - If some obligations can be neither proven nor disproven, then
50    ///   the same thing happens, but the resulting query is marked as ambiguous.
51    /// - Finally, if any of the obligations result in a hard error,
52    ///   then `Err(NoSolution)` is returned.
53    #[instrument(skip(self, inference_vars, answer, fulfill_cx), level = "trace")]
54    pub fn make_canonicalized_query_response<T>(
55        &self,
56        inference_vars: CanonicalVarValues<'tcx>,
57        answer: T,
58        fulfill_cx: &mut dyn TraitEngine<'tcx, ScrubbedTraitError<'tcx>>,
59    ) -> Result<CanonicalQueryResponse<'tcx, T>, NoSolution>
60    where
61        T: Debug + TypeFoldable<TyCtxt<'tcx>>,
62        Canonical<'tcx, QueryResponse<'tcx, T>>: ArenaAllocatable<'tcx>,
63    {
64        let query_response = self.make_query_response(inference_vars, answer, fulfill_cx)?;
65        debug!("query_response = {:#?}", query_response);
66        let canonical_result = self.canonicalize_response(query_response);
67        debug!("canonical_result = {:#?}", canonical_result);
68
69        Ok(self.tcx.arena.alloc(canonical_result))
70    }
71
72    /// A version of `make_canonicalized_query_response` that does
73    /// not pack in obligations, for contexts that want to drop
74    /// pending obligations instead of treating them as an ambiguity (e.g.
75    /// typeck "probing" contexts).
76    ///
77    /// If you DO want to keep track of pending obligations (which
78    /// include all region obligations, so this includes all cases
79    /// that care about regions) with this function, you have to
80    /// do it yourself, by e.g., having them be a part of the answer.
81    pub fn make_query_response_ignoring_pending_obligations<T>(
82        &self,
83        inference_vars: CanonicalVarValues<'tcx>,
84        answer: T,
85    ) -> Canonical<'tcx, QueryResponse<'tcx, T>>
86    where
87        T: Debug + TypeFoldable<TyCtxt<'tcx>>,
88    {
89        self.canonicalize_response(QueryResponse {
90            var_values: inference_vars,
91            region_constraints: QueryRegionConstraints::default(),
92            certainty: Certainty::Proven, // Ambiguities are OK!
93            opaque_types: vec![],
94            value: answer,
95        })
96    }
97
98    /// Helper for `make_canonicalized_query_response` that does
99    /// everything up until the final canonicalization.
100    #[instrument(skip(self, fulfill_cx), level = "debug")]
101    fn make_query_response<T>(
102        &self,
103        inference_vars: CanonicalVarValues<'tcx>,
104        answer: T,
105        fulfill_cx: &mut dyn TraitEngine<'tcx, ScrubbedTraitError<'tcx>>,
106    ) -> Result<QueryResponse<'tcx, T>, NoSolution>
107    where
108        T: Debug + TypeFoldable<TyCtxt<'tcx>>,
109    {
110        let tcx = self.tcx;
111
112        // Select everything, returning errors.
113        let errors = fulfill_cx.select_all_or_error(self);
114
115        // True error!
116        if errors.iter().any(|e| e.is_true_error()) {
117            return Err(NoSolution);
118        }
119
120        let region_obligations = self.take_registered_region_obligations();
121        debug!(?region_obligations);
122        let region_constraints = self.with_region_constraints(|region_constraints| {
123            make_query_region_constraints(
124                tcx,
125                region_obligations
126                    .iter()
127                    .map(|r_o| (r_o.sup_type, r_o.sub_region, r_o.origin.to_constraint_category())),
128                region_constraints,
129            )
130        });
131        debug!(?region_constraints);
132
133        let certainty = if errors.is_empty() { Certainty::Proven } else { Certainty::Ambiguous };
134
135        let opaque_types = self.take_opaque_types_for_query_response();
136
137        Ok(QueryResponse {
138            var_values: inference_vars,
139            region_constraints,
140            certainty,
141            value: answer,
142            opaque_types,
143        })
144    }
145
146    /// Used by the new solver as that one takes the opaque types at the end of a probe
147    /// to deal with multiple candidates without having to recompute them.
148    pub fn clone_opaque_types_for_query_response(
149        &self,
150    ) -> Vec<(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)> {
151        self.inner
152            .borrow()
153            .opaque_type_storage
154            .opaque_types
155            .iter()
156            .map(|(k, v)| (*k, v.ty))
157            .collect()
158    }
159
160    fn take_opaque_types_for_query_response(&self) -> Vec<(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)> {
161        self.take_opaque_types().into_iter().map(|(k, v)| (k, v.ty)).collect()
162    }
163
164    /// Given the (canonicalized) result to a canonical query,
165    /// instantiates the result so it can be used, plugging in the
166    /// values from the canonical query. (Note that the result may
167    /// have been ambiguous; you should check the certainty level of
168    /// the query before applying this function.)
169    ///
170    /// To get a good understanding of what is happening here, check
171    /// out the [chapter in the rustc dev guide][c].
172    ///
173    /// [c]: https://rust-lang.github.io/chalk/book/canonical_queries/canonicalization.html#processing-the-canonicalized-query-result
174    pub fn instantiate_query_response_and_region_obligations<R>(
175        &self,
176        cause: &ObligationCause<'tcx>,
177        param_env: ty::ParamEnv<'tcx>,
178        original_values: &OriginalQueryValues<'tcx>,
179        query_response: &Canonical<'tcx, QueryResponse<'tcx, R>>,
180    ) -> InferResult<'tcx, R>
181    where
182        R: Debug + TypeFoldable<TyCtxt<'tcx>>,
183    {
184        let InferOk { value: result_args, mut obligations } =
185            self.query_response_instantiation(cause, param_env, original_values, query_response)?;
186
187        obligations.extend(self.query_outlives_constraints_into_obligations(
188            cause,
189            param_env,
190            &query_response.value.region_constraints.outlives,
191            &result_args,
192        ));
193
194        let user_result: R =
195            query_response.instantiate_projected(self.tcx, &result_args, |q_r| q_r.value.clone());
196
197        Ok(InferOk { value: user_result, obligations })
198    }
199
200    /// An alternative to
201    /// `instantiate_query_response_and_region_obligations` that is more
202    /// efficient for NLL. NLL is a bit more advanced in the
203    /// "transition to chalk" than the rest of the compiler. During
204    /// the NLL type check, all of the "processing" of types and
205    /// things happens in queries -- the NLL checker itself is only
206    /// interested in the region obligations (`'a: 'b` or `T: 'b`)
207    /// that come out of these queries, which it wants to convert into
208    /// MIR-based constraints and solve. Therefore, it is most
209    /// convenient for the NLL Type Checker to **directly consume**
210    /// the `QueryOutlivesConstraint` values that arise from doing a
211    /// query. This is contrast to other parts of the compiler, which
212    /// would prefer for those `QueryOutlivesConstraint` to be converted
213    /// into the older infcx-style constraints (e.g., calls to
214    /// `sub_regions` or `register_region_obligation`).
215    ///
216    /// Therefore, `instantiate_nll_query_response_and_region_obligations` performs the same
217    /// basic operations as `instantiate_query_response_and_region_obligations` but
218    /// it returns its result differently:
219    ///
220    /// - It creates an instantiation `S` that maps from the original
221    ///   query variables to the values computed in the query
222    ///   result. If any errors arise, they are propagated back as an
223    ///   `Err` result.
224    /// - In the case of a successful instantiation, we will append
225    ///   `QueryOutlivesConstraint` values onto the
226    ///   `output_query_region_constraints` vector for the solver to
227    ///   use (if an error arises, some values may also be pushed, but
228    ///   they should be ignored).
229    /// - It **can happen** (though it rarely does currently) that
230    ///   equating types and things will give rise to subobligations
231    ///   that must be processed. In this case, those subobligations
232    ///   are propagated back in the return value.
233    /// - Finally, the query result (of type `R`) is propagated back,
234    ///   after applying the instantiation `S`.
235    pub fn instantiate_nll_query_response_and_region_obligations<R>(
236        &self,
237        cause: &ObligationCause<'tcx>,
238        param_env: ty::ParamEnv<'tcx>,
239        original_values: &OriginalQueryValues<'tcx>,
240        query_response: &Canonical<'tcx, QueryResponse<'tcx, R>>,
241        output_query_region_constraints: &mut QueryRegionConstraints<'tcx>,
242    ) -> InferResult<'tcx, R>
243    where
244        R: Debug + TypeFoldable<TyCtxt<'tcx>>,
245    {
246        let InferOk { value: result_args, mut obligations } = self
247            .query_response_instantiation_guess(
248                cause,
249                param_env,
250                original_values,
251                query_response,
252            )?;
253
254        // Compute `QueryOutlivesConstraint` values that unify each of
255        // the original values `v_o` that was canonicalized into a
256        // variable...
257
258        let constraint_category = cause.to_constraint_category();
259
260        for (index, original_value) in original_values.var_values.iter().enumerate() {
261            // ...with the value `v_r` of that variable from the query.
262            let result_value = query_response.instantiate_projected(self.tcx, &result_args, |v| {
263                v.var_values[BoundVar::new(index)]
264            });
265            match (original_value.unpack(), result_value.unpack()) {
266                (GenericArgKind::Lifetime(re1), GenericArgKind::Lifetime(re2))
267                    if re1.is_erased() && re2.is_erased() =>
268                {
269                    // No action needed.
270                }
271
272                (GenericArgKind::Lifetime(v_o), GenericArgKind::Lifetime(v_r)) => {
273                    // To make `v_o = v_r`, we emit `v_o: v_r` and `v_r: v_o`.
274                    if v_o != v_r {
275                        output_query_region_constraints
276                            .outlives
277                            .push((ty::OutlivesPredicate(v_o.into(), v_r), constraint_category));
278                        output_query_region_constraints
279                            .outlives
280                            .push((ty::OutlivesPredicate(v_r.into(), v_o), constraint_category));
281                    }
282                }
283
284                (GenericArgKind::Type(v1), GenericArgKind::Type(v2)) => {
285                    obligations.extend(
286                        self.at(&cause, param_env)
287                            .eq(DefineOpaqueTypes::Yes, v1, v2)?
288                            .into_obligations(),
289                    );
290                }
291
292                (GenericArgKind::Const(v1), GenericArgKind::Const(v2)) => {
293                    obligations.extend(
294                        self.at(&cause, param_env)
295                            .eq(DefineOpaqueTypes::Yes, v1, v2)?
296                            .into_obligations(),
297                    );
298                }
299
300                _ => {
301                    bug!("kind mismatch, cannot unify {:?} and {:?}", original_value, result_value);
302                }
303            }
304        }
305
306        // ...also include the other query region constraints from the query.
307        output_query_region_constraints.outlives.extend(
308            query_response.value.region_constraints.outlives.iter().filter_map(|&r_c| {
309                let r_c = instantiate_value(self.tcx, &result_args, r_c);
310
311                // Screen out `'a: 'a` cases.
312                let ty::OutlivesPredicate(k1, r2) = r_c.0;
313                if k1 != r2.into() { Some(r_c) } else { None }
314            }),
315        );
316
317        let user_result: R =
318            query_response.instantiate_projected(self.tcx, &result_args, |q_r| q_r.value.clone());
319
320        Ok(InferOk { value: user_result, obligations })
321    }
322
323    /// Given the original values and the (canonicalized) result from
324    /// computing a query, returns an instantiation that can be applied
325    /// to the query result to convert the result back into the
326    /// original namespace.
327    ///
328    /// The instantiation also comes accompanied with subobligations
329    /// that arose from unification; these might occur if (for
330    /// example) we are doing lazy normalization and the value
331    /// assigned to a type variable is unified with an unnormalized
332    /// projection.
333    fn query_response_instantiation<R>(
334        &self,
335        cause: &ObligationCause<'tcx>,
336        param_env: ty::ParamEnv<'tcx>,
337        original_values: &OriginalQueryValues<'tcx>,
338        query_response: &Canonical<'tcx, QueryResponse<'tcx, R>>,
339    ) -> InferResult<'tcx, CanonicalVarValues<'tcx>>
340    where
341        R: Debug + TypeFoldable<TyCtxt<'tcx>>,
342    {
343        debug!(
344            "query_response_instantiation(original_values={:#?}, query_response={:#?})",
345            original_values, query_response,
346        );
347
348        let mut value = self.query_response_instantiation_guess(
349            cause,
350            param_env,
351            original_values,
352            query_response,
353        )?;
354
355        value.obligations.extend(
356            self.unify_query_response_instantiation_guess(
357                cause,
358                param_env,
359                original_values,
360                &value.value,
361                query_response,
362            )?
363            .into_obligations(),
364        );
365
366        Ok(value)
367    }
368
369    /// Given the original values and the (canonicalized) result from
370    /// computing a query, returns a **guess** at an instantiation that
371    /// can be applied to the query result to convert the result back
372    /// into the original namespace. This is called a **guess**
373    /// because it uses a quick heuristic to find the values for each
374    /// canonical variable; if that quick heuristic fails, then we
375    /// will instantiate fresh inference variables for each canonical
376    /// variable instead. Therefore, the result of this method must be
377    /// properly unified
378    #[instrument(level = "debug", skip(self, param_env))]
379    fn query_response_instantiation_guess<R>(
380        &self,
381        cause: &ObligationCause<'tcx>,
382        param_env: ty::ParamEnv<'tcx>,
383        original_values: &OriginalQueryValues<'tcx>,
384        query_response: &Canonical<'tcx, QueryResponse<'tcx, R>>,
385    ) -> InferResult<'tcx, CanonicalVarValues<'tcx>>
386    where
387        R: Debug + TypeFoldable<TyCtxt<'tcx>>,
388    {
389        // For each new universe created in the query result that did
390        // not appear in the original query, create a local
391        // superuniverse.
392        let mut universe_map = original_values.universe_map.clone();
393        let num_universes_in_query = original_values.universe_map.len();
394        let num_universes_in_response = query_response.max_universe.as_usize() + 1;
395        for _ in num_universes_in_query..num_universes_in_response {
396            universe_map.push(self.create_next_universe());
397        }
398        assert!(!universe_map.is_empty()); // always have the root universe
399        assert_eq!(universe_map[ty::UniverseIndex::ROOT.as_usize()], ty::UniverseIndex::ROOT);
400
401        // Every canonical query result includes values for each of
402        // the inputs to the query. Therefore, we begin by unifying
403        // these values with the original inputs that were
404        // canonicalized.
405        let result_values = &query_response.value.var_values;
406        assert_eq!(original_values.var_values.len(), result_values.len());
407
408        // Quickly try to find initial values for the canonical
409        // variables in the result in terms of the query. We do this
410        // by iterating down the values that the query gave to each of
411        // the canonical inputs. If we find that one of those values
412        // is directly equal to one of the canonical variables in the
413        // result, then we can type the corresponding value from the
414        // input. See the example above.
415        let mut opt_values: IndexVec<BoundVar, Option<GenericArg<'tcx>>> =
416            IndexVec::from_elem_n(None, query_response.variables.len());
417
418        // In terms of our example above, we are iterating over pairs like:
419        // [(?A, Vec<?0>), ('static, '?1), (?B, ?0)]
420        for (original_value, result_value) in iter::zip(&original_values.var_values, result_values)
421        {
422            match result_value.unpack() {
423                GenericArgKind::Type(result_value) => {
424                    // e.g., here `result_value` might be `?0` in the example above...
425                    if let ty::Bound(debruijn, b) = *result_value.kind() {
426                        // ...in which case we would set `canonical_vars[0]` to `Some(?U)`.
427
428                        // We only allow a `ty::INNERMOST` index in generic parameters.
429                        assert_eq!(debruijn, ty::INNERMOST);
430                        opt_values[b.var] = Some(*original_value);
431                    }
432                }
433                GenericArgKind::Lifetime(result_value) => {
434                    // e.g., here `result_value` might be `'?1` in the example above...
435                    if let ty::ReBound(debruijn, br) = *result_value {
436                        // ... in which case we would set `canonical_vars[0]` to `Some('static)`.
437
438                        // We only allow a `ty::INNERMOST` index in generic parameters.
439                        assert_eq!(debruijn, ty::INNERMOST);
440                        opt_values[br.var] = Some(*original_value);
441                    }
442                }
443                GenericArgKind::Const(result_value) => {
444                    if let ty::ConstKind::Bound(debruijn, b) = result_value.kind() {
445                        // ...in which case we would set `canonical_vars[0]` to `Some(const X)`.
446
447                        // We only allow a `ty::INNERMOST` index in generic parameters.
448                        assert_eq!(debruijn, ty::INNERMOST);
449                        opt_values[b] = Some(*original_value);
450                    }
451                }
452            }
453        }
454
455        // Create result arguments: if we found a value for a
456        // given variable in the loop above, use that. Otherwise, use
457        // a fresh inference variable.
458        let result_args = CanonicalVarValues {
459            var_values: self.tcx.mk_args_from_iter(
460                query_response.variables.iter().enumerate().map(|(index, info)| {
461                    if info.universe() != ty::UniverseIndex::ROOT {
462                        // A variable from inside a binder of the query. While ideally these shouldn't
463                        // exist at all, we have to deal with them for now.
464                        self.instantiate_canonical_var(cause.span, info, |u| {
465                            universe_map[u.as_usize()]
466                        })
467                    } else if info.is_existential() {
468                        match opt_values[BoundVar::new(index)] {
469                            Some(k) => k,
470                            None => self.instantiate_canonical_var(cause.span, info, |u| {
471                                universe_map[u.as_usize()]
472                            }),
473                        }
474                    } else {
475                        // For placeholders which were already part of the input, we simply map this
476                        // universal bound variable back the placeholder of the input.
477                        opt_values[BoundVar::new(index)].expect(
478                            "expected placeholder to be unified with itself during response",
479                        )
480                    }
481                }),
482            ),
483        };
484
485        let mut obligations = PredicateObligations::new();
486
487        // Carry all newly resolved opaque types to the caller's scope
488        for &(a, b) in &query_response.value.opaque_types {
489            let a = instantiate_value(self.tcx, &result_args, a);
490            let b = instantiate_value(self.tcx, &result_args, b);
491            debug!(?a, ?b, "constrain opaque type");
492            // We use equate here instead of, for example, just registering the
493            // opaque type's hidden value directly, because the hidden type may have been an inference
494            // variable that got constrained to the opaque type itself. In that case we want to equate
495            // the generic args of the opaque with the generic params of its hidden type version.
496            obligations.extend(
497                self.at(cause, param_env)
498                    .eq(
499                        DefineOpaqueTypes::Yes,
500                        Ty::new_opaque(self.tcx, a.def_id.to_def_id(), a.args),
501                        b,
502                    )?
503                    .obligations,
504            );
505        }
506
507        Ok(InferOk { value: result_args, obligations })
508    }
509
510    /// Given a "guess" at the values for the canonical variables in
511    /// the input, try to unify with the *actual* values found in the
512    /// query result. Often, but not always, this is a no-op, because
513    /// we already found the mapping in the "guessing" step.
514    ///
515    /// See also: [`Self::query_response_instantiation_guess`]
516    fn unify_query_response_instantiation_guess<R>(
517        &self,
518        cause: &ObligationCause<'tcx>,
519        param_env: ty::ParamEnv<'tcx>,
520        original_values: &OriginalQueryValues<'tcx>,
521        result_args: &CanonicalVarValues<'tcx>,
522        query_response: &Canonical<'tcx, QueryResponse<'tcx, R>>,
523    ) -> InferResult<'tcx, ()>
524    where
525        R: Debug + TypeFoldable<TyCtxt<'tcx>>,
526    {
527        // A closure that yields the result value for the given
528        // canonical variable; this is taken from
529        // `query_response.var_values` after applying the instantiation
530        // by `result_args`.
531        let instantiated_query_response = |index: BoundVar| -> GenericArg<'tcx> {
532            query_response.instantiate_projected(self.tcx, result_args, |v| v.var_values[index])
533        };
534
535        // Unify the original value for each variable with the value
536        // taken from `query_response` (after applying `result_args`).
537        self.unify_canonical_vars(cause, param_env, original_values, instantiated_query_response)
538    }
539
540    /// Converts the region constraints resulting from a query into an
541    /// iterator of obligations.
542    fn query_outlives_constraints_into_obligations(
543        &self,
544        cause: &ObligationCause<'tcx>,
545        param_env: ty::ParamEnv<'tcx>,
546        uninstantiated_region_constraints: &[QueryOutlivesConstraint<'tcx>],
547        result_args: &CanonicalVarValues<'tcx>,
548    ) -> impl Iterator<Item = PredicateObligation<'tcx>> {
549        uninstantiated_region_constraints.iter().map(move |&constraint| {
550            let predicate = instantiate_value(self.tcx, result_args, constraint);
551            self.query_outlives_constraint_to_obligation(predicate, cause.clone(), param_env)
552        })
553    }
554
555    pub fn query_outlives_constraint_to_obligation(
556        &self,
557        (predicate, _): QueryOutlivesConstraint<'tcx>,
558        cause: ObligationCause<'tcx>,
559        param_env: ty::ParamEnv<'tcx>,
560    ) -> Obligation<'tcx, ty::Predicate<'tcx>> {
561        let ty::OutlivesPredicate(k1, r2) = predicate;
562
563        let atom = match k1.unpack() {
564            GenericArgKind::Lifetime(r1) => ty::PredicateKind::Clause(
565                ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(r1, r2)),
566            ),
567            GenericArgKind::Type(t1) => ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(
568                ty::OutlivesPredicate(t1, r2),
569            )),
570            GenericArgKind::Const(..) => {
571                // Consts cannot outlive one another, so we don't expect to
572                // encounter this branch.
573                span_bug!(cause.span, "unexpected const outlives {:?}", predicate);
574            }
575        };
576        let predicate = ty::Binder::dummy(atom);
577
578        Obligation::new(self.tcx, cause, param_env, predicate)
579    }
580
581    /// Given two sets of values for the same set of canonical variables, unify them.
582    /// The second set is produced lazily by supplying indices from the first set.
583    fn unify_canonical_vars(
584        &self,
585        cause: &ObligationCause<'tcx>,
586        param_env: ty::ParamEnv<'tcx>,
587        variables1: &OriginalQueryValues<'tcx>,
588        variables2: impl Fn(BoundVar) -> GenericArg<'tcx>,
589    ) -> InferResult<'tcx, ()> {
590        let mut obligations = PredicateObligations::new();
591        for (index, value1) in variables1.var_values.iter().enumerate() {
592            let value2 = variables2(BoundVar::new(index));
593
594            match (value1.unpack(), value2.unpack()) {
595                (GenericArgKind::Type(v1), GenericArgKind::Type(v2)) => {
596                    obligations.extend(
597                        self.at(cause, param_env)
598                            .eq(DefineOpaqueTypes::Yes, v1, v2)?
599                            .into_obligations(),
600                    );
601                }
602                (GenericArgKind::Lifetime(re1), GenericArgKind::Lifetime(re2))
603                    if re1.is_erased() && re2.is_erased() =>
604                {
605                    // no action needed
606                }
607                (GenericArgKind::Lifetime(v1), GenericArgKind::Lifetime(v2)) => {
608                    obligations.extend(
609                        self.at(cause, param_env)
610                            .eq(DefineOpaqueTypes::Yes, v1, v2)?
611                            .into_obligations(),
612                    );
613                }
614                (GenericArgKind::Const(v1), GenericArgKind::Const(v2)) => {
615                    let ok = self.at(cause, param_env).eq(DefineOpaqueTypes::Yes, v1, v2)?;
616                    obligations.extend(ok.into_obligations());
617                }
618                _ => {
619                    bug!("kind mismatch, cannot unify {:?} and {:?}", value1, value2,);
620                }
621            }
622        }
623        Ok(InferOk { value: (), obligations })
624    }
625}
626
627/// Given the region obligations and constraints scraped from the infcx,
628/// creates query region constraints.
629pub fn make_query_region_constraints<'tcx>(
630    tcx: TyCtxt<'tcx>,
631    outlives_obligations: impl Iterator<Item = (Ty<'tcx>, ty::Region<'tcx>, ConstraintCategory<'tcx>)>,
632    region_constraints: &RegionConstraintData<'tcx>,
633) -> QueryRegionConstraints<'tcx> {
634    let RegionConstraintData { constraints, verifys } = region_constraints;
635
636    assert!(verifys.is_empty());
637
638    debug!(?constraints);
639
640    let outlives: Vec<_> = constraints
641        .iter()
642        .map(|(k, origin)| {
643            let constraint = match *k {
644                // Swap regions because we are going from sub (<=) to outlives
645                // (>=).
646                Constraint::VarSubVar(v1, v2) => ty::OutlivesPredicate(
647                    ty::Region::new_var(tcx, v2).into(),
648                    ty::Region::new_var(tcx, v1),
649                ),
650                Constraint::VarSubReg(v1, r2) => {
651                    ty::OutlivesPredicate(r2.into(), ty::Region::new_var(tcx, v1))
652                }
653                Constraint::RegSubVar(r1, v2) => {
654                    ty::OutlivesPredicate(ty::Region::new_var(tcx, v2).into(), r1)
655                }
656                Constraint::RegSubReg(r1, r2) => ty::OutlivesPredicate(r2.into(), r1),
657            };
658            (constraint, origin.to_constraint_category())
659        })
660        .chain(outlives_obligations.map(|(ty, r, constraint_category)| {
661            (ty::OutlivesPredicate(ty.into(), r), constraint_category)
662        }))
663        .collect();
664
665    QueryRegionConstraints { outlives }
666}