@@ -39,6 +39,9 @@ impl AdaptiveMap {
39
39
values : [ 0 ; SMALL_ELEMS ] ,
40
40
}
41
41
}
42
+
43
+ /// Expand into `Large` mode if we are at capacity and have no
44
+ /// zero-value pairs that can be trimmed.
42
45
#[ inline( never) ]
43
46
fn expand ( & mut self ) {
44
47
match self {
@@ -76,13 +79,25 @@ impl AdaptiveMap {
76
79
}
77
80
#[ inline( always) ]
78
81
fn get_or_insert < ' a > ( & ' a mut self , key : u32 ) -> & ' a mut u64 {
79
- let needs_expand = match self {
82
+ // Check whether the key is present and we are in small mode;
83
+ // if no to both, we need to expand first.
84
+ let ( needs_expand, small_mode_idx) = match self {
80
85
& mut Self :: Small { len, ref keys, .. } => {
81
- len == SMALL_ELEMS as u32 && !keys. iter ( ) . any ( |k| * k == key)
86
+ // Perform this scan but do not return right away;
87
+ // doing so runs into overlapping-borrow issues
88
+ // because the current non-lexical lifetimes
89
+ // implementation is not able to see that the `self`
90
+ // mutable borrow on return is only on the
91
+ // early-return path.
92
+ let small_mode_idx = keys. iter ( ) . position ( |k| * k == key) ;
93
+ let needs_expand = small_mode_idx. is_none ( ) && len == SMALL_ELEMS as u32 ;
94
+ ( needs_expand, small_mode_idx)
82
95
}
83
- _ => false ,
96
+ _ => ( false , None ) ,
84
97
} ;
98
+
85
99
if needs_expand {
100
+ assert ! ( small_mode_idx. is_none( ) ) ;
86
101
self . expand ( ) ;
87
102
}
88
103
@@ -92,11 +107,14 @@ impl AdaptiveMap {
92
107
ref mut keys,
93
108
ref mut values,
94
109
} => {
95
- for i in 0 ..* len {
96
- if keys[ i as usize ] == key {
97
- return & mut values[ i as usize ] ;
98
- }
110
+ // If we found the key already while checking whether
111
+ // we need to expand above, use that index to return
112
+ // early.
113
+ if let Some ( i) = small_mode_idx {
114
+ return & mut values[ i] ;
99
115
}
116
+ // Otherwise, the key must not be present; add a new
117
+ // entry.
100
118
assert ! ( * len < SMALL_ELEMS as u32 ) ;
101
119
let idx = * len;
102
120
* len += 1 ;
0 commit comments