Skip to content

Commit 7dca7cc

Browse files
lcnrMark-Simulacrum
authored andcommitted
cache types during normalization
1 parent b0db534 commit 7dca7cc

File tree

7 files changed

+83
-68
lines changed

7 files changed

+83
-68
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3424,6 +3424,7 @@ dependencies = [
34243424
name = "rustc_data_structures"
34253425
version = "0.0.0"
34263426
dependencies = [
3427+
"arrayvec",
34273428
"bitflags",
34283429
"cfg-if",
34293430
"crossbeam-utils 0.7.2",

src/librustc_data_structures/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ path = "lib.rs"
1010
doctest = false
1111

1212
[dependencies]
13+
arrayvec = { version = "0.5.1", default-features = false }
1314
ena = "0.14"
1415
indexmap = "1.5.1"
1516
tracing = "0.1"

src/librustc_data_structures/lib.rs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -85,24 +85,26 @@ pub mod sorted_map;
8585
pub mod stable_set;
8686
#[macro_use]
8787
pub mod stable_hasher;
88+
mod atomic_ref;
89+
pub mod fingerprint;
90+
pub mod profiling;
8891
pub mod sharded;
8992
pub mod stack;
9093
pub mod sync;
9194
pub mod thin_vec;
9295
pub mod tiny_list;
9396
pub mod transitive_relation;
94-
pub use ena::undo_log;
95-
pub use ena::unify;
96-
mod atomic_ref;
97-
pub mod fingerprint;
98-
pub mod profiling;
9997
pub mod vec_linked_list;
10098
pub mod work_queue;
10199
pub use atomic_ref::AtomicRef;
102100
pub mod frozen;
101+
pub mod mini_map;
103102
pub mod tagged_ptr;
104103
pub mod temp_dir;
105104

105+
pub use ena::undo_log;
106+
pub use ena::unify;
107+
106108
pub struct OnDrop<F: Fn()>(pub F);
107109

108110
impl<F: Fn()> OnDrop<F> {
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
use crate::fx::FxHashMap;
2+
use arrayvec::ArrayVec;
3+
4+
use std::hash::Hash;
5+
6+
/// Small-storage-optimized implementation of a map
7+
/// made specifically for caching results.
8+
///
9+
/// Stores elements in a small array up to a certain length
10+
/// and switches to `HashMap` when that length is exceeded.
11+
pub enum MiniMap<K, V> {
12+
Array(ArrayVec<[(K, V); 8]>),
13+
Map(FxHashMap<K, V>),
14+
}
15+
16+
impl<K: Eq + Hash, V> MiniMap<K, V> {
17+
/// Creates an empty `MiniMap`.
18+
pub fn new() -> Self {
19+
MiniMap::Array(ArrayVec::new())
20+
}
21+
22+
/// Inserts or updates value in the map.
23+
pub fn insert(&mut self, key: K, value: V) {
24+
match self {
25+
MiniMap::Array(array) => {
26+
for pair in array.iter_mut() {
27+
if pair.0 == key {
28+
pair.1 = value;
29+
return;
30+
}
31+
}
32+
if let Err(error) = array.try_push((key, value)) {
33+
let mut map: FxHashMap<K, V> = array.drain(..).collect();
34+
let (key, value) = error.element();
35+
map.insert(key, value);
36+
*self = MiniMap::Map(map);
37+
}
38+
}
39+
MiniMap::Map(map) => {
40+
map.insert(key, value);
41+
}
42+
}
43+
}
44+
45+
/// Return value by key if any.
46+
pub fn get(&self, key: &K) -> Option<&V> {
47+
match self {
48+
MiniMap::Array(array) => {
49+
for pair in array {
50+
if pair.0 == *key {
51+
return Some(&pair.1);
52+
}
53+
}
54+
return None;
55+
}
56+
MiniMap::Map(map) => {
57+
return map.get(key);
58+
}
59+
}
60+
}
61+
}

src/librustc_index/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,6 @@ path = "lib.rs"
1010
doctest = false
1111

1212
[dependencies]
13-
arrayvec = "0.5.1"
13+
arrayvec = { version = "0.5.1", default-features = false }
1414
rustc_serialize = { path = "../librustc_serialize" }
1515
rustc_macros = { path = "../librustc_macros" }

src/librustc_infer/infer/combine.rs

Lines changed: 1 addition & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,11 @@ use super::unify_key::replace_if_possible;
3131
use super::unify_key::{ConstVarValue, ConstVariableValue};
3232
use super::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
3333
use super::{InferCtxt, MiscVariable, TypeTrace};
34-
use arrayvec::ArrayVec;
35-
use rustc_data_structures::fx::FxHashMap;
36-
use std::hash::Hash;
3734

3835
use crate::traits::{Obligation, PredicateObligations};
3936

4037
use rustc_ast as ast;
38+
use rustc_data_structures::mini_map::MiniMap;
4139
use rustc_hir::def_id::DefId;
4240
use rustc_middle::traits::ObligationCause;
4341
use rustc_middle::ty::error::TypeError;
@@ -47,63 +45,6 @@ use rustc_middle::ty::{self, InferConst, ToPredicate, Ty, TyCtxt, TypeFoldable};
4745
use rustc_middle::ty::{IntType, UintType};
4846
use rustc_span::DUMMY_SP;
4947

50-
/// Small-storage-optimized implementation of a map
51-
/// made specifically for caching results.
52-
///
53-
/// Stores elements in a small array up to a certain length
54-
/// and switches to `HashMap` when that length is exceeded.
55-
enum MiniMap<K, V> {
56-
Array(ArrayVec<[(K, V); 8]>),
57-
Map(FxHashMap<K, V>),
58-
}
59-
60-
impl<K: Eq + Hash, V> MiniMap<K, V> {
61-
/// Creates an empty `MiniMap`.
62-
pub fn new() -> Self {
63-
MiniMap::Array(ArrayVec::new())
64-
}
65-
66-
/// Inserts or updates value in the map.
67-
pub fn insert(&mut self, key: K, value: V) {
68-
match self {
69-
MiniMap::Array(array) => {
70-
for pair in array.iter_mut() {
71-
if pair.0 == key {
72-
pair.1 = value;
73-
return;
74-
}
75-
}
76-
if let Err(error) = array.try_push((key, value)) {
77-
let mut map: FxHashMap<K, V> = array.drain(..).collect();
78-
let (key, value) = error.element();
79-
map.insert(key, value);
80-
*self = MiniMap::Map(map);
81-
}
82-
}
83-
MiniMap::Map(map) => {
84-
map.insert(key, value);
85-
}
86-
}
87-
}
88-
89-
/// Return value by key if any.
90-
pub fn get(&self, key: &K) -> Option<&V> {
91-
match self {
92-
MiniMap::Array(array) => {
93-
for pair in array {
94-
if pair.0 == *key {
95-
return Some(&pair.1);
96-
}
97-
}
98-
return None;
99-
}
100-
MiniMap::Map(map) => {
101-
return map.get(key);
102-
}
103-
}
104-
}
105-
}
106-
10748
#[derive(Clone)]
10849
pub struct CombineFields<'infcx, 'tcx> {
10950
pub infcx: &'infcx InferCtxt<'infcx, 'tcx>,

src/librustc_trait_selection/traits/query/normalize.rs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use crate::infer::canonical::OriginalQueryValues;
77
use crate::infer::{InferCtxt, InferOk};
88
use crate::traits::error_reporting::InferCtxtExt;
99
use crate::traits::{Obligation, ObligationCause, PredicateObligation, Reveal};
10+
use rustc_data_structures::mini_map::MiniMap;
1011
use rustc_data_structures::stack::ensure_sufficient_stack;
1112
use rustc_infer::traits::Normalized;
1213
use rustc_middle::ty::fold::{TypeFoldable, TypeFolder};
@@ -57,6 +58,7 @@ impl<'cx, 'tcx> AtExt<'tcx> for At<'cx, 'tcx> {
5758
param_env: self.param_env,
5859
obligations: vec![],
5960
error: false,
61+
cache: MiniMap::new(),
6062
anon_depth: 0,
6163
};
6264

@@ -85,6 +87,7 @@ struct QueryNormalizer<'cx, 'tcx> {
8587
cause: &'cx ObligationCause<'tcx>,
8688
param_env: ty::ParamEnv<'tcx>,
8789
obligations: Vec<PredicateObligation<'tcx>>,
90+
cache: MiniMap<Ty<'tcx>, Ty<'tcx>>,
8891
error: bool,
8992
anon_depth: usize,
9093
}
@@ -99,8 +102,12 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
99102
return ty;
100103
}
101104

105+
if let Some(ty) = self.cache.get(&ty) {
106+
return ty;
107+
}
108+
102109
let ty = ty.super_fold_with(self);
103-
match ty.kind {
110+
let res = (|| match ty.kind {
104111
ty::Opaque(def_id, substs) => {
105112
// Only normalize `impl Trait` after type-checking, usually in codegen.
106113
match self.param_env.reveal() {
@@ -197,7 +204,9 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
197204
}
198205

199206
_ => ty,
200-
}
207+
})();
208+
self.cache.insert(ty, res);
209+
res
201210
}
202211

203212
fn fold_const(&mut self, constant: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {

0 commit comments

Comments
 (0)