49
49
//! cycle head may then iterate, which may result in a new set of iterations on the inner cycle,
50
50
//! for each iteration of the outer cycle.
51
51
52
+ use thin_vec:: { thin_vec, ThinVec } ;
53
+
52
54
use crate :: key:: DatabaseKeyIndex ;
53
55
54
56
/// The maximum number of times we'll fixpoint-iterate before panicking.
@@ -97,21 +99,22 @@ pub struct CycleHead {
97
99
/// plural in case of nested cycles) representing the cycles it is part of, and the current
98
100
/// iteration count for each cycle head. This struct tracks these cycle heads.
99
101
#[ derive( Clone , Debug , Default ) ]
100
- #[ allow( clippy:: box_collection) ]
101
- pub struct CycleHeads ( Option < Box < Vec < CycleHead > > > ) ;
102
+ pub struct CycleHeads ( ThinVec < CycleHead > ) ;
102
103
103
104
impl CycleHeads {
104
105
pub ( crate ) fn is_empty ( & self ) -> bool {
105
- // We ensure in `remove` and `extend` that we never have an empty hashset, we always use
106
- // None to signify empty.
107
- self . 0 . is_none ( )
106
+ self . 0 . is_empty ( )
108
107
}
109
108
110
109
pub ( crate ) fn initial ( database_key_index : DatabaseKeyIndex ) -> Self {
111
- Self ( Some ( Box :: new ( vec ! [ CycleHead {
110
+ Self ( thin_vec ! [ CycleHead {
112
111
database_key_index,
113
112
iteration_count: 0 ,
114
- } ] ) ) )
113
+ } ] )
114
+ }
115
+
116
+ pub ( crate ) fn iter ( & self ) -> std:: slice:: Iter < ' _ , CycleHead > {
117
+ self . 0 . iter ( )
115
118
}
116
119
117
120
pub ( crate ) fn contains ( & self , value : & DatabaseKeyIndex ) -> bool {
@@ -120,117 +123,74 @@ impl CycleHeads {
120
123
}
121
124
122
125
pub ( crate ) fn remove ( & mut self , value : & DatabaseKeyIndex ) -> bool {
123
- let Some ( cycle_heads) = & mut self . 0 else {
124
- return false ;
125
- } ;
126
- let found = cycle_heads
126
+ let found = self
127
+ . 0
127
128
. iter ( )
128
129
. position ( |& head| head. database_key_index == * value) ;
129
130
let Some ( found) = found else { return false } ;
130
- cycle_heads. swap_remove ( found) ;
131
- if cycle_heads. is_empty ( ) {
132
- self . 0 . take ( ) ;
133
- }
131
+ self . 0 . swap_remove ( found) ;
134
132
true
135
133
}
136
134
135
+ pub ( crate ) fn clear ( & mut self ) {
136
+ self . 0 . clear ( ) ;
137
+ }
138
+
137
139
pub ( crate ) fn update_iteration_count (
138
140
& mut self ,
139
141
cycle_head_index : DatabaseKeyIndex ,
140
142
new_iteration_count : u32 ,
141
143
) {
142
- if let Some ( cycle_head) = self . 0 . as_mut ( ) . and_then ( |cycle_heads| {
143
- cycle_heads
144
- . iter_mut ( )
145
- . find ( |cycle_head| cycle_head. database_key_index == cycle_head_index)
146
- } ) {
144
+ if let Some ( cycle_head) = self
145
+ . 0
146
+ . iter_mut ( )
147
+ . find ( |cycle_head| cycle_head. database_key_index == cycle_head_index)
148
+ {
147
149
cycle_head. iteration_count = new_iteration_count;
148
150
}
149
151
}
150
152
151
153
#[ inline]
152
- pub ( crate ) fn insert_into ( self , cycle_heads : & mut Vec < CycleHead > ) {
153
- if let Some ( heads) = self . 0 {
154
- insert_into_impl ( & heads, cycle_heads) ;
155
- }
156
- }
157
-
158
154
pub ( crate ) fn extend ( & mut self , other : & Self ) {
159
- if let Some ( other) = & other. 0 {
160
- let heads = & mut * * self . 0 . get_or_insert_with ( || Box :: new ( Vec :: new ( ) ) ) ;
161
- insert_into_impl ( other, heads) ;
162
- }
163
- }
164
- }
165
-
166
- #[ inline]
167
- fn insert_into_impl ( insert_from : & Vec < CycleHead > , insert_into : & mut Vec < CycleHead > ) {
168
- insert_into. reserve ( insert_from. len ( ) ) ;
169
- for head in insert_from {
170
- if let Some ( existing) = insert_into
171
- . iter ( )
172
- . find ( |candidate| candidate. database_key_index == head. database_key_index )
173
- {
174
- assert ! ( existing. iteration_count == head. iteration_count) ;
175
- } else {
176
- insert_into. push ( * head) ;
155
+ self . 0 . reserve ( other. 0 . len ( ) ) ;
156
+
157
+ for head in other {
158
+ if let Some ( existing) = self
159
+ . 0
160
+ . iter ( )
161
+ . find ( |candidate| candidate. database_key_index == head. database_key_index )
162
+ {
163
+ assert ! ( existing. iteration_count == head. iteration_count) ;
164
+ } else {
165
+ self . 0 . push ( * head) ;
166
+ }
177
167
}
178
168
}
179
169
}
180
170
181
171
impl IntoIterator for CycleHeads {
182
172
type Item = CycleHead ;
183
- type IntoIter = <Vec < Self :: Item > as IntoIterator >:: IntoIter ;
173
+ type IntoIter = <ThinVec < Self :: Item > as IntoIterator >:: IntoIter ;
184
174
185
175
fn into_iter ( self ) -> Self :: IntoIter {
186
- self . 0 . map ( |heads| * heads) . unwrap_or_default ( ) . into_iter ( )
187
- }
188
- }
189
-
190
- pub struct CycleHeadsIter < ' a > ( std:: slice:: Iter < ' a , CycleHead > ) ;
191
-
192
- impl Iterator for CycleHeadsIter < ' _ > {
193
- type Item = CycleHead ;
194
-
195
- fn next ( & mut self ) -> Option < Self :: Item > {
196
- self . 0 . next ( ) . copied ( )
197
- }
198
-
199
- fn last ( self ) -> Option < Self :: Item > {
200
- self . 0 . last ( ) . copied ( )
176
+ self . 0 . into_iter ( )
201
177
}
202
178
}
203
179
204
- impl std:: iter:: FusedIterator for CycleHeadsIter < ' _ > { }
205
-
206
180
impl < ' a > std:: iter:: IntoIterator for & ' a CycleHeads {
207
- type Item = CycleHead ;
208
- type IntoIter = CycleHeadsIter < ' a > ;
181
+ type Item = & ' a CycleHead ;
182
+ type IntoIter = std :: slice :: Iter < ' a , CycleHead > ;
209
183
210
184
fn into_iter ( self ) -> Self :: IntoIter {
211
- CycleHeadsIter (
212
- self . 0
213
- . as_ref ( )
214
- . map ( |heads| heads. iter ( ) )
215
- . unwrap_or_default ( ) ,
216
- )
185
+ self . iter ( )
217
186
}
218
187
}
219
188
220
189
impl From < CycleHead > for CycleHeads {
221
190
fn from ( value : CycleHead ) -> Self {
222
- Self ( Some ( Box :: new ( vec ! [ value] ) ) )
223
- }
224
- }
225
-
226
- impl From < Vec < CycleHead > > for CycleHeads {
227
- fn from ( value : Vec < CycleHead > ) -> Self {
228
- Self ( if value. is_empty ( ) {
229
- None
230
- } else {
231
- Some ( Box :: new ( value) )
232
- } )
191
+ Self ( thin_vec ! [ value] )
233
192
}
234
193
}
235
194
236
- pub ( crate ) const EMPTY_CYCLE_HEADS : CycleHeads = CycleHeads ( None ) ;
195
+ pub ( crate ) static EMPTY_CYCLE_HEADS : std:: sync:: LazyLock < CycleHeads > =
196
+ std:: sync:: LazyLock :: new ( || CycleHeads ( ThinVec :: new ( ) ) ) ;
0 commit comments