Skip to content

Commit 1146c39

Browse files
committed
cache types during normalization
1 parent 4e8a8b4 commit 1146c39

File tree

7 files changed

+83
-68
lines changed

7 files changed

+83
-68
lines changed

Cargo.lock

+1
Original file line numberDiff line numberDiff line change
@@ -3435,6 +3435,7 @@ dependencies = [
34353435
name = "rustc_data_structures"
34363436
version = "0.0.0"
34373437
dependencies = [
3438+
"arrayvec",
34383439
"bitflags",
34393440
"cfg-if",
34403441
"crossbeam-utils 0.7.2",

compiler/rustc_data_structures/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ edition = "2018"
88
doctest = false
99

1010
[dependencies]
11+
arrayvec = { version = "0.5.1", default-features = false }
1112
ena = "0.14"
1213
indexmap = "1.5.1"
1314
tracing = "0.1"

compiler/rustc_data_structures/src/lib.rs

+7-5
Original file line numberDiff line numberDiff line change
@@ -87,25 +87,27 @@ pub mod sorted_map;
8787
pub mod stable_set;
8888
#[macro_use]
8989
pub mod stable_hasher;
90+
mod atomic_ref;
91+
pub mod fingerprint;
92+
pub mod profiling;
9093
pub mod sharded;
9194
pub mod stack;
9295
pub mod sync;
9396
pub mod thin_vec;
9497
pub mod tiny_list;
9598
pub mod transitive_relation;
96-
pub use ena::undo_log;
97-
pub use ena::unify;
98-
mod atomic_ref;
99-
pub mod fingerprint;
100-
pub mod profiling;
10199
pub mod vec_linked_list;
102100
pub mod work_queue;
103101
pub use atomic_ref::AtomicRef;
104102
pub mod frozen;
103+
pub mod mini_map;
105104
pub mod tagged_ptr;
106105
pub mod temp_dir;
107106
pub mod unhash;
108107

108+
pub use ena::undo_log;
109+
pub use ena::unify;
110+
109111
pub struct OnDrop<F: Fn()>(pub F);
110112

111113
impl<F: Fn()> OnDrop<F> {
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+
}

compiler/rustc_index/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,6 @@ edition = "2018"
88
doctest = false
99

1010
[dependencies]
11-
arrayvec = "0.5.1"
11+
arrayvec = { version = "0.5.1", default-features = false }
1212
rustc_serialize = { path = "../rustc_serialize" }
1313
rustc_macros = { path = "../rustc_macros" }

compiler/rustc_infer/src/infer/combine.rs

+1-60
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>,

compiler/rustc_trait_selection/src/traits/query/normalize.rs

+11-2
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)