Skip to content

Commit a28f536

Browse files
committed
Auto merge of rust-lang#14119 - Veykril:miniopt, r=Veykril
internal: Remove a few allocations in hir-ty::utils
2 parents f11cff8 + 8f5deb4 commit a28f536

File tree

3 files changed

+96
-93
lines changed

3 files changed

+96
-93
lines changed

crates/hir-ty/src/display.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -927,7 +927,7 @@ impl HirDisplay for CallableSig {
927927
}
928928
}
929929

930-
fn fn_traits(db: &dyn DefDatabase, trait_: TraitId) -> impl Iterator<Item = TraitId> {
930+
fn fn_traits(db: &dyn DefDatabase, trait_: TraitId) -> impl Iterator<Item = TraitId> + '_ {
931931
let krate = trait_.lookup(db).container.krate();
932932
utils::fn_traits(db, krate)
933933
}

crates/hir-ty/src/lower.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -1235,7 +1235,7 @@ fn named_associated_type_shorthand_candidates<R>(
12351235
mut cb: impl FnMut(&Name, &TraitRef, TypeAliasId) -> Option<R>,
12361236
) -> Option<R> {
12371237
let mut search = |t| {
1238-
for t in all_super_trait_refs(db, t) {
1238+
all_super_trait_refs(db, t, |t| {
12391239
let data = db.trait_data(t.hir_trait_id());
12401240

12411241
for (name, assoc_id) in &data.items {
@@ -1245,8 +1245,8 @@ fn named_associated_type_shorthand_candidates<R>(
12451245
}
12461246
}
12471247
}
1248-
}
1249-
None
1248+
None
1249+
})
12501250
};
12511251

12521252
match res {

crates/hir-ty/src/utils.rs

+92-89
Original file line numberDiff line numberDiff line change
@@ -27,23 +27,84 @@ use crate::{
2727
db::HirDatabase, ChalkTraitId, Interner, Substitution, TraitRef, TraitRefExt, WhereClause,
2828
};
2929

30-
pub(crate) fn fn_traits(db: &dyn DefDatabase, krate: CrateId) -> impl Iterator<Item = TraitId> {
31-
[
32-
db.lang_item(krate, LangItem::Fn),
33-
db.lang_item(krate, LangItem::FnMut),
34-
db.lang_item(krate, LangItem::FnOnce),
35-
]
36-
.into_iter()
37-
.flatten()
38-
.flat_map(|it| it.as_trait())
30+
pub(crate) fn fn_traits(
31+
db: &dyn DefDatabase,
32+
krate: CrateId,
33+
) -> impl Iterator<Item = TraitId> + '_ {
34+
[LangItem::Fn, LangItem::FnMut, LangItem::FnOnce]
35+
.into_iter()
36+
.filter_map(move |lang| db.lang_item(krate, lang))
37+
.flat_map(|it| it.as_trait())
3938
}
4039

41-
fn direct_super_traits(db: &dyn DefDatabase, trait_: TraitId) -> SmallVec<[TraitId; 4]> {
40+
/// Returns an iterator over the whole super trait hierarchy (including the
41+
/// trait itself).
42+
pub fn all_super_traits(db: &dyn DefDatabase, trait_: TraitId) -> SmallVec<[TraitId; 4]> {
43+
// we need to take care a bit here to avoid infinite loops in case of cycles
44+
// (i.e. if we have `trait A: B; trait B: A;`)
45+
46+
let mut result = smallvec![trait_];
47+
let mut i = 0;
48+
while let Some(&t) = result.get(i) {
49+
// yeah this is quadratic, but trait hierarchies should be flat
50+
// enough that this doesn't matter
51+
direct_super_traits(db, t, |tt| {
52+
if !result.contains(&tt) {
53+
result.push(tt);
54+
}
55+
});
56+
i += 1;
57+
}
58+
result
59+
}
60+
61+
/// Given a trait ref (`Self: Trait`), builds all the implied trait refs for
62+
/// super traits. The original trait ref will be included. So the difference to
63+
/// `all_super_traits` is that we keep track of type parameters; for example if
64+
/// we have `Self: Trait<u32, i32>` and `Trait<T, U>: OtherTrait<U>` we'll get
65+
/// `Self: OtherTrait<i32>`.
66+
pub(super) fn all_super_trait_refs<T>(
67+
db: &dyn HirDatabase,
68+
trait_ref: TraitRef,
69+
cb: impl FnMut(TraitRef) -> Option<T>,
70+
) -> Option<T> {
71+
let seen = iter::once(trait_ref.trait_id).collect();
72+
let mut stack = Vec::new();
73+
stack.push(trait_ref);
74+
SuperTraits { db, seen, stack }.find_map(cb)
75+
}
76+
77+
struct SuperTraits<'a> {
78+
db: &'a dyn HirDatabase,
79+
stack: Vec<TraitRef>,
80+
seen: FxHashSet<ChalkTraitId>,
81+
}
82+
83+
impl<'a> SuperTraits<'a> {
84+
fn elaborate(&mut self, trait_ref: &TraitRef) {
85+
direct_super_trait_refs(self.db, trait_ref, |trait_ref| {
86+
if !self.seen.contains(&trait_ref.trait_id) {
87+
self.stack.push(trait_ref);
88+
}
89+
});
90+
}
91+
}
92+
93+
impl<'a> Iterator for SuperTraits<'a> {
94+
type Item = TraitRef;
95+
96+
fn next(&mut self) -> Option<Self::Item> {
97+
if let Some(next) = self.stack.pop() {
98+
self.elaborate(&next);
99+
Some(next)
100+
} else {
101+
None
102+
}
103+
}
104+
}
105+
106+
fn direct_super_traits(db: &dyn DefDatabase, trait_: TraitId, cb: impl FnMut(TraitId)) {
42107
let resolver = trait_.resolver(db);
43-
// returning the iterator directly doesn't easily work because of
44-
// lifetime problems, but since there usually shouldn't be more than a
45-
// few direct traits this should be fine (we could even use some kind of
46-
// SmallVec if performance is a concern)
47108
let generic_params = db.generic_params(trait_.into());
48109
let trait_self = generic_params.find_trait_self_param();
49110
generic_params
@@ -73,18 +134,14 @@ fn direct_super_traits(db: &dyn DefDatabase, trait_: TraitId) -> SmallVec<[Trait
73134
Some(TypeNs::TraitId(t)) => Some(t),
74135
_ => None,
75136
})
76-
.collect()
137+
.for_each(cb);
77138
}
78139

79-
fn direct_super_trait_refs(db: &dyn HirDatabase, trait_ref: &TraitRef) -> Vec<TraitRef> {
80-
// returning the iterator directly doesn't easily work because of
81-
// lifetime problems, but since there usually shouldn't be more than a
82-
// few direct traits this should be fine (we could even use some kind of
83-
// SmallVec if performance is a concern)
140+
fn direct_super_trait_refs(db: &dyn HirDatabase, trait_ref: &TraitRef, cb: impl FnMut(TraitRef)) {
84141
let generic_params = db.generic_params(trait_ref.hir_trait_id().into());
85142
let trait_self = match generic_params.find_trait_self_param() {
86143
Some(p) => TypeOrConstParamId { parent: trait_ref.hir_trait_id().into(), local_id: p },
87-
None => return Vec::new(),
144+
None => return,
88145
};
89146
db.generic_predicates_for_param(trait_self.parent, trait_self, None)
90147
.iter()
@@ -100,72 +157,15 @@ fn direct_super_trait_refs(db: &dyn HirDatabase, trait_ref: &TraitRef) -> Vec<Tr
100157
})
101158
})
102159
.map(|pred| pred.substitute(Interner, &trait_ref.substitution))
103-
.collect()
104-
}
105-
106-
/// Returns an iterator over the whole super trait hierarchy (including the
107-
/// trait itself).
108-
pub fn all_super_traits(db: &dyn DefDatabase, trait_: TraitId) -> SmallVec<[TraitId; 4]> {
109-
// we need to take care a bit here to avoid infinite loops in case of cycles
110-
// (i.e. if we have `trait A: B; trait B: A;`)
111-
112-
let mut result = smallvec![trait_];
113-
let mut i = 0;
114-
while let Some(&t) = result.get(i) {
115-
// yeah this is quadratic, but trait hierarchies should be flat
116-
// enough that this doesn't matter
117-
for tt in direct_super_traits(db, t) {
118-
if !result.contains(&tt) {
119-
result.push(tt);
120-
}
121-
}
122-
i += 1;
123-
}
124-
result
125-
}
126-
127-
/// Given a trait ref (`Self: Trait`), builds all the implied trait refs for
128-
/// super traits. The original trait ref will be included. So the difference to
129-
/// `all_super_traits` is that we keep track of type parameters; for example if
130-
/// we have `Self: Trait<u32, i32>` and `Trait<T, U>: OtherTrait<U>` we'll get
131-
/// `Self: OtherTrait<i32>`.
132-
pub(super) fn all_super_trait_refs(db: &dyn HirDatabase, trait_ref: TraitRef) -> SuperTraits<'_> {
133-
SuperTraits { db, seen: iter::once(trait_ref.trait_id).collect(), stack: vec![trait_ref] }
134-
}
135-
136-
pub(super) struct SuperTraits<'a> {
137-
db: &'a dyn HirDatabase,
138-
stack: Vec<TraitRef>,
139-
seen: FxHashSet<ChalkTraitId>,
140-
}
141-
142-
impl<'a> SuperTraits<'a> {
143-
fn elaborate(&mut self, trait_ref: &TraitRef) {
144-
let mut trait_refs = direct_super_trait_refs(self.db, trait_ref);
145-
trait_refs.retain(|tr| !self.seen.contains(&tr.trait_id));
146-
self.stack.extend(trait_refs);
147-
}
148-
}
149-
150-
impl<'a> Iterator for SuperTraits<'a> {
151-
type Item = TraitRef;
152-
153-
fn next(&mut self) -> Option<Self::Item> {
154-
if let Some(next) = self.stack.pop() {
155-
self.elaborate(&next);
156-
Some(next)
157-
} else {
158-
None
159-
}
160-
}
160+
.for_each(cb);
161161
}
162162

163163
pub(super) fn associated_type_by_name_including_super_traits(
164164
db: &dyn HirDatabase,
165165
trait_ref: TraitRef,
166166
name: &Name,
167167
) -> Option<(TraitRef, TypeAliasId)> {
168-
all_super_trait_refs(db, trait_ref).find_map(|t| {
168+
all_super_trait_refs(db, trait_ref, |t| {
169169
let assoc_type = db.trait_data(t.hir_trait_id()).associated_type_by_name(name)?;
170170
Some((t, assoc_type))
171171
})
@@ -238,15 +238,18 @@ impl Generics {
238238

239239
/// (parent total, self param, type param list, const param list, impl trait)
240240
pub(crate) fn provenance_split(&self) -> (usize, usize, usize, usize, usize) {
241-
let ty_iter = || self.params.iter().filter_map(|x| x.1.type_param());
242-
243-
let self_params =
244-
ty_iter().filter(|p| p.provenance == TypeParamProvenance::TraitSelf).count();
245-
let type_params =
246-
ty_iter().filter(|p| p.provenance == TypeParamProvenance::TypeParamList).count();
247-
let impl_trait_params =
248-
ty_iter().filter(|p| p.provenance == TypeParamProvenance::ArgumentImplTrait).count();
249-
let const_params = self.params.iter().filter_map(|x| x.1.const_param()).count();
241+
let mut self_params = 0;
242+
let mut type_params = 0;
243+
let mut impl_trait_params = 0;
244+
let mut const_params = 0;
245+
self.params.iter().for_each(|(_, data)| match data {
246+
TypeOrConstParamData::TypeParamData(p) => match p.provenance {
247+
TypeParamProvenance::TypeParamList => type_params += 1,
248+
TypeParamProvenance::TraitSelf => self_params += 1,
249+
TypeParamProvenance::ArgumentImplTrait => impl_trait_params += 1,
250+
},
251+
TypeOrConstParamData::ConstParamData(_) => const_params += 1,
252+
});
250253

251254
let parent_len = self.parent_generics().map_or(0, Generics::len);
252255
(parent_len, self_params, type_params, const_params, impl_trait_params)

0 commit comments

Comments
 (0)