Unnamed repository; edit this file 'description' to name the repository.
-rw-r--r--crates/hir-def/src/generics.rs99
-rw-r--r--crates/hir-ty/src/generics.rs31
-rw-r--r--crates/hir-ty/src/lower.rs114
3 files changed, 120 insertions, 124 deletions
diff --git a/crates/hir-def/src/generics.rs b/crates/hir-def/src/generics.rs
index 1d880c9eee..ebaaef66db 100644
--- a/crates/hir-def/src/generics.rs
+++ b/crates/hir-def/src/generics.rs
@@ -249,13 +249,62 @@ impl GenericParams {
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.module(db).krate;
+ let krate = def.krate(db);
let cfg_options = db.crate_graph();
let cfg_options = &cfg_options[krate].cfg_options;
@@ -368,54 +417,6 @@ impl GenericParams {
}),
}
}
-
- 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
- }
- })
- }
}
#[derive(Clone, Default)]
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()
diff --git a/crates/hir-ty/src/lower.rs b/crates/hir-ty/src/lower.rs
index a6dd41ae20..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)