Skip to content

Commit 46ec74e

Browse files
committed
Auto merge of #71268 - estebank:devectorize, r=eddyb
Remove some `Vec` allocations to improve performance This claws back most of the performance lost in #69745. r? @eddyb
2 parents d81f559 + e7e3001 commit 46ec74e

File tree

20 files changed

+132
-169
lines changed

20 files changed

+132
-169
lines changed

src/librustc_infer/infer/outlives/verify.rs

+4-8
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,7 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
223223
// like `T` and `T::Item`. It may not work as well for things
224224
// like `<T as Foo<'a>>::Item`.
225225
let c_b = self.param_env.caller_bounds;
226-
let param_bounds = self.collect_outlives_from_predicate_list(&compare_ty, c_b);
226+
let param_bounds = self.collect_outlives_from_predicate_list(&compare_ty, c_b.into_iter());
227227

228228
// Next, collect regions we scraped from the well-formedness
229229
// constraints in the fn signature. To do that, we walk the list
@@ -315,15 +315,12 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
315315
let tcx = self.tcx;
316316
let assoc_item = tcx.associated_item(assoc_item_def_id);
317317
let trait_def_id = assoc_item.container.assert_trait();
318-
let trait_predicates =
319-
tcx.predicates_of(trait_def_id).predicates.iter().map(|(p, _)| *p).collect();
318+
let trait_predicates = tcx.predicates_of(trait_def_id).predicates.iter().map(|(p, _)| *p);
320319
let identity_substs = InternalSubsts::identity_for_item(tcx, assoc_item_def_id);
321320
let identity_proj = tcx.mk_projection(assoc_item_def_id, identity_substs);
322321
self.collect_outlives_from_predicate_list(
323322
move |ty| ty == identity_proj,
324-
traits::elaborate_predicates(tcx, trait_predicates)
325-
.map(|o| o.predicate)
326-
.collect::<Vec<_>>(),
323+
traits::elaborate_predicates(tcx, trait_predicates).map(|o| o.predicate),
327324
)
328325
.map(|b| b.1)
329326
}
@@ -337,10 +334,9 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
337334
fn collect_outlives_from_predicate_list(
338335
&self,
339336
compare_ty: impl Fn(Ty<'tcx>) -> bool,
340-
predicates: impl IntoIterator<Item = impl AsRef<ty::Predicate<'tcx>>>,
337+
predicates: impl Iterator<Item = impl AsRef<ty::Predicate<'tcx>>>,
341338
) -> impl Iterator<Item = ty::OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>>> {
342339
predicates
343-
.into_iter()
344340
.filter_map(|p| p.as_ref().to_opt_type_outlives())
345341
.filter_map(|p| p.no_bound_vars())
346342
.filter(move |p| compare_ty(p.0))

src/librustc_infer/traits/util.rs

+7-10
Original file line numberDiff line numberDiff line change
@@ -97,24 +97,22 @@ pub fn elaborate_trait_ref<'tcx>(
9797
tcx: TyCtxt<'tcx>,
9898
trait_ref: ty::PolyTraitRef<'tcx>,
9999
) -> Elaborator<'tcx> {
100-
elaborate_predicates(tcx, vec![trait_ref.without_const().to_predicate()])
100+
elaborate_predicates(tcx, std::iter::once(trait_ref.without_const().to_predicate()))
101101
}
102102

103103
pub fn elaborate_trait_refs<'tcx>(
104104
tcx: TyCtxt<'tcx>,
105105
trait_refs: impl Iterator<Item = ty::PolyTraitRef<'tcx>>,
106106
) -> Elaborator<'tcx> {
107-
let predicates = trait_refs.map(|trait_ref| trait_ref.without_const().to_predicate()).collect();
107+
let predicates = trait_refs.map(|trait_ref| trait_ref.without_const().to_predicate());
108108
elaborate_predicates(tcx, predicates)
109109
}
110110

111111
pub fn elaborate_predicates<'tcx>(
112112
tcx: TyCtxt<'tcx>,
113-
mut predicates: Vec<ty::Predicate<'tcx>>,
113+
predicates: impl Iterator<Item = ty::Predicate<'tcx>>,
114114
) -> Elaborator<'tcx> {
115-
let mut visited = PredicateSet::new(tcx);
116-
predicates.retain(|pred| visited.insert(pred));
117-
let obligations: Vec<_> =
115+
let obligations =
118116
predicates.into_iter().map(|predicate| predicate_obligation(predicate, None)).collect();
119117
elaborate_obligations(tcx, obligations)
120118
}
@@ -151,21 +149,20 @@ impl Elaborator<'tcx> {
151149
// Get predicates declared on the trait.
152150
let predicates = tcx.super_predicates_of(data.def_id());
153151

154-
let obligations = predicates.predicates.iter().map(|(pred, span)| {
152+
let obligations = predicates.predicates.into_iter().map(|(pred, span)| {
155153
predicate_obligation(
156154
pred.subst_supertrait(tcx, &data.to_poly_trait_ref()),
157155
Some(*span),
158156
)
159157
});
160-
debug!("super_predicates: data={:?} predicates={:?}", data, &obligations);
158+
debug!("super_predicates: data={:?}", data);
161159

162160
// Only keep those bounds that we haven't already seen.
163161
// This is necessary to prevent infinite recursion in some
164162
// cases. One common case is when people define
165163
// `trait Sized: Sized { }` rather than `trait Sized { }`.
166164
let visited = &mut self.visited;
167-
let obligations =
168-
obligations.filter(|obligation| visited.insert(&obligation.predicate));
165+
let obligations = obligations.filter(|o| visited.insert(&o.predicate));
169166

170167
self.stack.extend(obligations);
171168
}

src/librustc_middle/ty/trait_def.rs

+5-7
Original file line numberDiff line numberDiff line change
@@ -168,15 +168,13 @@ impl<'tcx> TyCtxt<'tcx> {
168168
}
169169

170170
/// Returns a vector containing all impls
171-
pub fn all_impls(self, def_id: DefId) -> Vec<DefId> {
172-
let impls = self.trait_impls_of(def_id);
171+
pub fn all_impls(self, def_id: DefId) -> impl Iterator<Item = DefId> + 'tcx {
172+
let TraitImpls { blanket_impls, non_blanket_impls } = self.trait_impls_of(def_id);
173173

174-
impls
175-
.blanket_impls
176-
.iter()
177-
.chain(impls.non_blanket_impls.values().flatten())
174+
blanket_impls
175+
.into_iter()
176+
.chain(non_blanket_impls.into_iter().map(|(_, v)| v).flatten())
178177
.cloned()
179-
.collect()
180178
}
181179
}
182180

src/librustc_mir/transform/const_prop.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -116,8 +116,7 @@ impl<'tcx> MirPass<'tcx> for ConstProp {
116116
.predicates_of(source.def_id())
117117
.predicates
118118
.iter()
119-
.filter_map(|(p, _)| if p.is_global() { Some(*p) } else { None })
120-
.collect();
119+
.filter_map(|(p, _)| if p.is_global() { Some(*p) } else { None });
121120
if !traits::normalize_and_test_predicates(
122121
tcx,
123122
traits::elaborate_predicates(tcx, predicates).map(|o| o.predicate).collect(),

src/librustc_trait_selection/opaque_types.rs

+6-7
Original file line numberDiff line numberDiff line change
@@ -418,7 +418,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
418418
let opaque_type = tcx.mk_opaque(def_id, opaque_defn.substs);
419419

420420
let required_region_bounds =
421-
required_region_bounds(tcx, opaque_type, bounds.predicates);
421+
required_region_bounds(tcx, opaque_type, bounds.predicates.into_iter());
422422
debug_assert!(!required_region_bounds.is_empty());
423423

424424
for required_region in required_region_bounds {
@@ -1137,7 +1137,8 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> {
11371137

11381138
debug!("instantiate_opaque_types: bounds={:?}", bounds);
11391139

1140-
let required_region_bounds = required_region_bounds(tcx, ty, bounds.predicates.clone());
1140+
let required_region_bounds =
1141+
required_region_bounds(tcx, ty, bounds.predicates.iter().cloned());
11411142
debug!("instantiate_opaque_types: required_region_bounds={:?}", required_region_bounds);
11421143

11431144
// Make sure that we are in fact defining the *entire* type
@@ -1259,17 +1260,15 @@ pub fn may_define_opaque_type(
12591260
crate fn required_region_bounds(
12601261
tcx: TyCtxt<'tcx>,
12611262
erased_self_ty: Ty<'tcx>,
1262-
predicates: Vec<ty::Predicate<'tcx>>,
1263+
predicates: impl Iterator<Item = ty::Predicate<'tcx>>,
12631264
) -> Vec<ty::Region<'tcx>> {
1264-
debug!(
1265-
"required_region_bounds(erased_self_ty={:?}, predicates={:?})",
1266-
erased_self_ty, predicates
1267-
);
1265+
debug!("required_region_bounds(erased_self_ty={:?})", erased_self_ty);
12681266

12691267
assert!(!erased_self_ty.has_escaping_bound_vars());
12701268

12711269
traits::elaborate_predicates(tcx, predicates)
12721270
.filter_map(|obligation| {
1271+
debug!("required_region_bounds(obligation={:?})", obligation);
12731272
match obligation.predicate {
12741273
ty::Predicate::Projection(..)
12751274
| ty::Predicate::Trait(..)

src/librustc_trait_selection/traits/auto_trait.rs

+7-6
Original file line numberDiff line numberDiff line change
@@ -281,7 +281,7 @@ impl AutoTraitFinder<'tcx> {
281281
},
282282
}));
283283

284-
let mut computed_preds: FxHashSet<_> = param_env.caller_bounds.iter().cloned().collect();
284+
let computed_preds = param_env.caller_bounds.iter().cloned();
285285
let mut user_computed_preds: FxHashSet<_> =
286286
user_env.caller_bounds.iter().cloned().collect();
287287

@@ -358,10 +358,11 @@ impl AutoTraitFinder<'tcx> {
358358
_ => panic!("Unexpected error for '{:?}': {:?}", ty, result),
359359
};
360360

361-
computed_preds.extend(user_computed_preds.iter().cloned());
362-
let normalized_preds =
363-
elaborate_predicates(tcx, computed_preds.iter().cloned().collect())
364-
.map(|o| o.predicate);
361+
let normalized_preds = elaborate_predicates(
362+
tcx,
363+
computed_preds.clone().chain(user_computed_preds.iter().cloned()),
364+
)
365+
.map(|o| o.predicate);
365366
new_env =
366367
ty::ParamEnv::new(tcx.mk_predicates(normalized_preds), param_env.reveal, None);
367368
}
@@ -739,7 +740,7 @@ impl AutoTraitFinder<'tcx> {
739740
if p.ty().skip_binder().has_infer_types() {
740741
if !self.evaluate_nested_obligations(
741742
ty,
742-
v.clone().iter().cloned(),
743+
v.into_iter(),
743744
computed_preds,
744745
fresh_preds,
745746
predicates,

src/librustc_trait_selection/traits/error_reporting/mod.rs

+3-7
Original file line numberDiff line numberDiff line change
@@ -1017,7 +1017,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> {
10171017
}
10181018
};
10191019

1020-
for obligation in super::elaborate_predicates(self.tcx, vec![*cond]) {
1020+
for obligation in super::elaborate_predicates(self.tcx, std::iter::once(*cond)) {
10211021
if let ty::Predicate::Trait(implication, _) = obligation.predicate {
10221022
let error = error.to_poly_trait_ref();
10231023
let implication = implication.to_poly_trait_ref();
@@ -1218,22 +1218,18 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> {
12181218

12191219
match simp {
12201220
Some(simp) => all_impls
1221-
.iter()
1222-
.filter_map(|&def_id| {
1221+
.filter_map(|def_id| {
12231222
let imp = self.tcx.impl_trait_ref(def_id).unwrap();
12241223
let imp_simp = fast_reject::simplify_type(self.tcx, imp.self_ty(), true);
12251224
if let Some(imp_simp) = imp_simp {
12261225
if simp != imp_simp {
12271226
return None;
12281227
}
12291228
}
1230-
12311229
Some(imp)
12321230
})
12331231
.collect(),
1234-
None => {
1235-
all_impls.iter().map(|&def_id| self.tcx.impl_trait_ref(def_id).unwrap()).collect()
1236-
}
1232+
None => all_impls.map(|def_id| self.tcx.impl_trait_ref(def_id).unwrap()).collect(),
12371233
}
12381234
}
12391235

src/librustc_trait_selection/traits/mod.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -110,8 +110,8 @@ pub enum TraitQueryMode {
110110
pub fn predicates_for_generics<'tcx>(
111111
cause: ObligationCause<'tcx>,
112112
param_env: ty::ParamEnv<'tcx>,
113-
generic_bounds: &ty::InstantiatedPredicates<'tcx>,
114-
) -> PredicateObligations<'tcx> {
113+
generic_bounds: ty::InstantiatedPredicates<'tcx>,
114+
) -> impl Iterator<Item = PredicateObligation<'tcx>> {
115115
util::predicates_for_generics(cause, 0, param_env, generic_bounds)
116116
}
117117

@@ -297,7 +297,7 @@ pub fn normalize_param_env_or_error<'tcx>(
297297
);
298298

299299
let mut predicates: Vec<_> =
300-
util::elaborate_predicates(tcx, unnormalized_env.caller_bounds.to_vec())
300+
util::elaborate_predicates(tcx, unnormalized_env.caller_bounds.into_iter().cloned())
301301
.map(|obligation| obligation.predicate)
302302
.collect();
303303

src/librustc_trait_selection/traits/object_safety.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -302,7 +302,7 @@ fn generics_require_sized_self(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
302302
// Search for a predicate like `Self : Sized` amongst the trait bounds.
303303
let predicates = tcx.predicates_of(def_id);
304304
let predicates = predicates.instantiate_identity(tcx).predicates;
305-
elaborate_predicates(tcx, predicates).any(|obligation| match obligation.predicate {
305+
elaborate_predicates(tcx, predicates.into_iter()).any(|obligation| match obligation.predicate {
306306
ty::Predicate::Trait(ref trait_pred, _) => {
307307
trait_pred.def_id() == sized_def_id && trait_pred.skip_binder().self_ty().is_param(0)
308308
}

src/librustc_trait_selection/traits/project.rs

+6-10
Original file line numberDiff line numberDiff line change
@@ -900,7 +900,7 @@ fn assemble_candidates_from_trait_def<'cx, 'tcx>(
900900
// If so, extract what we know from the trait and try to come up with a good answer.
901901
let trait_predicates = tcx.predicates_of(def_id);
902902
let bounds = trait_predicates.instantiate(tcx, substs);
903-
let bounds = elaborate_predicates(tcx, bounds.predicates).map(|o| o.predicate);
903+
let bounds = elaborate_predicates(tcx, bounds.predicates.into_iter()).map(|o| o.predicate);
904904
assemble_candidates_from_predicates(
905905
selcx,
906906
obligation,
@@ -911,16 +911,14 @@ fn assemble_candidates_from_trait_def<'cx, 'tcx>(
911911
)
912912
}
913913

914-
fn assemble_candidates_from_predicates<'cx, 'tcx, I>(
914+
fn assemble_candidates_from_predicates<'cx, 'tcx>(
915915
selcx: &mut SelectionContext<'cx, 'tcx>,
916916
obligation: &ProjectionTyObligation<'tcx>,
917917
obligation_trait_ref: &ty::TraitRef<'tcx>,
918918
candidate_set: &mut ProjectionTyCandidateSet<'tcx>,
919919
ctor: fn(ty::PolyProjectionPredicate<'tcx>) -> ProjectionTyCandidate<'tcx>,
920-
env_predicates: I,
921-
) where
922-
I: IntoIterator<Item = ty::Predicate<'tcx>>,
923-
{
920+
env_predicates: impl Iterator<Item = ty::Predicate<'tcx>>,
921+
) {
924922
debug!("assemble_candidates_from_predicates(obligation={:?})", obligation);
925923
let infcx = selcx.infcx();
926924
for predicate in env_predicates {
@@ -1153,10 +1151,8 @@ fn confirm_object_candidate<'cx, 'tcx>(
11531151
object_ty
11541152
),
11551153
};
1156-
let env_predicates = data
1157-
.projection_bounds()
1158-
.map(|p| p.with_self_ty(selcx.tcx(), object_ty).to_predicate())
1159-
.collect();
1154+
let env_predicates =
1155+
data.projection_bounds().map(|p| p.with_self_ty(selcx.tcx(), object_ty).to_predicate());
11601156
let env_predicate = {
11611157
let env_predicates = elaborate_predicates(selcx.tcx(), env_predicates);
11621158

src/librustc_trait_selection/traits/select.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1443,7 +1443,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
14431443
bounds
14441444
);
14451445

1446-
let elaborated_predicates = util::elaborate_predicates(self.tcx(), bounds.predicates);
1446+
let elaborated_predicates =
1447+
util::elaborate_predicates(self.tcx(), bounds.predicates.into_iter());
14471448
let matching_bound = elaborated_predicates.filter_to_traits().find(|bound| {
14481449
self.infcx.probe(|_| {
14491450
self.match_projection(

src/librustc_trait_selection/traits/specialize/mod.rs

+15-19
Original file line numberDiff line numberDiff line change
@@ -189,26 +189,22 @@ fn fulfill_implication<'a, 'tcx>(
189189

190190
let selcx = &mut SelectionContext::new(&infcx);
191191
let target_substs = infcx.fresh_substs_for_item(DUMMY_SP, target_impl);
192-
let (target_trait_ref, mut obligations) =
192+
let (target_trait_ref, obligations) =
193193
impl_trait_ref_and_oblig(selcx, param_env, target_impl, target_substs);
194-
debug!(
195-
"fulfill_implication: target_trait_ref={:?}, obligations={:?}",
196-
target_trait_ref, obligations
197-
);
198194

199195
// do the impls unify? If not, no specialization.
200-
match infcx.at(&ObligationCause::dummy(), param_env).eq(source_trait_ref, target_trait_ref) {
201-
Ok(InferOk { obligations: o, .. }) => {
202-
obligations.extend(o);
203-
}
204-
Err(_) => {
205-
debug!(
206-
"fulfill_implication: {:?} does not unify with {:?}",
207-
source_trait_ref, target_trait_ref
208-
);
209-
return Err(());
210-
}
211-
}
196+
let more_obligations =
197+
match infcx.at(&ObligationCause::dummy(), param_env).eq(source_trait_ref, target_trait_ref)
198+
{
199+
Ok(InferOk { obligations, .. }) => obligations,
200+
Err(_) => {
201+
debug!(
202+
"fulfill_implication: {:?} does not unify with {:?}",
203+
source_trait_ref, target_trait_ref
204+
);
205+
return Err(());
206+
}
207+
};
212208

213209
// attempt to prove all of the predicates for impl2 given those for impl1
214210
// (which are packed up in penv)
@@ -226,7 +222,7 @@ fn fulfill_implication<'a, 'tcx>(
226222
// we already make a mockery out of the region system, so
227223
// why not ignore them a bit earlier?
228224
let mut fulfill_cx = FulfillmentContext::new_ignoring_regions();
229-
for oblig in obligations.into_iter() {
225+
for oblig in obligations.chain(more_obligations) {
230226
fulfill_cx.register_predicate_obligation(&infcx, oblig);
231227
}
232228
match fulfill_cx.select_all_or_error(infcx) {
@@ -261,7 +257,7 @@ pub(super) fn specialization_graph_provider(
261257
) -> &specialization_graph::Graph {
262258
let mut sg = specialization_graph::Graph::new();
263259

264-
let mut trait_impls = tcx.all_impls(trait_id);
260+
let mut trait_impls: Vec<_> = tcx.all_impls(trait_id).collect();
265261

266262
// The coherence checking implementation seems to rely on impls being
267263
// iterated over (roughly) in definition order, so we are sorting by

0 commit comments

Comments
 (0)