Unnamed repository; edit this file 'description' to name the repository.
Auto merge of #17530 - Veykril:lifetime-order, r=Veykril
Move lifetimes in front of type and const params but after self
bors 2024-07-02
parent 73c97e3 · parent baa959f · commit 4981f00
-rw-r--r--crates/hir-def/src/child_by_source.rs4
-rw-r--r--crates/hir-def/src/generics.rs417
-rw-r--r--crates/hir-def/src/item_tree/pretty.rs18
-rw-r--r--crates/hir-def/src/resolver.rs8
-rw-r--r--crates/hir-def/src/src.rs4
-rw-r--r--crates/hir-ty/src/chalk_ext.rs2
-rw-r--r--crates/hir-ty/src/generics.rs35
-rw-r--r--crates/hir-ty/src/lower.rs116
-rw-r--r--crates/hir-ty/src/mir/lower.rs2
-rw-r--r--crates/hir-ty/src/utils.rs3
-rw-r--r--crates/hir/src/display.rs23
-rw-r--r--crates/hir/src/lib.rs30
12 files changed, 333 insertions, 329 deletions
diff --git a/crates/hir-def/src/child_by_source.rs b/crates/hir-def/src/child_by_source.rs
index 106109eb18..0438278ca2 100644
--- a/crates/hir-def/src/child_by_source.rs
+++ b/crates/hir-def/src/child_by_source.rs
@@ -214,8 +214,8 @@ impl ChildBySource for GenericDefId {
}
let generic_params = db.generic_params(*self);
- let mut toc_idx_iter = generic_params.type_or_consts.iter().map(|(idx, _)| idx);
- let lts_idx_iter = generic_params.lifetimes.iter().map(|(idx, _)| idx);
+ let mut toc_idx_iter = generic_params.iter_type_or_consts().map(|(idx, _)| idx);
+ let lts_idx_iter = generic_params.iter_lt().map(|(idx, _)| idx);
// For traits the first type index is `Self`, skip it.
if let GenericDefId::TraitId(_) = *self {
diff --git a/crates/hir-def/src/generics.rs b/crates/hir-def/src/generics.rs
index ca02501567..ebaaef66db 100644
--- a/crates/hir-def/src/generics.rs
+++ b/crates/hir-def/src/generics.rs
@@ -28,6 +28,7 @@ use crate::{
LocalLifetimeParamId, LocalTypeOrConstParamId, Lookup, TypeOrConstParamId, TypeParamId,
};
+/// The index of the self param in the generic of the non-parent definition.
const SELF_PARAM_ID_IN_SELF: la_arena::Idx<TypeOrConstParamData> =
LocalTypeOrConstParamId::from_raw(RawIdx::from_u32(0));
@@ -158,9 +159,9 @@ pub enum GenericParamDataRef<'a> {
/// Data about the generic parameters of a function, struct, impl, etc.
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
pub struct GenericParams {
- pub type_or_consts: Arena<TypeOrConstParamData>,
- pub lifetimes: Arena<LifetimeParamData>,
- pub where_predicates: Box<[WherePredicate]>,
+ type_or_consts: Arena<TypeOrConstParamData>,
+ lifetimes: Arena<LifetimeParamData>,
+ where_predicates: Box<[WherePredicate]>,
}
impl ops::Index<LocalTypeOrConstParamId> for GenericParams {
@@ -205,6 +206,219 @@ pub enum WherePredicateTypeTarget {
TypeOrConstParam(LocalTypeOrConstParamId),
}
+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 len_lifetimes(&self) -> usize {
+ self.lifetimes.len()
+ }
+
+ #[inline]
+ pub fn len_type_or_consts(&self) -> usize {
+ self.type_or_consts.len()
+ }
+
+ #[inline]
+ pub fn is_empty(&self) -> bool {
+ self.len() == 0
+ }
+
+ #[inline]
+ pub fn where_predicates(&self) -> std::slice::Iter<'_, WherePredicate> {
+ self.where_predicates.iter()
+ }
+
+ /// Iterator of type_or_consts field
+ #[inline]
+ pub fn iter_type_or_consts(
+ &self,
+ ) -> impl DoubleEndedIterator<Item = (LocalTypeOrConstParamId, &TypeOrConstParamData)> {
+ self.type_or_consts.iter()
+ }
+
+ /// Iterator of lifetimes field
+ #[inline]
+ pub fn iter_lt(
+ &self,
+ ) -> impl DoubleEndedIterator<Item = (LocalLifetimeParamId, &LifetimeParamData)> {
+ self.lifetimes.iter()
+ }
+
+ pub fn find_type_by_name(&self, name: &Name, parent: GenericDefId) -> Option<TypeParamId> {
+ self.type_or_consts.iter().find_map(|(id, p)| {
+ if p.name().as_ref() == Some(&name) && p.type_param().is_some() {
+ Some(TypeParamId::from_unchecked(TypeOrConstParamId { local_id: id, parent }))
+ } else {
+ None
+ }
+ })
+ }
+
+ pub fn find_const_by_name(&self, name: &Name, parent: GenericDefId) -> Option<ConstParamId> {
+ self.type_or_consts.iter().find_map(|(id, p)| {
+ if p.name().as_ref() == Some(&name) && p.const_param().is_some() {
+ Some(ConstParamId::from_unchecked(TypeOrConstParamId { local_id: id, parent }))
+ } else {
+ None
+ }
+ })
+ }
+
+ #[inline]
+ 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(
+ &self,
+ name: &Name,
+ parent: GenericDefId,
+ ) -> Option<LifetimeParamId> {
+ self.lifetimes.iter().find_map(|(id, p)| {
+ if &p.name == name {
+ Some(LifetimeParamId { local_id: id, parent })
+ } else {
+ None
+ }
+ })
+ }
+
+ pub(crate) fn generic_params_query(
+ db: &dyn DefDatabase,
+ def: GenericDefId,
+ ) -> Interned<GenericParams> {
+ let _p = tracing::info_span!("generic_params_query").entered();
+
+ let krate = def.krate(db);
+ let cfg_options = db.crate_graph();
+ let cfg_options = &cfg_options[krate].cfg_options;
+
+ // Returns the generic parameters that are enabled under the current `#[cfg]` options
+ let enabled_params =
+ |params: &Interned<GenericParams>, item_tree: &ItemTree, parent: GenericModItem| {
+ let enabled = |param| item_tree.attrs(db, krate, param).is_cfg_enabled(cfg_options);
+ let attr_owner_ct = |param| AttrOwner::TypeOrConstParamData(parent, param);
+ let attr_owner_lt = |param| AttrOwner::LifetimeParamData(parent, param);
+
+ // In the common case, no parameters will by disabled by `#[cfg]` attributes.
+ // Therefore, make a first pass to check if all parameters are enabled and, if so,
+ // clone the `Interned<GenericParams>` instead of recreating an identical copy.
+ let all_type_or_consts_enabled =
+ params.type_or_consts.iter().all(|(idx, _)| enabled(attr_owner_ct(idx)));
+ let all_lifetimes_enabled =
+ params.lifetimes.iter().all(|(idx, _)| enabled(attr_owner_lt(idx)));
+
+ if all_type_or_consts_enabled && all_lifetimes_enabled {
+ params.clone()
+ } else {
+ Interned::new(GenericParams {
+ type_or_consts: all_type_or_consts_enabled
+ .then(|| params.type_or_consts.clone())
+ .unwrap_or_else(|| {
+ params
+ .type_or_consts
+ .iter()
+ .filter(|&(idx, _)| enabled(attr_owner_ct(idx)))
+ .map(|(_, param)| param.clone())
+ .collect()
+ }),
+ lifetimes: all_lifetimes_enabled
+ .then(|| params.lifetimes.clone())
+ .unwrap_or_else(|| {
+ params
+ .lifetimes
+ .iter()
+ .filter(|&(idx, _)| enabled(attr_owner_lt(idx)))
+ .map(|(_, param)| param.clone())
+ .collect()
+ }),
+ where_predicates: params.where_predicates.clone(),
+ })
+ }
+ };
+ fn id_to_generics<Id: GenericsItemTreeNode>(
+ db: &dyn DefDatabase,
+ id: impl for<'db> Lookup<
+ Database<'db> = dyn DefDatabase + 'db,
+ Data = impl ItemTreeLoc<Id = Id>,
+ >,
+ enabled_params: impl Fn(
+ &Interned<GenericParams>,
+ &ItemTree,
+ GenericModItem,
+ ) -> Interned<GenericParams>,
+ ) -> Interned<GenericParams>
+ where
+ FileItemTreeId<Id>: Into<GenericModItem>,
+ {
+ let id = id.lookup(db).item_tree_id();
+ let tree = id.item_tree(db);
+ let item = &tree[id.value];
+ enabled_params(item.generic_params(), &tree, id.value.into())
+ }
+
+ match def {
+ GenericDefId::FunctionId(id) => {
+ let loc = id.lookup(db);
+ let tree = loc.id.item_tree(db);
+ let item = &tree[loc.id.value];
+
+ let enabled_params =
+ enabled_params(&item.explicit_generic_params, &tree, loc.id.value.into());
+
+ let module = loc.container.module(db);
+ let func_data = db.function_data(id);
+ if func_data.params.is_empty() {
+ enabled_params
+ } else {
+ let mut generic_params = GenericParamsCollector {
+ type_or_consts: enabled_params.type_or_consts.clone(),
+ lifetimes: enabled_params.lifetimes.clone(),
+ where_predicates: enabled_params.where_predicates.clone().into(),
+ };
+
+ // Don't create an `Expander` if not needed since this
+ // could cause a reparse after the `ItemTree` has been created due to the spanmap.
+ let mut expander = Lazy::new(|| {
+ (module.def_map(db), Expander::new(db, loc.id.file_id(), module))
+ });
+ for param in func_data.params.iter() {
+ generic_params.fill_implicit_impl_trait_args(db, &mut expander, param);
+ }
+ Interned::new(generic_params.finish())
+ }
+ }
+ GenericDefId::AdtId(AdtId::StructId(id)) => id_to_generics(db, id, enabled_params),
+ GenericDefId::AdtId(AdtId::EnumId(id)) => id_to_generics(db, id, enabled_params),
+ GenericDefId::AdtId(AdtId::UnionId(id)) => id_to_generics(db, id, enabled_params),
+ GenericDefId::TraitId(id) => id_to_generics(db, id, enabled_params),
+ GenericDefId::TraitAliasId(id) => id_to_generics(db, id, enabled_params),
+ GenericDefId::TypeAliasId(id) => id_to_generics(db, id, enabled_params),
+ GenericDefId::ImplId(id) => id_to_generics(db, id, enabled_params),
+ GenericDefId::ConstId(_) => Interned::new(GenericParams {
+ type_or_consts: Default::default(),
+ lifetimes: Default::default(),
+ where_predicates: Default::default(),
+ }),
+ }
+ }
+}
+
#[derive(Clone, Default)]
pub(crate) struct GenericParamsCollector {
pub(crate) type_or_consts: Arena<TypeOrConstParamData>,
@@ -441,200 +655,3 @@ 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)> {
- self.type_or_consts.iter()
- }
-
- /// Iterator of lifetimes field
- #[inline]
- pub fn iter_lt(
- &self,
- ) -> impl DoubleEndedIterator<Item = (LocalLifetimeParamId, &LifetimeParamData)> {
- self.lifetimes.iter()
- }
-
- pub(crate) fn generic_params_query(
- db: &dyn DefDatabase,
- def: GenericDefId,
- ) -> Interned<GenericParams> {
- let _p = tracing::info_span!("generic_params_query").entered();
-
- let krate = def.module(db).krate;
- let cfg_options = db.crate_graph();
- let cfg_options = &cfg_options[krate].cfg_options;
-
- // Returns the generic parameters that are enabled under the current `#[cfg]` options
- let enabled_params =
- |params: &Interned<GenericParams>, item_tree: &ItemTree, parent: GenericModItem| {
- let enabled = |param| item_tree.attrs(db, krate, param).is_cfg_enabled(cfg_options);
- let attr_owner_ct = |param| AttrOwner::TypeOrConstParamData(parent, param);
- let attr_owner_lt = |param| AttrOwner::LifetimeParamData(parent, param);
-
- // In the common case, no parameters will by disabled by `#[cfg]` attributes.
- // Therefore, make a first pass to check if all parameters are enabled and, if so,
- // clone the `Interned<GenericParams>` instead of recreating an identical copy.
- let all_type_or_consts_enabled =
- params.type_or_consts.iter().all(|(idx, _)| enabled(attr_owner_ct(idx)));
- let all_lifetimes_enabled =
- params.lifetimes.iter().all(|(idx, _)| enabled(attr_owner_lt(idx)));
-
- if all_type_or_consts_enabled && all_lifetimes_enabled {
- params.clone()
- } else {
- Interned::new(GenericParams {
- type_or_consts: all_type_or_consts_enabled
- .then(|| params.type_or_consts.clone())
- .unwrap_or_else(|| {
- params
- .type_or_consts
- .iter()
- .filter(|&(idx, _)| enabled(attr_owner_ct(idx)))
- .map(|(_, param)| param.clone())
- .collect()
- }),
- lifetimes: all_lifetimes_enabled
- .then(|| params.lifetimes.clone())
- .unwrap_or_else(|| {
- params
- .lifetimes
- .iter()
- .filter(|&(idx, _)| enabled(attr_owner_lt(idx)))
- .map(|(_, param)| param.clone())
- .collect()
- }),
- where_predicates: params.where_predicates.clone(),
- })
- }
- };
- fn id_to_generics<Id: GenericsItemTreeNode>(
- db: &dyn DefDatabase,
- id: impl for<'db> Lookup<
- Database<'db> = dyn DefDatabase + 'db,
- Data = impl ItemTreeLoc<Id = Id>,
- >,
- enabled_params: impl Fn(
- &Interned<GenericParams>,
- &ItemTree,
- GenericModItem,
- ) -> Interned<GenericParams>,
- ) -> Interned<GenericParams>
- where
- FileItemTreeId<Id>: Into<GenericModItem>,
- {
- let id = id.lookup(db).item_tree_id();
- let tree = id.item_tree(db);
- let item = &tree[id.value];
- enabled_params(item.generic_params(), &tree, id.value.into())
- }
-
- match def {
- GenericDefId::FunctionId(id) => {
- let loc = id.lookup(db);
- let tree = loc.id.item_tree(db);
- let item = &tree[loc.id.value];
-
- let enabled_params =
- enabled_params(&item.explicit_generic_params, &tree, loc.id.value.into());
-
- let module = loc.container.module(db);
- let func_data = db.function_data(id);
- if func_data.params.is_empty() {
- enabled_params
- } else {
- let mut generic_params = GenericParamsCollector {
- type_or_consts: enabled_params.type_or_consts.clone(),
- lifetimes: enabled_params.lifetimes.clone(),
- where_predicates: enabled_params.where_predicates.clone().into(),
- };
-
- // Don't create an `Expander` if not needed since this
- // could cause a reparse after the `ItemTree` has been created due to the spanmap.
- let mut expander = Lazy::new(|| {
- (module.def_map(db), Expander::new(db, loc.id.file_id(), module))
- });
- for param in func_data.params.iter() {
- generic_params.fill_implicit_impl_trait_args(db, &mut expander, param);
- }
- Interned::new(generic_params.finish())
- }
- }
- GenericDefId::AdtId(AdtId::StructId(id)) => id_to_generics(db, id, enabled_params),
- GenericDefId::AdtId(AdtId::EnumId(id)) => id_to_generics(db, id, enabled_params),
- GenericDefId::AdtId(AdtId::UnionId(id)) => id_to_generics(db, id, enabled_params),
- GenericDefId::TraitId(id) => id_to_generics(db, id, enabled_params),
- GenericDefId::TraitAliasId(id) => id_to_generics(db, id, enabled_params),
- GenericDefId::TypeAliasId(id) => id_to_generics(db, id, enabled_params),
- GenericDefId::ImplId(id) => id_to_generics(db, id, enabled_params),
- GenericDefId::ConstId(_) => Interned::new(GenericParams {
- type_or_consts: Default::default(),
- lifetimes: Default::default(),
- where_predicates: Default::default(),
- }),
- }
- }
-
- pub fn find_type_by_name(&self, name: &Name, parent: GenericDefId) -> Option<TypeParamId> {
- self.type_or_consts.iter().find_map(|(id, p)| {
- if p.name().as_ref() == Some(&name) && p.type_param().is_some() {
- Some(TypeParamId::from_unchecked(TypeOrConstParamId { local_id: id, parent }))
- } else {
- None
- }
- })
- }
-
- pub fn find_const_by_name(&self, name: &Name, parent: GenericDefId) -> Option<ConstParamId> {
- self.type_or_consts.iter().find_map(|(id, p)| {
- if p.name().as_ref() == Some(&name) && p.const_param().is_some() {
- Some(ConstParamId::from_unchecked(TypeOrConstParamId { local_id: id, parent }))
- } else {
- None
- }
- })
- }
-
- 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(
- &self,
- name: &Name,
- parent: GenericDefId,
- ) -> Option<LifetimeParamId> {
- self.lifetimes.iter().find_map(|(id, p)| {
- if &p.name == name {
- Some(LifetimeParamId { local_id: id, parent })
- } else {
- None
- }
- })
- }
-}
diff --git a/crates/hir-def/src/item_tree/pretty.rs b/crates/hir-def/src/item_tree/pretty.rs
index 2803678a33..6283ae23b5 100644
--- a/crates/hir-def/src/item_tree/pretty.rs
+++ b/crates/hir-def/src/item_tree/pretty.rs
@@ -532,7 +532,7 @@ impl Printer<'_> {
w!(self, "<");
let mut first = true;
- for (idx, lt) in params.lifetimes.iter() {
+ for (idx, lt) in params.iter_lt() {
if !first {
w!(self, ", ");
}
@@ -540,7 +540,7 @@ impl Printer<'_> {
self.print_attrs_of(AttrOwner::LifetimeParamData(parent, idx), " ");
w!(self, "{}", lt.name.display(self.db.upcast()));
}
- for (idx, x) in params.type_or_consts.iter() {
+ for (idx, x) in params.iter_type_or_consts() {
if !first {
w!(self, ", ");
}
@@ -570,13 +570,13 @@ impl Printer<'_> {
}
fn print_where_clause(&mut self, params: &GenericParams) -> bool {
- if params.where_predicates.is_empty() {
+ if params.where_predicates().next().is_none() {
return false;
}
w!(self, "\nwhere");
self.indented(|this| {
- for (i, pred) in params.where_predicates.iter().enumerate() {
+ for (i, pred) in params.where_predicates().enumerate() {
if i != 0 {
wln!(this, ",");
}
@@ -607,12 +607,10 @@ impl Printer<'_> {
match target {
WherePredicateTypeTarget::TypeRef(ty) => this.print_type_ref(ty),
- WherePredicateTypeTarget::TypeOrConstParam(id) => {
- match &params.type_or_consts[*id].name() {
- Some(name) => w!(this, "{}", name.display(self.db.upcast())),
- None => w!(this, "_anon_{}", id.into_raw()),
- }
- }
+ WherePredicateTypeTarget::TypeOrConstParam(id) => match params[*id].name() {
+ Some(name) => w!(this, "{}", name.display(self.db.upcast())),
+ None => w!(this, "_anon_{}", id.into_raw()),
+ },
}
w!(this, ": ");
this.print_type_bounds(std::slice::from_ref(bound));
diff --git a/crates/hir-def/src/resolver.rs b/crates/hir-def/src/resolver.rs
index a83157415c..e5c1f93bbd 100644
--- a/crates/hir-def/src/resolver.rs
+++ b/crates/hir-def/src/resolver.rs
@@ -596,7 +596,7 @@ impl Resolver {
Scope::GenericParams { params, def } => Some((params, def)),
_ => None,
})
- .flat_map(|(params, def)| params.where_predicates.iter().zip(iter::repeat(def)))
+ .flat_map(|(params, def)| params.where_predicates().zip(iter::repeat(def)))
}
pub fn generic_def(&self) -> Option<GenericDefId> {
@@ -758,10 +758,10 @@ impl Scope {
}
Scope::GenericParams { params, def: parent } => {
let parent = *parent;
- for (local_id, param) in params.type_or_consts.iter() {
+ for (local_id, param) in params.iter_type_or_consts() {
if let Some(name) = &param.name() {
let id = TypeOrConstParamId { parent, local_id };
- let data = &db.generic_params(parent).type_or_consts[local_id];
+ let data = &db.generic_params(parent)[local_id];
acc.add(
name,
ScopeDef::GenericParam(match data {
@@ -775,7 +775,7 @@ impl Scope {
);
}
}
- for (local_id, param) in params.lifetimes.iter() {
+ for (local_id, param) in params.iter_lt() {
let id = LifetimeParamId { parent, local_id };
acc.add(&param.name, ScopeDef::GenericParam(id.into()))
}
diff --git a/crates/hir-def/src/src.rs b/crates/hir-def/src/src.rs
index 2b1da8c34e..a0d2079e0d 100644
--- a/crates/hir-def/src/src.rs
+++ b/crates/hir-def/src/src.rs
@@ -64,7 +64,7 @@ impl HasChildSource<LocalTypeOrConstParamId> for GenericDefId {
db: &dyn DefDatabase,
) -> InFile<ArenaMap<LocalTypeOrConstParamId, Self::Value>> {
let generic_params = db.generic_params(*self);
- let mut idx_iter = generic_params.type_or_consts.iter().map(|(idx, _)| idx);
+ let mut idx_iter = generic_params.iter_type_or_consts().map(|(idx, _)| idx);
let (file_id, generic_params_list) = self.file_id_and_params_of(db);
@@ -103,7 +103,7 @@ impl HasChildSource<LocalLifetimeParamId> for GenericDefId {
db: &dyn DefDatabase,
) -> InFile<ArenaMap<LocalLifetimeParamId, Self::Value>> {
let generic_params = db.generic_params(*self);
- let idx_iter = generic_params.lifetimes.iter().map(|(idx, _)| idx);
+ let idx_iter = generic_params.iter_lt().map(|(idx, _)| idx);
let (file_id, generic_params_list) = self.file_id_and_params_of(db);
diff --git a/crates/hir-ty/src/chalk_ext.rs b/crates/hir-ty/src/chalk_ext.rs
index 320e5bd8a2..d0d217d270 100644
--- a/crates/hir-ty/src/chalk_ext.rs
+++ b/crates/hir-ty/src/chalk_ext.rs
@@ -309,7 +309,7 @@ impl TyExt for Ty {
TyKind::Placeholder(idx) => {
let id = from_placeholder_idx(db, *idx);
let generic_params = db.generic_params(id.parent);
- let param_data = &generic_params.type_or_consts[id.local_id];
+ let param_data = &generic_params[id.local_id];
match param_data {
TypeOrConstParamData::TypeParamData(p) => match p.provenance {
hir_def::generics::TypeParamProvenance::ArgumentImplTrait => {
diff --git a/crates/hir-ty/src/generics.rs b/crates/hir-ty/src/generics.rs
index 2685dc0ef8..a96c101a38 100644
--- a/crates/hir-ty/src/generics.rs
+++ b/crates/hir-ty/src/generics.rs
@@ -2,8 +2,8 @@
//!
//! The layout for generics as expected by chalk are as follows:
//! - Optional Self parameter
-//! - Type or Const parameters
//! - Lifetime parameters
+//! - Type or Const parameters
//! - Parent parameters
//!
//! where parent follows the same scheme.
@@ -20,19 +20,23 @@ use hir_def::{
LocalLifetimeParamId, LocalTypeOrConstParamId, Lookup, TypeOrConstParamId, TypeParamId,
};
use intern::Interned;
+use itertools::chain;
use stdx::TupleExt;
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 }
+ let params = db.generic_params(def);
+ let has_trait_self_param = params.trait_self_param().is_some();
+ Generics { def, params, parent_generics, has_trait_self_param }
}
#[derive(Clone, Debug)]
pub(crate) struct Generics {
def: GenericDefId,
params: Interned<GenericParams>,
parent_generics: Option<Box<Generics>>,
+ has_trait_self_param: bool,
}
impl<T> ops::Index<T> for Generics
@@ -74,10 +78,6 @@ impl Generics {
self.params.iter_type_or_consts().map(from_toc_id(self)).map(TupleExt::head)
}
- pub(crate) fn iter_self_lt_id(&self) -> impl DoubleEndedIterator<Item = GenericParamId> + '_ {
- self.params.iter_lt().map(from_lt_id(self)).map(TupleExt::head)
- }
-
/// Iterate over the params followed by the parent params.
pub(crate) fn iter(
&self,
@@ -89,10 +89,9 @@ impl Generics {
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)))
+ let mut toc = self.params.iter_type_or_consts().map(from_toc_id(self));
+ let trait_self_param = self.has_trait_self_param.then(|| toc.next()).flatten();
+ chain!(trait_self_param, self.params.iter_lt().map(from_lt_id(self)), toc)
}
/// Iterator over types and const params of parent.
@@ -100,8 +99,9 @@ impl Generics {
&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)
+ let mut toc = it.params.iter_type_or_consts().map(from_toc_id(it));
+ let trait_self_param = it.has_trait_self_param.then(|| toc.next()).flatten();
+ chain!(trait_self_param, it.params.iter_lt().map(from_lt_id(it)), toc)
})
}
@@ -145,8 +145,11 @@ impl Generics {
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)
+ debug_assert!(idx <= self.params.len_type_or_consts());
+ if self.params.trait_self_param() == Some(param.local_id) {
+ return Some(idx);
+ }
+ Some(self.params.len_lifetimes() + idx)
} else {
debug_assert_eq!(self.parent_generics().map(|it| it.def), Some(param.parent));
self.parent_generics()
@@ -163,8 +166,8 @@ impl Generics {
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)
+ debug_assert!(idx <= self.params.len_lifetimes());
+ Some(self.params.trait_self_param().is_some() as usize + idx)
} else {
debug_assert_eq!(self.parent_generics().map(|it| it.def), Some(lifetime.parent));
self.parent_generics()
diff --git a/crates/hir-ty/src/lower.rs b/crates/hir-ty/src/lower.rs
index 54f4ee782f..d421e72d36 100644
--- a/crates/hir-ty/src/lower.rs
+++ b/crates/hir-ty/src/lower.rs
@@ -384,14 +384,18 @@ impl<'a> TyLoweringContext<'a> {
type_params,
const_params,
_impl_trait_params,
- _lifetime_params,
+ lifetime_params,
) = self
.generics()
.expect("variable impl trait lowering must be in a generic def")
.provenance_split();
TyKind::BoundVar(BoundVar::new(
self.in_binders,
- idx as usize + self_param as usize + type_params + const_params,
+ idx as usize
+ + self_param as usize
+ + type_params
+ + const_params
+ + lifetime_params,
))
.intern(Interner)
}
@@ -816,8 +820,8 @@ impl<'a> TyLoweringContext<'a> {
// Order is
// - Optional Self parameter
- // - Type or Const parameters
// - Lifetime parameters
+ // - Type or Const parameters
// - Parent parameters
let def_generics = generics(self.db.upcast(), def);
let (
@@ -839,7 +843,6 @@ impl<'a> TyLoweringContext<'a> {
let ty_error = || TyKind::Error.intern(Interner).cast(Interner);
let mut def_toc_iter = def_generics.iter_self_type_or_consts_id();
- let mut def_lt_iter = def_generics.iter_self_lt_id();
let fill_self_param = || {
if self_param {
let self_ty = explicit_self_ty.map(|x| x.cast(Interner)).unwrap_or_else(ty_error);
@@ -852,56 +855,56 @@ impl<'a> TyLoweringContext<'a> {
};
let mut had_explicit_args = false;
- let mut lifetimes = SmallVec::<[_; 1]>::new();
if let Some(&GenericArgs { ref args, has_self_type, .. }) = args_and_bindings {
- if !has_self_type {
- fill_self_param();
- }
- let expected_num = if has_self_type {
- self_param as usize + type_params + const_params
+ // Fill in the self param first
+ if has_self_type && self_param {
+ had_explicit_args = true;
+ if let Some(id) = def_toc_iter.next() {
+ assert!(matches!(id, GenericParamId::TypeParamId(_)));
+ had_explicit_args = true;
+ if let GenericArg::Type(ty) = &args[0] {
+ substs.push(self.lower_ty(ty).cast(Interner));
+ }
+ }
} else {
- type_params + const_params
+ fill_self_param()
};
- let skip = if has_self_type && !self_param { 1 } else { 0 };
- // if non-lifetime args are provided, it should be all of them, but we can't rely on that
+
+ // Then fill in the supplied lifetime args, or error lifetimes if there are too few
+ // (default lifetimes aren't a thing)
for arg in args
.iter()
- .filter(|arg| !matches!(arg, GenericArg::Lifetime(_)))
- .skip(skip)
- .take(expected_num)
+ .filter_map(|arg| match arg {
+ GenericArg::Lifetime(arg) => Some(self.lower_lifetime(arg)),
+ _ => None,
+ })
+ .chain(iter::repeat(error_lifetime()))
+ .take(lifetime_params)
{
- if let Some(id) = def_toc_iter.next() {
- had_explicit_args = true;
- let arg = generic_arg_to_chalk(
- self.db,
- id,
- arg,
- &mut (),
- |_, type_ref| self.lower_ty(type_ref),
- |_, const_ref, ty| self.lower_const(const_ref, ty),
- |_, lifetime_ref| self.lower_lifetime(lifetime_ref),
- );
- substs.push(arg);
- }
+ substs.push(arg.cast(Interner));
}
- for arg in args
+ let skip = if has_self_type { 1 } else { 0 };
+ // Fill in supplied type and const args
+ // Note if non-lifetime args are provided, it should be all of them, but we can't rely on that
+ for (arg, id) in args
.iter()
- .filter(|arg| matches!(arg, GenericArg::Lifetime(_)))
- .take(lifetime_params)
+ .filter(|arg| !matches!(arg, GenericArg::Lifetime(_)))
+ .skip(skip)
+ .take(type_params + const_params)
+ .zip(def_toc_iter)
{
- if let Some(id) = def_lt_iter.next() {
- let arg = generic_arg_to_chalk(
- self.db,
- id,
- arg,
- &mut (),
- |_, type_ref| self.lower_ty(type_ref),
- |_, const_ref, ty| self.lower_const(const_ref, ty),
- |_, lifetime_ref| self.lower_lifetime(lifetime_ref),
- );
- lifetimes.push(arg);
- }
+ had_explicit_args = true;
+ let arg = generic_arg_to_chalk(
+ self.db,
+ id,
+ arg,
+ &mut (),
+ |_, type_ref| self.lower_ty(type_ref),
+ |_, const_ref, ty| self.lower_const(const_ref, ty),
+ |_, lifetime_ref| self.lower_lifetime(lifetime_ref),
+ );
+ substs.push(arg);
}
} else {
fill_self_param();
@@ -923,16 +926,16 @@ impl<'a> TyLoweringContext<'a> {
}
_ => false,
};
- if (!infer_args || had_explicit_args) && !is_assoc_ty() {
+ let fill_defaults = (!infer_args || had_explicit_args) && !is_assoc_ty();
+ if fill_defaults {
let defaults = &*self.db.generic_defaults(def);
let (item, _parent) = defaults.split_at(item_len);
- let (toc, lt) = item.split_at(item_len - lifetime_params);
let parent_from = item_len - substs.len();
let mut rem =
def_generics.iter_id().skip(substs.len()).map(param_to_err).collect::<Vec<_>>();
// Fill in defaults for type/const params
- for (idx, default_ty) in toc[substs.len()..].iter().enumerate() {
+ for (idx, default_ty) in item[substs.len()..].iter().enumerate() {
// each default can depend on the previous parameters
let substs_so_far = Substitution::from_iter(
Interner,
@@ -940,20 +943,9 @@ impl<'a> TyLoweringContext<'a> {
);
substs.push(default_ty.clone().substitute(Interner, &substs_so_far));
}
- let n_lifetimes = lifetimes.len();
- // Fill in deferred lifetimes
- substs.extend(lifetimes);
- // Fill in defaults for lifetime params
- for default_ty in &lt[n_lifetimes..] {
- // these are always errors so skipping is fine
- substs.push(default_ty.skip_binders().clone());
- }
- // Fill in remaining def params and parent params
+ // Fill in remaining parent params
substs.extend(rem.drain(parent_from..));
} else {
- substs.extend(def_toc_iter.map(param_to_err));
- // Fill in deferred lifetimes
- substs.extend(lifetimes);
// Fill in remaining def params and parent params
substs.extend(def_generics.iter_id().skip(substs.len()).map(param_to_err));
}
@@ -1725,8 +1717,8 @@ pub(crate) fn generic_predicates_query(
})
.collect::<Vec<_>>();
- let subst = generics.bound_vars_subst(db, DebruijnIndex::INNERMOST);
- if !subst.is_empty(Interner) {
+ if generics.len() > 0 {
+ let subst = generics.bound_vars_subst(db, DebruijnIndex::INNERMOST);
let explicitly_unsized_tys = ctx.unsized_types.into_inner();
if let Some(implicitly_sized_predicates) =
implicitly_sized_clauses(db, def, &explicitly_unsized_tys, &subst, &resolver)
@@ -2071,7 +2063,7 @@ pub(crate) fn impl_self_ty_query(db: &dyn HirDatabase, impl_id: ImplId) -> Binde
// returns None if def is a type arg
pub(crate) fn const_param_ty_query(db: &dyn HirDatabase, def: ConstParamId) -> Ty {
let parent_data = db.generic_params(def.parent());
- let data = &parent_data.type_or_consts[def.local_id()];
+ let data = &parent_data[def.local_id()];
let resolver = def.parent().resolver(db.upcast());
let ctx = TyLoweringContext::new(db, &resolver, def.parent().into());
match data {
diff --git a/crates/hir-ty/src/mir/lower.rs b/crates/hir-ty/src/mir/lower.rs
index 0569d06695..f7119c303a 100644
--- a/crates/hir-ty/src/mir/lower.rs
+++ b/crates/hir-ty/src/mir/lower.rs
@@ -183,7 +183,7 @@ impl MirLowerError {
},
MirLowerError::GenericArgNotProvided(id, subst) => {
let parent = id.parent;
- let param = &db.generic_params(parent).type_or_consts[id.local_id];
+ let param = &db.generic_params(parent)[id.local_id];
writeln!(
f,
"Generic arg not provided for {}",
diff --git a/crates/hir-ty/src/utils.rs b/crates/hir-ty/src/utils.rs
index 969999cdb8..738e842146 100644
--- a/crates/hir-ty/src/utils.rs
+++ b/crates/hir-ty/src/utils.rs
@@ -157,8 +157,7 @@ fn direct_super_traits(db: &dyn DefDatabase, trait_: TraitId, cb: impl FnMut(Tra
let generic_params = db.generic_params(trait_.into());
let trait_self = generic_params.trait_self_param();
generic_params
- .where_predicates
- .iter()
+ .where_predicates()
.filter_map(|pred| match pred {
WherePredicate::ForLifetime { target, bound, .. }
| WherePredicate::TypeBound { target, bound } => {
diff --git a/crates/hir/src/display.rs b/crates/hir/src/display.rs
index 79069ed66b..72e79af75d 100644
--- a/crates/hir/src/display.rs
+++ b/crates/hir/src/display.rs
@@ -452,7 +452,7 @@ impl HirDisplay for TypeOrConstParam {
impl HirDisplay for TypeParam {
fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
let params = f.db.generic_params(self.id.parent());
- let param_data = &params.type_or_consts[self.id.local_id()];
+ let param_data = &params[self.id.local_id()];
let substs = TyBuilder::placeholder_subst(f.db, self.id.parent());
let krate = self.id.parent().krate(f.db).id;
let ty =
@@ -539,11 +539,10 @@ fn write_generic_params(
f: &mut HirFormatter<'_>,
) -> Result<(), HirDisplayError> {
let params = f.db.generic_params(def);
- if params.lifetimes.is_empty()
- && params.type_or_consts.iter().all(|it| it.1.const_param().is_none())
+ if params.iter_lt().next().is_none()
+ && params.iter_type_or_consts().all(|it| it.1.const_param().is_none())
&& params
- .type_or_consts
- .iter()
+ .iter_type_or_consts()
.filter_map(|it| it.1.type_param())
.all(|param| !matches!(param.provenance, TypeParamProvenance::TypeParamList))
{
@@ -560,11 +559,11 @@ fn write_generic_params(
f.write_str(", ")
}
};
- for (_, lifetime) in params.lifetimes.iter() {
+ for (_, lifetime) in params.iter_lt() {
delim(f)?;
write!(f, "{}", lifetime.name.display(f.db.upcast()))?;
}
- for (_, ty) in params.type_or_consts.iter() {
+ for (_, ty) in params.iter_type_or_consts() {
if let Some(name) = &ty.name() {
match ty {
TypeOrConstParamData::TypeParamData(ty) => {
@@ -612,11 +611,11 @@ fn write_where_clause(
}
fn has_disaplayable_predicates(params: &Interned<GenericParams>) -> bool {
- params.where_predicates.iter().any(|pred| {
+ params.where_predicates().any(|pred| {
!matches!(
pred,
WherePredicate::TypeBound { target: WherePredicateTypeTarget::TypeOrConstParam(id), .. }
- if params.type_or_consts[*id].name().is_none()
+ if params[*id].name().is_none()
)
})
}
@@ -631,13 +630,13 @@ fn write_where_predicates(
let is_unnamed_type_target =
|params: &Interned<GenericParams>, target: &WherePredicateTypeTarget| {
matches!(target,
- WherePredicateTypeTarget::TypeOrConstParam(id) if params.type_or_consts[*id].name().is_none()
+ WherePredicateTypeTarget::TypeOrConstParam(id) if params[*id].name().is_none()
)
};
let write_target = |target: &WherePredicateTypeTarget, f: &mut HirFormatter<'_>| match target {
WherePredicateTypeTarget::TypeRef(ty) => ty.hir_fmt(f),
- WherePredicateTypeTarget::TypeOrConstParam(id) => match params.type_or_consts[*id].name() {
+ WherePredicateTypeTarget::TypeOrConstParam(id) => match params[*id].name() {
Some(name) => write!(f, "{}", name.display(f.db.upcast())),
None => f.write_str("{unnamed}"),
},
@@ -653,7 +652,7 @@ fn write_where_predicates(
_ => false,
};
- let mut iter = params.where_predicates.iter().peekable();
+ let mut iter = params.where_predicates().peekable();
while let Some(pred) = iter.next() {
if matches!(pred, TypeBound { target, .. } if is_unnamed_type_target(params, target)) {
continue;
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index cd916330c2..18a5325db6 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -665,7 +665,7 @@ impl Module {
}
let parent = impl_def.id.into();
let generic_params = db.generic_params(parent);
- let lifetime_params = generic_params.lifetimes.iter().map(|(local_id, _)| {
+ let lifetime_params = generic_params.iter_lt().map(|(local_id, _)| {
GenericParamId::LifetimeParamId(LifetimeParamId { parent, local_id })
});
let type_params = generic_params
@@ -1540,8 +1540,7 @@ impl Adt {
resolver
.generic_params()
.and_then(|gp| {
- gp.lifetimes
- .iter()
+ gp.iter_lt()
// there should only be a single lifetime
// but `Arena` requires to use an iterator
.nth(0)
@@ -2503,8 +2502,7 @@ impl Trait {
count_required_only: bool,
) -> usize {
db.generic_params(self.id.into())
- .type_or_consts
- .iter()
+ .iter_type_or_consts()
.filter(|(_, ty)| !matches!(ty, TypeOrConstParamData::TypeParamData(ty) if ty.provenance != TypeParamProvenance::TypeParamList))
.filter(|(_, ty)| !count_required_only || !ty.has_default())
.count()
@@ -3125,7 +3123,7 @@ impl_from!(
impl GenericDef {
pub fn params(self, db: &dyn HirDatabase) -> Vec<GenericParam> {
let generics = db.generic_params(self.into());
- let ty_params = generics.type_or_consts.iter().map(|(local_id, _)| {
+ let ty_params = generics.iter_type_or_consts().map(|(local_id, _)| {
let toc = TypeOrConstParam { id: TypeOrConstParamId { parent: self.into(), local_id } };
match toc.split(db) {
Either::Left(it) => GenericParam::ConstParam(it),
@@ -3142,8 +3140,7 @@ impl GenericDef {
pub fn lifetime_params(self, db: &dyn HirDatabase) -> Vec<LifetimeParam> {
let generics = db.generic_params(self.into());
generics
- .lifetimes
- .iter()
+ .iter_lt()
.map(|(local_id, _)| LifetimeParam {
id: LifetimeParamId { parent: self.into(), local_id },
})
@@ -3153,8 +3150,7 @@ impl GenericDef {
pub fn type_or_const_params(self, db: &dyn HirDatabase) -> Vec<TypeOrConstParam> {
let generics = db.generic_params(self.into());
generics
- .type_or_consts
- .iter()
+ .iter_type_or_consts()
.map(|(local_id, _)| TypeOrConstParam {
id: TypeOrConstParamId { parent: self.into(), local_id },
})
@@ -3496,7 +3492,7 @@ impl TypeParam {
/// argument)?
pub fn is_implicit(self, db: &dyn HirDatabase) -> bool {
let params = db.generic_params(self.id.parent());
- let data = &params.type_or_consts[self.id.local_id()];
+ let data = &params[self.id.local_id()];
match data.type_param().unwrap().provenance {
hir_def::generics::TypeParamProvenance::TypeParamList => false,
hir_def::generics::TypeParamProvenance::TraitSelf
@@ -3550,7 +3546,7 @@ pub struct LifetimeParam {
impl LifetimeParam {
pub fn name(self, db: &dyn HirDatabase) -> Name {
let params = db.generic_params(self.id.parent);
- params.lifetimes[self.id.local_id].name.clone()
+ params[self.id.local_id].name.clone()
}
pub fn module(self, db: &dyn HirDatabase) -> Module {
@@ -3574,7 +3570,7 @@ impl ConstParam {
pub fn name(self, db: &dyn HirDatabase) -> Name {
let params = db.generic_params(self.id.parent());
- match params.type_or_consts[self.id.local_id()].name() {
+ match params[self.id.local_id()].name() {
Some(it) => it.clone(),
None => {
never!();
@@ -3617,7 +3613,7 @@ pub struct TypeOrConstParam {
impl TypeOrConstParam {
pub fn name(self, db: &dyn HirDatabase) -> Name {
let params = db.generic_params(self.id.parent);
- match params.type_or_consts[self.id.local_id].name() {
+ match params[self.id.local_id].name() {
Some(n) => n.clone(),
_ => Name::missing(),
}
@@ -3633,7 +3629,7 @@ impl TypeOrConstParam {
pub fn split(self, db: &dyn HirDatabase) -> Either<ConstParam, TypeParam> {
let params = db.generic_params(self.id.parent);
- match &params.type_or_consts[self.id.local_id] {
+ match &params[self.id.local_id] {
hir_def::generics::TypeOrConstParamData::TypeParamData(_) => {
Either::Right(TypeParam { id: TypeParamId::from_unchecked(self.id) })
}
@@ -3652,7 +3648,7 @@ impl TypeOrConstParam {
pub fn as_type_param(self, db: &dyn HirDatabase) -> Option<TypeParam> {
let params = db.generic_params(self.id.parent);
- match &params.type_or_consts[self.id.local_id] {
+ match &params[self.id.local_id] {
hir_def::generics::TypeOrConstParamData::TypeParamData(_) => {
Some(TypeParam { id: TypeParamId::from_unchecked(self.id) })
}
@@ -3662,7 +3658,7 @@ impl TypeOrConstParam {
pub fn as_const_param(self, db: &dyn HirDatabase) -> Option<ConstParam> {
let params = db.generic_params(self.id.parent);
- match &params.type_or_consts[self.id.local_id] {
+ match &params[self.id.local_id] {
hir_def::generics::TypeOrConstParamData::TypeParamData(_) => None,
hir_def::generics::TypeOrConstParamData::ConstParamData(_) => {
Some(ConstParam { id: ConstParamId::from_unchecked(self.id) })