Skip to content

Commit

Permalink
Auto merge of #114611 - nnethercote:type-system-chess, r=compiler-errors
Browse files Browse the repository at this point in the history
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`
  • Loading branch information
bors committed Aug 18, 2023
2 parents fe3eae3 + 698f0e3 commit a1e1dba
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 10 deletions.
24 changes: 23 additions & 1 deletion compiler/rustc_infer/src/traits/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ mod structural_impls;
pub mod util;

use std::cmp;
use std::hash::{Hash, Hasher};

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

impl<'tcx, T: PartialEq> PartialEq<Obligation<'tcx, T>> for Obligation<'tcx, T> {
#[inline]
fn eq(&self, other: &Obligation<'tcx, T>) -> bool {
// Ignore `cause` and `recursion_depth`. This is a small performance
// win for a few crates, and a huge performance win for the crate in
// https://github.com/rust-lang/rustc-perf/pull/1680, which greatly
// stresses the trait system.
self.param_env == other.param_env && self.predicate == other.predicate
}
}

impl<T: Eq> Eq for Obligation<'_, T> {}

impl<T: Hash> Hash for Obligation<'_, T> {
fn hash<H: Hasher>(&self, state: &mut H) -> () {
// See the comment on `Obligation::eq`.
self.param_env.hash(state);
self.predicate.hash(state);
}
}

impl<'tcx, P> From<Obligation<'tcx, P>> for solve::Goal<'tcx, P> {
fn from(value: Obligation<'tcx, P>) -> Self {
solve::Goal { param_env: value.param_env, predicate: value.predicate }
Expand Down
13 changes: 4 additions & 9 deletions compiler/rustc_trait_selection/src/traits/project.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1214,7 +1214,7 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(

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

let mut result = if projected_term.has_projections() {
let result = if projected_term.has_projections() {
let mut normalizer = AssocTypeNormalizer::new(
selcx,
param_env,
Expand All @@ -1224,19 +1224,14 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
);
let normalized_ty = normalizer.fold(projected_term);

let mut deduped = SsoHashSet::with_capacity(projected_obligations.len());
projected_obligations.retain(|obligation| deduped.insert(obligation.clone()));

Normalized { value: normalized_ty, obligations: projected_obligations }
} else {
Normalized { value: projected_term, obligations: projected_obligations }
};

let mut deduped: SsoHashSet<_> = Default::default();
result.obligations.retain(|projected_obligation| {
if !deduped.insert(projected_obligation.clone()) {
return false;
}
true
});

if use_cache {
infcx.inner.borrow_mut().projection_cache().insert_term(cache_key, result.clone());
}
Expand Down

0 comments on commit a1e1dba

Please sign in to comment.