Replace remaining fold calls

This commit is contained in:
Florian Diebold 2021-04-08 13:32:48 +02:00
parent caee3b6c2d
commit 0f058d61ce
3 changed files with 104 additions and 59 deletions

View File

@ -18,7 +18,7 @@
use std::ops::Index;
use std::sync::Arc;
use chalk_ir::{cast::Cast, Mutability};
use chalk_ir::{cast::Cast, DebruijnIndex, Mutability};
use hir_def::{
body::Body,
data::{ConstData, FunctionData, StaticData},
@ -41,8 +41,9 @@
TypeWalk,
};
use crate::{
db::HirDatabase, infer::diagnostics::InferenceDiagnostic, lower::ImplTraitLoweringMode,
to_assoc_type_id, AliasEq, AliasTy, Canonical, Interner, TyBuilder, TyExt, TyKind,
db::HirDatabase, fold_tys, infer::diagnostics::InferenceDiagnostic,
lower::ImplTraitLoweringMode, to_assoc_type_id, AliasEq, AliasTy, Canonical, Interner,
TyBuilder, TyExt, TyKind,
};
// This lint has a false positive here. See the link below for details.
@ -323,7 +324,7 @@ fn insert_type_vars_shallow(&mut self, ty: Ty) -> Ty {
}
fn insert_type_vars(&mut self, ty: Ty) -> Ty {
ty.fold(&mut |ty| self.insert_type_vars_shallow(ty))
fold_tys(ty, |ty, _| self.insert_type_vars_shallow(ty), DebruijnIndex::INNERMOST)
}
fn resolve_obligations_as_possible(&mut self) {
@ -434,12 +435,16 @@ fn resolve_associated_type_with_params(
/// to do it as well.
fn normalize_associated_types_in(&mut self, ty: Ty) -> Ty {
let ty = self.resolve_ty_as_possible(ty);
ty.fold(&mut |ty| match ty.kind(&Interner) {
TyKind::Alias(AliasTy::Projection(proj_ty)) => {
self.normalize_projection_ty(proj_ty.clone())
}
_ => ty,
})
fold_tys(
ty,
|ty, _| match ty.kind(&Interner) {
TyKind::Alias(AliasTy::Projection(proj_ty)) => {
self.normalize_projection_ty(proj_ty.clone())
}
_ => ty,
},
DebruijnIndex::INNERMOST,
)
}
fn normalize_projection_ty(&mut self, proj_ty: ProjectionTy) -> Ty {

View File

@ -3,15 +3,15 @@
use std::borrow::Cow;
use chalk_ir::{
interner::HasInterner, FloatTy, IntTy, TyVariableKind, UniverseIndex, VariableKind,
fold::Fold, interner::HasInterner, FloatTy, IntTy, TyVariableKind, UniverseIndex, VariableKind,
};
use ena::unify::{InPlaceUnificationTable, NoError, UnifyKey, UnifyValue};
use super::{DomainGoal, InferenceContext};
use crate::{
AliasEq, AliasTy, BoundVar, Canonical, CanonicalVarKinds, DebruijnIndex, FnPointer, FnSubst,
InEnvironment, InferenceVar, Interner, Scalar, Substitution, Ty, TyExt, TyKind, TypeWalk,
WhereClause,
fold_tys, AliasEq, AliasTy, BoundVar, Canonical, CanonicalVarKinds, DebruijnIndex, FnPointer,
FnSubst, InEnvironment, InferenceVar, Interner, Scalar, Substitution, Ty, TyExt, TyKind,
TypeWalk, WhereClause,
};
impl<'a> InferenceContext<'a> {
@ -53,9 +53,14 @@ fn add(&mut self, free_var: InferenceVar, kind: TyVariableKind) -> usize {
})
}
fn do_canonicalize<T: TypeWalk>(&mut self, t: T, binders: DebruijnIndex) -> T {
t.fold_binders(
&mut |ty, binders| match ty.kind(&Interner) {
fn do_canonicalize<T: Fold<Interner, Result = T> + HasInterner<Interner = Interner>>(
&mut self,
t: T,
binders: DebruijnIndex,
) -> T {
fold_tys(
t,
|ty, binders| match ty.kind(&Interner) {
&TyKind::InferenceVar(var, kind) => {
let inner = from_inference_var(var);
if self.var_stack.contains(&inner) {
@ -485,55 +490,63 @@ pub(crate) fn resolve_ty_shallow<'b>(&mut self, ty: &'b Ty) -> Cow<'b, Ty> {
/// be resolved as far as possible, i.e. contain no type variables with
/// known type.
fn resolve_ty_as_possible_inner(&mut self, tv_stack: &mut Vec<TypeVarId>, ty: Ty) -> Ty {
ty.fold(&mut |ty| match ty.kind(&Interner) {
&TyKind::InferenceVar(tv, kind) => {
let inner = from_inference_var(tv);
if tv_stack.contains(&inner) {
cov_mark::hit!(type_var_cycles_resolve_as_possible);
// recursive type
return self.type_variable_table.fallback_value(tv, kind);
fold_tys(
ty,
|ty, _| match ty.kind(&Interner) {
&TyKind::InferenceVar(tv, kind) => {
let inner = from_inference_var(tv);
if tv_stack.contains(&inner) {
cov_mark::hit!(type_var_cycles_resolve_as_possible);
// recursive type
return self.type_variable_table.fallback_value(tv, kind);
}
if let Some(known_ty) =
self.var_unification_table.inlined_probe_value(inner).known()
{
// known_ty may contain other variables that are known by now
tv_stack.push(inner);
let result = self.resolve_ty_as_possible_inner(tv_stack, known_ty.clone());
tv_stack.pop();
result
} else {
ty
}
}
if let Some(known_ty) =
self.var_unification_table.inlined_probe_value(inner).known()
{
// known_ty may contain other variables that are known by now
tv_stack.push(inner);
let result = self.resolve_ty_as_possible_inner(tv_stack, known_ty.clone());
tv_stack.pop();
result
} else {
ty
}
}
_ => ty,
})
_ => ty,
},
DebruijnIndex::INNERMOST,
)
}
/// Resolves the type completely; type variables without known type are
/// replaced by TyKind::Unknown.
fn resolve_ty_completely_inner(&mut self, tv_stack: &mut Vec<TypeVarId>, ty: Ty) -> Ty {
ty.fold(&mut |ty| match ty.kind(&Interner) {
&TyKind::InferenceVar(tv, kind) => {
let inner = from_inference_var(tv);
if tv_stack.contains(&inner) {
cov_mark::hit!(type_var_cycles_resolve_completely);
// recursive type
return self.type_variable_table.fallback_value(tv, kind);
fold_tys(
ty,
|ty, _| match ty.kind(&Interner) {
&TyKind::InferenceVar(tv, kind) => {
let inner = from_inference_var(tv);
if tv_stack.contains(&inner) {
cov_mark::hit!(type_var_cycles_resolve_completely);
// recursive type
return self.type_variable_table.fallback_value(tv, kind);
}
if let Some(known_ty) =
self.var_unification_table.inlined_probe_value(inner).known()
{
// known_ty may contain other variables that are known by now
tv_stack.push(inner);
let result = self.resolve_ty_completely_inner(tv_stack, known_ty.clone());
tv_stack.pop();
result
} else {
self.type_variable_table.fallback_value(tv, kind)
}
}
if let Some(known_ty) =
self.var_unification_table.inlined_probe_value(inner).known()
{
// known_ty may contain other variables that are known by now
tv_stack.push(inner);
let result = self.resolve_ty_completely_inner(tv_stack, known_ty.clone());
tv_stack.pop();
result
} else {
self.type_variable_table.fallback_value(tv, kind)
}
}
_ => ty,
})
_ => ty,
},
DebruijnIndex::INNERMOST,
)
}
}

View File

@ -328,3 +328,30 @@ fn fold_free_var_ty(
}
t.fold_with(&mut FreeVarFolder(f), DebruijnIndex::INNERMOST).expect("fold failed unexpectedly")
}
pub(crate) fn fold_tys<T: HasInterner<Interner = Interner> + Fold<Interner>>(
t: T,
f: impl FnMut(Ty, DebruijnIndex) -> Ty,
binders: DebruijnIndex,
) -> T::Result {
use chalk_ir::{
fold::{Folder, SuperFold},
Fallible,
};
struct TyFolder<F>(F);
impl<'i, F: FnMut(Ty, DebruijnIndex) -> Ty + 'i> Folder<'i, Interner> for TyFolder<F> {
fn as_dyn(&mut self) -> &mut dyn Folder<'i, Interner> {
self
}
fn interner(&self) -> &'i Interner {
&Interner
}
fn fold_ty(&mut self, ty: Ty, outer_binder: DebruijnIndex) -> Fallible<Ty> {
let ty = ty.super_fold_with(self.as_dyn(), outer_binder)?;
Ok(self.0(ty, outer_binder))
}
}
t.fold_with(&mut TyFolder(f), binders).expect("fold failed unexpectedly")
}