update Generics iter methods to return GenericParamId

This commit is contained in:
dfireBird 2024-03-09 01:08:35 +05:30
parent d6e3929841
commit a6c8cbfd91
No known key found for this signature in database
GPG key ID: 26D522CA5FC2B93D
7 changed files with 181 additions and 111 deletions

View file

@ -102,6 +102,46 @@ impl TypeOrConstParamData {
impl_from!(TypeParamData, ConstParamData for 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. /// Data about the generic parameters of a function, struct, impl, etc.
#[derive(Clone, PartialEq, Eq, Debug, Hash)] #[derive(Clone, PartialEq, Eq, Debug, Hash)]
pub struct GenericParams { pub struct GenericParams {

View file

@ -9,8 +9,7 @@ use chalk_ir::{
AdtId, DebruijnIndex, Scalar, AdtId, DebruijnIndex, Scalar,
}; };
use hir_def::{ use hir_def::{
builtin_type::BuiltinType, generics::TypeOrConstParamData, ConstParamId, DefWithBodyId, builtin_type::BuiltinType, DefWithBodyId, GenericDefId, GenericParamId, TraitId, TypeAliasId,
GenericDefId, TraitId, TypeAliasId,
}; };
use smallvec::SmallVec; use smallvec::SmallVec;
@ -209,10 +208,11 @@ impl TyBuilder<()> {
Substitution::from_iter( Substitution::from_iter(
Interner, Interner,
params.iter_id().map(|id| match id { params.iter_id().map(|id| match id {
either::Either::Left(_) => TyKind::Error.intern(Interner).cast(Interner), GenericParamId::TypeParamId(_) => TyKind::Error.intern(Interner).cast(Interner),
either::Either::Right(id) => { GenericParamId::ConstParamId(id) => {
unknown_const_as_generic(db.const_param_ty(id)).cast(Interner) unknown_const_as_generic(db.const_param_ty(id)).cast(Interner)
} }
GenericParamId::LifetimeParamId(_) => error_lifetime().cast(Interner),
}), }),
) )
} }
@ -225,16 +225,13 @@ impl TyBuilder<()> {
) -> TyBuilder<()> { ) -> TyBuilder<()> {
let generics = generics(db.upcast(), def.into()); let generics = generics(db.upcast(), def.into());
assert!(generics.parent_generics().is_some() == parent_subst.is_some()); assert!(generics.parent_generics().is_some() == parent_subst.is_some());
let lt_iter = generics.iter_lt_self().map(|_| ParamKind::Lifetime);
let params = generics let params = generics
.iter_self() .iter_self()
.map(|(id, data)| match data { .map(|(id, _data)| match id {
TypeOrConstParamData::TypeParamData(_) => ParamKind::Type, GenericParamId::TypeParamId(_) => ParamKind::Type,
TypeOrConstParamData::ConstParamData(_) => { GenericParamId::ConstParamId(id) => ParamKind::Const(db.const_param_ty(id)),
ParamKind::Const(db.const_param_ty(ConstParamId::from_unchecked(id))) GenericParamId::LifetimeParamId(_) => ParamKind::Lifetime,
}
}) })
.chain(lt_iter)
.collect(); .collect();
TyBuilder::new((), params, parent_subst) TyBuilder::new((), params, parent_subst)
} }

View file

@ -8,13 +8,12 @@ use std::{
use chalk_ir::{cast::Cast, fold::Shift, DebruijnIndex, Mutability, TyVariableKind}; use chalk_ir::{cast::Cast, fold::Shift, DebruijnIndex, Mutability, TyVariableKind};
use either::Either; use either::Either;
use hir_def::{ use hir_def::{
generics::TypeOrConstParamData,
hir::{ hir::{
ArithOp, Array, BinaryOp, ClosureKind, Expr, ExprId, LabelId, Literal, Statement, UnaryOp, ArithOp, Array, BinaryOp, ClosureKind, Expr, ExprId, LabelId, Literal, Statement, UnaryOp,
}, },
lang_item::{LangItem, LangItemTarget}, lang_item::{LangItem, LangItemTarget},
path::{GenericArgs, Path}, path::{GenericArgs, Path},
BlockId, ConstParamId, FieldId, ItemContainerId, Lookup, TupleFieldId, TupleId, BlockId, FieldId, GenericParamId, ItemContainerId, Lookup, TupleFieldId, TupleId,
}; };
use hir_expand::name::{name, Name}; use hir_expand::name::{name, Name};
use stdx::always; use stdx::always;
@ -1836,7 +1835,7 @@ impl InferenceContext<'_> {
.args .args
.iter() .iter()
.take(type_params + const_params + lifetime_params) .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( if let Some(g) = generic_arg_to_chalk(
self.db, self.db,
@ -1866,16 +1865,16 @@ impl InferenceContext<'_> {
// Handle everything else as unknown. This also handles generic arguments for the method's // 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. // parent (impl or trait), which should come after those for the method.
for (id, data) in def_generics.iter().skip(substs.len()) { for (id, _data) in def_generics.iter().skip(substs.len()) {
match data { match id {
TypeOrConstParamData::TypeParamData(_) => { GenericParamId::TypeParamId(_) => {
substs.push(self.table.new_type_var().cast(Interner)) substs.push(self.table.new_type_var().cast(Interner))
} }
TypeOrConstParamData::ConstParamData(_) => substs.push( GenericParamId::ConstParamId(id) => {
self.table substs.push(self.table.new_const_var(self.db.const_param_ty(id)).cast(Interner))
.new_const_var(self.db.const_param_ty(ConstParamId::from_unchecked(id))) }
.cast(Interner), // FIXME: create `new_lifetime_var` in infer
), GenericParamId::LifetimeParamId(_) => substs.push(static_lifetime().cast(Interner)),
} }
} }
assert_eq!(substs.len(), total_len); assert_eq!(substs.len(), total_len);

View file

@ -337,7 +337,7 @@ pub(crate) fn make_binders_with_count<T: HasInterner<Interner = Interner>>(
generics: &Generics, generics: &Generics,
value: T, value: T,
) -> Binders<T> { ) -> Binders<T> {
let it = generics.iter_id_with_lt().take(count); let it = generics.iter_id().take(count);
Binders::new( Binders::new(
VariableKinds::from_iter( VariableKinds::from_iter(

View file

@ -18,13 +18,13 @@ use chalk_ir::{
cast::Cast, fold::Shift, fold::TypeFoldable, interner::HasInterner, Mutability, Safety, cast::Cast, fold::Shift, fold::TypeFoldable, interner::HasInterner, Mutability, Safety,
}; };
use either::Either;
use hir_def::{ use hir_def::{
builtin_type::BuiltinType, builtin_type::BuiltinType,
data::adt::StructKind, data::adt::StructKind,
expander::Expander, expander::Expander,
generics::{ generics::{
TypeOrConstParamData, TypeParamProvenance, WherePredicate, WherePredicateTypeTarget, GenericParamData, TypeOrConstParamData, TypeParamProvenance, WherePredicate,
WherePredicateTypeTarget,
}, },
lang_item::LangItem, lang_item::LangItem,
nameres::MacroSubNs, nameres::MacroSubNs,
@ -354,13 +354,18 @@ impl<'a> TyLoweringContext<'a> {
.filter(|(_, data)| { .filter(|(_, data)| {
matches!( matches!(
data, data,
TypeOrConstParamData::TypeParamData(data) GenericParamData::TypeParamData(data)
if data.provenance == TypeParamProvenance::ArgumentImplTrait if data.provenance == TypeParamProvenance::ArgumentImplTrait
) )
}) })
.nth(idx as usize) .nth(idx as usize)
.map_or(TyKind::Error, |(id, _)| { .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) param.intern(Interner)
} else { } else {
@ -837,7 +842,7 @@ impl<'a> TyLoweringContext<'a> {
let ty_error = TyKind::Error.intern(Interner).cast(Interner); 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 = || { let fill_self_params = || {
for x in explicit_self_ty for x in explicit_self_ty
@ -1732,9 +1737,9 @@ pub(crate) fn generic_defaults_query(
let generic_params = generics(db.upcast(), def); let generic_params = generics(db.upcast(), def);
let parent_start_idx = generic_params.len_self(); 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 { match p {
TypeOrConstParamData::TypeParamData(p) => { GenericParamData::TypeParamData(p) => {
let mut ty = let mut ty =
p.default.as_ref().map_or(TyKind::Error.intern(Interner), |t| ctx.lower_ty(t)); p.default.as_ref().map_or(TyKind::Error.intern(Interner), |t| ctx.lower_ty(t));
// Each default can only refer to previous parameters. // 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); ty = fallback_bound_vars(ty, idx, parent_start_idx);
crate::make_binders(db, &generic_params, ty.cast(Interner)) 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( let mut val = p.default.as_ref().map_or_else(
|| { || unknown_const_as_generic(db.const_param_ty(id.into())),
unknown_const_as_generic(
db.const_param_ty(ConstParamId::from_unchecked(id)),
)
},
|c| { |c| {
let c = ctx.lower_const(c, ctx.lower_ty(&p.ty)); let c = ctx.lower_const(c, ctx.lower_ty(&p.ty));
c.cast(Interner) c.cast(Interner)
@ -1759,15 +1764,12 @@ pub(crate) fn generic_defaults_query(
val = fallback_bound_vars(val, idx, parent_start_idx); val = fallback_bound_vars(val, idx, parent_start_idx);
make_binders(db, &generic_params, val) 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 defaults
} }
@ -1782,8 +1784,9 @@ pub(crate) fn generic_defaults_recover(
// we still need one default per parameter // we still need one default per parameter
let defaults = Arc::from_iter(generic_params.iter_id().map(|id| { let defaults = Arc::from_iter(generic_params.iter_id().map(|id| {
let val = match id { let val = match id {
Either::Left(_) => TyKind::Error.intern(Interner).cast(Interner), GenericParamId::TypeParamId(_) => TyKind::Error.intern(Interner).cast(Interner),
Either::Right(id) => unknown_const_as_generic(db.const_param_ty(id)), 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) crate::make_binders(db, &generic_params, val)
})); }));

View file

@ -184,8 +184,16 @@ impl Filler<'_> {
self.generics self.generics
.as_ref() .as_ref()
.and_then(|it| it.iter().nth(b.index)) .and_then(|it| it.iter().nth(b.index))
.unwrap() .and_then(|(id, _)| match id {
.0, 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(), self.subst.clone(),
) )
})? })?

View file

@ -9,12 +9,11 @@ use chalk_ir::{
fold::{FallibleTypeFolder, Shift}, fold::{FallibleTypeFolder, Shift},
BoundVar, DebruijnIndex, BoundVar, DebruijnIndex,
}; };
use either::Either;
use hir_def::{ use hir_def::{
db::DefDatabase, db::DefDatabase,
generics::{ generics::{
GenericParams, LifetimeParamData, TypeOrConstParamData, TypeParamProvenance, GenericParamData, GenericParams, LifetimeParamData, TypeOrConstParamData,
WherePredicate, WherePredicateTypeTarget, TypeParamProvenance, WherePredicate, WherePredicateTypeTarget,
}, },
lang_item::LangItem, lang_item::LangItem,
resolver::{HasResolver, TypeNs}, resolver::{HasResolver, TypeNs},
@ -271,81 +270,102 @@ pub(crate) struct Generics {
} }
impl Generics { impl Generics {
pub(crate) fn iter_id(&self) -> impl Iterator<Item = Either<TypeParamId, ConstParamId>> + '_ { pub(crate) fn iter_id(&self) -> impl Iterator<Item = GenericParamId> + '_ {
self.iter().map(|(id, data)| match data { self.iter().map(|(id, _)| id)
TypeOrConstParamData::TypeParamData(_) => Either::Left(TypeParamId::from_unchecked(id)),
TypeOrConstParamData::ConstParamData(_) => {
Either::Right(ConstParamId::from_unchecked(id))
}
})
} }
/// Iterator over types and const params of self, then parent. /// Iterator over types and const params of self, then parent.
pub(crate) fn iter<'a>( pub(crate) fn iter<'a>(
&'a self, &'a self,
) -> impl DoubleEndedIterator<Item = (TypeOrConstParamId, &'a TypeOrConstParamData)> + 'a { ) -> impl DoubleEndedIterator<Item = (GenericParamId, GenericParamData)> + 'a {
let to_toc_id = |it: &'a Generics| { let from_toc_id = |it: &'a Generics| {
move |(local_id, p)| (TypeOrConstParamId { parent: it.def, local_id }, p) 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. /// Iterate over types and const params without parent params.
pub(crate) fn iter_self<'a>( pub(crate) fn iter_self<'a>(
&'a self, &'a self,
) -> impl DoubleEndedIterator<Item = (TypeOrConstParamId, &'a TypeOrConstParamData)> + 'a { ) -> impl DoubleEndedIterator<Item = (GenericParamId, GenericParamData)> + 'a {
let to_toc_id = |it: &'a Generics| { let from_toc_id = |it: &'a Generics| {
move |(local_id, p)| (TypeOrConstParamId { parent: it.def, local_id }, p) 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))
let from_lt_id = |it: &'a Generics| {
move |(local_id, p): (_, &LifetimeParamData)| {
(
GenericParamId::LifetimeParamId(LifetimeParamId { parent: it.def, local_id }),
GenericParamData::LifetimeParamData(p.clone()),
)
}
};
self.params.iter().map(from_toc_id(self)).chain(self.params.iter_lt().map(from_lt_id(self)))
} }
/// Iterator over types and const params of parent. /// Iterator over types and const params of parent.
pub(crate) fn iter_parent( pub(crate) fn iter_parent(
&self, &self,
) -> impl DoubleEndedIterator<Item = (TypeOrConstParamId, &TypeOrConstParamData)> { ) -> impl DoubleEndedIterator<Item = (GenericParamId, GenericParamData)> + '_ {
self.parent_generics().into_iter().flat_map(|it| { self.parent_generics().into_iter().flat_map(|it| {
let to_toc_id = let from_toc_id = move |(local_id, p): (_, &TypeOrConstParamData)| {
move |(local_id, p)| (TypeOrConstParamId { parent: it.def, local_id }, p); let id = TypeOrConstParamId { parent: it.def, local_id };
it.params.iter().map(to_toc_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()),
),
} }
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 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))
}
fn iter_lt_parent( let from_lt_id = move |(local_id, p): (_, &LifetimeParamData)| {
&self, (
) -> impl DoubleEndedIterator<Item = (LifetimeParamId, &LifetimeParamData)> { GenericParamId::LifetimeParamId(LifetimeParamId { parent: it.def, local_id }),
self.parent_generics().into_iter().flat_map(|it| { GenericParamData::LifetimeParamData(p.clone()),
let to_id = move |(local_id, p)| (LifetimeParamId { parent: it.def, local_id }, p); )
it.params.iter_lt().map(to_id) };
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 {
Substitution::from_iter( Substitution::from_iter(
Interner, 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) GenericParamId::ConstParamId(id) => BoundVar::new(debruijn, idx)
.to_const(Interner, db.const_param_ty(id)) .to_const(Interner, db.const_param_ty(id))
.cast(Interner), .cast(Interner),
@ -456,12 +476,15 @@ impl Generics {
Substitution::from_iter( Substitution::from_iter(
Interner, Interner,
self.iter_id().map(|id| match id { 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) crate::to_placeholder_idx(db, id.into()).to_ty(Interner).cast(Interner)
} }
Either::Right(id) => crate::to_placeholder_idx(db, id.into()) GenericParamId::ConstParamId(id) => crate::to_placeholder_idx(db, id.into())
.to_const(Interner, db.const_param_ty(id)) .to_const(Interner, db.const_param_ty(id.into()))
.cast(Interner), .cast(Interner),
GenericParamId::LifetimeParamId(id) => {
crate::lt_to_placeholder_idx(db, id.into()).to_lifetime(Interner).cast(Interner)
}
}), }),
) )
} }