diff options
Diffstat (limited to 'crates/hir_ty/src/infer')
-rw-r--r-- | crates/hir_ty/src/infer/unify.rs | 111 |
1 files changed, 62 insertions, 49 deletions
diff --git a/crates/hir_ty/src/infer/unify.rs b/crates/hir_ty/src/infer/unify.rs index c3d9e81c3..ffa324b6d 100644 --- a/crates/hir_ty/src/infer/unify.rs +++ b/crates/hir_ty/src/infer/unify.rs | |||
@@ -3,15 +3,15 @@ | |||
3 | use std::borrow::Cow; | 3 | use std::borrow::Cow; |
4 | 4 | ||
5 | use chalk_ir::{ | 5 | use chalk_ir::{ |
6 | interner::HasInterner, FloatTy, IntTy, TyVariableKind, UniverseIndex, VariableKind, | 6 | fold::Fold, interner::HasInterner, FloatTy, IntTy, TyVariableKind, UniverseIndex, VariableKind, |
7 | }; | 7 | }; |
8 | use ena::unify::{InPlaceUnificationTable, NoError, UnifyKey, UnifyValue}; | 8 | use ena::unify::{InPlaceUnificationTable, NoError, UnifyKey, UnifyValue}; |
9 | 9 | ||
10 | use super::{DomainGoal, InferenceContext}; | 10 | use super::{DomainGoal, InferenceContext}; |
11 | use crate::{ | 11 | use crate::{ |
12 | AliasEq, AliasTy, BoundVar, Canonical, CanonicalVarKinds, DebruijnIndex, FnPointer, FnSubst, | 12 | fold_tys, AliasEq, AliasTy, BoundVar, Canonical, CanonicalVarKinds, DebruijnIndex, FnPointer, |
13 | InEnvironment, InferenceVar, Interner, Scalar, Substitution, Ty, TyExt, TyKind, TypeWalk, | 13 | FnSubst, InEnvironment, InferenceVar, Interner, Scalar, Substitution, Ty, TyExt, TyKind, |
14 | WhereClause, | 14 | TypeWalk, WhereClause, |
15 | }; | 15 | }; |
16 | 16 | ||
17 | impl<'a> InferenceContext<'a> { | 17 | impl<'a> InferenceContext<'a> { |
@@ -53,9 +53,14 @@ impl<'a, 'b> Canonicalizer<'a, 'b> { | |||
53 | }) | 53 | }) |
54 | } | 54 | } |
55 | 55 | ||
56 | fn do_canonicalize<T: TypeWalk>(&mut self, t: T, binders: DebruijnIndex) -> T { | 56 | fn do_canonicalize<T: Fold<Interner, Result = T> + HasInterner<Interner = Interner>>( |
57 | t.fold_binders( | 57 | &mut self, |
58 | &mut |ty, binders| match ty.kind(&Interner) { | 58 | t: T, |
59 | binders: DebruijnIndex, | ||
60 | ) -> T { | ||
61 | fold_tys( | ||
62 | t, | ||
63 | |ty, binders| match ty.kind(&Interner) { | ||
59 | &TyKind::InferenceVar(var, kind) => { | 64 | &TyKind::InferenceVar(var, kind) => { |
60 | let inner = from_inference_var(var); | 65 | let inner = from_inference_var(var); |
61 | if self.var_stack.contains(&inner) { | 66 | if self.var_stack.contains(&inner) { |
@@ -485,55 +490,63 @@ impl InferenceTable { | |||
485 | /// be resolved as far as possible, i.e. contain no type variables with | 490 | /// be resolved as far as possible, i.e. contain no type variables with |
486 | /// known type. | 491 | /// known type. |
487 | fn resolve_ty_as_possible_inner(&mut self, tv_stack: &mut Vec<TypeVarId>, ty: Ty) -> Ty { | 492 | fn resolve_ty_as_possible_inner(&mut self, tv_stack: &mut Vec<TypeVarId>, ty: Ty) -> Ty { |
488 | ty.fold(&mut |ty| match ty.kind(&Interner) { | 493 | fold_tys( |
489 | &TyKind::InferenceVar(tv, kind) => { | 494 | ty, |
490 | let inner = from_inference_var(tv); | 495 | |ty, _| match ty.kind(&Interner) { |
491 | if tv_stack.contains(&inner) { | 496 | &TyKind::InferenceVar(tv, kind) => { |
492 | cov_mark::hit!(type_var_cycles_resolve_as_possible); | 497 | let inner = from_inference_var(tv); |
493 | // recursive type | 498 | if tv_stack.contains(&inner) { |
494 | return self.type_variable_table.fallback_value(tv, kind); | 499 | cov_mark::hit!(type_var_cycles_resolve_as_possible); |
495 | } | 500 | // recursive type |
496 | if let Some(known_ty) = | 501 | return self.type_variable_table.fallback_value(tv, kind); |
497 | self.var_unification_table.inlined_probe_value(inner).known() | 502 | } |
498 | { | 503 | if let Some(known_ty) = |
499 | // known_ty may contain other variables that are known by now | 504 | self.var_unification_table.inlined_probe_value(inner).known() |
500 | tv_stack.push(inner); | 505 | { |
501 | let result = self.resolve_ty_as_possible_inner(tv_stack, known_ty.clone()); | 506 | // known_ty may contain other variables that are known by now |
502 | tv_stack.pop(); | 507 | tv_stack.push(inner); |
503 | result | 508 | let result = self.resolve_ty_as_possible_inner(tv_stack, known_ty.clone()); |
504 | } else { | 509 | tv_stack.pop(); |
505 | ty | 510 | result |
511 | } else { | ||
512 | ty | ||
513 | } | ||
506 | } | 514 | } |
507 | } | 515 | _ => ty, |
508 | _ => ty, | 516 | }, |
509 | }) | 517 | DebruijnIndex::INNERMOST, |
518 | ) | ||
510 | } | 519 | } |
511 | 520 | ||
512 | /// Resolves the type completely; type variables without known type are | 521 | /// Resolves the type completely; type variables without known type are |
513 | /// replaced by TyKind::Unknown. | 522 | /// replaced by TyKind::Unknown. |
514 | fn resolve_ty_completely_inner(&mut self, tv_stack: &mut Vec<TypeVarId>, ty: Ty) -> Ty { | 523 | fn resolve_ty_completely_inner(&mut self, tv_stack: &mut Vec<TypeVarId>, ty: Ty) -> Ty { |
515 | ty.fold(&mut |ty| match ty.kind(&Interner) { | 524 | fold_tys( |
516 | &TyKind::InferenceVar(tv, kind) => { | 525 | ty, |
517 | let inner = from_inference_var(tv); | 526 | |ty, _| match ty.kind(&Interner) { |
518 | if tv_stack.contains(&inner) { | 527 | &TyKind::InferenceVar(tv, kind) => { |
519 | cov_mark::hit!(type_var_cycles_resolve_completely); | 528 | let inner = from_inference_var(tv); |
520 | // recursive type | 529 | if tv_stack.contains(&inner) { |
521 | return self.type_variable_table.fallback_value(tv, kind); | 530 | cov_mark::hit!(type_var_cycles_resolve_completely); |
522 | } | 531 | // recursive type |
523 | if let Some(known_ty) = | 532 | return self.type_variable_table.fallback_value(tv, kind); |
524 | self.var_unification_table.inlined_probe_value(inner).known() | 533 | } |
525 | { | 534 | if let Some(known_ty) = |
526 | // known_ty may contain other variables that are known by now | 535 | self.var_unification_table.inlined_probe_value(inner).known() |
527 | tv_stack.push(inner); | 536 | { |
528 | let result = self.resolve_ty_completely_inner(tv_stack, known_ty.clone()); | 537 | // known_ty may contain other variables that are known by now |
529 | tv_stack.pop(); | 538 | tv_stack.push(inner); |
530 | result | 539 | let result = self.resolve_ty_completely_inner(tv_stack, known_ty.clone()); |
531 | } else { | 540 | tv_stack.pop(); |
532 | self.type_variable_table.fallback_value(tv, kind) | 541 | result |
542 | } else { | ||
543 | self.type_variable_table.fallback_value(tv, kind) | ||
544 | } | ||
533 | } | 545 | } |
534 | } | 546 | _ => ty, |
535 | _ => ty, | 547 | }, |
536 | }) | 548 | DebruijnIndex::INNERMOST, |
549 | ) | ||
537 | } | 550 | } |
538 | } | 551 | } |
539 | 552 | ||