mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-17 09:23:05 +00:00
Merge generics and where predicates and prevent duplicates in where predicates
This commit is contained in:
parent
11663b1b48
commit
af45040acd
@ -12,7 +12,7 @@ pub(crate) mod utils;
|
|||||||
|
|
||||||
use rustc_ast as ast;
|
use rustc_ast as ast;
|
||||||
use rustc_attr as attr;
|
use rustc_attr as attr;
|
||||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
|
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet, IndexEntry};
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::def::{CtorKind, DefKind, Res};
|
use rustc_hir::def::{CtorKind, DefKind, Res};
|
||||||
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
|
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
|
||||||
@ -598,47 +598,105 @@ pub(crate) fn clean_generics<'tcx>(
|
|||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
let mut params = ThinVec::with_capacity(gens.params.len());
|
let mut bound_predicates = FxIndexMap::default();
|
||||||
for p in gens.params.iter().filter(|p| !is_impl_trait(p) && !is_elided_lifetime(p)) {
|
let mut region_predicates = FxIndexMap::default();
|
||||||
let p = clean_generic_param(cx, Some(gens), p);
|
let mut eq_predicates = ThinVec::default();
|
||||||
params.push(p);
|
for pred in gens.predicates.iter().filter_map(|x| clean_where_predicate(x, cx)) {
|
||||||
}
|
match pred {
|
||||||
params.extend(impl_trait_params);
|
WherePredicate::BoundPredicate { ty, bounds, bound_params } => {
|
||||||
|
match bound_predicates.entry(ty) {
|
||||||
let mut generics = Generics {
|
IndexEntry::Vacant(v) => {
|
||||||
params,
|
v.insert((bounds, bound_params));
|
||||||
where_predicates: gens
|
}
|
||||||
.predicates
|
IndexEntry::Occupied(mut o) => {
|
||||||
.iter()
|
// we merge both bounds.
|
||||||
.filter_map(|x| clean_where_predicate(x, cx))
|
for bound in bounds {
|
||||||
.collect(),
|
if !o.get().0.contains(&bound) {
|
||||||
};
|
o.get_mut().0.push(bound);
|
||||||
|
}
|
||||||
// Some duplicates are generated for ?Sized bounds between type params and where
|
}
|
||||||
// predicates. The point in here is to move the bounds definitions from type params
|
for bound_param in bound_params {
|
||||||
// to where predicates when such cases occur.
|
if !o.get().1.contains(&bound_param) {
|
||||||
for where_pred in &mut generics.where_predicates {
|
o.get_mut().1.push(bound_param);
|
||||||
match *where_pred {
|
|
||||||
WherePredicate::BoundPredicate { ty: Generic(ref name), ref mut bounds, .. } => {
|
|
||||||
if bounds.is_empty() {
|
|
||||||
for param in &mut generics.params {
|
|
||||||
match param.kind {
|
|
||||||
GenericParamDefKind::Lifetime { .. } => {}
|
|
||||||
GenericParamDefKind::Type { bounds: ref mut ty_bounds, .. } => {
|
|
||||||
if ¶m.name == name {
|
|
||||||
mem::swap(bounds, ty_bounds);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
GenericParamDefKind::Const { .. } => {}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => continue,
|
WherePredicate::RegionPredicate { lifetime, bounds } => {
|
||||||
|
match region_predicates.entry(lifetime) {
|
||||||
|
IndexEntry::Vacant(v) => {
|
||||||
|
v.insert(bounds);
|
||||||
|
}
|
||||||
|
IndexEntry::Occupied(mut o) => {
|
||||||
|
// we merge both bounds.
|
||||||
|
for bound in bounds {
|
||||||
|
if !o.get().contains(&bound) {
|
||||||
|
o.get_mut().push(bound);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
WherePredicate::EqPredicate { lhs, rhs, bound_params } => {
|
||||||
|
eq_predicates.push(WherePredicate::EqPredicate { lhs, rhs, bound_params });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
generics
|
|
||||||
|
let mut params = ThinVec::with_capacity(gens.params.len());
|
||||||
|
// In this loop, we gather the generic parameters (`<'a, B: 'a>`) and check if they have
|
||||||
|
// bounds in the where predicates. If so, we move their bounds into the where predicates
|
||||||
|
// while also preventing duplicates.
|
||||||
|
for p in gens.params.iter().filter(|p| !is_impl_trait(p) && !is_elided_lifetime(p)) {
|
||||||
|
let mut p = clean_generic_param(cx, Some(gens), p);
|
||||||
|
match &mut p.kind {
|
||||||
|
GenericParamDefKind::Lifetime { ref mut outlives } => {
|
||||||
|
if let Some(region_pred) = region_predicates.get_mut(&Lifetime(p.name)) {
|
||||||
|
// We merge bounds in the `where` clause.
|
||||||
|
for outlive in outlives.drain(..) {
|
||||||
|
let outlive = GenericBound::Outlives(outlive);
|
||||||
|
if !region_pred.contains(&outlive) {
|
||||||
|
region_pred.push(outlive);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
GenericParamDefKind::Type { bounds, synthetic: false, .. } => {
|
||||||
|
if let Some(bound_pred) = bound_predicates.get_mut(&Type::Generic(p.name)) {
|
||||||
|
// We merge bounds in the `where` clause.
|
||||||
|
for bound in bounds.drain(..) {
|
||||||
|
if !bound_pred.0.contains(&bound) {
|
||||||
|
bound_pred.0.push(bound);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
GenericParamDefKind::Type { .. } | GenericParamDefKind::Const { .. } => {
|
||||||
|
// nothing to do here.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
params.push(p);
|
||||||
|
}
|
||||||
|
params.extend(impl_trait_params);
|
||||||
|
|
||||||
|
Generics {
|
||||||
|
params,
|
||||||
|
where_predicates: bound_predicates
|
||||||
|
.into_iter()
|
||||||
|
.map(|(ty, (bounds, bound_params))| WherePredicate::BoundPredicate {
|
||||||
|
ty,
|
||||||
|
bounds,
|
||||||
|
bound_params,
|
||||||
|
})
|
||||||
|
.chain(
|
||||||
|
region_predicates
|
||||||
|
.into_iter()
|
||||||
|
.map(|(lifetime, bounds)| WherePredicate::RegionPredicate { lifetime, bounds }),
|
||||||
|
)
|
||||||
|
.chain(eq_predicates.into_iter())
|
||||||
|
.collect(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn clean_ty_generics<'tcx>(
|
fn clean_ty_generics<'tcx>(
|
||||||
|
Loading…
Reference in New Issue
Block a user