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 #[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 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 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 (&TyKind::InferenceVar(var1, kind1), &TyKind::InferenceVar(var2, kind2)) => {
122 if matches!(kind1, TyVariableKind::General)
123 && matches!(kind2, TyVariableKind::General)
124 {
125 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 self.unify_var_var(var1, var2)
140 } else if kind1 == TyVariableKind::General {
141 self.unify_general_var_specific_ty(var1, b.clone())
143 } else if kind2 == TyVariableKind::General {
144 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 (&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 (&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 (_, &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 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 (&TyKind::Function(_), _) | (_, &TyKind::Function(_)) => Err(NoSolution),
203
204 (_, &TyKind::Placeholder(_)) | (&TyKind::Placeholder(_), _) => Err(NoSolution),
206
207 (_, &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, 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 Zip::zip_with(
288 self,
289 variance.xform(Variance::Contravariant),
290 lifetime_a,
291 lifetime_b,
292 )?;
293 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 #[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 #[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 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 #[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 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 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 #[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 #[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 (TyVariableKind::General, _, _)
857 | (TyVariableKind::Integer, true, _)
859 | (TyVariableKind::Float, _, true) => {
861 },
862 _ => return Err(NoSolution),
863 }
864
865 let var = EnaVariable::from(var);
866
867 let universe_index = self.table.universe_of_unbound_var(var);
873 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 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 (&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 (&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 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 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 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 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)) }
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)) }
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 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 Ok(ui.to_lifetime(interner)) }
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 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 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 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 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 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 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 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 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}