Skip to content

Commit e288d05

Browse files
committed
Introduce an abstraction for EvaluationCache and SelectionCache.
1 parent 2c28244 commit e288d05

File tree

4 files changed

+81
-87
lines changed

4 files changed

+81
-87
lines changed

src/librustc_middle/traits/select.rs

+8-50
Original file line numberDiff line numberDiff line change
@@ -6,29 +6,18 @@ use self::EvaluationResult::*;
66

77
use super::{SelectionError, SelectionResult};
88

9-
use crate::dep_graph::DepNodeIndex;
10-
use crate::ty::{self, TyCtxt};
9+
use crate::ty;
1110

12-
use rustc_data_structures::fx::FxHashMap;
13-
use rustc_data_structures::sync::Lock;
1411
use rustc_hir::def_id::DefId;
12+
use rustc_query_system::cache::Cache;
1513

16-
#[derive(Clone, Default)]
17-
pub struct SelectionCache<'tcx> {
18-
pub hashmap: Lock<
19-
FxHashMap<
20-
ty::ParamEnvAnd<'tcx, ty::TraitRef<'tcx>>,
21-
WithDepNode<SelectionResult<'tcx, SelectionCandidate<'tcx>>>,
22-
>,
23-
>,
24-
}
14+
pub type SelectionCache<'tcx> = Cache<
15+
ty::ParamEnvAnd<'tcx, ty::TraitRef<'tcx>>,
16+
SelectionResult<'tcx, SelectionCandidate<'tcx>>,
17+
>;
2518

26-
impl<'tcx> SelectionCache<'tcx> {
27-
/// Actually frees the underlying memory in contrast to what stdlib containers do on `clear`
28-
pub fn clear(&self) {
29-
*self.hashmap.borrow_mut() = Default::default();
30-
}
31-
}
19+
pub type EvaluationCache<'tcx> =
20+
Cache<ty::ParamEnvAnd<'tcx, ty::PolyTraitRef<'tcx>>, EvaluationResult>;
3221

3322
/// The selection process begins by considering all impls, where
3423
/// clauses, and so forth that might resolve an obligation. Sometimes
@@ -265,37 +254,6 @@ impl<'tcx> From<OverflowError> for SelectionError<'tcx> {
265254
}
266255
}
267256

268-
#[derive(Clone, Default)]
269-
pub struct EvaluationCache<'tcx> {
270-
pub hashmap: Lock<
271-
FxHashMap<ty::ParamEnvAnd<'tcx, ty::PolyTraitRef<'tcx>>, WithDepNode<EvaluationResult>>,
272-
>,
273-
}
274-
275-
impl<'tcx> EvaluationCache<'tcx> {
276-
/// Actually frees the underlying memory in contrast to what stdlib containers do on `clear`
277-
pub fn clear(&self) {
278-
*self.hashmap.borrow_mut() = Default::default();
279-
}
280-
}
281-
282-
#[derive(Clone, Eq, PartialEq)]
283-
pub struct WithDepNode<T> {
284-
dep_node: DepNodeIndex,
285-
cached_value: T,
286-
}
287-
288-
impl<T: Clone> WithDepNode<T> {
289-
pub fn new(dep_node: DepNodeIndex, cached_value: T) -> Self {
290-
WithDepNode { dep_node, cached_value }
291-
}
292-
293-
pub fn get(&self, tcx: TyCtxt<'_>) -> T {
294-
tcx.dep_graph.read_index(self.dep_node);
295-
self.cached_value.clone()
296-
}
297-
}
298-
299257
#[derive(Clone, Debug)]
300258
pub enum IntercrateAmbiguityCause {
301259
DownstreamCrate { trait_desc: String, self_desc: Option<String> },

src/librustc_query_system/cache.rs

+62
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
//! Cache for candidate selection.
2+
3+
use crate::dep_graph::DepNodeIndex;
4+
use crate::query::QueryContext;
5+
6+
use rustc_data_structures::fx::FxHashMap;
7+
use rustc_data_structures::sync::HashMapExt;
8+
use rustc_data_structures::sync::Lock;
9+
10+
use std::hash::Hash;
11+
12+
#[derive(Clone)]
13+
pub struct Cache<Key, Value> {
14+
hashmap: Lock<FxHashMap<Key, WithDepNode<Value>>>,
15+
}
16+
17+
impl<Key, Value> Default for Cache<Key, Value> {
18+
fn default() -> Self {
19+
Self { hashmap: Default::default() }
20+
}
21+
}
22+
23+
impl<Key, Value> Cache<Key, Value> {
24+
/// Actually frees the underlying memory in contrast to what stdlib containers do on `clear`
25+
pub fn clear(&self) {
26+
*self.hashmap.borrow_mut() = Default::default();
27+
}
28+
}
29+
30+
impl<Key: Eq + Hash, Value: Clone> Cache<Key, Value> {
31+
pub fn get<CTX: QueryContext>(&self, key: &Key, tcx: CTX) -> Option<Value> {
32+
Some(self.hashmap.borrow().get(key)?.get(tcx))
33+
}
34+
35+
pub fn insert(&self, key: Key, dep_node: DepNodeIndex, value: Value) {
36+
self.hashmap.borrow_mut().insert(key, WithDepNode::new(dep_node, value));
37+
}
38+
39+
pub fn insert_same(&self, key: Key, dep_node: DepNodeIndex, value: Value)
40+
where
41+
Value: Eq,
42+
{
43+
self.hashmap.borrow_mut().insert_same(key, WithDepNode::new(dep_node, value));
44+
}
45+
}
46+
47+
#[derive(Clone, Eq, PartialEq)]
48+
pub struct WithDepNode<T> {
49+
dep_node: DepNodeIndex,
50+
cached_value: T,
51+
}
52+
53+
impl<T: Clone> WithDepNode<T> {
54+
pub fn new(dep_node: DepNodeIndex, cached_value: T) -> Self {
55+
WithDepNode { dep_node, cached_value }
56+
}
57+
58+
pub fn get<CTX: QueryContext>(&self, tcx: CTX) -> T {
59+
tcx.dep_graph().read_index(self.dep_node);
60+
self.cached_value.clone()
61+
}
62+
}

src/librustc_query_system/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,6 @@ extern crate log;
1111
#[macro_use]
1212
extern crate rustc_data_structures;
1313

14+
pub mod cache;
1415
pub mod dep_graph;
1516
pub mod query;

src/librustc_trait_selection/traits/select/mod.rs

+10-37
Original file line numberDiff line numberDiff line change
@@ -833,17 +833,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
833833
) -> Option<EvaluationResult> {
834834
let tcx = self.tcx();
835835
if self.can_use_global_caches(param_env) {
836-
let cache = tcx.evaluation_cache.hashmap.borrow();
837-
if let Some(cached) = cache.get(&param_env.and(trait_ref)) {
838-
return Some(cached.get(tcx));
836+
if let Some(res) = tcx.evaluation_cache.get(&param_env.and(trait_ref), tcx) {
837+
return Some(res);
839838
}
840839
}
841-
self.infcx
842-
.evaluation_cache
843-
.hashmap
844-
.borrow()
845-
.get(&param_env.and(trait_ref))
846-
.map(|v| v.get(tcx))
840+
self.infcx.evaluation_cache.get(&param_env.and(trait_ref), tcx)
847841
}
848842

849843
fn insert_evaluation_cache(
@@ -869,21 +863,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
869863
// FIXME: Due to #50507 this overwrites the different values
870864
// This should be changed to use HashMapExt::insert_same
871865
// when that is fixed
872-
self.tcx()
873-
.evaluation_cache
874-
.hashmap
875-
.borrow_mut()
876-
.insert(param_env.and(trait_ref), WithDepNode::new(dep_node, result));
866+
self.tcx().evaluation_cache.insert(param_env.and(trait_ref), dep_node, result);
877867
return;
878868
}
879869
}
880870

881871
debug!("insert_evaluation_cache(trait_ref={:?}, candidate={:?})", trait_ref, result,);
882-
self.infcx
883-
.evaluation_cache
884-
.hashmap
885-
.borrow_mut()
886-
.insert(param_env.and(trait_ref), WithDepNode::new(dep_node, result));
872+
self.infcx.evaluation_cache.insert(param_env.and(trait_ref), dep_node, result);
887873
}
888874

889875
/// For various reasons, it's possible for a subobligation
@@ -1180,17 +1166,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
11801166
let tcx = self.tcx();
11811167
let trait_ref = &cache_fresh_trait_pred.skip_binder().trait_ref;
11821168
if self.can_use_global_caches(param_env) {
1183-
let cache = tcx.selection_cache.hashmap.borrow();
1184-
if let Some(cached) = cache.get(&param_env.and(*trait_ref)) {
1185-
return Some(cached.get(tcx));
1169+
if let Some(res) = tcx.selection_cache.get(&param_env.and(*trait_ref), tcx) {
1170+
return Some(res);
11861171
}
11871172
}
1188-
self.infcx
1189-
.selection_cache
1190-
.hashmap
1191-
.borrow()
1192-
.get(&param_env.and(*trait_ref))
1193-
.map(|v| v.get(tcx))
1173+
self.infcx.selection_cache.get(&param_env.and(*trait_ref), tcx)
11941174
}
11951175

11961176
/// Determines whether can we safely cache the result
@@ -1248,10 +1228,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
12481228
trait_ref, candidate,
12491229
);
12501230
// This may overwrite the cache with the same value.
1251-
tcx.selection_cache
1252-
.hashmap
1253-
.borrow_mut()
1254-
.insert(param_env.and(trait_ref), WithDepNode::new(dep_node, candidate));
1231+
tcx.selection_cache.insert(param_env.and(trait_ref), dep_node, candidate);
12551232
return;
12561233
}
12571234
}
@@ -1261,11 +1238,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
12611238
"insert_candidate_cache(trait_ref={:?}, candidate={:?}) local",
12621239
trait_ref, candidate,
12631240
);
1264-
self.infcx
1265-
.selection_cache
1266-
.hashmap
1267-
.borrow_mut()
1268-
.insert(param_env.and(trait_ref), WithDepNode::new(dep_node, candidate));
1241+
self.infcx.selection_cache.insert(param_env.and(trait_ref), dep_node, candidate);
12691242
}
12701243

12711244
fn match_projection_obligation_against_definition_bounds(

0 commit comments

Comments
 (0)