Skip to content

Commit 9356650

Browse files
committed
wip: perf: re-add optimisation
1 parent aa2eda6 commit 9356650

File tree

10 files changed

+69
-43
lines changed

10 files changed

+69
-43
lines changed

compiler/rustc_trait_selection/src/traits/fulfill.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,11 @@ use super::{
2424
};
2525
use crate::error_reporting::InferCtxtErrorExt;
2626
use crate::infer::{InferCtxt, TyOrConstInferVar};
27+
use crate::traits::EvaluateConstErr;
2728
use crate::traits::normalize::normalize_with_depth_to;
2829
use crate::traits::project::{PolyProjectionObligation, ProjectionCacheKeyExt as _};
2930
use crate::traits::query::evaluate_obligation::InferCtxtExt;
30-
use crate::traits::{EvaluateConstErr, sizedness_fast_path};
31+
use crate::traits::util::extended_sizedness_fast_path;
3132

3233
pub(crate) type PendingPredicateObligations<'tcx> = ThinVec<PendingPredicateObligation<'tcx>>;
3334

@@ -335,7 +336,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
335336

336337
let infcx = self.selcx.infcx;
337338

338-
if sizedness_fast_path(infcx.tcx, obligation.predicate) {
339+
if extended_sizedness_fast_path(infcx, obligation) {
339340
return ProcessResult::Changed(thin_vec::thin_vec![]);
340341
}
341342

compiler/rustc_trait_selection/src/traits/mod.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,10 @@ pub use self::specialize::{
6464
};
6565
pub use self::structural_normalize::StructurallyNormalizeExt;
6666
pub use self::util::{
67-
BoundVarReplacer, PlaceholderReplacer, elaborate, expand_trait_aliases, impl_item_is_final,
68-
sizedness_fast_path, supertrait_def_ids, supertraits, transitive_bounds_that_define_assoc_item,
69-
upcast_choices, with_replaced_escaping_bound_vars,
67+
BoundVarReplacer, PlaceholderReplacer, elaborate, expand_trait_aliases,
68+
extended_sizedness_fast_path, impl_item_is_final, sizedness_fast_path, supertrait_def_ids,
69+
supertraits, transitive_bounds_that_define_assoc_item, upcast_choices,
70+
with_replaced_escaping_bound_vars,
7071
};
7172
use crate::error_reporting::InferCtxtErrorExt;
7273
use crate::infer::outlives::env::OutlivesEnvironment;

compiler/rustc_trait_selection/src/traits/query/type_op/prove_predicate.rs

+1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ impl<'tcx> super::QueryTypeOp<'tcx> for ProvePredicate<'tcx> {
1515
tcx: TyCtxt<'tcx>,
1616
key: &ParamEnvAnd<'tcx, Self>,
1717
) -> Option<Self::QueryResponse> {
18+
// Using `extended_sizedness_fast_path` with a fresh `InferCtxt` causes an ICE.
1819
if sizedness_fast_path(tcx, key.value.predicate) {
1920
return Some(());
2021
}

compiler/rustc_trait_selection/src/traits/select/mod.rs

+3-4
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,8 @@ use crate::infer::{InferCtxt, InferOk, TypeFreshener};
4848
use crate::solve::InferCtxtSelectExt as _;
4949
use crate::traits::normalize::{normalize_with_depth, normalize_with_depth_to};
5050
use crate::traits::project::{ProjectAndUnifyResult, ProjectionCacheKeyExt};
51-
use crate::traits::{
52-
EvaluateConstErr, ProjectionCacheKey, Unimplemented, effects, sizedness_fast_path,
53-
};
51+
use crate::traits::util::extended_sizedness_fast_path;
52+
use crate::traits::{EvaluateConstErr, ProjectionCacheKey, Unimplemented, effects};
5453

5554
mod _match;
5655
mod candidate_assembly;
@@ -604,7 +603,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
604603
None => self.check_recursion_limit(&obligation, &obligation)?,
605604
}
606605

607-
if sizedness_fast_path(self.tcx(), obligation.predicate) {
606+
if extended_sizedness_fast_path(self.infcx, &obligation) {
608607
return Ok(EvaluatedToOk);
609608
}
610609

compiler/rustc_trait_selection/src/traits/util.rs

+29-4
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
44
use rustc_hir::LangItem;
55
use rustc_hir::def_id::DefId;
66
use rustc_infer::infer::InferCtxt;
7-
use rustc_infer::traits::PolyTraitObligation;
87
pub use rustc_infer::traits::util::*;
8+
use rustc_infer::traits::{PolyTraitObligation, PredicateObligation};
99
use rustc_middle::bug;
1010
use rustc_middle::ty::{
1111
self, PolyTraitPredicate, SizedTraitKind, Ty, TyCtxt, TypeFoldable, TypeFolder,
@@ -508,10 +508,35 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for PlaceholderReplacer<'_, 'tcx> {
508508
}
509509
}
510510

511+
/// In addition to checks in `sizedness_fast_path`, exists early if for `MetaSized` obligation with
512+
/// a matching `Sized` obligation in the `ParamEnv`.
513+
pub fn extended_sizedness_fast_path<'tcx>(
514+
infcx: &InferCtxt<'tcx>,
515+
obligation: &PredicateObligation<'tcx>,
516+
) -> bool {
517+
if sizedness_fast_path(infcx.tcx, obligation.predicate) {
518+
return true;
519+
}
520+
521+
if let Some(trait_clause) = obligation.predicate.as_trait_clause() {
522+
if unelaborated_sizedness_candidate_from_obligation(
523+
infcx,
524+
&obligation.with(infcx.tcx, trait_clause),
525+
)
526+
.is_some()
527+
{
528+
debug!("fast path -- metasized paramenv");
529+
return true;
530+
}
531+
}
532+
533+
false
534+
}
535+
536+
/// Proving `Sized`/`MetaSized`/`PointeeSized`, very often on "obviously sized" types like
537+
/// `&T`, accounts for about 60% percentage of the predicates we have to prove. In these cases,
538+
/// skip canonicalization and as much trait solving machinery as possible.
511539
pub fn sizedness_fast_path<'tcx>(tcx: TyCtxt<'tcx>, predicate: ty::Predicate<'tcx>) -> bool {
512-
// Proving `Sized`/`MetaSized`/`PointeeSized`, very often on "obviously sized" types like
513-
// `&T`, accounts for about 60% percentage of the predicates we have to prove. No need to
514-
// canonicalize and all that for such cases.
515540
if let ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_ref)) =
516541
predicate.kind().skip_binder()
517542
{

compiler/rustc_traits/src/codegen.rs

+12-5
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,11 @@
66
use rustc_infer::infer::TyCtxtInferExt;
77
use rustc_middle::bug;
88
use rustc_middle::traits::CodegenObligationError;
9-
use rustc_middle::ty::{self, PseudoCanonicalInput, TyCtxt, TypeVisitableExt, Upcast};
9+
use rustc_middle::ty::{self, PseudoCanonicalInput, TyCtxt, TypeVisitableExt};
1010
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
1111
use rustc_trait_selection::traits::{
1212
ImplSource, Obligation, ObligationCause, ObligationCtxt, ScrubbedTraitError, SelectionContext,
13-
Unimplemented, sizedness_fast_path,
13+
Unimplemented, extended_sizedness_fast_path,
1414
};
1515
use tracing::debug;
1616

@@ -34,15 +34,22 @@ pub(crate) fn codegen_select_candidate<'tcx>(
3434
let (infcx, param_env) = tcx.infer_ctxt().ignoring_regions().build_with_typing_env(typing_env);
3535
let mut selcx = SelectionContext::new(&infcx);
3636

37-
if sizedness_fast_path(tcx, trait_ref.upcast(tcx)) {
37+
let obligation_cause = ObligationCause::dummy();
38+
let obligation = Obligation::new(tcx, obligation_cause, param_env, trait_ref);
39+
40+
if extended_sizedness_fast_path(&infcx, &obligation) {
3841
return Ok(&*tcx.arena.alloc(ImplSource::Builtin(
3942
ty::solve::BuiltinImplSource::Trivial,
4043
Default::default(),
4144
)));
4245
}
4346

44-
let obligation_cause = ObligationCause::dummy();
45-
let obligation = Obligation::new(tcx, obligation_cause, param_env, trait_ref);
47+
// Calling `sizedness_fast_path` upcasts to `PolyObligation`, rather than `TraitObligation`
48+
let obligation = if let Some(clause) = obligation.predicate.as_trait_clause() {
49+
obligation.with(tcx, clause.skip_binder())
50+
} else {
51+
bug!("trait ref upcast to non-trait clause");
52+
};
4653

4754
let selection = match selcx.select(&obligation) {
4855
Ok(Some(selection)) => selection,

compiler/rustc_traits/src/evaluate_obligation.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use rustc_span::DUMMY_SP;
55
use rustc_trait_selection::traits::query::CanonicalPredicateGoal;
66
use rustc_trait_selection::traits::{
77
EvaluationResult, Obligation, ObligationCause, OverflowError, SelectionContext, TraitQueryMode,
8-
sizedness_fast_path,
8+
extended_sizedness_fast_path,
99
};
1010
use tracing::debug;
1111

@@ -24,12 +24,12 @@ fn evaluate_obligation<'tcx>(
2424
debug!("evaluate_obligation: goal={:#?}", goal);
2525
let ParamEnvAnd { param_env, value: predicate } = goal;
2626

27-
if sizedness_fast_path(tcx, predicate) {
28-
return Ok(EvaluationResult::EvaluatedToOk);
29-
}
30-
3127
let mut selcx = SelectionContext::with_query_mode(infcx, TraitQueryMode::Canonical);
3228
let obligation = Obligation::new(tcx, ObligationCause::dummy(), param_env, predicate);
3329

30+
if extended_sizedness_fast_path(infcx, &obligation) {
31+
return Ok(EvaluationResult::EvaluatedToOk);
32+
}
33+
3434
selcx.evaluate_root_obligation(&obligation)
3535
}

tests/ui/sized-hierarchy/generic-const-exprs.stderr

+9-9
Original file line numberDiff line numberDiff line change
@@ -2,30 +2,30 @@ error: internal compiler error: Encountered anon const with inference variable a
22
|
33
= error: internal compiler error: Encountered anon const with inference variable args but no error reported
44
|
5-
= note: delayed at compiler/rustc_trait_selection/src/traits/mod.rs:596:27 - disabled backtrace
5+
= note: delayed at compiler/rustc_trait_selection/src/traits/mod.rs:597:27 - disabled backtrace
66
= error: internal compiler error: Encountered anon const with inference variable args but no error reported
77
|
8-
= note: delayed at compiler/rustc_trait_selection/src/traits/mod.rs:596:27 - disabled backtrace
8+
= note: delayed at compiler/rustc_trait_selection/src/traits/mod.rs:597:27 - disabled backtrace
99
= error: internal compiler error: Encountered anon const with inference variable args but no error reported
1010
|
11-
= note: delayed at compiler/rustc_trait_selection/src/traits/mod.rs:596:27 - disabled backtrace
11+
= note: delayed at compiler/rustc_trait_selection/src/traits/mod.rs:597:27 - disabled backtrace
1212
= error: internal compiler error: Encountered anon const with inference variable args but no error reported
1313
|
14-
= note: delayed at compiler/rustc_trait_selection/src/traits/mod.rs:596:27 - disabled backtrace
14+
= note: delayed at compiler/rustc_trait_selection/src/traits/mod.rs:597:27 - disabled backtrace
1515
= error: internal compiler error: Encountered anon const with inference variable args but no error reported
1616
|
17-
= note: delayed at compiler/rustc_trait_selection/src/traits/mod.rs:596:27 - disabled backtrace
17+
= note: delayed at compiler/rustc_trait_selection/src/traits/mod.rs:597:27 - disabled backtrace
1818
= error: internal compiler error: Encountered anon const with inference variable args but no error reported
1919
|
20-
= note: delayed at compiler/rustc_trait_selection/src/traits/mod.rs:596:27 - disabled backtrace
20+
= note: delayed at compiler/rustc_trait_selection/src/traits/mod.rs:597:27 - disabled backtrace
2121
= error: internal compiler error: Encountered anon const with inference variable args but no error reported
2222
|
23-
= note: delayed at compiler/rustc_trait_selection/src/traits/mod.rs:596:27 - disabled backtrace
23+
= note: delayed at compiler/rustc_trait_selection/src/traits/mod.rs:597:27 - disabled backtrace
2424
= error: internal compiler error: Encountered anon const with inference variable args but no error reported
2525
|
26-
= note: delayed at compiler/rustc_trait_selection/src/traits/mod.rs:596:27 - disabled backtrace
26+
= note: delayed at compiler/rustc_trait_selection/src/traits/mod.rs:597:27 - disabled backtrace
2727
= error: internal compiler error: Encountered anon const with inference variable args but no error reported
2828
|
29-
= note: delayed at compiler/rustc_trait_selection/src/traits/mod.rs:596:27 - disabled backtrace
29+
= note: delayed at compiler/rustc_trait_selection/src/traits/mod.rs:597:27 - disabled backtrace
3030
= query stack during panic:
3131
end of query stack

tests/ui/where-clauses/ignore-err-clauses.rs

-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
use std::ops::Add;
22

33
fn dbl<T>(x: T) -> <T as Add>::Output
4-
//~^ ERROR type annotations needed
54
where
65
T: Copy + Add,
76
UUU: Copy,
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,9 @@
11
error[E0412]: cannot find type `UUU` in this scope
2-
--> $DIR/ignore-err-clauses.rs:7:5
2+
--> $DIR/ignore-err-clauses.rs:6:5
33
|
44
LL | UUU: Copy,
55
| ^^^ not found in this scope
66

7-
error[E0282]: type annotations needed
8-
--> $DIR/ignore-err-clauses.rs:3:14
9-
|
10-
LL | fn dbl<T>(x: T) -> <T as Add>::Output
11-
| ^ cannot infer type for type parameter `T`
12-
13-
error: aborting due to 2 previous errors
7+
error: aborting due to 1 previous error
148

15-
Some errors have detailed explanations: E0282, E0412.
16-
For more information about an error, try `rustc --explain E0282`.
9+
For more information about this error, try `rustc --explain E0412`.

0 commit comments

Comments
 (0)