chalk_solve/infer/
unify.rs

1use super::var::*;
2use super::*;
3use crate::debug_span;
4use chalk_ir::cast::Cast;
5use chalk_ir::fold::{FallibleTypeFolder, TypeFoldable};
6use chalk_ir::interner::{HasInterner, Interner};
7use chalk_ir::zip::{Zip, Zipper};
8use chalk_ir::UnificationDatabase;
9use std::fmt::Debug;
10use tracing::{debug, instrument};
11
12impl<I: Interner> InferenceTable<I> {
13    pub fn relate<T>(
14        &mut self,
15        interner: I,
16        db: &dyn UnificationDatabase<I>,
17        environment: &Environment<I>,
18        variance: Variance,
19        a: &T,
20        b: &T,
21    ) -> Fallible<RelationResult<I>>
22    where
23        T: ?Sized + Zip<I>,
24    {
25        let snapshot = self.snapshot();
26        match Unifier::new(interner, db, self, environment).relate(variance, a, b) {
27            Ok(r) => {
28                self.commit(snapshot);
29                Ok(r)
30            }
31            Err(e) => {
32                self.rollback_to(snapshot);
33                Err(e)
34            }
35        }
36    }
37}
38
39struct Unifier<'t, I: Interner> {
40    table: &'t mut InferenceTable<I>,
41    environment: &'t Environment<I>,
42    goals: Vec<InEnvironment<Goal<I>>>,
43    interner: I,
44    db: &'t dyn UnificationDatabase<I>,
45}
46
47#[derive(Debug)]
48pub struct RelationResult<I: Interner> {
49    pub goals: Vec<InEnvironment<Goal<I>>>,
50}
51
52impl<'t, I: Interner> Unifier<'t, I> {
53    fn new(
54        interner: I,
55        db: &'t dyn UnificationDatabase<I>,
56        table: &'t mut InferenceTable<I>,
57        environment: &'t Environment<I>,
58    ) -> Self {
59        Unifier {
60            environment,
61            table,
62            goals: vec![],
63            interner,
64            db,
65        }
66    }
67
68    /// The main entry point for the `Unifier` type and really the
69    /// only type meant to be called externally. Performs a
70    /// relation of `a` and `b` and returns the Unification Result.
71    #[instrument(level = "debug", skip(self))]
72    fn relate<T>(mut self, variance: Variance, a: &T, b: &T) -> Fallible<RelationResult<I>>
73    where
74        T: ?Sized + Zip<I>,
75    {
76        Zip::zip_with(&mut self, variance, a, b)?;
77        let interner = self.interner();
78        let mut goals = self.goals;
79        let table = self.table;
80        // Sometimes we'll produce a lifetime outlives goal which we later solve by unification
81        // Technically, these *will* get canonicalized to the same bound var and so that will end up
82        // as a goal like `^0.0 <: ^0.0`, which is trivially true. But, we remove those *here*, which
83        // might help caching.
84        goals.retain(|g| match g.goal.data(interner) {
85            GoalData::SubtypeGoal(SubtypeGoal { a, b }) => {
86                let n_a = table.ty_root(interner, a);
87                let n_b = table.ty_root(interner, b);
88                let a = n_a.as_ref().unwrap_or(a);
89                let b = n_b.as_ref().unwrap_or(b);
90                a != b
91            }
92            _ => true,
93        });
94        Ok(RelationResult { goals })
95    }
96
97    /// Relate `a`, `b` with the variance such that if `variance = Covariant`, `a` is
98    /// a subtype of `b`.
99    fn relate_ty_ty(&mut self, variance: Variance, a: &Ty<I>, b: &Ty<I>) -> Fallible<()> {
100        let interner = self.interner;
101
102        let n_a = self.table.normalize_ty_shallow(interner, a);
103        let n_b = self.table.normalize_ty_shallow(interner, b);
104        let a = n_a.as_ref().unwrap_or(a);
105        let b = n_b.as_ref().unwrap_or(b);
106
107        debug_span!("relate_ty_ty", ?variance, ?a, ?b);
108
109        if a.kind(interner) == b.kind(interner) {
110            return Ok(());
111        }
112
113        match (a.kind(interner), b.kind(interner)) {
114            // Relating two inference variables:
115            // First, if either variable is a float or int kind, then we always
116            // unify if they match. This is because float and ints don't have
117            // subtype relationships.
118            // If both kinds are general then:
119            // If `Invariant`, unify them in the underlying ena table.
120            // If `Covariant` or `Contravariant`, push `SubtypeGoal`
121            (&TyKind::InferenceVar(var1, kind1), &TyKind::InferenceVar(var2, kind2)) => {
122                if matches!(kind1, TyVariableKind::General)
123                    && matches!(kind2, TyVariableKind::General)
124                {
125                    // Both variable kinds are general; so unify if invariant, otherwise push subtype goal
126                    match variance {
127                        Variance::Invariant => self.unify_var_var(var1, var2),
128                        Variance::Covariant => {
129                            self.push_subtype_goal(a.clone(), b.clone());
130                            Ok(())
131                        }
132                        Variance::Contravariant => {
133                            self.push_subtype_goal(b.clone(), a.clone());
134                            Ok(())
135                        }
136                    }
137                } else if kind1 == kind2 {
138                    // At least one kind is not general, but they match, so unify
139                    self.unify_var_var(var1, var2)
140                } else if kind1 == TyVariableKind::General {
141                    // First kind is general, second isn't, unify
142                    self.unify_general_var_specific_ty(var1, b.clone())
143                } else if kind2 == TyVariableKind::General {
144                    // Second kind is general, first isn't, unify
145                    self.unify_general_var_specific_ty(var2, a.clone())
146                } else {
147                    debug!(
148                        "Tried to unify mis-matching inference variables: {:?} and {:?}",
149                        kind1, kind2
150                    );
151                    Err(NoSolution)
152                }
153            }
154
155            // Unifying `forall<X> { T }` with some other forall type `forall<X> { U }`
156            (&TyKind::Function(ref fn1), &TyKind::Function(ref fn2)) => {
157                if fn1.sig == fn2.sig {
158                    Zip::zip_with(
159                        self,
160                        variance,
161                        &fn1.clone().into_binders(interner),
162                        &fn2.clone().into_binders(interner),
163                    )
164                } else {
165                    Err(NoSolution)
166                }
167            }
168
169            (&TyKind::Placeholder(ref p1), &TyKind::Placeholder(ref p2)) => {
170                Zip::zip_with(self, variance, p1, p2)
171            }
172
173            // Unifying two dyn is possible if they have the same bounds.
174            (&TyKind::Dyn(ref qwc1), &TyKind::Dyn(ref qwc2)) => {
175                Zip::zip_with(self, variance, qwc1, qwc2)
176            }
177
178            (TyKind::BoundVar(_), _) | (_, TyKind::BoundVar(_)) => panic!(
179                "unification encountered bound variable: a={:?} b={:?}",
180                a, b
181            ),
182
183            // Unifying an alias type with some other type `U`.
184            (_, &TyKind::Alias(ref alias)) => self.relate_alias_ty(variance.invert(), alias, a),
185            (&TyKind::Alias(ref alias), _) => self.relate_alias_ty(variance, alias, b),
186
187            (&TyKind::InferenceVar(var, kind), ty_data) => {
188                let ty = ty_data.clone().intern(interner);
189                self.relate_var_ty(variance, var, kind, &ty)
190            }
191            (ty_data, &TyKind::InferenceVar(var, kind)) => {
192                // We need to invert the variance if inference var is `b` because we pass it in
193                // as `a` to relate_var_ty
194                let ty = ty_data.clone().intern(interner);
195                self.relate_var_ty(variance.invert(), var, kind, &ty)
196            }
197
198            (TyKind::Error, _) | (_, TyKind::Error) => Ok(()),
199
200            // This would correspond to unifying a `fn` type with a non-fn
201            // type in Rust; error.
202            (&TyKind::Function(_), _) | (_, &TyKind::Function(_)) => Err(NoSolution),
203
204            // Cannot unify (e.g.) some struct type `Foo` and a placeholder like `T`
205            (_, &TyKind::Placeholder(_)) | (&TyKind::Placeholder(_), _) => Err(NoSolution),
206
207            // Cannot unify `dyn Trait` with things like structs or placeholders
208            (_, &TyKind::Dyn(_)) | (&TyKind::Dyn(_), _) => Err(NoSolution),
209
210            (TyKind::Adt(id_a, substitution_a), TyKind::Adt(id_b, substitution_b)) => {
211                if id_a != id_b {
212                    return Err(NoSolution);
213                }
214                self.zip_substs(
215                    variance,
216                    Some(self.unification_database().adt_variance(*id_a)),
217                    substitution_a.as_slice(interner),
218                    substitution_b.as_slice(interner),
219                )
220            }
221            (
222                TyKind::AssociatedType(id_a, substitution_a),
223                TyKind::AssociatedType(id_b, substitution_b),
224            ) => {
225                if id_a != id_b {
226                    return Err(NoSolution);
227                }
228                self.zip_substs(
229                    variance,
230                    None, // TODO: AssociatedType variances?
231                    substitution_a.as_slice(interner),
232                    substitution_b.as_slice(interner),
233                )
234            }
235            (TyKind::Scalar(scalar_a), TyKind::Scalar(scalar_b)) => {
236                Zip::zip_with(self, variance, scalar_a, scalar_b)
237            }
238            (TyKind::Str, TyKind::Str) => Ok(()),
239            (TyKind::Tuple(arity_a, substitution_a), TyKind::Tuple(arity_b, substitution_b)) => {
240                if arity_a != arity_b {
241                    return Err(NoSolution);
242                }
243                self.zip_substs(
244                    variance,
245                    Some(Variances::from_iter(
246                        self.interner,
247                        std::iter::repeat(Variance::Covariant).take(*arity_a),
248                    )),
249                    substitution_a.as_slice(interner),
250                    substitution_b.as_slice(interner),
251                )
252            }
253            (
254                TyKind::OpaqueType(id_a, substitution_a),
255                TyKind::OpaqueType(id_b, substitution_b),
256            ) => {
257                if id_a != id_b {
258                    return Err(NoSolution);
259                }
260                self.zip_substs(
261                    variance,
262                    None,
263                    substitution_a.as_slice(interner),
264                    substitution_b.as_slice(interner),
265                )
266            }
267            (TyKind::Slice(ty_a), TyKind::Slice(ty_b)) => Zip::zip_with(self, variance, ty_a, ty_b),
268            (TyKind::FnDef(id_a, substitution_a), TyKind::FnDef(id_b, substitution_b)) => {
269                if id_a != id_b {
270                    return Err(NoSolution);
271                }
272                self.zip_substs(
273                    variance,
274                    Some(self.unification_database().fn_def_variance(*id_a)),
275                    substitution_a.as_slice(interner),
276                    substitution_b.as_slice(interner),
277                )
278            }
279            (
280                TyKind::Ref(mutability_a, lifetime_a, ty_a),
281                TyKind::Ref(mutability_b, lifetime_b, ty_b),
282            ) => {
283                if mutability_a != mutability_b {
284                    return Err(NoSolution);
285                }
286                // The lifetime is `Contravariant`
287                Zip::zip_with(
288                    self,
289                    variance.xform(Variance::Contravariant),
290                    lifetime_a,
291                    lifetime_b,
292                )?;
293                // The type is `Covariant` when not mut, `Invariant` otherwise
294                let output_variance = match mutability_a {
295                    Mutability::Not => Variance::Covariant,
296                    Mutability::Mut => Variance::Invariant,
297                };
298                Zip::zip_with(self, variance.xform(output_variance), ty_a, ty_b)
299            }
300            (TyKind::Raw(mutability_a, ty_a), TyKind::Raw(mutability_b, ty_b)) => {
301                if mutability_a != mutability_b {
302                    return Err(NoSolution);
303                }
304                let ty_variance = match mutability_a {
305                    Mutability::Not => Variance::Covariant,
306                    Mutability::Mut => Variance::Invariant,
307                };
308                Zip::zip_with(self, variance.xform(ty_variance), ty_a, ty_b)
309            }
310            (TyKind::Never, TyKind::Never) => Ok(()),
311            (TyKind::Array(ty_a, const_a), TyKind::Array(ty_b, const_b)) => {
312                Zip::zip_with(self, variance, ty_a, ty_b)?;
313                Zip::zip_with(self, variance, const_a, const_b)
314            }
315            (TyKind::Closure(id_a, substitution_a), TyKind::Closure(id_b, substitution_b)) => {
316                if id_a != id_b {
317                    return Err(NoSolution);
318                }
319                self.zip_substs(
320                    variance,
321                    None,
322                    substitution_a.as_slice(interner),
323                    substitution_b.as_slice(interner),
324                )
325            }
326            (TyKind::Coroutine(id_a, substitution_a), TyKind::Coroutine(id_b, substitution_b)) => {
327                if id_a != id_b {
328                    return Err(NoSolution);
329                }
330                self.zip_substs(
331                    variance,
332                    None,
333                    substitution_a.as_slice(interner),
334                    substitution_b.as_slice(interner),
335                )
336            }
337            (
338                TyKind::CoroutineWitness(id_a, substitution_a),
339                TyKind::CoroutineWitness(id_b, substitution_b),
340            ) => {
341                if id_a != id_b {
342                    return Err(NoSolution);
343                }
344                self.zip_substs(
345                    variance,
346                    None,
347                    substitution_a.as_slice(interner),
348                    substitution_b.as_slice(interner),
349                )
350            }
351            (TyKind::Foreign(id_a), TyKind::Foreign(id_b)) => {
352                Zip::zip_with(self, variance, id_a, id_b)
353            }
354
355            (_, _) => Err(NoSolution),
356        }
357    }
358
359    /// Unify two inference variables
360    #[instrument(level = "debug", skip(self))]
361    fn unify_var_var(&mut self, a: InferenceVar, b: InferenceVar) -> Fallible<()> {
362        let var1 = EnaVariable::from(a);
363        let var2 = EnaVariable::from(b);
364        self.table
365            .unify
366            .unify_var_var(var1, var2)
367            .expect("unification of two unbound variables cannot fail");
368        Ok(())
369    }
370
371    /// Unify a general inference variable with a specific inference variable
372    /// (type kind is not `General`). For example, unify a `TyVariableKind::General`
373    /// inference variable with a `TyVariableKind::Integer` variable, resulting in the
374    /// general inference variable narrowing to an integer variable.
375
376    #[instrument(level = "debug", skip(self))]
377    fn unify_general_var_specific_ty(
378        &mut self,
379        general_var: InferenceVar,
380        specific_ty: Ty<I>,
381    ) -> Fallible<()> {
382        self.table
383            .unify
384            .unify_var_value(
385                general_var,
386                InferenceValue::from_ty(self.interner, specific_ty),
387            )
388            .unwrap();
389
390        Ok(())
391    }
392
393    #[instrument(level = "debug", skip(self))]
394    fn relate_binders<'a, T>(
395        &mut self,
396        variance: Variance,
397        a: &Binders<T>,
398        b: &Binders<T>,
399    ) -> Fallible<()>
400    where
401        T: Clone + TypeFoldable<I> + HasInterner<Interner = I> + Zip<I>,
402        't: 'a,
403    {
404        // for<'a...> T == for<'b...> U
405        //
406        // if:
407        //
408        // for<'a...> exists<'b...> T == U &&
409        // for<'b...> exists<'a...> T == U
410
411        // for<'a...> T <: for<'b...> U
412        //
413        // if
414        //
415        // for<'b...> exists<'a...> T <: U
416
417        let interner = self.interner;
418
419        if let Variance::Invariant | Variance::Contravariant = variance {
420            let a_universal = self
421                .table
422                .instantiate_binders_universally(interner, a.clone());
423            let b_existential = self
424                .table
425                .instantiate_binders_existentially(interner, b.clone());
426            Zip::zip_with(self, Variance::Contravariant, &a_universal, &b_existential)?;
427        }
428
429        if let Variance::Invariant | Variance::Covariant = variance {
430            let b_universal = self
431                .table
432                .instantiate_binders_universally(interner, b.clone());
433            let a_existential = self
434                .table
435                .instantiate_binders_existentially(interner, a.clone());
436            Zip::zip_with(self, Variance::Covariant, &a_existential, &b_universal)?;
437        }
438
439        Ok(())
440    }
441
442    /// Relate an alias like `<T as Trait>::Item` or `impl Trait` with some other
443    /// type `ty`. If the variance is `Invariant`, creates a goal like
444    ///
445    /// ```notrust
446    /// AliasEq(<T as Trait>::Item = U) // associated type projection
447    /// AliasEq(impl Trait = U) // impl trait
448    /// ```
449    /// Otherwise, this creates a new variable `?X`, creates a goal like
450    /// ```notrust
451    /// AliasEq(Alias = ?X)
452    /// ```
453    /// and relates `?X` and `ty`.
454    #[instrument(level = "debug", skip(self))]
455    fn relate_alias_ty(
456        &mut self,
457        variance: Variance,
458        alias: &AliasTy<I>,
459        ty: &Ty<I>,
460    ) -> Fallible<()> {
461        let interner = self.interner;
462        match variance {
463            Variance::Invariant => {
464                self.goals.push(InEnvironment::new(
465                    self.environment,
466                    AliasEq {
467                        alias: alias.clone(),
468                        ty: ty.clone(),
469                    }
470                    .cast(interner),
471                ));
472                Ok(())
473            }
474            Variance::Covariant | Variance::Contravariant => {
475                let var = self
476                    .table
477                    .new_variable(UniverseIndex::root())
478                    .to_ty(interner);
479                self.goals.push(InEnvironment::new(
480                    self.environment,
481                    AliasEq {
482                        alias: alias.clone(),
483                        ty: var.clone(),
484                    }
485                    .cast(interner),
486                ));
487                self.relate_ty_ty(variance, &var, ty)
488            }
489        }
490    }
491
492    #[instrument(level = "debug", skip(self))]
493    fn generalize_ty(
494        &mut self,
495        ty: &Ty<I>,
496        universe_index: UniverseIndex,
497        variance: Variance,
498    ) -> Ty<I> {
499        let interner = self.interner;
500        match ty.kind(interner) {
501            TyKind::Adt(id, substitution) => {
502                let variances = if matches!(variance, Variance::Invariant) {
503                    None
504                } else {
505                    Some(self.unification_database().adt_variance(*id))
506                };
507                let get_variance = |i| {
508                    variances
509                        .as_ref()
510                        .map(|v| v.as_slice(interner)[i])
511                        .unwrap_or(Variance::Invariant)
512                };
513                TyKind::Adt(
514                    *id,
515                    self.generalize_substitution(substitution, universe_index, get_variance),
516                )
517                .intern(interner)
518            }
519            TyKind::AssociatedType(id, substitution) => TyKind::AssociatedType(
520                *id,
521                self.generalize_substitution(substitution, universe_index, |_| variance),
522            )
523            .intern(interner),
524            TyKind::Scalar(scalar) => TyKind::Scalar(*scalar).intern(interner),
525            TyKind::Str => TyKind::Str.intern(interner),
526            TyKind::Tuple(arity, substitution) => TyKind::Tuple(
527                *arity,
528                self.generalize_substitution(substitution, universe_index, |_| variance),
529            )
530            .intern(interner),
531            TyKind::OpaqueType(id, substitution) => TyKind::OpaqueType(
532                *id,
533                self.generalize_substitution(substitution, universe_index, |_| variance),
534            )
535            .intern(interner),
536            TyKind::Slice(ty) => {
537                TyKind::Slice(self.generalize_ty(ty, universe_index, variance)).intern(interner)
538            }
539            TyKind::FnDef(id, substitution) => {
540                let variances = if matches!(variance, Variance::Invariant) {
541                    None
542                } else {
543                    Some(self.unification_database().fn_def_variance(*id))
544                };
545                let get_variance = |i| {
546                    variances
547                        .as_ref()
548                        .map(|v| v.as_slice(interner)[i])
549                        .unwrap_or(Variance::Invariant)
550                };
551                TyKind::FnDef(
552                    *id,
553                    self.generalize_substitution(substitution, universe_index, get_variance),
554                )
555                .intern(interner)
556            }
557            TyKind::Ref(mutability, lifetime, ty) => {
558                let lifetime_variance = variance.xform(Variance::Contravariant);
559                let ty_variance = match mutability {
560                    Mutability::Not => Variance::Covariant,
561                    Mutability::Mut => Variance::Invariant,
562                };
563                TyKind::Ref(
564                    *mutability,
565                    self.generalize_lifetime(lifetime, universe_index, lifetime_variance),
566                    self.generalize_ty(ty, universe_index, ty_variance),
567                )
568                .intern(interner)
569            }
570            TyKind::Raw(mutability, ty) => {
571                let ty_variance = match mutability {
572                    Mutability::Not => Variance::Covariant,
573                    Mutability::Mut => Variance::Invariant,
574                };
575                TyKind::Raw(
576                    *mutability,
577                    self.generalize_ty(ty, universe_index, ty_variance),
578                )
579                .intern(interner)
580            }
581            TyKind::Never => TyKind::Never.intern(interner),
582            TyKind::Array(ty, const_) => TyKind::Array(
583                self.generalize_ty(ty, universe_index, variance),
584                self.generalize_const(const_, universe_index),
585            )
586            .intern(interner),
587            TyKind::Closure(id, substitution) => TyKind::Closure(
588                *id,
589                self.generalize_substitution(substitution, universe_index, |_| variance),
590            )
591            .intern(interner),
592            TyKind::Coroutine(id, substitution) => TyKind::Coroutine(
593                *id,
594                self.generalize_substitution(substitution, universe_index, |_| variance),
595            )
596            .intern(interner),
597            TyKind::CoroutineWitness(id, substitution) => TyKind::CoroutineWitness(
598                *id,
599                self.generalize_substitution(substitution, universe_index, |_| variance),
600            )
601            .intern(interner),
602            TyKind::Foreign(id) => TyKind::Foreign(*id).intern(interner),
603            TyKind::Error => TyKind::Error.intern(interner),
604            TyKind::Dyn(dyn_ty) => {
605                let DynTy { bounds, lifetime } = dyn_ty;
606                let lifetime = self.generalize_lifetime(
607                    lifetime,
608                    universe_index,
609                    variance.xform(Variance::Contravariant),
610                );
611
612                let bounds = bounds.map_ref(|value| {
613                    let iter = value.iter(interner).map(|sub_var| {
614                        sub_var.map_ref(|clause| {
615                            match clause {
616                                WhereClause::Implemented(trait_ref) => {
617                                    let TraitRef {
618                                        ref substitution,
619                                        trait_id,
620                                    } = *trait_ref;
621                                    let substitution = self.generalize_substitution_skip_self(
622                                        substitution,
623                                        universe_index,
624                                        |_| Some(variance),
625                                    );
626                                    WhereClause::Implemented(TraitRef {
627                                        substitution,
628                                        trait_id,
629                                    })
630                                }
631                                WhereClause::AliasEq(alias_eq) => {
632                                    let AliasEq { alias, ty: _ } = alias_eq;
633                                    let alias = match alias {
634                                        AliasTy::Opaque(opaque_ty) => {
635                                            let OpaqueTy {
636                                                ref substitution,
637                                                opaque_ty_id,
638                                            } = *opaque_ty;
639                                            let substitution = self.generalize_substitution(
640                                                substitution,
641                                                universe_index,
642                                                |_| variance,
643                                            );
644                                            AliasTy::Opaque(OpaqueTy {
645                                                substitution,
646                                                opaque_ty_id,
647                                            })
648                                        }
649                                        AliasTy::Projection(projection_ty) => {
650                                            let ProjectionTy {
651                                                ref substitution,
652                                                associated_ty_id,
653                                            } = *projection_ty;
654                                            // TODO: We should be skipping "self", which
655                                            // would be the first element of
656                                            // "trait_params" if we had a
657                                            // `RustIrDatabase` to call
658                                            // `split_projection` on...
659                                            // let (assoc_ty_datum, trait_params, assoc_type_params) = s.db().split_projection(&self);
660                                            let substitution = self.generalize_substitution(
661                                                substitution,
662                                                universe_index,
663                                                |_| variance,
664                                            );
665                                            AliasTy::Projection(ProjectionTy {
666                                                substitution,
667                                                associated_ty_id,
668                                            })
669                                        }
670                                    };
671                                    let ty =
672                                        self.table.new_variable(universe_index).to_ty(interner);
673                                    WhereClause::AliasEq(AliasEq { alias, ty })
674                                }
675                                WhereClause::TypeOutlives(_) => {
676                                    let lifetime_var = self.table.new_variable(universe_index);
677                                    let lifetime = lifetime_var.to_lifetime(interner);
678                                    let ty_var = self.table.new_variable(universe_index);
679                                    let ty = ty_var.to_ty(interner);
680                                    WhereClause::TypeOutlives(TypeOutlives { ty, lifetime })
681                                }
682                                WhereClause::LifetimeOutlives(_) => {
683                                    unreachable!("dyn Trait never contains LifetimeOutlive bounds")
684                                }
685                            }
686                        })
687                    });
688                    QuantifiedWhereClauses::from_iter(interner, iter)
689                });
690
691                TyKind::Dyn(DynTy { bounds, lifetime }).intern(interner)
692            }
693            TyKind::Function(fn_ptr) => {
694                let FnPointer {
695                    num_binders,
696                    sig,
697                    ref substitution,
698                } = *fn_ptr;
699
700                let len = substitution.0.len(interner);
701                let vars = substitution.0.iter(interner).enumerate().map(|(i, var)| {
702                    if i < len - 1 {
703                        self.generalize_generic_var(
704                            var,
705                            universe_index,
706                            variance.xform(Variance::Contravariant),
707                        )
708                    } else {
709                        self.generalize_generic_var(
710                            substitution.0.as_slice(interner).last().unwrap(),
711                            universe_index,
712                            variance,
713                        )
714                    }
715                });
716
717                let substitution = FnSubst(Substitution::from_iter(interner, vars));
718
719                TyKind::Function(FnPointer {
720                    num_binders,
721                    sig,
722                    substitution,
723                })
724                .intern(interner)
725            }
726            TyKind::Placeholder(_) | TyKind::BoundVar(_) => {
727                debug!("just generalizing to the ty itself: {:?}", ty);
728                // BoundVar and PlaceHolder have no internal values to be
729                // generic over, so we just relate directly to it
730                ty.clone()
731            }
732            TyKind::Alias(_) => {
733                let ena_var = self.table.new_variable(universe_index);
734                ena_var.to_ty(interner)
735            }
736            TyKind::InferenceVar(_var, kind) => {
737                if matches!(kind, TyVariableKind::Integer | TyVariableKind::Float) {
738                    ty.clone()
739                } else if let Some(ty) = self.table.normalize_ty_shallow(interner, ty) {
740                    self.generalize_ty(&ty, universe_index, variance)
741                } else if matches!(variance, Variance::Invariant) {
742                    ty.clone()
743                } else {
744                    let ena_var = self.table.new_variable(universe_index);
745                    ena_var.to_ty(interner)
746                }
747            }
748        }
749    }
750
751    #[instrument(level = "debug", skip(self))]
752    fn generalize_lifetime(
753        &mut self,
754        lifetime: &Lifetime<I>,
755        universe_index: UniverseIndex,
756        variance: Variance,
757    ) -> Lifetime<I> {
758        if matches!(lifetime.data(self.interner), LifetimeData::BoundVar(_))
759            || matches!(variance, Variance::Invariant)
760        {
761            lifetime.clone()
762        } else {
763            self.table
764                .new_variable(universe_index)
765                .to_lifetime(self.interner)
766        }
767    }
768
769    #[instrument(level = "debug", skip(self))]
770    fn generalize_const(&mut self, const_: &Const<I>, universe_index: UniverseIndex) -> Const<I> {
771        let data = const_.data(self.interner);
772        if matches!(data.value, ConstValue::BoundVar(_)) {
773            const_.clone()
774        } else {
775            self.table
776                .new_variable(universe_index)
777                .to_const(self.interner, data.ty.clone())
778        }
779    }
780
781    fn generalize_generic_var(
782        &mut self,
783        sub_var: &GenericArg<I>,
784        universe_index: UniverseIndex,
785        variance: Variance,
786    ) -> GenericArg<I> {
787        let interner = self.interner;
788        (match sub_var.data(interner) {
789            GenericArgData::Ty(ty) => {
790                GenericArgData::Ty(self.generalize_ty(ty, universe_index, variance))
791            }
792            GenericArgData::Lifetime(lifetime) => GenericArgData::Lifetime(
793                self.generalize_lifetime(lifetime, universe_index, variance),
794            ),
795            GenericArgData::Const(const_value) => {
796                GenericArgData::Const(self.generalize_const(const_value, universe_index))
797            }
798        })
799        .intern(interner)
800    }
801
802    /// Generalizes all but the first
803    #[instrument(level = "debug", skip(self, get_variance))]
804    fn generalize_substitution_skip_self<F: Fn(usize) -> Option<Variance>>(
805        &mut self,
806        substitution: &Substitution<I>,
807        universe_index: UniverseIndex,
808        get_variance: F,
809    ) -> Substitution<I> {
810        let interner = self.interner;
811        let vars = substitution.iter(interner).enumerate().map(|(i, sub_var)| {
812            if i == 0 {
813                sub_var.clone()
814            } else {
815                let variance = get_variance(i).unwrap_or(Variance::Invariant);
816                self.generalize_generic_var(sub_var, universe_index, variance)
817            }
818        });
819        Substitution::from_iter(interner, vars)
820    }
821
822    #[instrument(level = "debug", skip(self, get_variance))]
823    fn generalize_substitution<F: Fn(usize) -> Variance>(
824        &mut self,
825        substitution: &Substitution<I>,
826        universe_index: UniverseIndex,
827        get_variance: F,
828    ) -> Substitution<I> {
829        let interner = self.interner;
830        let vars = substitution.iter(interner).enumerate().map(|(i, sub_var)| {
831            let variance = get_variance(i);
832            self.generalize_generic_var(sub_var, universe_index, variance)
833        });
834
835        Substitution::from_iter(interner, vars)
836    }
837
838    /// Unify an inference variable `var` with some non-inference
839    /// variable `ty`, just bind `var` to `ty`. But we must enforce two conditions:
840    ///
841    /// - `var` does not appear inside of `ty` (the standard `OccursCheck`)
842    /// - `ty` does not reference anything in a lifetime that could not be named in `var`
843    ///   (the extended `OccursCheck` created to handle universes)
844    #[instrument(level = "debug", skip(self))]
845    fn relate_var_ty(
846        &mut self,
847        variance: Variance,
848        var: InferenceVar,
849        var_kind: TyVariableKind,
850        ty: &Ty<I>,
851    ) -> Fallible<()> {
852        let interner = self.interner;
853
854        match (var_kind, ty.is_integer(interner), ty.is_float(interner)) {
855            // General inference variables can unify with any type
856            (TyVariableKind::General, _, _)
857            // Integer inference variables can only unify with integer types
858            | (TyVariableKind::Integer, true, _)
859            // Float inference variables can only unify with float types
860            | (TyVariableKind::Float, _, true) => {
861            },
862            _ => return Err(NoSolution),
863        }
864
865        let var = EnaVariable::from(var);
866
867        // Determine the universe index associated with this
868        // variable. This is basically a count of the number of
869        // `forall` binders that had been introduced at the point
870        // this variable was created -- though it may change over time
871        // as the variable is unified.
872        let universe_index = self.table.universe_of_unbound_var(var);
873        // let universe_index = self.table.max_universe();
874
875        debug!("relate_var_ty: universe index of var: {:?}", universe_index);
876
877        debug!("trying fold_with on {:?}", ty);
878        let ty1 = ty
879            .clone()
880            .try_fold_with(
881                &mut OccursCheck::new(self, var, universe_index),
882                DebruijnIndex::INNERMOST,
883            )
884            .map_err(|e| {
885                debug!("failed to fold {:?}", ty);
886                e
887            })?;
888
889        // "Generalize" types. This ensures that we aren't accidentally forcing
890        // too much onto `var`. Instead of directly setting `var` equal to `ty`,
891        // we just take the outermost structure we _know_ `var` holds, and then
892        // apply that to `ty`. This involves creating new inference vars for
893        // everything inside `var`, then calling `relate_ty_ty` to relate those
894        // inference vars to the things they generalized with the correct
895        // variance.
896
897        // The main problem this solves is that lifetime relationships are
898        // relationships, not just eq ones. So when solving &'a u32 <: U,
899        // generalizing we would end up with U = &'a u32. Instead, we want
900        // U = &'b u32, with a lifetime constraint 'a <: 'b. This matters
901        // especially when solving multiple constraints - for example, &'a u32
902        // <: U, &'b u32 <: U (where without generalizing, we'd end up with 'a
903        // <: 'b, where we really want 'a <: 'c, 'b <: 'c for some 'c).
904
905        // Example operation: consider `ty` as `&'x SomeType`. To generalize
906        // this, we create two new vars `'0` and `1`. Then we relate `var` with
907        // `&'0 1` and `&'0 1` with `&'x SomeType`. The second relation will
908        // recurse, and we'll end up relating `'0` with `'x` and `1` with `SomeType`.
909        let generalized_val = self.generalize_ty(&ty1, universe_index, variance);
910
911        debug!("var {:?} generalized to {:?}", var, generalized_val);
912
913        self.table
914            .unify
915            .unify_var_value(
916                var,
917                InferenceValue::from_ty(interner, generalized_val.clone()),
918            )
919            .unwrap();
920        debug!("var {:?} set to {:?}", var, generalized_val);
921
922        self.relate_ty_ty(variance, &generalized_val, &ty1)?;
923
924        debug!(
925            "generalized version {:?} related to original {:?}",
926            generalized_val, ty1
927        );
928
929        Ok(())
930    }
931
932    fn relate_lifetime_lifetime(
933        &mut self,
934        variance: Variance,
935        a: &Lifetime<I>,
936        b: &Lifetime<I>,
937    ) -> Fallible<()> {
938        let interner = self.interner;
939
940        let n_a = self.table.normalize_lifetime_shallow(interner, a);
941        let n_b = self.table.normalize_lifetime_shallow(interner, b);
942        let a = n_a.as_ref().unwrap_or(a);
943        let b = n_b.as_ref().unwrap_or(b);
944
945        debug_span!("relate_lifetime_lifetime", ?variance, ?a, ?b);
946
947        match (a.data(interner), b.data(interner)) {
948            (&LifetimeData::InferenceVar(var_a), &LifetimeData::InferenceVar(var_b)) => {
949                let var_a = EnaVariable::from(var_a);
950                let var_b = EnaVariable::from(var_b);
951                debug!(?var_a, ?var_b);
952                self.table.unify.unify_var_var(var_a, var_b).unwrap();
953                Ok(())
954            }
955
956            (
957                &LifetimeData::InferenceVar(a_var),
958                &LifetimeData::Placeholder(PlaceholderIndex { ui, .. }),
959            ) => self.unify_lifetime_var(variance, a_var, b, ui),
960
961            (
962                &LifetimeData::Placeholder(PlaceholderIndex { ui, .. }),
963                &LifetimeData::InferenceVar(b_var),
964            ) => self.unify_lifetime_var(variance.invert(), b_var, a, ui),
965
966            (&LifetimeData::InferenceVar(a_var), &LifetimeData::Erased)
967            | (&LifetimeData::InferenceVar(a_var), &LifetimeData::Static)
968            | (&LifetimeData::InferenceVar(a_var), &LifetimeData::Error) => {
969                self.unify_lifetime_var(variance, a_var, b, UniverseIndex::root())
970            }
971
972            (&LifetimeData::Erased, &LifetimeData::InferenceVar(b_var))
973            | (&LifetimeData::Static, &LifetimeData::InferenceVar(b_var))
974            | (&LifetimeData::Error, &LifetimeData::InferenceVar(b_var)) => {
975                self.unify_lifetime_var(variance.invert(), b_var, a, UniverseIndex::root())
976            }
977
978            (&LifetimeData::Static, &LifetimeData::Static)
979            | (&LifetimeData::Erased, &LifetimeData::Erased) => Ok(()),
980
981            (&LifetimeData::Static, &LifetimeData::Placeholder(_))
982            | (&LifetimeData::Static, &LifetimeData::Erased)
983            | (&LifetimeData::Placeholder(_), &LifetimeData::Static)
984            | (&LifetimeData::Placeholder(_), &LifetimeData::Placeholder(_))
985            | (&LifetimeData::Placeholder(_), &LifetimeData::Erased)
986            | (&LifetimeData::Erased, &LifetimeData::Static)
987            | (&LifetimeData::Erased, &LifetimeData::Placeholder(_)) => {
988                if a != b {
989                    self.push_lifetime_outlives_goals(variance, a.clone(), b.clone());
990                    Ok(())
991                } else {
992                    Ok(())
993                }
994            }
995
996            (LifetimeData::Error, _) | (_, LifetimeData::Error) => Ok(()),
997            (LifetimeData::BoundVar(_), _) | (_, LifetimeData::BoundVar(_)) => panic!(
998                "unification encountered bound variable: a={:?} b={:?}",
999                a, b
1000            ),
1001
1002            (LifetimeData::Phantom(..), _) | (_, LifetimeData::Phantom(..)) => unreachable!(),
1003        }
1004    }
1005
1006    #[instrument(level = "debug", skip(self))]
1007    fn unify_lifetime_var(
1008        &mut self,
1009        variance: Variance,
1010        var: InferenceVar,
1011        value: &Lifetime<I>,
1012        value_ui: UniverseIndex,
1013    ) -> Fallible<()> {
1014        let var = EnaVariable::from(var);
1015        let var_ui = self.table.universe_of_unbound_var(var);
1016        if var_ui.can_see(value_ui) && matches!(variance, Variance::Invariant) {
1017            debug!("{:?} in {:?} can see {:?}; unifying", var, var_ui, value_ui);
1018            self.table
1019                .unify
1020                .unify_var_value(
1021                    var,
1022                    InferenceValue::from_lifetime(self.interner, value.clone()),
1023                )
1024                .unwrap();
1025            Ok(())
1026        } else {
1027            debug!(
1028                "{:?} in {:?} cannot see {:?}; pushing constraint",
1029                var, var_ui, value_ui
1030            );
1031            self.push_lifetime_outlives_goals(
1032                variance,
1033                var.to_lifetime(self.interner),
1034                value.clone(),
1035            );
1036            Ok(())
1037        }
1038    }
1039
1040    fn relate_const_const<'a>(
1041        &mut self,
1042        variance: Variance,
1043        a: &'a Const<I>,
1044        b: &'a Const<I>,
1045    ) -> Fallible<()> {
1046        let interner = self.interner;
1047
1048        let n_a = self.table.normalize_const_shallow(interner, a);
1049        let n_b = self.table.normalize_const_shallow(interner, b);
1050        let a = n_a.as_ref().unwrap_or(a);
1051        let b = n_b.as_ref().unwrap_or(b);
1052
1053        debug_span!("relate_const_const", ?variance, ?a, ?b);
1054
1055        let ConstData {
1056            ty: a_ty,
1057            value: a_val,
1058        } = a.data(interner);
1059        let ConstData {
1060            ty: b_ty,
1061            value: b_val,
1062        } = b.data(interner);
1063
1064        self.relate_ty_ty(variance, a_ty, b_ty)?;
1065
1066        match (a_val, b_val) {
1067            // Unifying two inference variables: unify them in the underlying
1068            // ena table.
1069            (&ConstValue::InferenceVar(var1), &ConstValue::InferenceVar(var2)) => {
1070                debug!(?var1, ?var2, "relate_ty_ty");
1071                let var1 = EnaVariable::from(var1);
1072                let var2 = EnaVariable::from(var2);
1073                self.table
1074                    .unify
1075                    .unify_var_var(var1, var2)
1076                    .expect("unification of two unbound variables cannot fail");
1077                Ok(())
1078            }
1079
1080            // Unifying an inference variables with a non-inference variable.
1081            (&ConstValue::InferenceVar(var), &ConstValue::Concrete(_))
1082            | (&ConstValue::InferenceVar(var), &ConstValue::Placeholder(_)) => {
1083                debug!(?var, ty=?b, "unify_var_ty");
1084                self.unify_var_const(var, b)
1085            }
1086
1087            (&ConstValue::Concrete(_), &ConstValue::InferenceVar(var))
1088            | (&ConstValue::Placeholder(_), &ConstValue::InferenceVar(var)) => {
1089                debug!(?var, ty=?a, "unify_var_ty");
1090                self.unify_var_const(var, a)
1091            }
1092
1093            (&ConstValue::Placeholder(p1), &ConstValue::Placeholder(p2)) => {
1094                Zip::zip_with(self, variance, &p1, &p2)
1095            }
1096
1097            (&ConstValue::Concrete(ref ev1), &ConstValue::Concrete(ref ev2)) => {
1098                if ev1.const_eq(a_ty, ev2, interner) {
1099                    Ok(())
1100                } else {
1101                    Err(NoSolution)
1102                }
1103            }
1104
1105            (&ConstValue::Concrete(_), &ConstValue::Placeholder(_))
1106            | (&ConstValue::Placeholder(_), &ConstValue::Concrete(_)) => Err(NoSolution),
1107
1108            (ConstValue::BoundVar(_), _) | (_, ConstValue::BoundVar(_)) => panic!(
1109                "unification encountered bound variable: a={:?} b={:?}",
1110                a, b
1111            ),
1112        }
1113    }
1114
1115    #[instrument(level = "debug", skip(self))]
1116    fn unify_var_const(&mut self, var: InferenceVar, c: &Const<I>) -> Fallible<()> {
1117        let interner = self.interner;
1118        let var = EnaVariable::from(var);
1119
1120        // Determine the universe index associated with this
1121        // variable. This is basically a count of the number of
1122        // `forall` binders that had been introduced at the point
1123        // this variable was created -- though it may change over time
1124        // as the variable is unified.
1125        let universe_index = self.table.universe_of_unbound_var(var);
1126
1127        let c1 = c.clone().try_fold_with(
1128            &mut OccursCheck::new(self, var, universe_index),
1129            DebruijnIndex::INNERMOST,
1130        )?;
1131
1132        debug!("unify_var_const: var {:?} set to {:?}", var, c1);
1133        self.table
1134            .unify
1135            .unify_var_value(var, InferenceValue::from_const(interner, c1))
1136            .unwrap();
1137
1138        Ok(())
1139    }
1140
1141    /// Relate `a`, `b` such that if `variance = Covariant`, `a` is a subtype of
1142    /// `b` and thus `a` must outlive `b`.
1143    fn push_lifetime_outlives_goals(&mut self, variance: Variance, a: Lifetime<I>, b: Lifetime<I>) {
1144        debug!(
1145            "pushing lifetime outlives goals for a={:?} b={:?} with variance {:?}",
1146            a, b, variance
1147        );
1148        if matches!(variance, Variance::Invariant | Variance::Contravariant) {
1149            self.goals.push(InEnvironment::new(
1150                self.environment,
1151                WhereClause::LifetimeOutlives(LifetimeOutlives {
1152                    a: a.clone(),
1153                    b: b.clone(),
1154                })
1155                .cast(self.interner),
1156            ));
1157        }
1158        if matches!(variance, Variance::Invariant | Variance::Covariant) {
1159            self.goals.push(InEnvironment::new(
1160                self.environment,
1161                WhereClause::LifetimeOutlives(LifetimeOutlives { a: b, b: a }).cast(self.interner),
1162            ));
1163        }
1164    }
1165
1166    /// Pushes a goal of `a` being a subtype of `b`.
1167    fn push_subtype_goal(&mut self, a: Ty<I>, b: Ty<I>) {
1168        let subtype_goal = GoalData::SubtypeGoal(SubtypeGoal { a, b }).intern(self.interner());
1169        self.goals
1170            .push(InEnvironment::new(self.environment, subtype_goal));
1171    }
1172}
1173
1174impl<'i, I: Interner> Zipper<I> for Unifier<'i, I> {
1175    fn zip_tys(&mut self, variance: Variance, a: &Ty<I>, b: &Ty<I>) -> Fallible<()> {
1176        debug!("zip_tys {:?}, {:?}, {:?}", variance, a, b);
1177        self.relate_ty_ty(variance, a, b)
1178    }
1179
1180    fn zip_lifetimes(
1181        &mut self,
1182        variance: Variance,
1183        a: &Lifetime<I>,
1184        b: &Lifetime<I>,
1185    ) -> Fallible<()> {
1186        self.relate_lifetime_lifetime(variance, a, b)
1187    }
1188
1189    fn zip_consts(&mut self, variance: Variance, a: &Const<I>, b: &Const<I>) -> Fallible<()> {
1190        self.relate_const_const(variance, a, b)
1191    }
1192
1193    fn zip_binders<T>(&mut self, variance: Variance, a: &Binders<T>, b: &Binders<T>) -> Fallible<()>
1194    where
1195        T: Clone + HasInterner<Interner = I> + Zip<I> + TypeFoldable<I>,
1196    {
1197        // The binders that appear in types (apart from quantified types, which are
1198        // handled in `unify_ty`) appear as part of `dyn Trait` and `impl Trait` types.
1199        //
1200        // They come in two varieties:
1201        //
1202        // * The existential binder from `dyn Trait` / `impl Trait`
1203        //   (representing the hidden "self" type)
1204        // * The `for<..>` binders from higher-ranked traits.
1205        //
1206        // In both cases we can use the same `relate_binders` routine.
1207
1208        self.relate_binders(variance, a, b)
1209    }
1210
1211    fn interner(&self) -> I {
1212        self.interner
1213    }
1214
1215    fn unification_database(&self) -> &dyn UnificationDatabase<I> {
1216        self.db
1217    }
1218}
1219
1220struct OccursCheck<'u, 't, I: Interner> {
1221    unifier: &'u mut Unifier<'t, I>,
1222    var: EnaVariable<I>,
1223    universe_index: UniverseIndex,
1224}
1225
1226impl<'u, 't, I: Interner> OccursCheck<'u, 't, I> {
1227    fn new(
1228        unifier: &'u mut Unifier<'t, I>,
1229        var: EnaVariable<I>,
1230        universe_index: UniverseIndex,
1231    ) -> Self {
1232        OccursCheck {
1233            unifier,
1234            var,
1235            universe_index,
1236        }
1237    }
1238}
1239
1240impl<'i, I: Interner> FallibleTypeFolder<I> for OccursCheck<'_, 'i, I> {
1241    type Error = NoSolution;
1242
1243    fn as_dyn(&mut self) -> &mut dyn FallibleTypeFolder<I, Error = Self::Error> {
1244        self
1245    }
1246
1247    fn try_fold_free_placeholder_ty(
1248        &mut self,
1249        universe: PlaceholderIndex,
1250        _outer_binder: DebruijnIndex,
1251    ) -> Fallible<Ty<I>> {
1252        let interner = self.interner();
1253        if self.universe_index < universe.ui {
1254            debug!(
1255                "OccursCheck aborting because self.universe_index ({:?}) < universe.ui ({:?})",
1256                self.universe_index, universe.ui
1257            );
1258            Err(NoSolution)
1259        } else {
1260            Ok(universe.to_ty(interner)) // no need to shift, not relative to depth
1261        }
1262    }
1263
1264    fn try_fold_free_placeholder_const(
1265        &mut self,
1266        ty: Ty<I>,
1267        universe: PlaceholderIndex,
1268        _outer_binder: DebruijnIndex,
1269    ) -> Fallible<Const<I>> {
1270        let interner = self.interner();
1271        if self.universe_index < universe.ui {
1272            Err(NoSolution)
1273        } else {
1274            Ok(universe.to_const(interner, ty)) // no need to shift, not relative to depth
1275        }
1276    }
1277
1278    #[instrument(level = "debug", skip(self))]
1279    fn try_fold_free_placeholder_lifetime(
1280        &mut self,
1281        ui: PlaceholderIndex,
1282        _outer_binder: DebruijnIndex,
1283    ) -> Fallible<Lifetime<I>> {
1284        let interner = self.interner();
1285        if self.universe_index < ui.ui {
1286            // Scenario is like:
1287            //
1288            // exists<T> forall<'b> ?T = Foo<'b>
1289            //
1290            // unlike with a type variable, this **might** be
1291            // ok.  Ultimately it depends on whether the
1292            // `forall` also introduced relations to lifetimes
1293            // nameable in T. To handle that, we introduce a
1294            // fresh region variable `'x` in same universe as `T`
1295            // and add a side-constraint that `'x = 'b`:
1296            //
1297            // exists<'x> forall<'b> ?T = Foo<'x>, where 'x = 'b
1298
1299            let tick_x = self.unifier.table.new_variable(self.universe_index);
1300            self.unifier.push_lifetime_outlives_goals(
1301                Variance::Invariant,
1302                tick_x.to_lifetime(interner),
1303                ui.to_lifetime(interner),
1304            );
1305            Ok(tick_x.to_lifetime(interner))
1306        } else {
1307            // If the `ui` is higher than `self.universe_index`, then we can name
1308            // this lifetime, no problem.
1309            Ok(ui.to_lifetime(interner)) // no need to shift, not relative to depth
1310        }
1311    }
1312
1313    fn try_fold_inference_ty(
1314        &mut self,
1315        var: InferenceVar,
1316        kind: TyVariableKind,
1317        _outer_binder: DebruijnIndex,
1318    ) -> Fallible<Ty<I>> {
1319        let interner = self.interner();
1320        let var = EnaVariable::from(var);
1321        match self.unifier.table.unify.probe_value(var) {
1322            // If this variable already has a value, fold over that value instead.
1323            InferenceValue::Bound(normalized_ty) => {
1324                let normalized_ty = normalized_ty.assert_ty_ref(interner);
1325                let normalized_ty = normalized_ty
1326                    .clone()
1327                    .try_fold_with(self, DebruijnIndex::INNERMOST)?;
1328                assert!(!normalized_ty.needs_shift(interner));
1329                Ok(normalized_ty)
1330            }
1331
1332            // Otherwise, check the universe of the variable, and also
1333            // check for cycles with `self.var` (which this will soon
1334            // become the value of).
1335            InferenceValue::Unbound(ui) => {
1336                if self.unifier.table.unify.unioned(var, self.var) {
1337                    debug!(
1338                        "OccursCheck aborting because {:?} unioned with {:?}",
1339                        var, self.var,
1340                    );
1341                    return Err(NoSolution);
1342                }
1343
1344                if self.universe_index < ui {
1345                    // Scenario is like:
1346                    //
1347                    // ?A = foo(?B)
1348                    //
1349                    // where ?A is in universe 0 and ?B is in universe 1.
1350                    // This is OK, if ?B is promoted to universe 0.
1351                    self.unifier
1352                        .table
1353                        .unify
1354                        .unify_var_value(var, InferenceValue::Unbound(self.universe_index))
1355                        .unwrap();
1356                }
1357
1358                Ok(var.to_ty_with_kind(interner, kind))
1359            }
1360        }
1361    }
1362
1363    fn try_fold_inference_const(
1364        &mut self,
1365        ty: Ty<I>,
1366        var: InferenceVar,
1367        _outer_binder: DebruijnIndex,
1368    ) -> Fallible<Const<I>> {
1369        let interner = self.interner();
1370        let var = EnaVariable::from(var);
1371        match self.unifier.table.unify.probe_value(var) {
1372            // If this variable already has a value, fold over that value instead.
1373            InferenceValue::Bound(normalized_const) => {
1374                let normalized_const = normalized_const.assert_const_ref(interner);
1375                let normalized_const = normalized_const
1376                    .clone()
1377                    .try_fold_with(self, DebruijnIndex::INNERMOST)?;
1378                assert!(!normalized_const.needs_shift(interner));
1379                Ok(normalized_const)
1380            }
1381
1382            // Otherwise, check the universe of the variable, and also
1383            // check for cycles with `self.var` (which this will soon
1384            // become the value of).
1385            InferenceValue::Unbound(ui) => {
1386                if self.unifier.table.unify.unioned(var, self.var) {
1387                    return Err(NoSolution);
1388                }
1389
1390                if self.universe_index < ui {
1391                    // Scenario is like:
1392                    //
1393                    // forall<const A> exists<const B> ?C = Foo<B>
1394                    //
1395                    // where A is in universe 0 and B is in universe 1.
1396                    // This is OK, if B is promoted to universe 0.
1397                    self.unifier
1398                        .table
1399                        .unify
1400                        .unify_var_value(var, InferenceValue::Unbound(self.universe_index))
1401                        .unwrap();
1402                }
1403
1404                Ok(var.to_const(interner, ty))
1405            }
1406        }
1407    }
1408
1409    fn try_fold_inference_lifetime(
1410        &mut self,
1411        var: InferenceVar,
1412        outer_binder: DebruijnIndex,
1413    ) -> Fallible<Lifetime<I>> {
1414        // a free existentially bound region; find the
1415        // inference variable it corresponds to
1416        let interner = self.interner();
1417        let var = EnaVariable::from(var);
1418        match self.unifier.table.unify.probe_value(var) {
1419            InferenceValue::Unbound(ui) => {
1420                if self.universe_index < ui {
1421                    // Scenario is like:
1422                    //
1423                    // exists<T> forall<'b> exists<'a> ?T = Foo<'a>
1424                    //
1425                    // where ?A is in universe 0 and `'b` is in universe 1.
1426                    // This is OK, if `'b` is promoted to universe 0.
1427                    self.unifier
1428                        .table
1429                        .unify
1430                        .unify_var_value(var, InferenceValue::Unbound(self.universe_index))
1431                        .unwrap();
1432                }
1433                Ok(var.to_lifetime(interner))
1434            }
1435
1436            InferenceValue::Bound(l) => {
1437                let l = l.assert_lifetime_ref(interner);
1438                let l = l.clone().try_fold_with(self, outer_binder)?;
1439                assert!(!l.needs_shift(interner));
1440                Ok(l)
1441            }
1442        }
1443    }
1444
1445    fn forbid_free_vars(&self) -> bool {
1446        true
1447    }
1448
1449    fn interner(&self) -> I {
1450        self.unifier.interner
1451    }
1452}