diff options
-rw-r--r-- | crates/hir_ty/src/infer.rs | 25 | ||||
-rw-r--r-- | crates/hir_ty/src/infer/unify.rs | 111 | ||||
-rw-r--r-- | crates/hir_ty/src/lib.rs | 27 |
3 files changed, 104 insertions, 59 deletions
diff --git a/crates/hir_ty/src/infer.rs b/crates/hir_ty/src/infer.rs index 531159e54..1d8184ef5 100644 --- a/crates/hir_ty/src/infer.rs +++ b/crates/hir_ty/src/infer.rs | |||
@@ -18,7 +18,7 @@ use std::mem; | |||
18 | use std::ops::Index; | 18 | use std::ops::Index; |
19 | use std::sync::Arc; | 19 | use std::sync::Arc; |
20 | 20 | ||
21 | use chalk_ir::{cast::Cast, Mutability}; | 21 | use chalk_ir::{cast::Cast, DebruijnIndex, Mutability}; |
22 | use hir_def::{ | 22 | use hir_def::{ |
23 | body::Body, | 23 | body::Body, |
24 | data::{ConstData, FunctionData, StaticData}, | 24 | data::{ConstData, FunctionData, StaticData}, |
@@ -41,8 +41,9 @@ use super::{ | |||
41 | TypeWalk, | 41 | TypeWalk, |
42 | }; | 42 | }; |
43 | use crate::{ | 43 | use crate::{ |
44 | db::HirDatabase, infer::diagnostics::InferenceDiagnostic, lower::ImplTraitLoweringMode, | 44 | db::HirDatabase, fold_tys, infer::diagnostics::InferenceDiagnostic, |
45 | to_assoc_type_id, AliasEq, AliasTy, Canonical, Interner, TyBuilder, TyExt, TyKind, | 45 | lower::ImplTraitLoweringMode, to_assoc_type_id, AliasEq, AliasTy, Canonical, Interner, |
46 | TyBuilder, TyExt, TyKind, | ||
46 | }; | 47 | }; |
47 | 48 | ||
48 | // This lint has a false positive here. See the link below for details. | 49 | // This lint has a false positive here. See the link below for details. |
@@ -323,7 +324,7 @@ impl<'a> InferenceContext<'a> { | |||
323 | } | 324 | } |
324 | 325 | ||
325 | fn insert_type_vars(&mut self, ty: Ty) -> Ty { | 326 | fn insert_type_vars(&mut self, ty: Ty) -> Ty { |
326 | ty.fold(&mut |ty| self.insert_type_vars_shallow(ty)) | 327 | fold_tys(ty, |ty, _| self.insert_type_vars_shallow(ty), DebruijnIndex::INNERMOST) |
327 | } | 328 | } |
328 | 329 | ||
329 | fn resolve_obligations_as_possible(&mut self) { | 330 | fn resolve_obligations_as_possible(&mut self) { |
@@ -434,12 +435,16 @@ impl<'a> InferenceContext<'a> { | |||
434 | /// to do it as well. | 435 | /// to do it as well. |
435 | fn normalize_associated_types_in(&mut self, ty: Ty) -> Ty { | 436 | fn normalize_associated_types_in(&mut self, ty: Ty) -> Ty { |
436 | let ty = self.resolve_ty_as_possible(ty); | 437 | let ty = self.resolve_ty_as_possible(ty); |
437 | ty.fold(&mut |ty| match ty.kind(&Interner) { | 438 | fold_tys( |
438 | TyKind::Alias(AliasTy::Projection(proj_ty)) => { | 439 | ty, |
439 | self.normalize_projection_ty(proj_ty.clone()) | 440 | |ty, _| match ty.kind(&Interner) { |
440 | } | 441 | TyKind::Alias(AliasTy::Projection(proj_ty)) => { |
441 | _ => ty, | 442 | self.normalize_projection_ty(proj_ty.clone()) |
442 | }) | 443 | } |
444 | _ => ty, | ||
445 | }, | ||
446 | DebruijnIndex::INNERMOST, | ||
447 | ) | ||
443 | } | 448 | } |
444 | 449 | ||
445 | fn normalize_projection_ty(&mut self, proj_ty: ProjectionTy) -> Ty { | 450 | fn normalize_projection_ty(&mut self, proj_ty: ProjectionTy) -> Ty { |
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 | ||
diff --git a/crates/hir_ty/src/lib.rs b/crates/hir_ty/src/lib.rs index 60680ec86..f7af8b8aa 100644 --- a/crates/hir_ty/src/lib.rs +++ b/crates/hir_ty/src/lib.rs | |||
@@ -328,3 +328,30 @@ pub(crate) fn fold_free_vars<T: HasInterner<Interner = Interner> + Fold<Interner | |||
328 | } | 328 | } |
329 | t.fold_with(&mut FreeVarFolder(f), DebruijnIndex::INNERMOST).expect("fold failed unexpectedly") | 329 | t.fold_with(&mut FreeVarFolder(f), DebruijnIndex::INNERMOST).expect("fold failed unexpectedly") |
330 | } | 330 | } |
331 | |||
332 | pub(crate) fn fold_tys<T: HasInterner<Interner = Interner> + Fold<Interner>>( | ||
333 | t: T, | ||
334 | f: impl FnMut(Ty, DebruijnIndex) -> Ty, | ||
335 | binders: DebruijnIndex, | ||
336 | ) -> T::Result { | ||
337 | use chalk_ir::{ | ||
338 | fold::{Folder, SuperFold}, | ||
339 | Fallible, | ||
340 | }; | ||
341 | struct TyFolder<F>(F); | ||
342 | impl<'i, F: FnMut(Ty, DebruijnIndex) -> Ty + 'i> Folder<'i, Interner> for TyFolder<F> { | ||
343 | fn as_dyn(&mut self) -> &mut dyn Folder<'i, Interner> { | ||
344 | self | ||
345 | } | ||
346 | |||
347 | fn interner(&self) -> &'i Interner { | ||
348 | &Interner | ||
349 | } | ||
350 | |||
351 | fn fold_ty(&mut self, ty: Ty, outer_binder: DebruijnIndex) -> Fallible<Ty> { | ||
352 | let ty = ty.super_fold_with(self.as_dyn(), outer_binder)?; | ||
353 | Ok(self.0(ty, outer_binder)) | ||
354 | } | ||
355 | } | ||
356 | t.fold_with(&mut TyFolder(f), binders).expect("fold failed unexpectedly") | ||
357 | } | ||