@@ -253,9 +253,9 @@ impl<'db> UseDefMapBuilder<'db> {
253
253
254
254
/// Restore the current builder visible-definitions state to the given snapshot.
255
255
pub ( super ) fn restore ( & mut self , snapshot : FlowSnapshot ) {
256
- // We never remove symbols from `definitions_by_symbol` (its an IndexVec, and the symbol
257
- // IDs need to line up), so the current number of recorded symbols must always be equal or
258
- // greater than the number of symbols in a previously-recorded snapshot.
256
+ // We never remove symbols from `definitions_by_symbol` (it's an IndexVec, and the symbol
257
+ // IDs must line up), so the current number of known symbols must always be equal to or
258
+ // greater than the number of known symbols in a previously-taken snapshot.
259
259
let num_symbols = self . definitions_by_symbol . len ( ) ;
260
260
debug_assert ! ( num_symbols >= snapshot. definitions_by_symbol. len( ) ) ;
261
261
@@ -272,8 +272,7 @@ impl<'db> UseDefMapBuilder<'db> {
272
272
/// Merge the given snapshot into the current state, reflecting that we might have taken either
273
273
/// path to get here. The new visible-definitions state for each symbol should include
274
274
/// definitions from both the prior state and the snapshot.
275
- #[ allow( clippy:: needless_pass_by_value) ]
276
- pub ( super ) fn merge ( & mut self , snapshot : FlowSnapshot ) {
275
+ pub ( super ) fn merge ( & mut self , snapshot : & FlowSnapshot ) {
277
276
// The tricky thing about merging two Ranges pointing into `all_definitions` is that if the
278
277
// two Ranges aren't already adjacent in `all_definitions`, we will have to copy at least
279
278
// one or the other of the ranges to the end of `all_definitions` so as to make them
@@ -282,48 +281,60 @@ impl<'db> UseDefMapBuilder<'db> {
282
281
// It's possible we may end up with some old entries in `all_definitions` that nobody is
283
282
// pointing to, but that's OK.
284
283
285
- for ( symbol_id, to_merge) in snapshot. definitions_by_symbol . iter_enumerated ( ) {
286
- let current = & mut self . definitions_by_symbol [ symbol_id] ;
284
+ // We never remove symbols from `definitions_by_symbol` (it's an IndexVec, and the symbol
285
+ // IDs must line up), so the current number of known symbols must always be equal to or
286
+ // greater than the number of known symbols in a previously-taken snapshot.
287
+ debug_assert ! ( self . definitions_by_symbol. len( ) >= snapshot. definitions_by_symbol. len( ) ) ;
288
+
289
+ for ( symbol_id, current) in self . definitions_by_symbol . iter_mut_enumerated ( ) {
290
+ let Some ( snapshot) = snapshot. definitions_by_symbol . get ( symbol_id) else {
291
+ // Symbol not present in snapshot, so it's unbound from that path.
292
+ current. may_be_unbound = true ;
293
+ continue ;
294
+ } ;
287
295
288
296
// If the symbol can be unbound in either predecessor, it can be unbound post-merge.
289
- current. may_be_unbound |= to_merge . may_be_unbound ;
297
+ current. may_be_unbound |= snapshot . may_be_unbound ;
290
298
291
299
// Merge the definition ranges.
292
- if current. definitions_range == to_merge. definitions_range {
293
- // Ranges already identical, nothing to do!
294
- } else if current. definitions_range . end == to_merge. definitions_range . start {
295
- // Ranges are adjacent (`current` first), just merge them into one range.
296
- current. definitions_range =
297
- ( current. definitions_range . start ) ..( to_merge. definitions_range . end ) ;
298
- } else if current. definitions_range . start == to_merge. definitions_range . end {
299
- // Ranges are adjacent (`to_merge` first), just merge them into one range.
300
- current. definitions_range =
301
- ( to_merge. definitions_range . start ) ..( current. definitions_range . end ) ;
302
- } else if current. definitions_range . end == self . all_definitions . len ( ) {
303
- // Ranges are not adjacent, `current` is at the end of `all_definitions`, we need
304
- // to copy `to_merge` to the end so they are adjacent and can be merged into one
305
- // range.
306
- self . all_definitions
307
- . extend_from_within ( to_merge. definitions_range . clone ( ) ) ;
308
- current. definitions_range . end = self . all_definitions . len ( ) ;
309
- } else if to_merge. definitions_range . end == self . all_definitions . len ( ) {
310
- // Ranges are not adjacent, `to_merge` is at the end of `all_definitions`, we need
311
- // to copy `current` to the end so they are adjacent and can be merged into one
312
- // range.
313
- self . all_definitions
314
- . extend_from_within ( current. definitions_range . clone ( ) ) ;
315
- current. definitions_range . start = to_merge. definitions_range . start ;
316
- current. definitions_range . end = self . all_definitions . len ( ) ;
300
+ let current = & mut current. definitions_range ;
301
+ let snapshot = & snapshot. definitions_range ;
302
+
303
+ // We never create reversed ranges.
304
+ debug_assert ! ( current. end >= current. start) ;
305
+ debug_assert ! ( snapshot. end >= snapshot. start) ;
306
+
307
+ if current == snapshot {
308
+ // Ranges already identical, nothing to do.
309
+ } else if snapshot. is_empty ( ) {
310
+ // Merging from an empty range; nothing to do.
311
+ } else if ( * current) . is_empty ( ) {
312
+ // Merging to an empty range; just use the incoming range.
313
+ * current = snapshot. clone ( ) ;
314
+ } else if snapshot. end >= current. start && snapshot. start <= current. end {
315
+ // Ranges are adjacent or overlapping, merge them in-place.
316
+ * current = current. start . min ( snapshot. start ) ..current. end . max ( snapshot. end ) ;
317
+ } else if current. end == self . all_definitions . len ( ) {
318
+ // Ranges are not adjacent or overlapping, `current` is at the end of
319
+ // `all_definitions`, we need to copy `snapshot` to the end so they are adjacent
320
+ // and can be merged into one range.
321
+ self . all_definitions . extend_from_within ( snapshot. clone ( ) ) ;
322
+ current. end = self . all_definitions . len ( ) ;
323
+ } else if snapshot. end == self . all_definitions . len ( ) {
324
+ // Ranges are not adjacent or overlapping, `snapshot` is at the end of
325
+ // `all_definitions`, we need to copy `current` to the end so they are adjacent and
326
+ // can be merged into one range.
327
+ self . all_definitions . extend_from_within ( current. clone ( ) ) ;
328
+ current. start = snapshot. start ;
329
+ current. end = self . all_definitions . len ( ) ;
317
330
} else {
318
331
// Ranges are not adjacent and neither one is at the end of `all_definitions`, we
319
332
// have to copy both to the end so they are adjacent and we can merge them.
320
333
let start = self . all_definitions . len ( ) ;
321
- self . all_definitions
322
- . extend_from_within ( current. definitions_range . clone ( ) ) ;
323
- self . all_definitions
324
- . extend_from_within ( to_merge. definitions_range . clone ( ) ) ;
325
- current. definitions_range . start = start;
326
- current. definitions_range . end = self . all_definitions . len ( ) ;
334
+ self . all_definitions . extend_from_within ( current. clone ( ) ) ;
335
+ self . all_definitions . extend_from_within ( snapshot. clone ( ) ) ;
336
+ current. start = start;
337
+ current. end = self . all_definitions . len ( ) ;
327
338
}
328
339
}
329
340
}
0 commit comments