@@ -31,7 +31,9 @@ use super::unify_key::replace_if_possible;
3131use super :: unify_key:: { ConstVarValue , ConstVariableValue } ;
3232use super :: unify_key:: { ConstVariableOrigin , ConstVariableOriginKind } ;
3333use super :: { InferCtxt , MiscVariable , TypeTrace } ;
34+ use arrayvec:: ArrayVec ;
3435use rustc_data_structures:: fx:: FxHashMap ;
36+ use std:: hash:: Hash ;
3537
3638use crate :: traits:: { Obligation , PredicateObligations } ;
3739
@@ -45,6 +47,63 @@ use rustc_middle::ty::{self, InferConst, ToPredicate, Ty, TyCtxt, TypeFoldable};
4547use rustc_middle:: ty:: { IntType , UintType } ;
4648use rustc_span:: DUMMY_SP ;
4749
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+
48107#[ derive( Clone ) ]
49108pub struct CombineFields < ' infcx , ' tcx > {
50109 pub infcx : & ' infcx InferCtxt < ' infcx , ' tcx > ,
@@ -380,7 +439,7 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> {
380439 needs_wf : false ,
381440 root_ty : ty,
382441 param_env : self . param_env ,
383- cache : FxHashMap :: default ( ) ,
442+ cache : MiniMap :: new ( ) ,
384443 } ;
385444
386445 let ty = match generalize. relate ( ty, ty) {
@@ -441,7 +500,7 @@ struct Generalizer<'cx, 'tcx> {
441500
442501 param_env : ty:: ParamEnv < ' tcx > ,
443502
444- cache : FxHashMap < ( Ty < ' tcx > , Ty < ' tcx > ) , RelateResult < ' tcx , Ty < ' tcx > > > ,
503+ cache : MiniMap < ( Ty < ' tcx > , Ty < ' tcx > ) , RelateResult < ' tcx , Ty < ' tcx > > > ,
445504}
446505
447506/// Result from a generalization operation. This includes
0 commit comments