Skip to content

Commit a1e1dba

Browse files
committed
Auto merge of rust-lang#114611 - nnethercote:type-system-chess, r=compiler-errors
Speed up compilation of `type-system-chess` [`type-system-chess`](rust-lang/rustc-perf#1680) is an unusual program that implements a compile-time chess position solver in the trait system(!) This PR is about making it compile faster. r? `@ghost`
2 parents fe3eae3 + 698f0e3 commit a1e1dba

File tree

2 files changed

+27
-10
lines changed

2 files changed

+27
-10
lines changed

compiler/rustc_infer/src/traits/mod.rs

+23-1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ mod structural_impls;
99
pub mod util;
1010

1111
use std::cmp;
12+
use std::hash::{Hash, Hasher};
1213

1314
use hir::def_id::LocalDefId;
1415
use rustc_hir as hir;
@@ -36,7 +37,7 @@ pub use rustc_middle::traits::*;
3637
/// either identifying an `impl` (e.g., `impl Eq for i32`) that
3738
/// satisfies the obligation, or else finding a bound that is in
3839
/// scope. The eventual result is usually a `Selection` (defined below).
39-
#[derive(Clone, PartialEq, Eq, Hash)]
40+
#[derive(Clone)]
4041
pub struct Obligation<'tcx, T> {
4142
/// The reason we have to prove this thing.
4243
pub cause: ObligationCause<'tcx>,
@@ -55,6 +56,27 @@ pub struct Obligation<'tcx, T> {
5556
pub recursion_depth: usize,
5657
}
5758

59+
impl<'tcx, T: PartialEq> PartialEq<Obligation<'tcx, T>> for Obligation<'tcx, T> {
60+
#[inline]
61+
fn eq(&self, other: &Obligation<'tcx, T>) -> bool {
62+
// Ignore `cause` and `recursion_depth`. This is a small performance
63+
// win for a few crates, and a huge performance win for the crate in
64+
// https://github.com/rust-lang/rustc-perf/pull/1680, which greatly
65+
// stresses the trait system.
66+
self.param_env == other.param_env && self.predicate == other.predicate
67+
}
68+
}
69+
70+
impl<T: Eq> Eq for Obligation<'_, T> {}
71+
72+
impl<T: Hash> Hash for Obligation<'_, T> {
73+
fn hash<H: Hasher>(&self, state: &mut H) -> () {
74+
// See the comment on `Obligation::eq`.
75+
self.param_env.hash(state);
76+
self.predicate.hash(state);
77+
}
78+
}
79+
5880
impl<'tcx, P> From<Obligation<'tcx, P>> for solve::Goal<'tcx, P> {
5981
fn from(value: Obligation<'tcx, P>) -> Self {
6082
solve::Goal { param_env: value.param_env, predicate: value.predicate }

compiler/rustc_trait_selection/src/traits/project.rs

+4-9
Original file line numberDiff line numberDiff line change
@@ -1214,7 +1214,7 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
12141214

12151215
let projected_term = selcx.infcx.resolve_vars_if_possible(projected_term);
12161216

1217-
let mut result = if projected_term.has_projections() {
1217+
let result = if projected_term.has_projections() {
12181218
let mut normalizer = AssocTypeNormalizer::new(
12191219
selcx,
12201220
param_env,
@@ -1224,19 +1224,14 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
12241224
);
12251225
let normalized_ty = normalizer.fold(projected_term);
12261226

1227+
let mut deduped = SsoHashSet::with_capacity(projected_obligations.len());
1228+
projected_obligations.retain(|obligation| deduped.insert(obligation.clone()));
1229+
12271230
Normalized { value: normalized_ty, obligations: projected_obligations }
12281231
} else {
12291232
Normalized { value: projected_term, obligations: projected_obligations }
12301233
};
12311234

1232-
let mut deduped: SsoHashSet<_> = Default::default();
1233-
result.obligations.retain(|projected_obligation| {
1234-
if !deduped.insert(projected_obligation.clone()) {
1235-
return false;
1236-
}
1237-
true
1238-
});
1239-
12401235
if use_cache {
12411236
infcx.inner.borrow_mut().projection_cache().insert_term(cache_key, result.clone());
12421237
}

0 commit comments

Comments
 (0)