rust/src/librustc_traits/evaluate_obligation.rs
bors e3175c34b4 Auto merge of #61754 - nikomatsakis:trait-caching-perf-3, r=pnkfelix
create a "provisional cache" to restore performance in the case of cycles

Introduce a "provisional cache" that caches the results of auto trait resolutions but keeps them from entering the *main* cache until everything is ready. This turned out a bit more complex than I hoped, but I don't see another short term fix -- happy to take suggestions! In the meantime, it's very clear we need to rework the trait solver. This resolves the extreme performance slowdown experienced in #60846 -- I plan to add a perf.rust-lang.org regression test to track this.

Caveat: I've not run `x.py test` in full yet.

r? @pnkfelix
cc @arielb1

Fixes #60846
2019-06-16 14:58:05 +00:00

36 lines
1.0 KiB
Rust

use rustc::traits::query::CanonicalPredicateGoal;
use rustc::traits::{
EvaluationResult, Obligation, ObligationCause, OverflowError, SelectionContext, TraitQueryMode,
};
use rustc::ty::query::Providers;
use rustc::ty::{ParamEnvAnd, TyCtxt};
use syntax::source_map::DUMMY_SP;
crate fn provide(p: &mut Providers<'_>) {
*p = Providers {
evaluate_obligation,
..*p
};
}
fn evaluate_obligation<'tcx>(
tcx: TyCtxt<'tcx>,
canonical_goal: CanonicalPredicateGoal<'tcx>,
) -> Result<EvaluationResult, OverflowError> {
tcx.infer_ctxt().enter_with_canonical(
DUMMY_SP,
&canonical_goal,
|ref infcx, goal, _canonical_inference_vars| {
let ParamEnvAnd {
param_env,
value: predicate,
} = goal;
let mut selcx = SelectionContext::with_query_mode(&infcx, TraitQueryMode::Canonical);
let obligation = Obligation::new(ObligationCause::dummy(), param_env, predicate);
selcx.evaluate_root_obligation(&obligation)
},
)
}