mirror of
https://github.com/rust-lang/rust-analyzer
synced 2025-01-13 21:54:42 +00:00
Move lifetimes in front of type and const params but after self
This commit is contained in:
parent
966798b7ba
commit
baa959fa99
3 changed files with 122 additions and 126 deletions
|
@ -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)]
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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_map(|arg| match arg {
|
||||
GenericArg::Lifetime(arg) => Some(self.lower_lifetime(arg)),
|
||||
_ => None,
|
||||
})
|
||||
.chain(iter::repeat(error_lifetime()))
|
||||
.take(lifetime_params)
|
||||
{
|
||||
substs.push(arg.cast(Interner));
|
||||
}
|
||||
|
||||
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(_)))
|
||||
.skip(skip)
|
||||
.take(expected_num)
|
||||
.take(type_params + const_params)
|
||||
.zip(def_toc_iter)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
for arg in args
|
||||
.iter()
|
||||
.filter(|arg| matches!(arg, GenericArg::Lifetime(_)))
|
||||
.take(lifetime_params)
|
||||
{
|
||||
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 <[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)
|
||||
|
|
Loading…
Reference in a new issue