Unnamed repository; edit this file 'description' to name the repository.
-rw-r--r--crates/hir-def/src/generics.rs32
-rw-r--r--crates/hir-def/src/lib.rs1
-rw-r--r--crates/hir-ty/src/builder.rs8
-rw-r--r--crates/hir-ty/src/chalk_db.rs7
-rw-r--r--crates/hir-ty/src/chalk_ext.rs10
-rw-r--r--crates/hir-ty/src/consteval.rs13
-rw-r--r--crates/hir-ty/src/display.rs13
-rw-r--r--crates/hir-ty/src/generics.rs263
-rw-r--r--crates/hir-ty/src/infer.rs18
-rw-r--r--crates/hir-ty/src/infer/closure.rs10
-rw-r--r--crates/hir-ty/src/infer/expr.rs21
-rw-r--r--crates/hir-ty/src/infer/path.rs9
-rw-r--r--crates/hir-ty/src/lib.rs8
-rw-r--r--crates/hir-ty/src/lower.rs94
-rw-r--r--crates/hir-ty/src/mir/lower.rs3
-rw-r--r--crates/hir-ty/src/mir/monomorphization.rs2
-rw-r--r--crates/hir-ty/src/utils.rs292
17 files changed, 401 insertions, 403 deletions
diff --git a/crates/hir-def/src/generics.rs b/crates/hir-def/src/generics.rs
index acead9dc17..b9f8082391 100644
--- a/crates/hir-def/src/generics.rs
+++ b/crates/hir-def/src/generics.rs
@@ -11,7 +11,7 @@ use hir_expand::{
ExpandResult,
};
use intern::Interned;
-use la_arena::Arena;
+use la_arena::{Arena, RawIdx};
use once_cell::unsync::Lazy;
use stdx::impl_from;
use syntax::ast::{self, HasGenericParams, HasName, HasTypeBounds};
@@ -28,6 +28,9 @@ use crate::{
LocalLifetimeParamId, LocalTypeOrConstParamId, Lookup, TypeOrConstParamId, TypeParamId,
};
+const SELF_PARAM_ID_IN_SELF: la_arena::Idx<TypeOrConstParamData> =
+ LocalTypeOrConstParamId::from_raw(RawIdx::from_u32(0));
+
/// Data about a generic type parameter (to a function, struct, impl, ...).
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
pub struct TypeParamData {
@@ -441,15 +444,18 @@ impl GenericParamsCollector {
impl GenericParams {
/// Number of Generic parameters (type_or_consts + lifetimes)
+ #[inline]
pub fn len(&self) -> usize {
self.type_or_consts.len() + self.lifetimes.len()
}
+ #[inline]
pub fn is_empty(&self) -> bool {
self.len() == 0
}
/// Iterator of type_or_consts field
+ #[inline]
pub fn iter_type_or_consts(
&self,
) -> impl DoubleEndedIterator<Item = (LocalTypeOrConstParamId, &TypeOrConstParamData)> {
@@ -457,6 +463,7 @@ impl GenericParams {
}
/// Iterator of lifetimes field
+ #[inline]
pub fn iter_lt(
&self,
) -> impl DoubleEndedIterator<Item = (LocalLifetimeParamId, &LifetimeParamData)> {
@@ -605,17 +612,18 @@ impl GenericParams {
})
}
- pub fn find_trait_self_param(&self) -> Option<LocalTypeOrConstParamId> {
- self.type_or_consts.iter().find_map(|(id, p)| {
- matches!(
- p,
- TypeOrConstParamData::TypeParamData(TypeParamData {
- provenance: TypeParamProvenance::TraitSelf,
- ..
- })
- )
- .then(|| id)
- })
+ pub fn trait_self_param(&self) -> Option<LocalTypeOrConstParamId> {
+ if self.type_or_consts.is_empty() {
+ return None;
+ }
+ matches!(
+ self.type_or_consts[SELF_PARAM_ID_IN_SELF],
+ TypeOrConstParamData::TypeParamData(TypeParamData {
+ provenance: TypeParamProvenance::TraitSelf,
+ ..
+ })
+ )
+ .then(|| SELF_PARAM_ID_IN_SELF)
}
pub fn find_lifetime_by_name(
diff --git a/crates/hir-def/src/lib.rs b/crates/hir-def/src/lib.rs
index 0dcd9129d6..f6fe0c618a 100644
--- a/crates/hir-def/src/lib.rs
+++ b/crates/hir-def/src/lib.rs
@@ -923,6 +923,7 @@ pub enum GenericDefId {
ImplId(ImplId),
// enum variants cannot have generics themselves, but their parent enums
// can, and this makes some code easier to write
+ // FIXME: Try to remove this as that will reduce the amount of query slots generated per enum?
EnumVariantId(EnumVariantId),
// consts can have type parameters from their parents (i.e. associated consts of traits)
ConstId(ConstId),
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..8b6cde975f 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};
@@ -72,12 +71,12 @@ impl From<MirEvalError> for ConstEvalError {
}
}
-pub(crate) fn path_to_const(
+pub(crate) fn path_to_const<'g>(
db: &dyn HirDatabase,
resolver: &Resolver,
path: &Path,
mode: ParamLoweringMode,
- args: impl FnOnce() -> Option<Generics>,
+ args: impl FnOnce() -> Option<&'g Generics>,
debruijn: DebruijnIndex,
expected_ty: Ty,
) -> Option<Const> {
@@ -90,7 +89,7 @@ pub(crate) fn path_to_const(
}
ParamLoweringMode::Variable => {
let args = args();
- match args.as_ref().and_then(|args| args.type_or_const_param_idx(p.into())) {
+ match args.and_then(|args| args.type_or_const_param_idx(p.into())) {
Some(it) => ConstValue::BoundVar(BoundVar::new(debruijn, it)),
None => {
never!(
diff --git a/crates/hir-ty/src/display.rs b/crates/hir-ty/src/display.rs
index cd31845a51..66b5398b88 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,
@@ -493,7 +494,7 @@ impl HirDisplay for Const {
ConstValue::Placeholder(idx) => {
let id = from_placeholder_idx(f.db, *idx);
let generics = generics(f.db.upcast(), id.parent);
- let param_data = &generics.params[id.local_id];
+ let param_data = &generics[id.local_id];
write!(f, "{}", param_data.name().unwrap().display(f.db.upcast()))?;
Ok(())
}
@@ -988,7 +989,7 @@ impl HirDisplay for Ty {
if parameters.len(Interner) > 0 {
let generics = generics(db.upcast(), def.into());
- let (parent_len, self_, type_, const_, impl_, lifetime) =
+ let (parent_len, self_param, type_, const_, impl_, lifetime) =
generics.provenance_split();
let parameters = parameters.as_slice(Interner);
// We print all params except implicit impl Trait params. Still a bit weird; should we leave out parent and self?
@@ -996,7 +997,7 @@ impl HirDisplay for Ty {
// `parameters` are in the order of fn's params (including impl traits), fn's lifetimes
// parent's params (those from enclosing impl or trait, if any).
let (fn_params, other) =
- parameters.split_at(self_ + type_ + const_ + lifetime);
+ parameters.split_at(self_param as usize + type_ + const_ + lifetime);
let (_impl, parent_params) = other.split_at(impl_);
debug_assert_eq!(parent_params.len(), parent_len);
@@ -1215,7 +1216,7 @@ impl HirDisplay for Ty {
TyKind::Placeholder(idx) => {
let id = from_placeholder_idx(db, *idx);
let generics = generics(db.upcast(), id.parent);
- let param_data = &generics.params[id.local_id];
+ let param_data = &generics[id.local_id];
match param_data {
TypeOrConstParamData::TypeParamData(p) => match p.provenance {
TypeParamProvenance::TypeParamList | TypeParamProvenance::TraitSelf => {
@@ -1797,7 +1798,7 @@ impl HirDisplay for LifetimeData {
LifetimeData::Placeholder(idx) => {
let id = lt_from_placeholder_idx(f.db, *idx);
let generics = generics(f.db.upcast(), id.parent);
- let param_data = &generics.params[id.local_id];
+ let param_data = &generics[id.local_id];
write!(f, "{}", param_data.name.display(f.db.upcast()))?;
Ok(())
}
diff --git a/crates/hir-ty/src/generics.rs b/crates/hir-ty/src/generics.rs
new file mode 100644
index 0000000000..ea10e6881e
--- /dev/null
+++ b/crates/hir-ty/src/generics.rs
@@ -0,0 +1,263 @@
+//! Utilities for working with generics.
+//!
+//! The layout for generics as expected by chalk are as follows:
+//! - Optional Self parameter
+//! - Type or Const parameters
+//! - Lifetime parameters
+//! - Parent parameters
+//!
+//! where parent follows the same scheme.
+use std::ops;
+
+use chalk_ir::{cast::Cast as _, BoundVar, DebruijnIndex};
+use hir_def::{
+ db::DefDatabase,
+ generics::{
+ GenericParamDataRef, GenericParams, LifetimeParamData, TypeOrConstParamData,
+ TypeParamProvenance,
+ },
+ ConstParamId, GenericDefId, GenericParamId, ItemContainerId, LifetimeParamId,
+ LocalLifetimeParamId, LocalTypeOrConstParamId, Lookup, TypeOrConstParamId, TypeParamId,
+};
+use intern::Interned;
+
+use crate::{db::HirDatabase, lt_to_placeholder_idx, to_placeholder_idx, 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,
+ params: Interned<GenericParams>,
+ parent_generics: Option<Box<Generics>>,
+}
+
+impl<T> ops::Index<T> for Generics
+where
+ GenericParams: ops::Index<T>,
+{
+ type Output = <GenericParams as ops::Index<T>>::Output;
+ fn index(&self, index: T) -> &Self::Output {
+ &self.params[index]
+ }
+}
+
+impl Generics {
+ pub(crate) fn def(&self) -> GenericDefId {
+ self.def
+ }
+
+ pub(crate) fn iter_id(&self) -> impl Iterator<Item = GenericParamId> + '_ {
+ self.iter_self_id().chain(self.iter_parent_id())
+ }
+
+ pub(crate) fn iter_self_id(&self) -> impl Iterator<Item = GenericParamId> + '_ {
+ self.iter_self().map(|(id, _)| id)
+ }
+
+ fn iter_parent_id(&self) -> impl Iterator<Item = GenericParamId> + '_ {
+ self.iter_parent().map(|(id, _)| id)
+ }
+
+ pub(crate) fn iter_self_type_or_consts(
+ &self,
+ ) -> impl DoubleEndedIterator<Item = (LocalTypeOrConstParamId, &TypeOrConstParamData)> {
+ self.params.iter_type_or_consts()
+ }
+
+ /// Iterate over the params followed by the parent params.
+ pub(crate) fn iter(
+ &self,
+ ) -> impl DoubleEndedIterator<Item = (GenericParamId, GenericParamDataRef<'_>)> + '_ {
+ self.iter_self().chain(self.iter_parent())
+ }
+
+ /// Iterate over the params without parent params.
+ pub(crate) fn iter_self(
+ &self,
+ ) -> impl DoubleEndedIterator<Item = (GenericParamId, GenericParamDataRef<'_>)> + '_ {
+ 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.
+ fn iter_parent(
+ &self,
+ ) -> impl DoubleEndedIterator<Item = (GenericParamId, GenericParamDataRef<'_>)> + '_ {
+ self.parent_generics().into_iter().flat_map(|it| {
+ let lt_iter = it.params.iter_lt().map(from_lt_id(it));
+ it.params.iter_type_or_consts().map(from_toc_id(it)).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()
+ }
+
+ /// (parent total, self param, type params, const params, impl trait list, lifetimes)
+ pub(crate) fn provenance_split(&self) -> (usize, bool, usize, usize, usize, usize) {
+ let mut self_param = false;
+ let mut type_params = 0;
+ let mut impl_trait_params = 0;
+ let mut const_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_param |= true,
+ TypeParamProvenance::ArgumentImplTrait => impl_trait_params += 1,
+ },
+ TypeOrConstParamData::ConstParamData(_) => const_params += 1,
+ });
+
+ let lifetime_params = self.params.iter_lt().count();
+
+ let parent_len = self.parent_generics().map_or(0, Generics::len);
+ (parent_len, self_param, type_params, const_params, impl_trait_params, lifetime_params)
+ }
+
+ pub(crate) fn type_or_const_param_idx(&self, param: TypeOrConstParamId) -> Option<usize> {
+ self.find_type_or_const_param(param)
+ }
+
+ fn find_type_or_const_param(&self, param: TypeOrConstParamId) -> Option<usize> {
+ if param.parent == self.def {
+ let idx = param.local_id.into_raw().into_u32() as usize;
+ debug_assert!(idx <= self.params.type_or_consts.len());
+ Some(idx)
+ } else {
+ debug_assert_eq!(self.parent_generics().map(|it| it.def), Some(param.parent));
+ self.parent_generics()
+ .and_then(|g| g.find_type_or_const_param(param))
+ // Remember that parent parameters come after parameters for self.
+ .map(|idx| self.len_self() + idx)
+ }
+ }
+
+ pub(crate) fn lifetime_idx(&self, lifetime: LifetimeParamId) -> Option<usize> {
+ self.find_lifetime(lifetime)
+ }
+
+ fn find_lifetime(&self, lifetime: LifetimeParamId) -> Option<usize> {
+ if lifetime.parent == self.def {
+ let idx = lifetime.local_id.into_raw().into_u32() as usize;
+ debug_assert!(idx <= self.params.lifetimes.len());
+ Some(self.params.type_or_consts.len() + idx)
+ } else {
+ debug_assert_eq!(self.parent_generics().map(|it| it.def), Some(lifetime.parent));
+ self.parent_generics()
+ .and_then(|g| g.find_lifetime(lifetime))
+ .map(|idx| self.len_self() + idx)
+ }
+ }
+
+ 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) => {
+ to_placeholder_idx(db, id.into()).to_ty(Interner).cast(Interner)
+ }
+ GenericParamId::ConstParamId(id) => to_placeholder_idx(db, id.into())
+ .to_const(Interner, db.const_param_ty(id))
+ .cast(Interner),
+ GenericParamId::LifetimeParamId(id) => {
+ 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,
+ }
+}
+
+fn from_toc_id<'a>(
+ it: &'a Generics,
+) -> impl Fn(
+ (LocalTypeOrConstParamId, &'a TypeOrConstParamData),
+) -> (GenericParamId, GenericParamDataRef<'a>) {
+ move |(local_id, 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),
+ ),
+ }
+ }
+}
+
+fn from_lt_id<'a>(
+ it: &'a Generics,
+) -> impl Fn((LocalLifetimeParamId, &'a LifetimeParamData)) -> (GenericParamId, GenericParamDataRef<'a>)
+{
+ move |(local_id, p): (_, _)| {
+ (
+ GenericParamId::LifetimeParamId(LifetimeParamId { parent: it.def, local_id }),
+ GenericParamDataRef::LifetimeParamData(p),
+ )
+ }
+}
diff --git a/crates/hir-ty/src/infer.rs b/crates/hir-ty/src/infer.rs
index 25bce0b31a..aeb6e69ce7 100644
--- a/crates/hir-ty/src/infer.rs
+++ b/crates/hir-ty/src/infer.rs
@@ -49,6 +49,7 @@ use hir_def::{
use hir_expand::name::{name, Name};
use indexmap::IndexSet;
use la_arena::{ArenaMap, Entry};
+use once_cell::unsync::OnceCell;
use rustc_hash::{FxHashMap, FxHashSet};
use stdx::{always, never};
use triomphe::Arc;
@@ -56,11 +57,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,
@@ -526,6 +528,7 @@ pub(crate) struct InferenceContext<'a> {
pub(crate) owner: DefWithBodyId,
pub(crate) body: &'a Body,
pub(crate) resolver: Resolver,
+ generics: OnceCell<Option<Generics>>,
table: unify::InferenceTable<'a>,
/// The traits in scope, disregarding block modules. This is used for caching purposes.
traits_in_scope: FxHashSet<TraitId>,
@@ -611,6 +614,7 @@ impl<'a> InferenceContext<'a> {
) -> Self {
let trait_env = db.trait_environment_for_body(owner);
InferenceContext {
+ generics: OnceCell::new(),
result: InferenceResult::default(),
table: unify::InferenceTable::new(db, trait_env),
tuple_field_accesses_rev: Default::default(),
@@ -632,8 +636,14 @@ impl<'a> InferenceContext<'a> {
}
}
- pub(crate) fn generics(&self) -> Option<Generics> {
- Some(crate::utils::generics(self.db.upcast(), self.resolver.generic_def()?))
+ pub(crate) fn generics(&self) -> Option<&Generics> {
+ self.generics
+ .get_or_init(|| {
+ self.resolver
+ .generic_def()
+ .map(|def| crate::generics::generics(self.db.upcast(), def))
+ })
+ .as_ref()
}
// FIXME: This function should be private in module. It is currently only used in the consteval, since we need
@@ -1263,7 +1273,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..b7c7b66545 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,
@@ -337,7 +339,7 @@ impl CapturedItemWithoutTy {
fn replace_placeholder_with_binder(ctx: &mut InferenceContext<'_>, ty: Ty) -> Binders<Ty> {
struct Filler<'a> {
db: &'a dyn HirDatabase,
- generics: Generics,
+ generics: &'a Generics,
}
impl FallibleTypeFolder<Interner> for Filler<'_> {
type Error = ();
@@ -380,7 +382,7 @@ impl CapturedItemWithoutTy {
};
let filler = &mut Filler { db: ctx.db, generics };
let result = ty.clone().try_fold_with(filler, DebruijnIndex::INNERMOST).unwrap_or(ty);
- make_binders(ctx.db, &filler.generics, result)
+ make_binders(ctx.db, filler.generics, result)
}
}
}
diff --git a/crates/hir-ty/src/infer/expr.rs b/crates/hir-ty/src/infer/expr.rs
index 4c12786362..95f28531ac 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,
@@ -1830,13 +1830,13 @@ impl InferenceContext<'_> {
) -> Substitution {
let (
parent_params,
- self_params,
+ has_self_param,
type_params,
const_params,
impl_trait_params,
lifetime_params,
) = def_generics.provenance_split();
- assert_eq!(self_params, 0); // method shouldn't have another Self param
+ assert!(!has_self_param); // method shouldn't have another Self param
let total_len =
parent_params + type_params + const_params + impl_trait_params + lifetime_params;
let mut substs = Vec::with_capacity(total_len);
@@ -1844,13 +1844,11 @@ impl InferenceContext<'_> {
// handle provided arguments
if let Some(generic_args) = generic_args {
// if args are provided, it should be all of them, but we can't rely on that
- for (arg, kind_id) in generic_args
- .args
- .iter()
- .take(type_params + const_params + lifetime_params)
- .zip(def_generics.iter_id())
+ let self_params = type_params + const_params + lifetime_params;
+ for (arg, kind_id) in
+ generic_args.args.iter().zip(def_generics.iter_self_id()).take(self_params)
{
- if let Some(g) = generic_arg_to_chalk(
+ let arg = generic_arg_to_chalk(
self.db,
kind_id,
arg,
@@ -1869,9 +1867,8 @@ impl InferenceContext<'_> {
)
},
|this, lt_ref| this.make_lifetime(lt_ref),
- ) {
- substs.push(g);
- }
+ );
+ substs.push(arg);
}
};
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<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/crates/hir-ty/src/lower.rs b/crates/hir-ty/src/lower.rs
index 2e100d5c55..30d6b2f664 100644
--- a/crates/hir-ty/src/lower.rs
+++ b/crates/hir-ty/src/lower.rs
@@ -45,6 +45,7 @@ use hir_def::{
use hir_expand::{name::Name, ExpandResult};
use intern::Interned;
use la_arena::{Arena, ArenaMap};
+use once_cell::unsync::OnceCell;
use rustc_hash::FxHashSet;
use smallvec::SmallVec;
use stdx::{impl_from, never};
@@ -58,12 +59,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,
@@ -121,6 +123,7 @@ impl ImplTraitLoweringState {
pub struct TyLoweringContext<'a> {
pub db: &'a dyn HirDatabase,
resolver: &'a Resolver,
+ generics: OnceCell<Option<Generics>>,
in_binders: DebruijnIndex,
// FIXME: Should not be an `Option` but `Resolver` currently does not return owners in all cases
// where expected
@@ -152,6 +155,7 @@ impl<'a> TyLoweringContext<'a> {
Self {
db,
resolver,
+ generics: OnceCell::new(),
owner,
in_binders,
impl_trait_mode,
@@ -174,6 +178,7 @@ impl<'a> TyLoweringContext<'a> {
impl_trait_mode,
expander: RefCell::new(expander),
unsized_types: RefCell::new(unsized_types),
+ generics: self.generics.clone(),
..*self
};
let result = f(&new_ctx);
@@ -245,8 +250,10 @@ impl<'a> TyLoweringContext<'a> {
)
}
- fn generics(&self) -> Option<Generics> {
- Some(generics(self.db.upcast(), self.resolver.generic_def()?))
+ fn generics(&self) -> Option<&Generics> {
+ self.generics
+ .get_or_init(|| self.resolver.generic_def().map(|def| generics(self.db.upcast(), def)))
+ .as_ref()
}
pub fn lower_ty_ext(&self, type_ref: &TypeRef) -> (Ty, Option<TypeNs>) {
@@ -374,7 +381,7 @@ impl<'a> TyLoweringContext<'a> {
counter.set(idx + count_impl_traits(type_ref) as u16);
let (
_parent_params,
- self_params,
+ self_param,
type_params,
const_params,
_impl_trait_params,
@@ -385,7 +392,7 @@ impl<'a> TyLoweringContext<'a> {
.provenance_split();
TyKind::BoundVar(BoundVar::new(
self.in_binders,
- idx as usize + self_params + type_params + const_params,
+ idx as usize + self_param as usize + type_params + const_params,
))
.intern(Interner)
}
@@ -705,7 +712,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,
@@ -815,14 +823,14 @@ impl<'a> TyLoweringContext<'a> {
let def_generics = generics(self.db.upcast(), def);
let (
parent_params,
- self_params,
+ self_param,
type_params,
const_params,
impl_trait_params,
lifetime_params,
) = def_generics.provenance_split();
let item_len =
- self_params + type_params + const_params + impl_trait_params + lifetime_params;
+ self_param as usize + type_params + const_params + impl_trait_params + lifetime_params;
let total_len = parent_params + item_len;
let ty_error = TyKind::Error.intern(Interner).cast(Interner);
@@ -830,18 +838,16 @@ impl<'a> TyLoweringContext<'a> {
let mut def_generic_iter = def_generics.iter_id();
let fill_self_params = || {
- for x in explicit_self_ty
- .into_iter()
- .map(|x| x.cast(Interner))
- .chain(iter::repeat(ty_error.clone()))
- .take(self_params)
- {
+ if self_param {
+ let self_ty =
+ explicit_self_ty.map(|x| x.cast(Interner)).unwrap_or_else(|| ty_error.clone());
+
if let Some(id) = def_generic_iter.next() {
assert!(matches!(
id,
GenericParamId::TypeParamId(_) | GenericParamId::LifetimeParamId(_)
));
- substs.push(x);
+ substs.push(self_ty);
}
}
};
@@ -852,11 +858,11 @@ impl<'a> TyLoweringContext<'a> {
fill_self_params();
}
let expected_num = if generic_args.has_self_type {
- self_params + type_params + const_params
+ self_param as usize + type_params + const_params
} else {
type_params + const_params
};
- let skip = if generic_args.has_self_type && self_params == 0 { 1 } else { 0 };
+ let skip = if generic_args.has_self_type && !self_param { 1 } else { 0 };
// if args are provided, it should be all of them, but we can't rely on that
for arg in generic_args
.args
@@ -866,7 +872,7 @@ impl<'a> TyLoweringContext<'a> {
.take(expected_num)
{
if let Some(id) = def_generic_iter.next() {
- if let Some(x) = generic_arg_to_chalk(
+ let arg = generic_arg_to_chalk(
self.db,
id,
arg,
@@ -874,13 +880,9 @@ impl<'a> TyLoweringContext<'a> {
|_, type_ref| self.lower_ty(type_ref),
|_, const_ref, ty| self.lower_const(const_ref, ty),
|_, lifetime_ref| self.lower_lifetime(lifetime_ref),
- ) {
- had_explicit_args = true;
- substs.push(x);
- } else {
- // we just filtered them out
- never!("Unexpected lifetime argument");
- }
+ );
+ had_explicit_args = true;
+ substs.push(arg);
}
}
@@ -893,7 +895,7 @@ impl<'a> TyLoweringContext<'a> {
// Taking into the fact that def_generic_iter will always have lifetimes at the end
// Should have some test cases tho to test this behaviour more properly
if let Some(id) = def_generic_iter.next() {
- if let Some(x) = generic_arg_to_chalk(
+ let arg = generic_arg_to_chalk(
self.db,
id,
arg,
@@ -901,13 +903,9 @@ impl<'a> TyLoweringContext<'a> {
|_, type_ref| self.lower_ty(type_ref),
|_, const_ref, ty| self.lower_const(const_ref, ty),
|_, lifetime_ref| self.lower_lifetime(lifetime_ref),
- ) {
- had_explicit_args = true;
- substs.push(x);
- } else {
- // Never return a None explicitly
- never!("Unexpected None by generic_arg_to_chalk");
- }
+ );
+ had_explicit_args = true;
+ substs.push(arg);
}
}
} else {
@@ -1176,7 +1174,7 @@ impl<'a> TyLoweringContext<'a> {
let ty = if let Some(target_param_idx) = target_param_idx {
let mut counter = 0;
let generics = self.generics().expect("generics in scope");
- for (idx, data) in generics.params.type_or_consts.iter() {
+ for (idx, data) in generics.iter_self_type_or_consts() {
// Count the number of `impl Trait` things that appear before
// the target of our `bound`.
// Our counter within `impl_trait_mode` should be that number
@@ -1478,7 +1476,7 @@ fn named_associated_type_shorthand_candidates<R>(
// Handle `Self::Type` referring to own associated type in trait definitions
if let GenericDefId::TraitId(trait_id) = param_id.parent() {
let trait_generics = generics(db.upcast(), trait_id.into());
- if trait_generics.params[param_id.local_id()].is_trait_self() {
+ if trait_generics[param_id.local_id()].is_trait_self() {
let def_generics = generics(db.upcast(), def);
let starting_idx = match def {
GenericDefId::TraitId(_) => 0,
@@ -2168,7 +2166,6 @@ pub(crate) fn lower_to_chalk_mutability(m: hir_def::type_ref::Mutability) -> Mut
/// Checks if the provided generic arg matches its expected kind, then lower them via
/// provided closures. Use unknown if there was kind mismatch.
///
-/// Returns `Some` of the lowered generic arg. `None` if the provided arg is a lifetime.
pub(crate) fn generic_arg_to_chalk<'a, T>(
db: &dyn HirDatabase,
kind_id: GenericParamId,
@@ -2177,7 +2174,7 @@ pub(crate) fn generic_arg_to_chalk<'a, T>(
for_type: impl FnOnce(&mut T, &TypeRef) -> Ty + 'a,
for_const: impl FnOnce(&mut T, &ConstRef, Ty) -> Const + 'a,
for_lifetime: impl FnOnce(&mut T, &LifetimeRef) -> Lifetime + 'a,
-) -> Option<crate::GenericArg> {
+) -> crate::GenericArg {
let kind = match kind_id {
GenericParamId::TypeParamId(_) => ParamKind::Type,
GenericParamId::ConstParamId(id) => {
@@ -2186,7 +2183,7 @@ pub(crate) fn generic_arg_to_chalk<'a, T>(
}
GenericParamId::LifetimeParamId(_) => ParamKind::Lifetime,
};
- Some(match (arg, kind) {
+ match (arg, kind) {
(GenericArg::Type(type_ref), ParamKind::Type) => for_type(this, type_ref).cast(Interner),
(GenericArg::Const(c), ParamKind::Const(c_ty)) => for_const(this, c, c_ty).cast(Interner),
(GenericArg::Lifetime(lifetime_ref), ParamKind::Lifetime) => {
@@ -2199,11 +2196,12 @@ pub(crate) fn generic_arg_to_chalk<'a, T>(
// as types. Maybe here is not the best place to do it, but
// it works.
if let TypeRef::Path(p) = t {
- let p = p.mod_path()?;
- if p.kind == PathKind::Plain {
- if let [n] = p.segments() {
- let c = ConstRef::Path(n.clone());
- return Some(for_const(this, &c, c_ty).cast(Interner));
+ if let Some(p) = p.mod_path() {
+ if p.kind == PathKind::Plain {
+ if let [n] = p.segments() {
+ let c = ConstRef::Path(n.clone());
+ return for_const(this, &c, c_ty).cast(Interner);
+ }
}
}
}
@@ -2212,17 +2210,17 @@ pub(crate) fn generic_arg_to_chalk<'a, T>(
(GenericArg::Lifetime(_), ParamKind::Const(c_ty)) => unknown_const_as_generic(c_ty),
(GenericArg::Type(_), ParamKind::Lifetime) => error_lifetime().cast(Interner),
(GenericArg::Const(_), ParamKind::Lifetime) => error_lifetime().cast(Interner),
- })
+ }
}
-pub(crate) fn const_or_path_to_chalk(
+pub(crate) fn const_or_path_to_chalk<'g>(
db: &dyn HirDatabase,
resolver: &Resolver,
owner: TypeOwnerId,
expected_ty: Ty,
value: &ConstRef,
mode: ParamLoweringMode,
- args: impl FnOnce() -> Option<Generics>,
+ args: impl FnOnce() -> Option<&'g Generics>,
debruijn: DebruijnIndex,
) -> Const {
match value {
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..969999cdb8 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};
@@ -161,7 +155,7 @@ impl Iterator for ClauseElaborator<'_> {
fn direct_super_traits(db: &dyn DefDatabase, trait_: TraitId, cb: impl FnMut(TraitId)) {
let resolver = trait_.resolver(db);
let generic_params = db.generic_params(trait_.into());
- let trait_self = generic_params.find_trait_self_param();
+ let trait_self = generic_params.trait_self_param();
generic_params
.where_predicates
.iter()
@@ -194,7 +188,7 @@ fn direct_super_traits(db: &dyn DefDatabase, trait_: TraitId, cb: impl FnMut(Tra
fn direct_super_trait_refs(db: &dyn HirDatabase, trait_ref: &TraitRef, cb: impl FnMut(TraitRef)) {
let generic_params = db.generic_params(trait_ref.hir_trait_id().into());
- let trait_self = match generic_params.find_trait_self_param() {
+ let trait_self = match generic_params.trait_self_param() {
Some(p) => TypeOrConstParamId { parent: trait_ref.hir_trait_id().into(), local_id: p },
None => return,
};
@@ -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() {