aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_ty
diff options
context:
space:
mode:
Diffstat (limited to 'crates/hir_ty')
-rw-r--r--crates/hir_ty/src/infer.rs25
-rw-r--r--crates/hir_ty/src/infer/unify.rs111
-rw-r--r--crates/hir_ty/src/lib.rs27
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;
18use std::ops::Index; 18use std::ops::Index;
19use std::sync::Arc; 19use std::sync::Arc;
20 20
21use chalk_ir::{cast::Cast, Mutability}; 21use chalk_ir::{cast::Cast, DebruijnIndex, Mutability};
22use hir_def::{ 22use 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};
43use crate::{ 43use 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 @@
3use std::borrow::Cow; 3use std::borrow::Cow;
4 4
5use chalk_ir::{ 5use chalk_ir::{
6 interner::HasInterner, FloatTy, IntTy, TyVariableKind, UniverseIndex, VariableKind, 6 fold::Fold, interner::HasInterner, FloatTy, IntTy, TyVariableKind, UniverseIndex, VariableKind,
7}; 7};
8use ena::unify::{InPlaceUnificationTable, NoError, UnifyKey, UnifyValue}; 8use ena::unify::{InPlaceUnificationTable, NoError, UnifyKey, UnifyValue};
9 9
10use super::{DomainGoal, InferenceContext}; 10use super::{DomainGoal, InferenceContext};
11use crate::{ 11use 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
17impl<'a> InferenceContext<'a> { 17impl<'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
332pub(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}