Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir_ty/src/infer.rs')
| -rw-r--r-- | crates/hir_ty/src/infer.rs | 22 |
1 files changed, 21 insertions, 1 deletions
diff --git a/crates/hir_ty/src/infer.rs b/crates/hir_ty/src/infer.rs index 1bc19323da..95d9a6735a 100644 --- a/crates/hir_ty/src/infer.rs +++ b/crates/hir_ty/src/infer.rs @@ -16,7 +16,7 @@ use std::ops::Index; use std::sync::Arc; -use chalk_ir::{cast::Cast, DebruijnIndex, Mutability, Safety, Scalar}; +use chalk_ir::{cast::Cast, DebruijnIndex, Mutability, Safety, Scalar, TypeFlags}; use hir_def::{ body::Body, data::{ConstData, FunctionData, StaticData}, @@ -70,6 +70,26 @@ pub(crate) fn infer_query(db: &dyn HirDatabase, def: DefWithBodyId) -> Arc<Infer Arc::new(ctx.resolve_all()) } +/// Fully normalize all the types found within `ty` in context of `owner` body definition. +/// +/// This is appropriate to use only after type-check: it assumes +/// that normalization will succeed, for example. +pub(crate) fn normalize(db: &dyn HirDatabase, owner: DefWithBodyId, ty: Ty) -> Ty { + if !ty.data(Interner).flags.intersects(TypeFlags::HAS_PROJECTION) { + return ty; + } + let krate = owner.module(db.upcast()).krate(); + let trait_env = owner + .as_generic_def_id() + .map_or_else(|| Arc::new(TraitEnvironment::empty(krate)), |d| db.trait_environment(d)); + let mut table = unify::InferenceTable::new(db, trait_env.clone()); + + let ty_with_vars = table.normalize_associated_types_in(ty); + table.resolve_obligations_as_possible(); + table.propagate_diverging_flag(); + table.resolve_completely(ty_with_vars) +} + #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] enum ExprOrPatId { ExprId(ExprId), |