diff options
Diffstat (limited to 'compiler/rustc_middle/src')
| -rw-r--r-- | compiler/rustc_middle/src/traits/solve.rs | 4 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/traits/solve/cache.rs | 121 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/ty/context.rs | 29 |
3 files changed, 22 insertions, 132 deletions
diff --git a/compiler/rustc_middle/src/traits/solve.rs b/compiler/rustc_middle/src/traits/solve.rs index 7bc4c60f102..f659bf8125a 100644 --- a/compiler/rustc_middle/src/traits/solve.rs +++ b/compiler/rustc_middle/src/traits/solve.rs @@ -8,10 +8,6 @@ use crate::ty::{ self, FallibleTypeFolder, TyCtxt, TypeFoldable, TypeFolder, TypeVisitable, TypeVisitor, }; -mod cache; - -pub use cache::EvaluationCache; - pub type Goal<'tcx, P> = ir::solve::Goal<TyCtxt<'tcx>, P>; pub type QueryInput<'tcx, P> = ir::solve::QueryInput<TyCtxt<'tcx>, P>; pub type QueryResult<'tcx> = ir::solve::QueryResult<TyCtxt<'tcx>>; diff --git a/compiler/rustc_middle/src/traits/solve/cache.rs b/compiler/rustc_middle/src/traits/solve/cache.rs deleted file mode 100644 index 72a8d4eb405..00000000000 --- a/compiler/rustc_middle/src/traits/solve/cache.rs +++ /dev/null @@ -1,121 +0,0 @@ -use super::{inspect, CanonicalInput, QueryResult}; -use crate::ty::TyCtxt; -use rustc_data_structures::fx::{FxHashMap, FxHashSet}; -use rustc_data_structures::sync::Lock; -use rustc_query_system::cache::WithDepNode; -use rustc_query_system::dep_graph::DepNodeIndex; -use rustc_session::Limit; -use rustc_type_ir::solve::CacheData; - -/// The trait solver cache used by `-Znext-solver`. -/// -/// FIXME(@lcnr): link to some official documentation of how -/// this works. -#[derive(Default)] -pub struct EvaluationCache<'tcx> { - map: Lock<FxHashMap<CanonicalInput<'tcx>, CacheEntry<'tcx>>>, -} - -impl<'tcx> rustc_type_ir::inherent::EvaluationCache<TyCtxt<'tcx>> for &'tcx EvaluationCache<'tcx> { - /// Insert a final result into the global cache. - fn insert( - &self, - tcx: TyCtxt<'tcx>, - key: CanonicalInput<'tcx>, - proof_tree: Option<&'tcx inspect::CanonicalGoalEvaluationStep<TyCtxt<'tcx>>>, - additional_depth: usize, - encountered_overflow: bool, - cycle_participants: FxHashSet<CanonicalInput<'tcx>>, - dep_node: DepNodeIndex, - result: QueryResult<'tcx>, - ) { - let mut map = self.map.borrow_mut(); - let entry = map.entry(key).or_default(); - let data = WithDepNode::new(dep_node, QueryData { result, proof_tree }); - entry.cycle_participants.extend(cycle_participants); - if encountered_overflow { - entry.with_overflow.insert(additional_depth, data); - } else { - entry.success = Some(Success { data, additional_depth }); - } - - if cfg!(debug_assertions) { - drop(map); - let expected = CacheData { result, proof_tree, additional_depth, encountered_overflow }; - let actual = self.get(tcx, key, [], additional_depth); - if !actual.as_ref().is_some_and(|actual| expected == *actual) { - bug!("failed to lookup inserted element for {key:?}: {expected:?} != {actual:?}"); - } - } - } - - /// Try to fetch a cached result, checking the recursion limit - /// and handling root goals of coinductive cycles. - /// - /// If this returns `Some` the cache result can be used. - fn get( - &self, - tcx: TyCtxt<'tcx>, - key: CanonicalInput<'tcx>, - stack_entries: impl IntoIterator<Item = CanonicalInput<'tcx>>, - available_depth: usize, - ) -> Option<CacheData<TyCtxt<'tcx>>> { - let map = self.map.borrow(); - let entry = map.get(&key)?; - - for stack_entry in stack_entries { - if entry.cycle_participants.contains(&stack_entry) { - return None; - } - } - - if let Some(ref success) = entry.success { - if Limit(available_depth).value_within_limit(success.additional_depth) { - let QueryData { result, proof_tree } = success.data.get(tcx); - return Some(CacheData { - result, - proof_tree, - additional_depth: success.additional_depth, - encountered_overflow: false, - }); - } - } - - entry.with_overflow.get(&available_depth).map(|e| { - let QueryData { result, proof_tree } = e.get(tcx); - CacheData { - result, - proof_tree, - additional_depth: available_depth, - encountered_overflow: true, - } - }) - } -} - -struct Success<'tcx> { - data: WithDepNode<QueryData<'tcx>>, - additional_depth: usize, -} - -#[derive(Clone, Copy)] -pub struct QueryData<'tcx> { - pub result: QueryResult<'tcx>, - pub proof_tree: Option<&'tcx inspect::CanonicalGoalEvaluationStep<TyCtxt<'tcx>>>, -} - -/// The cache entry for a goal `CanonicalInput`. -/// -/// This contains results whose computation never hit the -/// recursion limit in `success`, and all results which hit -/// the recursion limit in `with_overflow`. -#[derive(Default)] -struct CacheEntry<'tcx> { - success: Option<Success<'tcx>>, - /// We have to be careful when caching roots of cycles. - /// - /// See the doc comment of `StackEntry::cycle_participants` for more - /// details. - cycle_participants: FxHashSet<CanonicalInput<'tcx>>, - with_overflow: FxHashMap<usize, WithDepNode<QueryData<'tcx>>>, -} diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index aee42bfe3aa..9e24ea485b2 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -59,6 +59,7 @@ use rustc_hir::lang_items::LangItem; use rustc_hir::{HirId, Node, TraitCandidate}; use rustc_index::IndexVec; use rustc_macros::{HashStable, TyDecodable, TyEncodable}; +use rustc_query_system::cache::WithDepNode; use rustc_query_system::dep_graph::DepNodeIndex; use rustc_query_system::ich::StableHashingContext; use rustc_serialize::opaque::{FileEncodeResult, FileEncoder}; @@ -75,7 +76,7 @@ use rustc_type_ir::fold::TypeFoldable; use rustc_type_ir::lang_items::TraitSolverLangItem; use rustc_type_ir::solve::SolverMode; use rustc_type_ir::TyKind::*; -use rustc_type_ir::{CollectAndApply, Interner, TypeFlags, WithCachedTypeInfo}; +use rustc_type_ir::{search_graph, CollectAndApply, Interner, TypeFlags, WithCachedTypeInfo}; use tracing::{debug, instrument}; use std::assert_matches::assert_matches; @@ -164,12 +165,26 @@ impl<'tcx> Interner for TyCtxt<'tcx> { type Clause = Clause<'tcx>; type Clauses = ty::Clauses<'tcx>; - type EvaluationCache = &'tcx solve::EvaluationCache<'tcx>; + type Tracked<T: fmt::Debug + Clone> = WithDepNode<T>; + fn mk_tracked<T: fmt::Debug + Clone>( + self, + data: T, + dep_node: DepNodeIndex, + ) -> Self::Tracked<T> { + WithDepNode::new(dep_node, data) + } + fn get_tracked<T: fmt::Debug + Clone>(self, tracked: &Self::Tracked<T>) -> T { + tracked.get(self) + } - fn evaluation_cache(self, mode: SolverMode) -> &'tcx solve::EvaluationCache<'tcx> { + fn with_global_cache<R>( + self, + mode: SolverMode, + f: impl FnOnce(&mut search_graph::GlobalCache<Self>) -> R, + ) -> R { match mode { - SolverMode::Normal => &self.new_solver_evaluation_cache, - SolverMode::Coherence => &self.new_solver_coherence_evaluation_cache, + SolverMode::Normal => f(&mut *self.new_solver_evaluation_cache.lock()), + SolverMode::Coherence => f(&mut *self.new_solver_coherence_evaluation_cache.lock()), } } @@ -1283,8 +1298,8 @@ pub struct GlobalCtxt<'tcx> { pub evaluation_cache: traits::EvaluationCache<'tcx>, /// Caches the results of goal evaluation in the new solver. - pub new_solver_evaluation_cache: solve::EvaluationCache<'tcx>, - pub new_solver_coherence_evaluation_cache: solve::EvaluationCache<'tcx>, + pub new_solver_evaluation_cache: Lock<search_graph::GlobalCache<TyCtxt<'tcx>>>, + pub new_solver_coherence_evaluation_cache: Lock<search_graph::GlobalCache<TyCtxt<'tcx>>>, pub canonical_param_env_cache: CanonicalParamEnvCache<'tcx>, |
