Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-ty/src/generics.rs')
-rw-r--r--crates/hir-ty/src/generics.rs31
1 files changed, 17 insertions, 14 deletions
diff --git a/crates/hir-ty/src/generics.rs b/crates/hir-ty/src/generics.rs
index 7fc60c41d7..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)
})
}
@@ -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()