Skip to content

Commit 33a9f16

Browse files
committed
avoid collecting Vec multiple times when normalize param_env
1 parent 1de00d1 commit 33a9f16

File tree

1 file changed

+27
-23
lines changed
  • compiler/rustc_trait_selection/src/traits

1 file changed

+27
-23
lines changed

compiler/rustc_trait_selection/src/traits/mod.rs

+27-23
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ use crate::infer::outlives::env::OutlivesEnvironment;
2828
use crate::infer::{InferCtxt, TyCtxtInferExt};
2929
use crate::traits::error_reporting::InferCtxtExt as _;
3030
use crate::traits::query::evaluate_obligation::InferCtxtExt as _;
31+
use rustc_data_structures::functor::IdFunctor;
3132
use rustc_errors::ErrorGuaranteed;
3233
use rustc_hir as hir;
3334
use rustc_hir::def_id::DefId;
@@ -219,6 +220,7 @@ fn do_normalize_predicates<'tcx>(
219220
cause: ObligationCause<'tcx>,
220221
elaborated_env: ty::ParamEnv<'tcx>,
221222
predicates: Vec<ty::Predicate<'tcx>>,
223+
outlives: bool,
222224
) -> Result<Vec<ty::Predicate<'tcx>>, ErrorGuaranteed> {
223225
let span = cause.span;
224226
// FIXME. We should really... do something with these region
@@ -235,7 +237,15 @@ fn do_normalize_predicates<'tcx>(
235237
// them here too, and we will remove this function when
236238
// we move over to lazy normalization *anyway*.
237239
tcx.infer_ctxt().ignoring_regions().enter(|infcx| {
238-
let predicates = match fully_normalize(&infcx, cause, elaborated_env, predicates) {
240+
let predicates = match predicates.try_map_id(|predicate| {
241+
if outlives
242+
!= matches!(predicate.kind().skip_binder(), ty::PredicateKind::TypeOutlives(..))
243+
{
244+
Ok(predicate)
245+
} else {
246+
fully_normalize(&infcx, cause.clone(), elaborated_env, predicate)
247+
}
248+
}) {
239249
Ok(predicates) => predicates,
240250
Err(errors) => {
241251
let reported = infcx.report_fulfillment_errors(&errors, None, false);
@@ -262,7 +272,15 @@ fn do_normalize_predicates<'tcx>(
262272
);
263273
}
264274

265-
match infcx.fully_resolve(predicates) {
275+
match predicates.try_map_id(|predicate| {
276+
if outlives
277+
!= matches!(predicate.kind().skip_binder(), ty::PredicateKind::TypeOutlives(..))
278+
{
279+
Ok(predicate)
280+
} else {
281+
infcx.fully_resolve(predicate)
282+
}
283+
}) {
266284
Ok(predicates) => Ok(predicates),
267285
Err(fixup_err) => {
268286
// If we encounter a fixup error, it means that some type
@@ -306,7 +324,7 @@ pub fn normalize_param_env_or_error<'tcx>(
306324
// parameter environments once for every fn as it goes,
307325
// and errors will get reported then; so outside of type inference we
308326
// can be sure that no errors should occur.
309-
let mut predicates: Vec<_> =
327+
let predicates: Vec<_> =
310328
util::elaborate_predicates(tcx, unnormalized_env.caller_bounds().into_iter())
311329
.map(|obligation| obligation.predicate)
312330
.collect();
@@ -337,53 +355,39 @@ pub fn normalize_param_env_or_error<'tcx>(
337355
//
338356
// This works fairly well because trait matching does not actually care about param-env
339357
// TypeOutlives predicates - these are normally used by regionck.
340-
let outlives_predicates: Vec<_> = predicates
341-
.drain_filter(|predicate| {
342-
matches!(predicate.kind().skip_binder(), ty::PredicateKind::TypeOutlives(..))
343-
})
344-
.collect();
345358

346-
debug!(
347-
"normalize_param_env_or_error: predicates=(non-outlives={:?}, outlives={:?})",
348-
predicates, outlives_predicates
349-
);
350-
let Ok(non_outlives_predicates) = do_normalize_predicates(
359+
let Ok(predicates) = do_normalize_predicates(
351360
tcx,
352361
cause.clone(),
353362
elaborated_env,
354363
predicates,
364+
false,
355365
) else {
356366
// An unnormalized env is better than nothing.
357367
debug!("normalize_param_env_or_error: errored resolving non-outlives predicates");
358368
return elaborated_env;
359369
};
360370

361-
debug!("normalize_param_env_or_error: non-outlives predicates={:?}", non_outlives_predicates);
362-
363371
// Not sure whether it is better to include the unnormalized TypeOutlives predicates
364372
// here. I believe they should not matter, because we are ignoring TypeOutlives param-env
365373
// predicates here anyway. Keeping them here anyway because it seems safer.
366-
let outlives_env: Vec<_> =
367-
non_outlives_predicates.iter().chain(&outlives_predicates).cloned().collect();
368374
let outlives_env = ty::ParamEnv::new(
369-
tcx.intern_predicates(&outlives_env),
375+
tcx.intern_predicates(&predicates),
370376
unnormalized_env.reveal(),
371377
unnormalized_env.constness(),
372378
);
373-
let Ok(outlives_predicates) = do_normalize_predicates(
379+
let Ok(predicates) = do_normalize_predicates(
374380
tcx,
375381
cause,
376382
outlives_env,
377-
outlives_predicates,
383+
predicates,
384+
true
378385
) else {
379386
// An unnormalized env is better than nothing.
380387
debug!("normalize_param_env_or_error: errored resolving outlives predicates");
381388
return elaborated_env;
382389
};
383-
debug!("normalize_param_env_or_error: outlives predicates={:?}", outlives_predicates);
384390

385-
let mut predicates = non_outlives_predicates;
386-
predicates.extend(outlives_predicates);
387391
debug!("normalize_param_env_or_error: final predicates={:?}", predicates);
388392
ty::ParamEnv::new(
389393
tcx.intern_predicates(&predicates),

0 commit comments

Comments
 (0)