diff --git a/crates/hir-ty/src/builder.rs b/crates/hir-ty/src/builder.rs index d6374658f1..52411f94ad 100644 --- a/crates/hir-ty/src/builder.rs +++ b/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/crates/hir-ty/src/chalk_db.rs b/crates/hir-ty/src/chalk_db.rs index 149e4dbaa5..0d8ceb68b2 100644 --- a/crates/hir-ty/src/chalk_db.rs +++ b/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/crates/hir-ty/src/chalk_ext.rs b/crates/hir-ty/src/chalk_ext.rs index d99ef6679e..4279c75651 100644 --- a/crates/hir-ty/src/chalk_ext.rs +++ b/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/crates/hir-ty/src/consteval.rs b/crates/hir-ty/src/consteval.rs index f09277a92e..aa7fc598b4 100644 --- a/crates/hir-ty/src/consteval.rs +++ b/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/crates/hir-ty/src/display.rs b/crates/hir-ty/src/display.rs index cd31845a51..de5e400194 100644 --- a/crates/hir-ty/src/display.rs +++ b/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/crates/hir-ty/src/generics.rs b/crates/hir-ty/src/generics.rs new file mode 100644 index 0000000000..235e04023d --- /dev/null +++ b/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, + parent_generics: Option>, +} + +impl Generics { + pub(crate) fn iter_id(&self) -> impl Iterator + '_ { + 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)> + '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)> + '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)> + '_ { + 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 { + 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 { + 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 { + 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/crates/hir-ty/src/infer.rs b/crates/hir-ty/src/infer.rs index 25bce0b31a..c82bac0c5c 100644 --- a/crates/hir-ty/src/infer.rs +++ b/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 { - 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/crates/hir-ty/src/infer/closure.rs b/crates/hir-ty/src/infer/closure.rs index a25498eff3..9f95e6edff 100644 --- a/crates/hir-ty/src/infer/closure.rs +++ b/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/crates/hir-ty/src/infer/expr.rs b/crates/hir-ty/src/infer/expr.rs index 4c12786362..5786d4d382 100644 --- a/crates/hir-ty/src/infer/expr.rs +++ b/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/crates/hir-ty/src/infer/path.rs b/crates/hir-ty/src/infer/path.rs index 9a1835b625..d876008cd5 100644 --- a/crates/hir-ty/src/infer/path.rs +++ b/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/crates/hir-ty/src/lib.rs b/crates/hir-ty/src/lib.rs index 9d596e957b..685aceb233 100644 --- a/crates/hir-ty/src/lib.rs +++ b/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 { - 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(value: T) -> Binders diff --git a/crates/hir-ty/src/lower.rs b/crates/hir-ty/src/lower.rs index 2e100d5c55..053474853c 100644 --- a/crates/hir-ty/src/lower.rs +++ b/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/crates/hir-ty/src/mir/lower.rs b/crates/hir-ty/src/mir/lower.rs index 6d662959f1..09302846f1 100644 --- a/crates/hir-ty/src/mir/lower.rs +++ b/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/crates/hir-ty/src/mir/monomorphization.rs b/crates/hir-ty/src/mir/monomorphization.rs index a384c9306e..43afa61504 100644 --- a/crates/hir-ty/src/mir/monomorphization.rs +++ b/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/crates/hir-ty/src/utils.rs b/crates/hir-ty/src/utils.rs index cff8e6b036..658d407001 100644 --- a/crates/hir-ty/src/utils.rs +++ b/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, - parent_generics: Option>, -} - -impl Generics { - pub(crate) fn iter_id(&self) -> impl Iterator + '_ { - 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)> + '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)> + '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)> + '_ { - 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 { - 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 { - 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 { - 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() {