Unnamed repository; edit this file 'description' to name the repository.
update `Generics` iter methods to return `GenericParamId`
dfireBird 2024-03-18
parent d6e3929 · commit a6c8cbf
-rw-r--r--crates/hir-def/src/generics.rs40
-rw-r--r--crates/hir-ty/src/builder.rs19
-rw-r--r--crates/hir-ty/src/infer/expr.rs21
-rw-r--r--crates/hir-ty/src/lib.rs2
-rw-r--r--crates/hir-ty/src/lower.rs49
-rw-r--r--crates/hir-ty/src/mir/monomorphization.rs12
-rw-r--r--crates/hir-ty/src/utils.rs149
7 files changed, 181 insertions, 111 deletions
diff --git a/crates/hir-def/src/generics.rs b/crates/hir-def/src/generics.rs
index 8bdd9c6587..c141acd2ec 100644
--- a/crates/hir-def/src/generics.rs
+++ b/crates/hir-def/src/generics.rs
@@ -102,6 +102,46 @@ impl TypeOrConstParamData {
impl_from!(TypeParamData, ConstParamData for TypeOrConstParamData);
+#[derive(Clone, PartialEq, Eq, Debug, Hash)]
+pub enum GenericParamData {
+ TypeParamData(TypeParamData),
+ ConstParamData(ConstParamData),
+ LifetimeParamData(LifetimeParamData),
+}
+
+impl GenericParamData {
+ pub fn name(&self) -> Option<&Name> {
+ match self {
+ GenericParamData::TypeParamData(it) => it.name.as_ref(),
+ GenericParamData::ConstParamData(it) => Some(&it.name),
+ GenericParamData::LifetimeParamData(it) => Some(&it.name),
+ }
+ }
+
+ pub fn type_param(&self) -> Option<&TypeParamData> {
+ match self {
+ GenericParamData::TypeParamData(it) => Some(it),
+ _ => None,
+ }
+ }
+
+ pub fn const_param(&self) -> Option<&ConstParamData> {
+ match self {
+ GenericParamData::ConstParamData(it) => Some(it),
+ _ => None,
+ }
+ }
+
+ pub fn lifetime_param(&self) -> Option<&LifetimeParamData> {
+ match self {
+ GenericParamData::LifetimeParamData(it) => Some(it),
+ _ => None,
+ }
+ }
+}
+
+impl_from!(TypeParamData, ConstParamData, LifetimeParamData for GenericParamData);
+
/// Data about the generic parameters of a function, struct, impl, etc.
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
pub struct GenericParams {
diff --git a/crates/hir-ty/src/builder.rs b/crates/hir-ty/src/builder.rs
index e311338a2d..536542f9a0 100644
--- a/crates/hir-ty/src/builder.rs
+++ b/crates/hir-ty/src/builder.rs
@@ -9,8 +9,7 @@ use chalk_ir::{
AdtId, DebruijnIndex, Scalar,
};
use hir_def::{
- builtin_type::BuiltinType, generics::TypeOrConstParamData, ConstParamId, DefWithBodyId,
- GenericDefId, TraitId, TypeAliasId,
+ builtin_type::BuiltinType, DefWithBodyId, GenericDefId, GenericParamId, TraitId, TypeAliasId,
};
use smallvec::SmallVec;
@@ -209,10 +208,11 @@ impl TyBuilder<()> {
Substitution::from_iter(
Interner,
params.iter_id().map(|id| match id {
- either::Either::Left(_) => TyKind::Error.intern(Interner).cast(Interner),
- either::Either::Right(id) => {
+ GenericParamId::TypeParamId(_) => TyKind::Error.intern(Interner).cast(Interner),
+ GenericParamId::ConstParamId(id) => {
unknown_const_as_generic(db.const_param_ty(id)).cast(Interner)
}
+ GenericParamId::LifetimeParamId(_) => error_lifetime().cast(Interner),
}),
)
}
@@ -225,16 +225,13 @@ impl TyBuilder<()> {
) -> TyBuilder<()> {
let generics = generics(db.upcast(), def.into());
assert!(generics.parent_generics().is_some() == parent_subst.is_some());
- let lt_iter = generics.iter_lt_self().map(|_| ParamKind::Lifetime);
let params = generics
.iter_self()
- .map(|(id, data)| match data {
- TypeOrConstParamData::TypeParamData(_) => ParamKind::Type,
- TypeOrConstParamData::ConstParamData(_) => {
- ParamKind::Const(db.const_param_ty(ConstParamId::from_unchecked(id)))
- }
+ .map(|(id, _data)| match id {
+ GenericParamId::TypeParamId(_) => ParamKind::Type,
+ GenericParamId::ConstParamId(id) => ParamKind::Const(db.const_param_ty(id)),
+ GenericParamId::LifetimeParamId(_) => ParamKind::Lifetime,
})
- .chain(lt_iter)
.collect();
TyBuilder::new((), params, parent_subst)
}
diff --git a/crates/hir-ty/src/infer/expr.rs b/crates/hir-ty/src/infer/expr.rs
index edfc8a8165..82f7e87ac9 100644
--- a/crates/hir-ty/src/infer/expr.rs
+++ b/crates/hir-ty/src/infer/expr.rs
@@ -8,13 +8,12 @@ use std::{
use chalk_ir::{cast::Cast, fold::Shift, DebruijnIndex, Mutability, TyVariableKind};
use either::Either;
use hir_def::{
- generics::TypeOrConstParamData,
hir::{
ArithOp, Array, BinaryOp, ClosureKind, Expr, ExprId, LabelId, Literal, Statement, UnaryOp,
},
lang_item::{LangItem, LangItemTarget},
path::{GenericArgs, Path},
- BlockId, ConstParamId, FieldId, ItemContainerId, Lookup, TupleFieldId, TupleId,
+ BlockId, FieldId, GenericParamId, ItemContainerId, Lookup, TupleFieldId, TupleId,
};
use hir_expand::name::{name, Name};
use stdx::always;
@@ -1836,7 +1835,7 @@ impl InferenceContext<'_> {
.args
.iter()
.take(type_params + const_params + lifetime_params)
- .zip(def_generics.iter_id_with_lt())
+ .zip(def_generics.iter_id())
{
if let Some(g) = generic_arg_to_chalk(
self.db,
@@ -1866,16 +1865,16 @@ impl InferenceContext<'_> {
// Handle everything else as unknown. This also handles generic arguments for the method's
// parent (impl or trait), which should come after those for the method.
- for (id, data) in def_generics.iter().skip(substs.len()) {
- match data {
- TypeOrConstParamData::TypeParamData(_) => {
+ for (id, _data) in def_generics.iter().skip(substs.len()) {
+ match id {
+ GenericParamId::TypeParamId(_) => {
substs.push(self.table.new_type_var().cast(Interner))
}
- TypeOrConstParamData::ConstParamData(_) => substs.push(
- self.table
- .new_const_var(self.db.const_param_ty(ConstParamId::from_unchecked(id)))
- .cast(Interner),
- ),
+ GenericParamId::ConstParamId(id) => {
+ substs.push(self.table.new_const_var(self.db.const_param_ty(id)).cast(Interner))
+ }
+ // FIXME: create `new_lifetime_var` in infer
+ GenericParamId::LifetimeParamId(_) => substs.push(static_lifetime().cast(Interner)),
}
}
assert_eq!(substs.len(), total_len);
diff --git a/crates/hir-ty/src/lib.rs b/crates/hir-ty/src/lib.rs
index f5410ca6a1..fc7ed79f5c 100644
--- a/crates/hir-ty/src/lib.rs
+++ b/crates/hir-ty/src/lib.rs
@@ -337,7 +337,7 @@ pub(crate) fn make_binders_with_count<T: HasInterner<Interner = Interner>>(
generics: &Generics,
value: T,
) -> Binders<T> {
- let it = generics.iter_id_with_lt().take(count);
+ let it = generics.iter_id().take(count);
Binders::new(
VariableKinds::from_iter(
diff --git a/crates/hir-ty/src/lower.rs b/crates/hir-ty/src/lower.rs
index 453ac2fca7..854893fcee 100644
--- a/crates/hir-ty/src/lower.rs
+++ b/crates/hir-ty/src/lower.rs
@@ -18,13 +18,13 @@ use chalk_ir::{
cast::Cast, fold::Shift, fold::TypeFoldable, interner::HasInterner, Mutability, Safety,
};
-use either::Either;
use hir_def::{
builtin_type::BuiltinType,
data::adt::StructKind,
expander::Expander,
generics::{
- TypeOrConstParamData, TypeParamProvenance, WherePredicate, WherePredicateTypeTarget,
+ GenericParamData, TypeOrConstParamData, TypeParamProvenance, WherePredicate,
+ WherePredicateTypeTarget,
},
lang_item::LangItem,
nameres::MacroSubNs,
@@ -354,13 +354,18 @@ impl<'a> TyLoweringContext<'a> {
.filter(|(_, data)| {
matches!(
data,
- TypeOrConstParamData::TypeParamData(data)
+ GenericParamData::TypeParamData(data)
if data.provenance == TypeParamProvenance::ArgumentImplTrait
)
})
.nth(idx as usize)
.map_or(TyKind::Error, |(id, _)| {
- TyKind::Placeholder(to_placeholder_idx(self.db, id))
+ if let GenericParamId::TypeParamId(id) = id {
+ TyKind::Placeholder(to_placeholder_idx(self.db, id.into()))
+ } else {
+ // we just filtered them out
+ unreachable!("Unexpected lifetime or const argument");
+ }
});
param.intern(Interner)
} else {
@@ -837,7 +842,7 @@ impl<'a> TyLoweringContext<'a> {
let ty_error = TyKind::Error.intern(Interner).cast(Interner);
- let mut def_generic_iter = def_generics.iter_id_with_lt();
+ let mut def_generic_iter = def_generics.iter_id();
let fill_self_params = || {
for x in explicit_self_ty
@@ -1732,9 +1737,9 @@ pub(crate) fn generic_defaults_query(
let generic_params = generics(db.upcast(), def);
let parent_start_idx = generic_params.len_self();
- let toc_iter = generic_params.iter().enumerate().map(|(idx, (id, p))| {
+ let defaults = Arc::from_iter(generic_params.iter().enumerate().map(|(idx, (id, p))| {
match p {
- TypeOrConstParamData::TypeParamData(p) => {
+ GenericParamData::TypeParamData(p) => {
let mut ty =
p.default.as_ref().map_or(TyKind::Error.intern(Interner), |t| ctx.lower_ty(t));
// Each default can only refer to previous parameters.
@@ -1743,13 +1748,13 @@ pub(crate) fn generic_defaults_query(
ty = fallback_bound_vars(ty, idx, parent_start_idx);
crate::make_binders(db, &generic_params, ty.cast(Interner))
}
- TypeOrConstParamData::ConstParamData(p) => {
+ GenericParamData::ConstParamData(p) => {
+ let GenericParamId::ConstParamId(id) = id else {
+ unreachable!("Unexpected lifetime or type argument")
+ };
+
let mut val = p.default.as_ref().map_or_else(
- || {
- unknown_const_as_generic(
- db.const_param_ty(ConstParamId::from_unchecked(id)),
- )
- },
+ || unknown_const_as_generic(db.const_param_ty(id.into())),
|c| {
let c = ctx.lower_const(c, ctx.lower_ty(&p.ty));
c.cast(Interner)
@@ -1759,15 +1764,12 @@ pub(crate) fn generic_defaults_query(
val = fallback_bound_vars(val, idx, parent_start_idx);
make_binders(db, &generic_params, val)
}
+ GenericParamData::LifetimeParamData(_) => {
+ // using static because it requires defaults
+ make_binders(db, &generic_params, static_lifetime().cast(Interner))
+ }
}
- });
-
- let lt_iter = generic_params
- .iter_lt()
- .enumerate()
- .map(|_| make_binders(db, &generic_params, static_lifetime().cast(Interner)));
-
- let defaults = Arc::from_iter(toc_iter.chain(lt_iter));
+ }));
defaults
}
@@ -1782,8 +1784,9 @@ pub(crate) fn generic_defaults_recover(
// we still need one default per parameter
let defaults = Arc::from_iter(generic_params.iter_id().map(|id| {
let val = match id {
- Either::Left(_) => TyKind::Error.intern(Interner).cast(Interner),
- Either::Right(id) => unknown_const_as_generic(db.const_param_ty(id)),
+ GenericParamId::TypeParamId(_) => TyKind::Error.intern(Interner).cast(Interner),
+ GenericParamId::ConstParamId(id) => unknown_const_as_generic(db.const_param_ty(id)),
+ GenericParamId::LifetimeParamId(_) => static_lifetime().cast(Interner),
};
crate::make_binders(db, &generic_params, val)
}));
diff --git a/crates/hir-ty/src/mir/monomorphization.rs b/crates/hir-ty/src/mir/monomorphization.rs
index 12ad67cdc4..d6557c3a81 100644
--- a/crates/hir-ty/src/mir/monomorphization.rs
+++ b/crates/hir-ty/src/mir/monomorphization.rs
@@ -184,8 +184,16 @@ impl Filler<'_> {
self.generics
.as_ref()
.and_then(|it| it.iter().nth(b.index))
- .unwrap()
- .0,
+ .and_then(|(id, _)| match id {
+ hir_def::GenericParamId::ConstParamId(id) => {
+ Some(hir_def::TypeOrConstParamId::from(id))
+ }
+ hir_def::GenericParamId::TypeParamId(id) => {
+ Some(hir_def::TypeOrConstParamId::from(id))
+ }
+ _ => None,
+ })
+ .unwrap(),
self.subst.clone(),
)
})?
diff --git a/crates/hir-ty/src/utils.rs b/crates/hir-ty/src/utils.rs
index 39e7bdd962..cadb099c2b 100644
--- a/crates/hir-ty/src/utils.rs
+++ b/crates/hir-ty/src/utils.rs
@@ -9,12 +9,11 @@ use chalk_ir::{
fold::{FallibleTypeFolder, Shift},
BoundVar, DebruijnIndex,
};
-use either::Either;
use hir_def::{
db::DefDatabase,
generics::{
- GenericParams, LifetimeParamData, TypeOrConstParamData, TypeParamProvenance,
- WherePredicate, WherePredicateTypeTarget,
+ GenericParamData, GenericParams, LifetimeParamData, TypeOrConstParamData,
+ TypeParamProvenance, WherePredicate, WherePredicateTypeTarget,
},
lang_item::LangItem,
resolver::{HasResolver, TypeNs},
@@ -271,81 +270,102 @@ pub(crate) struct Generics {
}
impl Generics {
- pub(crate) fn iter_id(&self) -> impl Iterator<Item = Either<TypeParamId, ConstParamId>> + '_ {
- self.iter().map(|(id, data)| match data {
- TypeOrConstParamData::TypeParamData(_) => Either::Left(TypeParamId::from_unchecked(id)),
- TypeOrConstParamData::ConstParamData(_) => {
- Either::Right(ConstParamId::from_unchecked(id))
- }
- })
+ pub(crate) fn iter_id(&self) -> impl Iterator<Item = GenericParamId> + '_ {
+ self.iter().map(|(id, _)| id)
}
/// Iterator over types and const params of self, then parent.
pub(crate) fn iter<'a>(
&'a self,
- ) -> impl DoubleEndedIterator<Item = (TypeOrConstParamId, &'a TypeOrConstParamData)> + 'a {
- let to_toc_id = |it: &'a Generics| {
- move |(local_id, p)| (TypeOrConstParamId { parent: it.def, local_id }, p)
+ ) -> impl DoubleEndedIterator<Item = (GenericParamId, GenericParamData)> + 'a {
+ let from_toc_id = |it: &'a Generics| {
+ move |(local_id, p): (_, &TypeOrConstParamData)| {
+ let id = TypeOrConstParamId { parent: it.def, local_id };
+ match p {
+ TypeOrConstParamData::TypeParamData(p) => (
+ GenericParamId::TypeParamId(TypeParamId::from_unchecked(id)),
+ GenericParamData::TypeParamData(p.clone()),
+ ),
+ TypeOrConstParamData::ConstParamData(p) => (
+ GenericParamId::ConstParamId(ConstParamId::from_unchecked(id)),
+ GenericParamData::ConstParamData(p.clone()),
+ ),
+ }
+ }
};
- self.params.iter().map(to_toc_id(self)).chain(self.iter_parent())
+
+ let from_lt_id = |it: &'a Generics| {
+ move |(local_id, p): (_, &LifetimeParamData)| {
+ (
+ GenericParamId::LifetimeParamId(LifetimeParamId { parent: it.def, local_id }),
+ GenericParamData::LifetimeParamData(p.clone()),
+ )
+ }
+ };
+
+ let lt_iter = self.params.iter_lt().map(from_lt_id(self));
+ self.params.iter().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 = (TypeOrConstParamId, &'a TypeOrConstParamData)> + 'a {
- let to_toc_id = |it: &'a Generics| {
- move |(local_id, p)| (TypeOrConstParamId { parent: it.def, local_id }, p)
+ ) -> impl DoubleEndedIterator<Item = (GenericParamId, GenericParamData)> + 'a {
+ let from_toc_id = |it: &'a Generics| {
+ move |(local_id, p): (_, &TypeOrConstParamData)| {
+ let id = TypeOrConstParamId { parent: it.def, local_id };
+ match p {
+ TypeOrConstParamData::TypeParamData(p) => (
+ GenericParamId::TypeParamId(TypeParamId::from_unchecked(id)),
+ GenericParamData::TypeParamData(p.clone()),
+ ),
+ TypeOrConstParamData::ConstParamData(p) => (
+ GenericParamId::ConstParamId(ConstParamId::from_unchecked(id)),
+ GenericParamData::ConstParamData(p.clone()),
+ ),
+ }
+ }
};
- self.params.iter().map(to_toc_id(self))
- }
- /// Iterator over types and const params of parent.
- pub(crate) fn iter_parent(
- &self,
- ) -> impl DoubleEndedIterator<Item = (TypeOrConstParamId, &TypeOrConstParamData)> {
- self.parent_generics().into_iter().flat_map(|it| {
- let to_toc_id =
- move |(local_id, p)| (TypeOrConstParamId { parent: it.def, local_id }, p);
- it.params.iter().map(to_toc_id)
- })
- }
-
- pub(crate) fn iter_id_with_lt(&self) -> impl Iterator<Item = GenericParamId> + '_ {
- let toc_iter = self.iter().map(|(id, data)| match data {
- TypeOrConstParamData::TypeParamData(_) => {
- GenericParamId::TypeParamId(TypeParamId::from_unchecked(id))
- }
- TypeOrConstParamData::ConstParamData(_) => {
- GenericParamId::ConstParamId(ConstParamId::from_unchecked(id))
+ let from_lt_id = |it: &'a Generics| {
+ move |(local_id, p): (_, &LifetimeParamData)| {
+ (
+ GenericParamId::LifetimeParamId(LifetimeParamId { parent: it.def, local_id }),
+ GenericParamData::LifetimeParamData(p.clone()),
+ )
}
- });
- let lt_iter = self.iter_lt().map(|(id, _)| GenericParamId::LifetimeParamId(id));
-
- toc_iter.chain(lt_iter)
- }
-
- pub(crate) fn iter_lt<'a>(
- &'a self,
- ) -> impl DoubleEndedIterator<Item = (LifetimeParamId, &'a LifetimeParamData)> + 'a {
- self.iter_lt_self().chain(self.iter_lt_parent())
- }
-
- fn iter_lt_self<'a>(
- &'a self,
- ) -> impl DoubleEndedIterator<Item = (LifetimeParamId, &'a LifetimeParamData)> + 'a {
- let to_id = |it: &'a Generics| {
- move |(local_id, p)| (LifetimeParamId { parent: it.def, local_id }, p)
};
- self.params.iter_lt().map(to_id(self))
+
+ self.params.iter().map(from_toc_id(self)).chain(self.params.iter_lt().map(from_lt_id(self)))
}
- fn iter_lt_parent(
+ /// Iterator over types and const params of parent.
+ pub(crate) fn iter_parent(
&self,
- ) -> impl DoubleEndedIterator<Item = (LifetimeParamId, &LifetimeParamData)> {
+ ) -> impl DoubleEndedIterator<Item = (GenericParamId, GenericParamData)> + '_ {
self.parent_generics().into_iter().flat_map(|it| {
- let to_id = move |(local_id, p)| (LifetimeParamId { parent: it.def, local_id }, p);
- it.params.iter_lt().map(to_id)
+ let from_toc_id = move |(local_id, p): (_, &TypeOrConstParamData)| {
+ let id = TypeOrConstParamId { parent: it.def, local_id };
+ match p {
+ TypeOrConstParamData::TypeParamData(p) => (
+ GenericParamId::TypeParamId(TypeParamId::from_unchecked(id)),
+ GenericParamData::TypeParamData(p.clone()),
+ ),
+ TypeOrConstParamData::ConstParamData(p) => (
+ GenericParamId::ConstParamId(ConstParamId::from_unchecked(id)),
+ GenericParamData::ConstParamData(p.clone()),
+ ),
+ }
+ };
+
+ let from_lt_id = move |(local_id, p): (_, &LifetimeParamData)| {
+ (
+ GenericParamId::LifetimeParamId(LifetimeParamId { parent: it.def, local_id }),
+ GenericParamData::LifetimeParamData(p.clone()),
+ )
+ };
+ let lt_iter = it.params.iter_lt().map(from_lt_id);
+ it.params.iter().map(from_toc_id).chain(lt_iter)
})
}
@@ -437,7 +457,7 @@ impl Generics {
) -> Substitution {
Substitution::from_iter(
Interner,
- self.iter_id_with_lt().enumerate().map(|(idx, id)| match id {
+ 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),
@@ -456,12 +476,15 @@ impl Generics {
Substitution::from_iter(
Interner,
self.iter_id().map(|id| match id {
- Either::Left(id) => {
+ GenericParamId::TypeParamId(id) => {
crate::to_placeholder_idx(db, id.into()).to_ty(Interner).cast(Interner)
}
- Either::Right(id) => crate::to_placeholder_idx(db, id.into())
- .to_const(Interner, db.const_param_ty(id))
+ GenericParamId::ConstParamId(id) => crate::to_placeholder_idx(db, id.into())
+ .to_const(Interner, db.const_param_ty(id.into()))
.cast(Interner),
+ GenericParamId::LifetimeParamId(id) => {
+ crate::lt_to_placeholder_idx(db, id.into()).to_lifetime(Interner).cast(Interner)
+ }
}),
)
}