about summary refs log tree commit diff
diff options
context:
space:
mode:
authorLukas Wirth <lukastw97@gmail.com>2024-06-21 10:49:19 +0200
committerLukas Wirth <lukastw97@gmail.com>2024-06-21 10:55:05 +0200
commit7b50a5ff431c977d5c2f5073aadd609692d61904 (patch)
tree1e981c71b5e8d34325e77dc170f62a9284640ab4
parent9b8b6f92b21e27d26ae334f091cab90f9f9678e5 (diff)
downloadrust-7b50a5ff431c977d5c2f5073aadd609692d61904.tar.gz
rust-7b50a5ff431c977d5c2f5073aadd609692d61904.zip
Extract generics module
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/builder.rs8
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs7
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/chalk_ext.rs10
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/consteval.rs7
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/display.rs3
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/generics.rs286
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/infer.rs7
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs6
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/infer/path.rs9
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/lib.rs8
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/lower.rs10
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs3
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/mir/monomorphization.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/utils.rs288
15 files changed, 333 insertions, 323 deletions
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/builder.rs b/src/tools/rust-analyzer/crates/hir-ty/src/builder.rs
index d6374658f19..52411f94ad0 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/builder.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/builder.rs
@@ -14,10 +14,10 @@ use hir_def::{
 use smallvec::SmallVec;
 
 use crate::{
-    consteval::unknown_const_as_generic, db::HirDatabase, error_lifetime,
-    infer::unify::InferenceTable, primitive, to_assoc_type_id, to_chalk_trait_id, utils::generics,
-    Binders, BoundVar, CallableSig, GenericArg, GenericArgData, Interner, ProjectionTy,
-    Substitution, TraitRef, Ty, TyDefId, TyExt, TyKind,
+    consteval::unknown_const_as_generic, db::HirDatabase, error_lifetime, generics::generics,
+    infer::unify::InferenceTable, primitive, to_assoc_type_id, to_chalk_trait_id, Binders,
+    BoundVar, CallableSig, GenericArg, GenericArgData, Interner, ProjectionTy, Substitution,
+    TraitRef, Ty, TyDefId, TyExt, TyKind,
 };
 
 #[derive(Debug, Clone, PartialEq, Eq)]
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs b/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs
index 149e4dbaa51..0d8ceb68b20 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs
@@ -20,13 +20,14 @@ use hir_expand::name::name;
 use crate::{
     db::{HirDatabase, InternedCoroutine},
     display::HirDisplay,
-    from_assoc_type_id, from_chalk_trait_id, from_foreign_def_id, make_binders,
-    make_single_type_binders,
+    from_assoc_type_id, from_chalk_trait_id, from_foreign_def_id,
+    generics::generics,
+    make_binders, make_single_type_binders,
     mapping::{from_chalk, ToChalk, TypeAliasAsValue},
     method_resolution::{TraitImpls, TyFingerprint, ALL_FLOAT_FPS, ALL_INT_FPS},
     to_assoc_type_id, to_chalk_trait_id,
     traits::ChalkContext,
-    utils::{generics, ClosureSubst},
+    utils::ClosureSubst,
     wrap_empty_binders, AliasEq, AliasTy, BoundVar, CallableDefId, DebruijnIndex, FnDefId,
     Interner, ProjectionTy, ProjectionTyExt, QuantifiedWhereClause, Substitution, TraitRef,
     TraitRefExt, Ty, TyBuilder, TyExt, TyKind, WhereClause,
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/chalk_ext.rs b/src/tools/rust-analyzer/crates/hir-ty/src/chalk_ext.rs
index d99ef6679e5..4279c756519 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/chalk_ext.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/chalk_ext.rs
@@ -12,12 +12,10 @@ use hir_def::{
 };
 
 use crate::{
-    db::HirDatabase,
-    from_assoc_type_id, from_chalk_trait_id, from_foreign_def_id, from_placeholder_idx,
-    to_chalk_trait_id,
-    utils::{generics, ClosureSubst},
-    AdtId, AliasEq, AliasTy, Binders, CallableDefId, CallableSig, Canonical, CanonicalVarKinds,
-    ClosureId, DynTy, FnPointer, ImplTraitId, InEnvironment, Interner, Lifetime, ProjectionTy,
+    db::HirDatabase, from_assoc_type_id, from_chalk_trait_id, from_foreign_def_id,
+    from_placeholder_idx, generics::generics, to_chalk_trait_id, utils::ClosureSubst, AdtId,
+    AliasEq, AliasTy, Binders, CallableDefId, CallableSig, Canonical, CanonicalVarKinds, ClosureId,
+    DynTy, FnPointer, ImplTraitId, InEnvironment, Interner, Lifetime, ProjectionTy,
     QuantifiedWhereClause, Substitution, TraitRef, Ty, TyBuilder, TyKind, TypeFlags, WhereClause,
 };
 
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/consteval.rs b/src/tools/rust-analyzer/crates/hir-ty/src/consteval.rs
index f09277a92e6..aa7fc598b49 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/consteval.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/consteval.rs
@@ -15,10 +15,9 @@ use stdx::never;
 use triomphe::Arc;
 
 use crate::{
-    db::HirDatabase, infer::InferenceContext, lower::ParamLoweringMode,
-    mir::monomorphize_mir_body_bad, to_placeholder_idx, utils::Generics, Const, ConstData,
-    ConstScalar, ConstValue, GenericArg, Interner, MemoryMap, Substitution, TraitEnvironment, Ty,
-    TyBuilder,
+    db::HirDatabase, generics::Generics, infer::InferenceContext, lower::ParamLoweringMode,
+    mir::monomorphize_mir_body_bad, to_placeholder_idx, Const, ConstData, ConstScalar, ConstValue,
+    GenericArg, Interner, MemoryMap, Substitution, TraitEnvironment, Ty, TyBuilder,
 };
 
 use super::mir::{interpret_mir, lower_to_mir, pad16, MirEvalError, MirLowerError};
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/display.rs b/src/tools/rust-analyzer/crates/hir-ty/src/display.rs
index cd31845a514..de5e400194e 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/display.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/display.rs
@@ -36,12 +36,13 @@ use crate::{
     consteval::try_const_usize,
     db::{HirDatabase, InternedClosure},
     from_assoc_type_id, from_foreign_def_id, from_placeholder_idx,
+    generics::generics,
     layout::Layout,
     lt_from_placeholder_idx,
     mapping::from_chalk,
     mir::pad16,
     primitive, to_assoc_type_id,
-    utils::{self, detect_variant_from_bytes, generics, ClosureSubst},
+    utils::{self, detect_variant_from_bytes, ClosureSubst},
     AdtId, AliasEq, AliasTy, Binders, CallableDefId, CallableSig, ConcreteConst, Const,
     ConstScalar, ConstValue, DomainGoal, FnAbi, GenericArg, ImplTraitId, Interner, Lifetime,
     LifetimeData, LifetimeOutlives, MemoryMap, Mutability, OpaqueTy, ProjectionTy, ProjectionTyExt,
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/generics.rs b/src/tools/rust-analyzer/crates/hir-ty/src/generics.rs
new file mode 100644
index 00000000000..235e04023db
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/generics.rs
@@ -0,0 +1,286 @@
+use chalk_ir::{cast::Cast as _, BoundVar, DebruijnIndex};
+use hir_def::{
+    db::DefDatabase,
+    generics::{
+        GenericParamDataRef, GenericParams, LifetimeParamData, TypeOrConstParamData,
+        TypeParamProvenance,
+    },
+    ConstParamId, GenericDefId, GenericParamId, ItemContainerId, LifetimeParamId, Lookup,
+    TypeOrConstParamId, TypeParamId,
+};
+use intern::Interned;
+
+use crate::{db::HirDatabase, Interner, Substitution};
+
+pub(crate) fn generics(db: &dyn DefDatabase, def: GenericDefId) -> Generics {
+    let parent_generics = parent_generic_def(db, def).map(|def| Box::new(generics(db, def)));
+    Generics { def, params: db.generic_params(def), parent_generics }
+}
+#[derive(Clone, Debug)]
+pub(crate) struct Generics {
+    def: GenericDefId,
+    pub(crate) params: Interned<GenericParams>,
+    parent_generics: Option<Box<Generics>>,
+}
+
+impl Generics {
+    pub(crate) fn iter_id(&self) -> impl Iterator<Item = GenericParamId> + '_ {
+        self.iter().map(|(id, _)| id)
+    }
+
+    pub(crate) fn def(&self) -> GenericDefId {
+        self.def
+    }
+
+    /// Iterator over types and const params of self, then parent.
+    pub(crate) fn iter<'a>(
+        &'a self,
+    ) -> impl DoubleEndedIterator<Item = (GenericParamId, GenericParamDataRef<'a>)> + 'a {
+        let from_toc_id = |it: &'a Generics| {
+            move |(local_id, p): (_, &'a TypeOrConstParamData)| {
+                let id = TypeOrConstParamId { parent: it.def, local_id };
+                match p {
+                    TypeOrConstParamData::TypeParamData(p) => (
+                        GenericParamId::TypeParamId(TypeParamId::from_unchecked(id)),
+                        GenericParamDataRef::TypeParamData(p),
+                    ),
+                    TypeOrConstParamData::ConstParamData(p) => (
+                        GenericParamId::ConstParamId(ConstParamId::from_unchecked(id)),
+                        GenericParamDataRef::ConstParamData(p),
+                    ),
+                }
+            }
+        };
+
+        let from_lt_id = |it: &'a Generics| {
+            move |(local_id, p): (_, &'a LifetimeParamData)| {
+                (
+                    GenericParamId::LifetimeParamId(LifetimeParamId { parent: it.def, local_id }),
+                    GenericParamDataRef::LifetimeParamData(p),
+                )
+            }
+        };
+
+        let lt_iter = self.params.iter_lt().map(from_lt_id(self));
+        self.params
+            .iter_type_or_consts()
+            .map(from_toc_id(self))
+            .chain(lt_iter)
+            .chain(self.iter_parent())
+    }
+
+    /// Iterate over types and const params without parent params.
+    pub(crate) fn iter_self<'a>(
+        &'a self,
+    ) -> impl DoubleEndedIterator<Item = (GenericParamId, GenericParamDataRef<'a>)> + 'a {
+        let from_toc_id = |it: &'a Generics| {
+            move |(local_id, p): (_, &'a TypeOrConstParamData)| {
+                let id = TypeOrConstParamId { parent: it.def, local_id };
+                match p {
+                    TypeOrConstParamData::TypeParamData(p) => (
+                        GenericParamId::TypeParamId(TypeParamId::from_unchecked(id)),
+                        GenericParamDataRef::TypeParamData(p),
+                    ),
+                    TypeOrConstParamData::ConstParamData(p) => (
+                        GenericParamId::ConstParamId(ConstParamId::from_unchecked(id)),
+                        GenericParamDataRef::ConstParamData(p),
+                    ),
+                }
+            }
+        };
+
+        let from_lt_id = |it: &'a Generics| {
+            move |(local_id, p): (_, &'a LifetimeParamData)| {
+                (
+                    GenericParamId::LifetimeParamId(LifetimeParamId { parent: it.def, local_id }),
+                    GenericParamDataRef::LifetimeParamData(p),
+                )
+            }
+        };
+
+        self.params
+            .iter_type_or_consts()
+            .map(from_toc_id(self))
+            .chain(self.params.iter_lt().map(from_lt_id(self)))
+    }
+
+    /// Iterator over types and const params of parent.
+    pub(crate) fn iter_parent(
+        &self,
+    ) -> impl DoubleEndedIterator<Item = (GenericParamId, GenericParamDataRef<'_>)> + '_ {
+        self.parent_generics().into_iter().flat_map(|it| {
+            let from_toc_id = move |(local_id, p)| {
+                let p: &_ = p;
+                let id = TypeOrConstParamId { parent: it.def, local_id };
+                match p {
+                    TypeOrConstParamData::TypeParamData(p) => (
+                        GenericParamId::TypeParamId(TypeParamId::from_unchecked(id)),
+                        GenericParamDataRef::TypeParamData(p),
+                    ),
+                    TypeOrConstParamData::ConstParamData(p) => (
+                        GenericParamId::ConstParamId(ConstParamId::from_unchecked(id)),
+                        GenericParamDataRef::ConstParamData(p),
+                    ),
+                }
+            };
+
+            let from_lt_id = move |(local_id, p): (_, _)| {
+                (
+                    GenericParamId::LifetimeParamId(LifetimeParamId { parent: it.def, local_id }),
+                    GenericParamDataRef::LifetimeParamData(p),
+                )
+            };
+            let lt_iter = it.params.iter_lt().map(from_lt_id);
+            it.params.iter_type_or_consts().map(from_toc_id).chain(lt_iter)
+        })
+    }
+
+    /// Returns total number of generic parameters in scope, including those from parent.
+    pub(crate) fn len(&self) -> usize {
+        let parent = self.parent_generics().map_or(0, Generics::len);
+        let child = self.params.len();
+        parent + child
+    }
+
+    /// Returns numbers of generic parameters excluding those from parent.
+    pub(crate) fn len_self(&self) -> usize {
+        self.params.len()
+    }
+
+    /// Returns number of generic parameter excluding those from parent
+    fn len_type_and_const_params(&self) -> usize {
+        self.params.type_or_consts.len()
+    }
+
+    /// (parent total, self param, type params, const params, impl trait list, lifetimes)
+    pub(crate) fn provenance_split(&self) -> (usize, usize, usize, usize, usize, usize) {
+        let mut self_params = 0;
+        let mut type_params = 0;
+        let mut impl_trait_params = 0;
+        let mut const_params = 0;
+        let mut lifetime_params = 0;
+        self.params.iter_type_or_consts().for_each(|(_, data)| match data {
+            TypeOrConstParamData::TypeParamData(p) => match p.provenance {
+                TypeParamProvenance::TypeParamList => type_params += 1,
+                TypeParamProvenance::TraitSelf => self_params += 1,
+                TypeParamProvenance::ArgumentImplTrait => impl_trait_params += 1,
+            },
+            TypeOrConstParamData::ConstParamData(_) => const_params += 1,
+        });
+
+        self.params.iter_lt().for_each(|(_, _)| lifetime_params += 1);
+
+        let parent_len = self.parent_generics().map_or(0, Generics::len);
+        (parent_len, self_params, type_params, const_params, impl_trait_params, lifetime_params)
+    }
+
+    pub(crate) fn type_or_const_param_idx(&self, param: TypeOrConstParamId) -> Option<usize> {
+        Some(self.find_type_or_const_param(param)?.0)
+    }
+
+    fn find_type_or_const_param(
+        &self,
+        param: TypeOrConstParamId,
+    ) -> Option<(usize, &TypeOrConstParamData)> {
+        if param.parent == self.def {
+            let idx = param.local_id.into_raw().into_u32() as usize;
+            if idx >= self.params.type_or_consts.len() {
+                return None;
+            }
+            Some((idx, &self.params.type_or_consts[param.local_id]))
+        } else {
+            self.parent_generics()
+                .and_then(|g| g.find_type_or_const_param(param))
+                // Remember that parent parameters come after parameters for self.
+                .map(|(idx, data)| (self.len_self() + idx, data))
+        }
+    }
+
+    pub(crate) fn lifetime_idx(&self, lifetime: LifetimeParamId) -> Option<usize> {
+        Some(self.find_lifetime(lifetime)?.0)
+    }
+
+    fn find_lifetime(&self, lifetime: LifetimeParamId) -> Option<(usize, &LifetimeParamData)> {
+        if lifetime.parent == self.def {
+            let idx = lifetime.local_id.into_raw().into_u32() as usize;
+            if idx >= self.params.lifetimes.len() {
+                return None;
+            }
+            Some((
+                self.len_type_and_const_params() + idx,
+                &self.params.lifetimes[lifetime.local_id],
+            ))
+        } else {
+            self.parent_generics()
+                .and_then(|g| g.find_lifetime(lifetime))
+                .map(|(idx, data)| (self.len_self() + idx, data))
+        }
+    }
+
+    pub(crate) fn parent_generics(&self) -> Option<&Generics> {
+        self.parent_generics.as_deref()
+    }
+
+    pub(crate) fn parent_or_self(&self) -> &Generics {
+        self.parent_generics.as_deref().unwrap_or(self)
+    }
+
+    /// Returns a Substitution that replaces each parameter by a bound variable.
+    pub(crate) fn bound_vars_subst(
+        &self,
+        db: &dyn HirDatabase,
+        debruijn: DebruijnIndex,
+    ) -> Substitution {
+        Substitution::from_iter(
+            Interner,
+            self.iter_id().enumerate().map(|(idx, id)| match id {
+                GenericParamId::ConstParamId(id) => BoundVar::new(debruijn, idx)
+                    .to_const(Interner, db.const_param_ty(id))
+                    .cast(Interner),
+                GenericParamId::TypeParamId(_) => {
+                    BoundVar::new(debruijn, idx).to_ty(Interner).cast(Interner)
+                }
+                GenericParamId::LifetimeParamId(_) => {
+                    BoundVar::new(debruijn, idx).to_lifetime(Interner).cast(Interner)
+                }
+            }),
+        )
+    }
+
+    /// Returns a Substitution that replaces each parameter by itself (i.e. `Ty::Param`).
+    pub(crate) fn placeholder_subst(&self, db: &dyn HirDatabase) -> Substitution {
+        Substitution::from_iter(
+            Interner,
+            self.iter_id().map(|id| match id {
+                GenericParamId::TypeParamId(id) => {
+                    crate::to_placeholder_idx(db, id.into()).to_ty(Interner).cast(Interner)
+                }
+                GenericParamId::ConstParamId(id) => crate::to_placeholder_idx(db, id.into())
+                    .to_const(Interner, db.const_param_ty(id))
+                    .cast(Interner),
+                GenericParamId::LifetimeParamId(id) => {
+                    crate::lt_to_placeholder_idx(db, id).to_lifetime(Interner).cast(Interner)
+                }
+            }),
+        )
+    }
+}
+
+fn parent_generic_def(db: &dyn DefDatabase, def: GenericDefId) -> Option<GenericDefId> {
+    let container = match def {
+        GenericDefId::FunctionId(it) => it.lookup(db).container,
+        GenericDefId::TypeAliasId(it) => it.lookup(db).container,
+        GenericDefId::ConstId(it) => it.lookup(db).container,
+        GenericDefId::EnumVariantId(it) => return Some(it.lookup(db).parent.into()),
+        GenericDefId::AdtId(_)
+        | GenericDefId::TraitId(_)
+        | GenericDefId::ImplId(_)
+        | GenericDefId::TraitAliasId(_) => return None,
+    };
+
+    match container {
+        ItemContainerId::ImplId(it) => Some(it.into()),
+        ItemContainerId::TraitId(it) => Some(it.into()),
+        ItemContainerId::ModuleId(_) | ItemContainerId::ExternBlockId(_) => None,
+    }
+}
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs
index 25bce0b31a4..c82bac0c5c8 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs
@@ -56,11 +56,12 @@ use triomphe::Arc;
 use crate::{
     db::HirDatabase,
     error_lifetime, fold_tys,
+    generics::Generics,
     infer::{coerce::CoerceMany, unify::InferenceTable},
     lower::ImplTraitLoweringMode,
     to_assoc_type_id,
     traits::FnTrait,
-    utils::{Generics, InTypeConstIdMetadata, UnevaluatedConstEvaluatorFolder},
+    utils::{InTypeConstIdMetadata, UnevaluatedConstEvaluatorFolder},
     AliasEq, AliasTy, Binders, ClosureId, Const, DomainGoal, GenericArg, Goal, ImplTraitId,
     ImplTraitIdx, InEnvironment, Interner, Lifetime, OpaqueTyId, ProjectionTy, Substitution,
     TraitEnvironment, Ty, TyBuilder, TyExt,
@@ -633,7 +634,7 @@ impl<'a> InferenceContext<'a> {
     }
 
     pub(crate) fn generics(&self) -> Option<Generics> {
-        Some(crate::utils::generics(self.db.upcast(), self.resolver.generic_def()?))
+        Some(crate::generics::generics(self.db.upcast(), self.resolver.generic_def()?))
     }
 
     // FIXME: This function should be private in module. It is currently only used in the consteval, since we need
@@ -1263,7 +1264,7 @@ impl<'a> InferenceContext<'a> {
                 forbid_unresolved_segments((ty, Some(var.into())), unresolved)
             }
             TypeNs::SelfType(impl_id) => {
-                let generics = crate::utils::generics(self.db.upcast(), impl_id.into());
+                let generics = crate::generics::generics(self.db.upcast(), impl_id.into());
                 let substs = generics.placeholder_subst(self.db);
                 let mut ty = self.db.impl_self_ty(impl_id).substitute(Interner, &substs);
 
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs
index a25498eff33..9f95e6edff2 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs
@@ -22,11 +22,13 @@ use stdx::never;
 
 use crate::{
     db::{HirDatabase, InternedClosure},
-    error_lifetime, from_chalk_trait_id, from_placeholder_idx, make_binders,
+    error_lifetime, from_chalk_trait_id, from_placeholder_idx,
+    generics::Generics,
+    make_binders,
     mir::{BorrowKind, MirSpan, MutBorrowKind, ProjectionElem},
     to_chalk_trait_id,
     traits::FnTrait,
-    utils::{self, elaborate_clause_supertraits, Generics},
+    utils::{self, elaborate_clause_supertraits},
     Adjust, Adjustment, AliasEq, AliasTy, Binders, BindingMode, ChalkTraitId, ClosureId, DynTy,
     DynTyExt, FnAbi, FnPointer, FnSig, Interner, OpaqueTy, ProjectionTyExt, Substitution, Ty,
     TyExt, WhereClause,
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs
index 4c12786362f..5786d4d3821 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs
@@ -24,6 +24,7 @@ use crate::{
     consteval,
     db::{InternedClosure, InternedCoroutine},
     error_lifetime,
+    generics::{generics, Generics},
     infer::{
         coerce::{CoerceMany, CoercionCause},
         find_continuable,
@@ -39,7 +40,6 @@ use crate::{
     primitive::{self, UintTy},
     static_lifetime, to_chalk_trait_id,
     traits::FnTrait,
-    utils::{generics, Generics},
     Adjust, Adjustment, AdtId, AutoBorrow, Binders, CallableDefId, FnAbi, FnPointer, FnSig,
     FnSubst, Interner, Rawness, Scalar, Substitution, TraitEnvironment, TraitRef, Ty, TyBuilder,
     TyExt, TyKind,
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/path.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/path.rs
index 9a1835b625b..d876008cd58 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/path.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/path.rs
@@ -12,11 +12,10 @@ use stdx::never;
 use crate::{
     builder::ParamKind,
     consteval, error_lifetime,
+    generics::generics,
     method_resolution::{self, VisibleFromModule},
-    to_chalk_trait_id,
-    utils::generics,
-    InferenceDiagnostic, Interner, Substitution, TraitRef, TraitRefExt, Ty, TyBuilder, TyExt,
-    TyKind, ValueTyDefId,
+    to_chalk_trait_id, InferenceDiagnostic, Interner, Substitution, TraitRef, TraitRefExt, Ty,
+    TyBuilder, TyExt, TyKind, ValueTyDefId,
 };
 
 use super::{ExprOrPatId, InferenceContext};
@@ -64,7 +63,7 @@ impl InferenceContext<'_> {
                 it.into()
             }
             ValueNs::ImplSelf(impl_id) => {
-                let generics = crate::utils::generics(self.db.upcast(), impl_id.into());
+                let generics = crate::generics::generics(self.db.upcast(), impl_id.into());
                 let substs = generics.placeholder_subst(self.db);
                 let ty = self.db.impl_self_ty(impl_id).substitute(Interner, &substs);
                 if let Some((AdtId::StructId(struct_id), substs)) = ty.as_adt() {
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs
index 9d596e957b6..685aceb2334 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs
@@ -22,6 +22,7 @@ extern crate ra_ap_rustc_pattern_analysis as rustc_pattern_analysis;
 mod builder;
 mod chalk_db;
 mod chalk_ext;
+mod generics;
 mod infer;
 mod inhabitedness;
 mod interner;
@@ -67,11 +68,10 @@ use rustc_hash::{FxHashMap, FxHashSet};
 use syntax::ast::{make, ConstArg};
 use traits::FnTrait;
 use triomphe::Arc;
-use utils::Generics;
 
 use crate::{
-    consteval::unknown_const, db::HirDatabase, display::HirDisplay, infer::unify::InferenceTable,
-    utils::generics,
+    consteval::unknown_const, db::HirDatabase, display::HirDisplay, generics::Generics,
+    infer::unify::InferenceTable,
 };
 
 pub use autoderef::autoderef;
@@ -289,7 +289,7 @@ impl Hash for ConstScalar {
 
 /// Return an index of a parameter in the generic type parameter list by it's id.
 pub fn param_idx(db: &dyn HirDatabase, id: TypeOrConstParamId) -> Option<usize> {
-    generics(db.upcast(), id.parent).type_or_const_param_idx(id)
+    generics::generics(db.upcast(), id.parent).type_or_const_param_idx(id)
 }
 
 pub(crate) fn wrap_empty_binders<T>(value: T) -> Binders<T>
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs
index 2e100d5c55b..053474853c7 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs
@@ -58,12 +58,13 @@ use crate::{
         unknown_const_as_generic,
     },
     db::HirDatabase,
-    error_lifetime, make_binders,
+    error_lifetime,
+    generics::{generics, Generics},
+    make_binders,
     mapping::{from_chalk_trait_id, lt_to_placeholder_idx, ToChalk},
     static_lifetime, to_assoc_type_id, to_chalk_trait_id, to_placeholder_idx,
     utils::{
-        self, all_super_trait_refs, associated_type_by_name_including_super_traits, generics,
-        Generics, InTypeConstIdMetadata,
+        all_super_trait_refs, associated_type_by_name_including_super_traits, InTypeConstIdMetadata,
     },
     AliasEq, AliasTy, Binders, BoundVar, CallableSig, Const, ConstScalar, DebruijnIndex, DynTy,
     FnAbi, FnPointer, FnSig, FnSubst, ImplTrait, ImplTraitId, ImplTraits, Interner, Lifetime,
@@ -705,7 +706,8 @@ impl<'a> TyLoweringContext<'a> {
                     None,
                 );
 
-                let len_self = utils::generics(self.db.upcast(), associated_ty.into()).len_self();
+                let len_self =
+                    crate::generics::generics(self.db.upcast(), associated_ty.into()).len_self();
 
                 let substs = Substitution::from_iter(
                     Interner,
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs
index 6d662959f19..09302846f1b 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs
@@ -28,6 +28,7 @@ use crate::{
     db::{HirDatabase, InternedClosure},
     display::HirDisplay,
     error_lifetime,
+    generics::generics,
     infer::{CaptureKind, CapturedItem, TypeMismatch},
     inhabitedness::is_ty_uninhabited_from,
     layout::LayoutError,
@@ -42,7 +43,7 @@ use crate::{
     },
     static_lifetime,
     traits::FnTrait,
-    utils::{generics, ClosureSubst},
+    utils::ClosureSubst,
     Adjust, Adjustment, AutoBorrow, CallableDefId, TyBuilder, TyExt,
 };
 
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/monomorphization.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/monomorphization.rs
index a384c9306ee..43afa615048 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/monomorphization.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/monomorphization.rs
@@ -21,8 +21,8 @@ use crate::{
     consteval::{intern_const_scalar, unknown_const},
     db::{HirDatabase, InternedClosure},
     from_placeholder_idx,
+    generics::{generics, Generics},
     infer::normalize,
-    utils::{generics, Generics},
     ClosureId, Const, Interner, ProjectionTy, Substitution, TraitEnvironment, Ty, TyKind,
 };
 
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs b/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs
index cff8e6b0368..658d4070018 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs
@@ -5,25 +5,19 @@ use std::{hash::Hash, iter};
 
 use base_db::CrateId;
 use chalk_ir::{
-    cast::Cast,
     fold::{FallibleTypeFolder, Shift},
-    BoundVar, DebruijnIndex,
+    DebruijnIndex,
 };
 use hir_def::{
     db::DefDatabase,
-    generics::{
-        GenericParamDataRef, GenericParams, LifetimeParamData, TypeOrConstParamData,
-        TypeParamProvenance, WherePredicate, WherePredicateTypeTarget,
-    },
+    generics::{WherePredicate, WherePredicateTypeTarget},
     lang_item::LangItem,
     resolver::{HasResolver, TypeNs},
     type_ref::{TraitBoundModifier, TypeRef},
-    ConstParamId, EnumId, EnumVariantId, FunctionId, GenericDefId, GenericParamId, ItemContainerId,
-    LifetimeParamId, Lookup, OpaqueInternableThing, TraitId, TypeAliasId, TypeOrConstParamId,
-    TypeParamId,
+    EnumId, EnumVariantId, FunctionId, Lookup, OpaqueInternableThing, TraitId, TypeAliasId,
+    TypeOrConstParamId,
 };
 use hir_expand::name::Name;
-use intern::Interned;
 use rustc_abi::TargetDataLayout;
 use rustc_hash::FxHashSet;
 use smallvec::{smallvec, SmallVec};
@@ -226,11 +220,6 @@ pub(super) fn associated_type_by_name_including_super_traits(
     })
 }
 
-pub(crate) fn generics(db: &dyn DefDatabase, def: GenericDefId) -> Generics {
-    let parent_generics = parent_generic_def(db, def).map(|def| Box::new(generics(db, def)));
-    Generics { def, params: db.generic_params(def), parent_generics }
-}
-
 /// It is a bit different from the rustc equivalent. Currently it stores:
 /// - 0: the function signature, encoded as a function pointer type
 /// - 1..n: generics of the parent
@@ -262,275 +251,6 @@ impl<'a> ClosureSubst<'a> {
     }
 }
 
-#[derive(Clone, Debug)]
-pub(crate) struct Generics {
-    def: GenericDefId,
-    pub(crate) params: Interned<GenericParams>,
-    parent_generics: Option<Box<Generics>>,
-}
-
-impl Generics {
-    pub(crate) fn iter_id(&self) -> impl Iterator<Item = GenericParamId> + '_ {
-        self.iter().map(|(id, _)| id)
-    }
-
-    pub(crate) fn def(&self) -> GenericDefId {
-        self.def
-    }
-
-    /// Iterator over types and const params of self, then parent.
-    pub(crate) fn iter<'a>(
-        &'a self,
-    ) -> impl DoubleEndedIterator<Item = (GenericParamId, GenericParamDataRef<'a>)> + 'a {
-        let from_toc_id = |it: &'a Generics| {
-            move |(local_id, p): (_, &'a TypeOrConstParamData)| {
-                let id = TypeOrConstParamId { parent: it.def, local_id };
-                match p {
-                    TypeOrConstParamData::TypeParamData(p) => (
-                        GenericParamId::TypeParamId(TypeParamId::from_unchecked(id)),
-                        GenericParamDataRef::TypeParamData(p),
-                    ),
-                    TypeOrConstParamData::ConstParamData(p) => (
-                        GenericParamId::ConstParamId(ConstParamId::from_unchecked(id)),
-                        GenericParamDataRef::ConstParamData(p),
-                    ),
-                }
-            }
-        };
-
-        let from_lt_id = |it: &'a Generics| {
-            move |(local_id, p): (_, &'a LifetimeParamData)| {
-                (
-                    GenericParamId::LifetimeParamId(LifetimeParamId { parent: it.def, local_id }),
-                    GenericParamDataRef::LifetimeParamData(p),
-                )
-            }
-        };
-
-        let lt_iter = self.params.iter_lt().map(from_lt_id(self));
-        self.params
-            .iter_type_or_consts()
-            .map(from_toc_id(self))
-            .chain(lt_iter)
-            .chain(self.iter_parent())
-    }
-
-    /// Iterate over types and const params without parent params.
-    pub(crate) fn iter_self<'a>(
-        &'a self,
-    ) -> impl DoubleEndedIterator<Item = (GenericParamId, GenericParamDataRef<'a>)> + 'a {
-        let from_toc_id = |it: &'a Generics| {
-            move |(local_id, p): (_, &'a TypeOrConstParamData)| {
-                let id = TypeOrConstParamId { parent: it.def, local_id };
-                match p {
-                    TypeOrConstParamData::TypeParamData(p) => (
-                        GenericParamId::TypeParamId(TypeParamId::from_unchecked(id)),
-                        GenericParamDataRef::TypeParamData(p),
-                    ),
-                    TypeOrConstParamData::ConstParamData(p) => (
-                        GenericParamId::ConstParamId(ConstParamId::from_unchecked(id)),
-                        GenericParamDataRef::ConstParamData(p),
-                    ),
-                }
-            }
-        };
-
-        let from_lt_id = |it: &'a Generics| {
-            move |(local_id, p): (_, &'a LifetimeParamData)| {
-                (
-                    GenericParamId::LifetimeParamId(LifetimeParamId { parent: it.def, local_id }),
-                    GenericParamDataRef::LifetimeParamData(p),
-                )
-            }
-        };
-
-        self.params
-            .iter_type_or_consts()
-            .map(from_toc_id(self))
-            .chain(self.params.iter_lt().map(from_lt_id(self)))
-    }
-
-    /// Iterator over types and const params of parent.
-    pub(crate) fn iter_parent(
-        &self,
-    ) -> impl DoubleEndedIterator<Item = (GenericParamId, GenericParamDataRef<'_>)> + '_ {
-        self.parent_generics().into_iter().flat_map(|it| {
-            let from_toc_id = move |(local_id, p)| {
-                let p: &_ = p;
-                let id = TypeOrConstParamId { parent: it.def, local_id };
-                match p {
-                    TypeOrConstParamData::TypeParamData(p) => (
-                        GenericParamId::TypeParamId(TypeParamId::from_unchecked(id)),
-                        GenericParamDataRef::TypeParamData(p),
-                    ),
-                    TypeOrConstParamData::ConstParamData(p) => (
-                        GenericParamId::ConstParamId(ConstParamId::from_unchecked(id)),
-                        GenericParamDataRef::ConstParamData(p),
-                    ),
-                }
-            };
-
-            let from_lt_id = move |(local_id, p): (_, _)| {
-                (
-                    GenericParamId::LifetimeParamId(LifetimeParamId { parent: it.def, local_id }),
-                    GenericParamDataRef::LifetimeParamData(p),
-                )
-            };
-            let lt_iter = it.params.iter_lt().map(from_lt_id);
-            it.params.iter_type_or_consts().map(from_toc_id).chain(lt_iter)
-        })
-    }
-
-    /// Returns total number of generic parameters in scope, including those from parent.
-    pub(crate) fn len(&self) -> usize {
-        let parent = self.parent_generics().map_or(0, Generics::len);
-        let child = self.params.len();
-        parent + child
-    }
-
-    /// Returns numbers of generic parameters and lifetimes excluding those from parent.
-    pub(crate) fn len_self(&self) -> usize {
-        self.params.len()
-    }
-
-    /// Returns number of generic parameter excluding those from parent
-    fn len_type_and_const_params(&self) -> usize {
-        self.params.type_or_consts.len()
-    }
-
-    /// (parent total, self param, type params, const params, impl trait list, lifetimes)
-    pub(crate) fn provenance_split(&self) -> (usize, usize, usize, usize, usize, usize) {
-        let mut self_params = 0;
-        let mut type_params = 0;
-        let mut impl_trait_params = 0;
-        let mut const_params = 0;
-        let mut lifetime_params = 0;
-        self.params.iter_type_or_consts().for_each(|(_, data)| match data {
-            TypeOrConstParamData::TypeParamData(p) => match p.provenance {
-                TypeParamProvenance::TypeParamList => type_params += 1,
-                TypeParamProvenance::TraitSelf => self_params += 1,
-                TypeParamProvenance::ArgumentImplTrait => impl_trait_params += 1,
-            },
-            TypeOrConstParamData::ConstParamData(_) => const_params += 1,
-        });
-
-        self.params.iter_lt().for_each(|(_, _)| lifetime_params += 1);
-
-        let parent_len = self.parent_generics().map_or(0, Generics::len);
-        (parent_len, self_params, type_params, const_params, impl_trait_params, lifetime_params)
-    }
-
-    pub(crate) fn type_or_const_param_idx(&self, param: TypeOrConstParamId) -> Option<usize> {
-        Some(self.find_type_or_const_param(param)?.0)
-    }
-
-    fn find_type_or_const_param(
-        &self,
-        param: TypeOrConstParamId,
-    ) -> Option<(usize, &TypeOrConstParamData)> {
-        if param.parent == self.def {
-            let idx = param.local_id.into_raw().into_u32() as usize;
-            if idx >= self.params.type_or_consts.len() {
-                return None;
-            }
-            Some((idx, &self.params.type_or_consts[param.local_id]))
-        } else {
-            self.parent_generics()
-                .and_then(|g| g.find_type_or_const_param(param))
-                // Remember that parent parameters come after parameters for self.
-                .map(|(idx, data)| (self.len_self() + idx, data))
-        }
-    }
-
-    pub(crate) fn lifetime_idx(&self, lifetime: LifetimeParamId) -> Option<usize> {
-        Some(self.find_lifetime(lifetime)?.0)
-    }
-
-    fn find_lifetime(&self, lifetime: LifetimeParamId) -> Option<(usize, &LifetimeParamData)> {
-        if lifetime.parent == self.def {
-            let idx = lifetime.local_id.into_raw().into_u32() as usize;
-            if idx >= self.params.lifetimes.len() {
-                return None;
-            }
-            Some((
-                self.len_type_and_const_params() + idx,
-                &self.params.lifetimes[lifetime.local_id],
-            ))
-        } else {
-            self.parent_generics()
-                .and_then(|g| g.find_lifetime(lifetime))
-                .map(|(idx, data)| (self.len_self() + idx, data))
-        }
-    }
-
-    pub(crate) fn parent_generics(&self) -> Option<&Generics> {
-        self.parent_generics.as_deref()
-    }
-
-    pub(crate) fn parent_or_self(&self) -> &Generics {
-        self.parent_generics.as_deref().unwrap_or(self)
-    }
-
-    /// Returns a Substitution that replaces each parameter by a bound variable.
-    pub(crate) fn bound_vars_subst(
-        &self,
-        db: &dyn HirDatabase,
-        debruijn: DebruijnIndex,
-    ) -> Substitution {
-        Substitution::from_iter(
-            Interner,
-            self.iter_id().enumerate().map(|(idx, id)| match id {
-                GenericParamId::ConstParamId(id) => BoundVar::new(debruijn, idx)
-                    .to_const(Interner, db.const_param_ty(id))
-                    .cast(Interner),
-                GenericParamId::TypeParamId(_) => {
-                    BoundVar::new(debruijn, idx).to_ty(Interner).cast(Interner)
-                }
-                GenericParamId::LifetimeParamId(_) => {
-                    BoundVar::new(debruijn, idx).to_lifetime(Interner).cast(Interner)
-                }
-            }),
-        )
-    }
-
-    /// Returns a Substitution that replaces each parameter by itself (i.e. `Ty::Param`).
-    pub(crate) fn placeholder_subst(&self, db: &dyn HirDatabase) -> Substitution {
-        Substitution::from_iter(
-            Interner,
-            self.iter_id().map(|id| match id {
-                GenericParamId::TypeParamId(id) => {
-                    crate::to_placeholder_idx(db, id.into()).to_ty(Interner).cast(Interner)
-                }
-                GenericParamId::ConstParamId(id) => crate::to_placeholder_idx(db, id.into())
-                    .to_const(Interner, db.const_param_ty(id))
-                    .cast(Interner),
-                GenericParamId::LifetimeParamId(id) => {
-                    crate::lt_to_placeholder_idx(db, id).to_lifetime(Interner).cast(Interner)
-                }
-            }),
-        )
-    }
-}
-
-fn parent_generic_def(db: &dyn DefDatabase, def: GenericDefId) -> Option<GenericDefId> {
-    let container = match def {
-        GenericDefId::FunctionId(it) => it.lookup(db).container,
-        GenericDefId::TypeAliasId(it) => it.lookup(db).container,
-        GenericDefId::ConstId(it) => it.lookup(db).container,
-        GenericDefId::EnumVariantId(it) => return Some(it.lookup(db).parent.into()),
-        GenericDefId::AdtId(_)
-        | GenericDefId::TraitId(_)
-        | GenericDefId::ImplId(_)
-        | GenericDefId::TraitAliasId(_) => return None,
-    };
-
-    match container {
-        ItemContainerId::ImplId(it) => Some(it.into()),
-        ItemContainerId::TraitId(it) => Some(it.into()),
-        ItemContainerId::ModuleId(_) | ItemContainerId::ExternBlockId(_) => None,
-    }
-}
-
 pub fn is_fn_unsafe_to_call(db: &dyn HirDatabase, func: FunctionId) -> bool {
     let data = db.function_data(func);
     if data.has_unsafe_kw() {