Skip to content

Commit 0c5d833

Browse files
author
Markus Westerlind
committed
Move projection_cache into the combined undo log
1 parent c50fc6e commit 0c5d833

File tree

6 files changed

+79
-53
lines changed

6 files changed

+79
-53
lines changed

Cargo.lock

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -485,7 +485,7 @@ version = "0.0.212"
485485
dependencies = [
486486
"cargo_metadata 0.9.1",
487487
"if_chain",
488-
"itertools 0.9.0",
488+
"itertools 0.8.0",
489489
"lazy_static 1.4.0",
490490
"pulldown-cmark 0.7.1",
491491
"quine-mc_cluskey",
@@ -1629,15 +1629,6 @@ dependencies = [
16291629
"either",
16301630
]
16311631

1632-
[[package]]
1633-
name = "itertools"
1634-
version = "0.9.0"
1635-
source = "registry+https://github.com/rust-lang/crates.io-index"
1636-
checksum = "284f18f85651fe11e8a991b2adb42cb078325c996ed026d994719efcfca1d54b"
1637-
dependencies = [
1638-
"either",
1639-
]
1640-
16411632
[[package]]
16421633
name = "itoa"
16431634
version = "0.4.4"
@@ -2188,7 +2179,6 @@ dependencies = [
21882179
"rustc-workspace-hack",
21892180
"rustc_version",
21902181
"serde",
2191-
"serde_json",
21922182
"shell-escape",
21932183
"vergen",
21942184
]

src/librustc_data_structures/snapshot_map/mod.rs

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use crate::fx::FxHashMap;
22
use crate::undo_log::{Rollback, Snapshots, UndoLogs, VecLog};
3+
use std::borrow::{Borrow, BorrowMut};
34
use std::hash::Hash;
45
use std::marker::PhantomData;
56
use std::ops;
@@ -10,6 +11,7 @@ pub use crate::undo_log::Snapshot;
1011
mod tests;
1112

1213
pub type SnapshotMapStorage<K, V> = SnapshotMap<K, V, FxHashMap<K, V>, ()>;
14+
pub type SnapshotMapRef<'a, K, V, L> = SnapshotMap<K, V, &'a mut FxHashMap<K, V>, &'a mut L>;
1315

1416
pub struct SnapshotMap<K, V, M = FxHashMap<K, V>, L = VecLog<UndoLog<K, V>>> {
1517
map: M,
@@ -43,16 +45,16 @@ impl<K, V, M, L> SnapshotMap<K, V, M, L> {
4345
impl<K, V, M, L> SnapshotMap<K, V, M, L>
4446
where
4547
K: Hash + Clone + Eq,
46-
M: AsMut<FxHashMap<K, V>> + AsRef<FxHashMap<K, V>>,
48+
M: BorrowMut<FxHashMap<K, V>> + Borrow<FxHashMap<K, V>>,
4749
L: UndoLogs<UndoLog<K, V>>,
4850
{
4951
pub fn clear(&mut self) {
50-
self.map.as_mut().clear();
52+
self.map.borrow_mut().clear();
5153
self.undo_log.clear();
5254
}
5355

5456
pub fn insert(&mut self, key: K, value: V) -> bool {
55-
match self.map.as_mut().insert(key.clone(), value) {
57+
match self.map.borrow_mut().insert(key.clone(), value) {
5658
None => {
5759
self.undo_log.push(UndoLog::Inserted(key));
5860
true
@@ -65,7 +67,7 @@ where
6567
}
6668

6769
pub fn remove(&mut self, key: K) -> bool {
68-
match self.map.as_mut().remove(&key) {
70+
match self.map.borrow_mut().remove(&key) {
6971
Some(old_value) => {
7072
self.undo_log.push(UndoLog::Overwrite(key, old_value));
7173
true
@@ -75,7 +77,7 @@ where
7577
}
7678

7779
pub fn get(&self, key: &K) -> Option<&V> {
78-
self.map.as_ref().get(key)
80+
self.map.borrow().get(key)
7981
}
8082
}
8183

@@ -99,11 +101,21 @@ where
99101
impl<'k, K, V, M, L> ops::Index<&'k K> for SnapshotMap<K, V, M, L>
100102
where
101103
K: Hash + Clone + Eq,
102-
M: AsRef<FxHashMap<K, V>>,
104+
M: Borrow<FxHashMap<K, V>>,
103105
{
104106
type Output = V;
105107
fn index(&self, key: &'k K) -> &V {
106-
&self.map.as_ref()[key]
108+
&self.map.borrow()[key]
109+
}
110+
}
111+
112+
impl<K, V, M, L> Rollback<UndoLog<K, V>> for SnapshotMap<K, V, M, L>
113+
where
114+
K: Eq + Hash,
115+
M: Rollback<UndoLog<K, V>>,
116+
{
117+
fn reverse(&mut self, undo: UndoLog<K, V>) {
118+
self.map.reverse(undo)
107119
}
108120
}
109121

src/librustc_infer/infer/mod.rs

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ pub struct InferCtxtInner<'tcx> {
141141
/// Cache for projections. This cache is snapshotted along with the infcx.
142142
///
143143
/// Public so that `traits::project` can use it.
144-
pub projection_cache: traits::ProjectionCache<'tcx>,
144+
pub projection_cache: traits::ProjectionCacheStorage<'tcx>,
145145

146146
/// We instantiate `UnificationTable` with `bounds<Ty>` because the types
147147
/// that might instantiate a general type variable have an order,
@@ -213,6 +213,10 @@ impl<'tcx> InferCtxtInner<'tcx> {
213213
}
214214
}
215215

216+
pub(crate) fn projection_cache(&mut self) -> traits::ProjectionCache<'tcx, '_> {
217+
self.projection_cache.with_log(&mut self.undo_log)
218+
}
219+
216220
fn type_variables(&mut self) -> type_variable::TypeVariableTable<'tcx, '_> {
217221
self.type_variables.with_log(&mut self.undo_log)
218222
}
@@ -265,6 +269,7 @@ pub(crate) enum UndoLog<'tcx> {
265269
FloatUnificationTable(sv::UndoLog<ut::Delegate<ty::FloatVid>>),
266270
RegionConstraintCollector(region_constraints::UndoLog<'tcx>),
267271
RegionUnificationTable(sv::UndoLog<ut::Delegate<ty::RegionVid>>),
272+
ProjectionCache(traits::UndoLog<'tcx>),
268273
}
269274

270275
impl<'tcx> From<region_constraints::UndoLog<'tcx>> for UndoLog<'tcx> {
@@ -327,6 +332,12 @@ impl<'tcx> From<sv::UndoLog<ut::Delegate<ty::RegionVid>>> for UndoLog<'tcx> {
327332
}
328333
}
329334

335+
impl<'tcx> From<traits::UndoLog<'tcx>> for UndoLog<'tcx> {
336+
fn from(l: traits::UndoLog<'tcx>) -> Self {
337+
Self::ProjectionCache(l)
338+
}
339+
}
340+
330341
pub(crate) type UnificationTable<'a, 'tcx, T> =
331342
ut::UnificationTable<ut::InPlace<T, &'a mut ut::UnificationStorage<T>, &'a mut Logs<'tcx>>>;
332343

@@ -336,6 +347,7 @@ struct RollbackView<'tcx, 'a> {
336347
int_unification_table: &'a mut ut::UnificationStorage<ty::IntVid>,
337348
float_unification_table: &'a mut ut::UnificationStorage<ty::FloatVid>,
338349
region_constraints: &'a mut RegionConstraintStorage<'tcx>,
350+
projection_cache: &'a mut traits::ProjectionCacheStorage<'tcx>,
339351
}
340352

341353
impl<'tcx> Rollback<UndoLog<'tcx>> for RollbackView<'tcx, '_> {
@@ -349,6 +361,7 @@ impl<'tcx> Rollback<UndoLog<'tcx>> for RollbackView<'tcx, '_> {
349361
UndoLog::RegionUnificationTable(undo) => {
350362
self.region_constraints.unification_table.reverse(undo)
351363
}
364+
UndoLog::ProjectionCache(undo) => self.projection_cache.reverse(undo),
352365
}
353366
}
354367
}
@@ -885,7 +898,6 @@ impl<'tcx> InferOk<'tcx, ()> {
885898

886899
#[must_use = "once you start a snapshot, you should always consume it"]
887900
pub struct CombinedSnapshot<'a, 'tcx> {
888-
projection_cache_snapshot: traits::ProjectionCacheSnapshot,
889901
undo_snapshot: Snapshot<'tcx>,
890902
type_snapshot: type_variable::Snapshot<'tcx>,
891903
const_snapshot: usize,
@@ -1016,7 +1028,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
10161028
inner.undo_log.num_open_snapshots += 1;
10171029
let undo_snapshot = Snapshot { undo_len: inner.undo_log.logs.len(), _marker: PhantomData };
10181030
CombinedSnapshot {
1019-
projection_cache_snapshot: inner.projection_cache.snapshot(),
10201031
undo_snapshot,
10211032
type_snapshot: inner.type_variables().snapshot(),
10221033
const_snapshot: inner.const_unification_table().len(),
@@ -1036,7 +1047,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
10361047
fn rollback_to(&self, cause: &str, snapshot: CombinedSnapshot<'a, 'tcx>) {
10371048
debug!("rollback_to(cause={})", cause);
10381049
let CombinedSnapshot {
1039-
projection_cache_snapshot,
10401050
undo_snapshot,
10411051
type_snapshot: _,
10421052
const_snapshot: _,
@@ -1062,6 +1072,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
10621072
int_unification_table,
10631073
float_unification_table,
10641074
region_constraints,
1075+
projection_cache,
10651076
..
10661077
} = inner;
10671078
inner.undo_log.rollback_to(
@@ -1071,17 +1082,16 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
10711082
int_unification_table,
10721083
float_unification_table,
10731084
region_constraints: region_constraints.as_mut().unwrap(),
1085+
projection_cache,
10741086
},
10751087
undo_snapshot,
10761088
);
1077-
inner.projection_cache.rollback_to(projection_cache_snapshot);
10781089
inner.region_obligations.truncate(region_obligations_snapshot);
10791090
}
10801091

10811092
fn commit_from(&self, snapshot: CombinedSnapshot<'a, 'tcx>) {
10821093
debug!("commit_from()");
10831094
let CombinedSnapshot {
1084-
projection_cache_snapshot,
10851095
undo_snapshot,
10861096
type_snapshot: _,
10871097
const_snapshot: _,
@@ -1100,7 +1110,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
11001110

11011111
let mut inner = self.inner.borrow_mut();
11021112
inner.undo_log.commit(undo_snapshot);
1103-
inner.projection_cache.commit(projection_cache_snapshot);
11041113
}
11051114

11061115
/// Executes `f` and commit the bindings.
@@ -1773,7 +1782,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
17731782
pub fn clear_caches(&self) {
17741783
self.selection_cache.clear();
17751784
self.evaluation_cache.clear();
1776-
self.inner.borrow_mut().projection_cache.clear();
1785+
self.inner.borrow_mut().projection_cache().clear();
17771786
}
17781787

17791788
fn universe(&self) -> ty::UniverseIndex {

src/librustc_infer/traits/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ pub use self::Vtable::*;
2020

2121
pub use self::engine::{TraitEngine, TraitEngineExt};
2222
pub use self::project::MismatchedProjectionTypes;
23+
pub(crate) use self::project::UndoLog;
2324
pub use self::project::{
2425
Normalized, NormalizedTy, ProjectionCache, ProjectionCacheEntry, ProjectionCacheKey,
2526
ProjectionCacheSnapshot, Reveal,

src/librustc_infer/traits/project.rs

Lines changed: 40 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ use rustc_middle::ty::{self, Ty};
88

99
pub use rustc_middle::traits::Reveal;
1010

11+
pub(crate) type UndoLog<'tcx> =
12+
snapshot_map::UndoLog<ProjectionCacheKey<'tcx>, ProjectionCacheEntry<'tcx>>;
13+
1114
#[derive(Clone)]
1215
pub struct MismatchedProjectionTypes<'tcx> {
1316
pub err: ty::error::TypeError<'tcx>,
@@ -58,9 +61,14 @@ impl<'tcx, T> Normalized<'tcx, T> {
5861
//
5962
// FIXME: we probably also want some sort of cross-infcx cache here to
6063
// reduce the amount of duplication. Let's see what we get with the Chalk reforms.
64+
pub struct ProjectionCache<'tcx, 'a> {
65+
map: &'a mut SnapshotMapStorage<ProjectionCacheKey<'tcx>, ProjectionCacheEntry<'tcx>>,
66+
undo_log: &'a mut Logs<'tcx>,
67+
}
68+
6169
#[derive(Default)]
62-
pub struct ProjectionCache<'tcx> {
63-
map: SnapshotMap<ProjectionCacheKey<'tcx>, ProjectionCacheEntry<'tcx>>,
70+
pub struct ProjectionCacheStorage<'tcx> {
71+
map: SnapshotMapStorage<ProjectionCacheKey<'tcx>, ProjectionCacheEntry<'tcx>>,
6472
}
6573

6674
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
@@ -82,26 +90,24 @@ pub enum ProjectionCacheEntry<'tcx> {
8290
NormalizedTy(NormalizedTy<'tcx>),
8391
}
8492

85-
// N.B., intentionally not Clone
86-
pub struct ProjectionCacheSnapshot {
87-
snapshot: Snapshot,
88-
}
89-
90-
impl<'tcx> ProjectionCache<'tcx> {
91-
pub fn clear(&mut self) {
92-
self.map.clear();
93-
}
94-
95-
pub fn snapshot(&mut self) -> ProjectionCacheSnapshot {
96-
ProjectionCacheSnapshot { snapshot: self.map.snapshot() }
93+
impl<'tcx> ProjectionCacheStorage<'tcx> {
94+
pub(crate) fn with_log<'a>(
95+
&'a mut self,
96+
undo_log: &'a mut Logs<'tcx>,
97+
) -> ProjectionCache<'tcx, 'a> {
98+
ProjectionCache { map: &mut self.map, undo_log }
9799
}
100+
}
98101

99-
pub fn rollback_to(&mut self, snapshot: ProjectionCacheSnapshot) {
100-
self.map.rollback_to(snapshot.snapshot);
102+
impl<'tcx> ProjectionCache<'tcx, '_> {
103+
fn map(
104+
&mut self,
105+
) -> SnapshotMapRef<'_, ProjectionCacheKey<'tcx>, ProjectionCacheEntry<'tcx>, Logs<'tcx>> {
106+
self.map.with_log(self.undo_log)
101107
}
102108

103-
pub fn commit(&mut self, snapshot: ProjectionCacheSnapshot) {
104-
self.map.commit(snapshot.snapshot);
109+
pub fn clear(&mut self) {
110+
self.map().clear();
105111
}
106112

107113
/// Try to start normalize `key`; returns an error if
@@ -111,11 +117,12 @@ impl<'tcx> ProjectionCache<'tcx> {
111117
&mut self,
112118
key: ProjectionCacheKey<'tcx>,
113119
) -> Result<(), ProjectionCacheEntry<'tcx>> {
114-
if let Some(entry) = self.map.get(&key) {
120+
let mut map = self.map();
121+
if let Some(entry) = map.get(&key) {
115122
return Err(entry.clone());
116123
}
117124

118-
self.map.insert(key, ProjectionCacheEntry::InProgress);
125+
map.insert(key, ProjectionCacheEntry::InProgress);
119126
Ok(())
120127
}
121128

@@ -125,7 +132,7 @@ impl<'tcx> ProjectionCache<'tcx> {
125132
"ProjectionCacheEntry::insert_ty: adding cache entry: key={:?}, value={:?}",
126133
key, value
127134
);
128-
let fresh_key = self.map.insert(key, ProjectionCacheEntry::NormalizedTy(value));
135+
let fresh_key = self.map().insert(key, ProjectionCacheEntry::NormalizedTy(value));
129136
assert!(!fresh_key, "never started projecting `{:?}`", key);
130137
}
131138

@@ -134,7 +141,8 @@ impl<'tcx> ProjectionCache<'tcx> {
134141
/// snapshot - if the snapshot is rolled back, the obligations will be
135142
/// marked as incomplete again).
136143
pub fn complete(&mut self, key: ProjectionCacheKey<'tcx>) {
137-
let ty = match self.map.get(&key) {
144+
let mut map = self.map();
145+
let ty = match map.get(&key) {
138146
Some(&ProjectionCacheEntry::NormalizedTy(ref ty)) => {
139147
debug!("ProjectionCacheEntry::complete({:?}) - completing {:?}", key, ty);
140148
ty.value
@@ -147,7 +155,7 @@ impl<'tcx> ProjectionCache<'tcx> {
147155
}
148156
};
149157

150-
self.map.insert(
158+
map.insert(
151159
key,
152160
ProjectionCacheEntry::NormalizedTy(Normalized { value: ty, obligations: vec![] }),
153161
);
@@ -159,7 +167,7 @@ impl<'tcx> ProjectionCache<'tcx> {
159167
// We want to insert `ty` with no obligations. If the existing value
160168
// already has no obligations (as is common) we don't insert anything.
161169
if !ty.obligations.is_empty() {
162-
self.map.insert(
170+
self.map().insert(
163171
key,
164172
ProjectionCacheEntry::NormalizedTy(Normalized {
165173
value: ty.value,
@@ -174,14 +182,20 @@ impl<'tcx> ProjectionCache<'tcx> {
174182
/// type information (in which case, the "fully resolved" key will
175183
/// be different).
176184
pub fn ambiguous(&mut self, key: ProjectionCacheKey<'tcx>) {
177-
let fresh = self.map.insert(key, ProjectionCacheEntry::Ambiguous);
185+
let fresh = self.map().insert(key, ProjectionCacheEntry::Ambiguous);
178186
assert!(!fresh, "never started projecting `{:?}`", key);
179187
}
180188

181189
/// Indicates that trying to normalize `key` resulted in
182190
/// error.
183191
pub fn error(&mut self, key: ProjectionCacheKey<'tcx>) {
184-
let fresh = self.map.insert(key, ProjectionCacheEntry::Error);
192+
let fresh = self.map().insert(key, ProjectionCacheEntry::Error);
185193
assert!(!fresh, "never started projecting `{:?}`", key);
186194
}
187195
}
196+
197+
impl<'tcx> Rollback<UndoLog<'tcx>> for ProjectionCacheStorage<'tcx> {
198+
fn reverse(&mut self, undo: UndoLog<'tcx>) {
199+
self.map.reverse(undo);
200+
}
201+
}

src/librustc_trait_selection/traits/select.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -471,7 +471,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
471471
if let Some(key) =
472472
ProjectionCacheKey::from_poly_projection_predicate(self, data)
473473
{
474-
self.infcx.inner.borrow_mut().projection_cache.complete(key);
474+
self.infcx.inner.borrow_mut().projection_cache().complete(key);
475475
}
476476
result
477477
}

0 commit comments

Comments
 (0)