Move lifetimes in front of type and const params but after self

This commit is contained in:
Lukas Wirth 2024-07-02 13:42:27 +02:00
parent 966798b7ba
commit baa959fa99
3 changed files with 122 additions and 126 deletions

View file

@ -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)
})
}
@ -146,7 +146,10 @@ impl Generics {
if param.parent == self.def {
let idx = param.local_id.into_raw().into_u32() as usize;
debug_assert!(idx <= self.params.len_type_or_consts());
Some(idx)
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()
@ -164,7 +167,7 @@ impl Generics {
if lifetime.parent == self.def {
let idx = lifetime.local_id.into_raw().into_u32() as usize;
debug_assert!(idx <= self.params.len_lifetimes());
Some(self.params.len_type_or_consts() + idx)
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()