mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-01 14:21:44 +00:00
Change generic parameter/argument order
This commit "inverts" the order of generic parameters/arguments of an item and its parent. This is to fulfill chalk's expectation on the order of `Substitution` for generic associated types and it's one step forward for their support (hopefully). Although chalk doesn't put any constraint on the order of `Substitution` for other items, it feels natural to get everything aligned rather than special casing GATs. One complication is that `TyBuilder` now demands its users to pass in parent's `Substitution` upon construction unless it's obvious that the the item has no parent (e.g. an ADT never has parent). All users *should* already know the parent of the item in question, and without this, it cannot be easily reasoned about whether we're pushing the argument for the item or for its parent. Quick comparison of how this commit changes `Substitution`: ```rust trait Trait<TP, const CP: usize> { type Type<TC, const CC: usize> = (); fn f<TC, const CC: usize>() {} } ``` - before this commit: `[Self, TP, CP, TC, CC]` for each trait item - after this commit: `[TC, CC, Self, TP, CP]` for each trait item
This commit is contained in:
parent
f8f5a5ea57
commit
4385d3dcd0
3 changed files with 141 additions and 87 deletions
|
@ -220,23 +220,30 @@ impl Generics {
|
|||
})
|
||||
}
|
||||
|
||||
/// Iterator over types and const params of parent, then self.
|
||||
/// Iterator over types and const params of self, then parent.
|
||||
pub(crate) fn iter<'a>(
|
||||
&'a self,
|
||||
) -> impl DoubleEndedIterator<Item = (TypeOrConstParamId, &'a TypeOrConstParamData)> + 'a {
|
||||
let to_toc_id = |it: &'a Generics| {
|
||||
move |(local_id, p)| (TypeOrConstParamId { parent: it.def, local_id }, p)
|
||||
};
|
||||
self.parent_generics()
|
||||
.into_iter()
|
||||
.flat_map(move |it| it.params.iter().map(to_toc_id(it)))
|
||||
.chain(self.params.iter().map(to_toc_id(self)))
|
||||
self.params.iter().map(to_toc_id(self)).chain(self.iter_parent())
|
||||
}
|
||||
|
||||
/// Iterate over types and const params without parent params.
|
||||
pub(crate) fn iter_self<'a>(
|
||||
&'a self,
|
||||
) -> impl DoubleEndedIterator<Item = (TypeOrConstParamId, &'a TypeOrConstParamData)> + 'a {
|
||||
let to_toc_id = |it: &'a Generics| {
|
||||
move |(local_id, p)| (TypeOrConstParamId { parent: it.def, local_id }, p)
|
||||
};
|
||||
self.params.iter().map(to_toc_id(self))
|
||||
}
|
||||
|
||||
/// Iterator over types and const params of parent.
|
||||
pub(crate) fn iter_parent<'a>(
|
||||
&'a self,
|
||||
) -> impl Iterator<Item = (TypeOrConstParamId, &'a TypeOrConstParamData)> + 'a {
|
||||
) -> impl DoubleEndedIterator<Item = (TypeOrConstParamId, &'a TypeOrConstParamData)> + 'a {
|
||||
self.parent_generics().into_iter().flat_map(|it| {
|
||||
let to_toc_id =
|
||||
move |(local_id, p)| (TypeOrConstParamId { parent: it.def, local_id }, p);
|
||||
|
@ -244,12 +251,18 @@ impl Generics {
|
|||
})
|
||||
}
|
||||
|
||||
/// Returns total number of generic parameters in scope, including those from parent.
|
||||
pub(crate) fn len(&self) -> usize {
|
||||
let parent = self.parent_generics().map_or(0, Generics::len);
|
||||
let child = self.params.type_or_consts.len();
|
||||
parent + child
|
||||
}
|
||||
|
||||
/// Returns numbers of generic parameters excluding those from parent.
|
||||
pub(crate) fn len_self(&self) -> usize {
|
||||
self.params.type_or_consts.len()
|
||||
}
|
||||
|
||||
/// (parent total, self param, type param list, const param list, impl trait)
|
||||
pub(crate) fn provenance_split(&self) -> (usize, usize, usize, usize, usize) {
|
||||
let ty_iter = || self.params.iter().filter_map(|x| x.1.type_param());
|
||||
|
@ -274,10 +287,12 @@ impl Generics {
|
|||
if param.parent == self.def {
|
||||
let (idx, (_local_id, data)) =
|
||||
self.params.iter().enumerate().find(|(_, (idx, _))| *idx == param.local_id)?;
|
||||
let parent_len = self.parent_generics().map_or(0, Generics::len);
|
||||
Some((parent_len + idx, data))
|
||||
Some((idx, data))
|
||||
} else {
|
||||
self.parent_generics().and_then(|g| g.find_param(param))
|
||||
self.parent_generics()
|
||||
.and_then(|g| g.find_param(param))
|
||||
// Remember that parent parameters come after parameters for self.
|
||||
.map(|(idx, data)| (self.len_self() + idx, data))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue