@@ -31,7 +31,9 @@ use super::unify_key::replace_if_possible;
31
31
use super :: unify_key:: { ConstVarValue , ConstVariableValue } ;
32
32
use super :: unify_key:: { ConstVariableOrigin , ConstVariableOriginKind } ;
33
33
use super :: { InferCtxt , MiscVariable , TypeTrace } ;
34
+ use arrayvec:: ArrayVec ;
34
35
use rustc_data_structures:: fx:: FxHashMap ;
36
+ use std:: hash:: Hash ;
35
37
36
38
use crate :: traits:: { Obligation , PredicateObligations } ;
37
39
@@ -45,6 +47,63 @@ use rustc_middle::ty::{self, InferConst, ToPredicate, Ty, TyCtxt, TypeFoldable};
45
47
use rustc_middle:: ty:: { IntType , UintType } ;
46
48
use rustc_span:: DUMMY_SP ;
47
49
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
+
48
107
#[ derive( Clone ) ]
49
108
pub struct CombineFields < ' infcx , ' tcx > {
50
109
pub infcx : & ' infcx InferCtxt < ' infcx , ' tcx > ,
@@ -380,7 +439,7 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> {
380
439
needs_wf : false ,
381
440
root_ty : ty,
382
441
param_env : self . param_env ,
383
- cache : FxHashMap :: default ( ) ,
442
+ cache : MiniMap :: new ( ) ,
384
443
} ;
385
444
386
445
let ty = match generalize. relate ( ty, ty) {
@@ -441,7 +500,7 @@ struct Generalizer<'cx, 'tcx> {
441
500
442
501
param_env : ty:: ParamEnv < ' tcx > ,
443
502
444
- cache : FxHashMap < ( Ty < ' tcx > , Ty < ' tcx > ) , RelateResult < ' tcx , Ty < ' tcx > > > ,
503
+ cache : MiniMap < ( Ty < ' tcx > , Ty < ' tcx > ) , RelateResult < ' tcx , Ty < ' tcx > > > ,
445
504
}
446
505
447
506
/// Result from a generalization operation. This includes
0 commit comments