@@ -161,9 +161,7 @@ pub struct BTreeMap<K, V> {
161
161
#[ stable( feature = "btree_drop" , since = "1.7.0" ) ]
162
162
unsafe impl < #[ may_dangle] K , #[ may_dangle] V > Drop for BTreeMap < K , V > {
163
163
fn drop ( & mut self ) {
164
- if let Some ( root) = self . root . take ( ) {
165
- Dropper { front : root. into_dying ( ) . first_leaf_edge ( ) , remaining_length : self . length } ;
166
- }
164
+ drop ( unsafe { ptr:: read ( self ) } . into_iter ( ) )
167
165
}
168
166
}
169
167
@@ -352,14 +350,6 @@ impl<K: fmt::Debug, V: fmt::Debug> fmt::Debug for IntoIter<K, V> {
352
350
}
353
351
}
354
352
355
- /// A simplified version of `IntoIter` that is not double-ended and has only one
356
- /// purpose: to drop the remainder of an `IntoIter`. Therefore it also serves to
357
- /// drop an entire tree without the need to first look up a `back` leaf edge.
358
- struct Dropper < K , V > {
359
- front : Handle < NodeRef < marker:: Dying , K , V , marker:: Leaf > , marker:: Edge > ,
360
- remaining_length : usize ,
361
- }
362
-
363
353
/// An iterator over the keys of a `BTreeMap`.
364
354
///
365
355
/// This `struct` is created by the [`keys`] method on [`BTreeMap`]. See its
@@ -1458,47 +1448,57 @@ impl<K, V> IntoIterator for BTreeMap<K, V> {
1458
1448
}
1459
1449
}
1460
1450
1461
- impl < K , V > Drop for Dropper < K , V > {
1451
+ #[ stable( feature = "btree_drop" , since = "1.7.0" ) ]
1452
+ impl < K , V > Drop for IntoIter < K , V > {
1462
1453
fn drop ( & mut self ) {
1463
- // Similar to advancing a non-fusing iterator.
1464
- fn next_or_end < K , V > (
1465
- this : & mut Dropper < K , V > ,
1466
- ) -> Option < Handle < NodeRef < marker:: Dying , K , V , marker:: LeafOrInternal > , marker:: KV > >
1467
- {
1468
- if this. remaining_length == 0 {
1469
- unsafe { ptr:: read ( & this. front ) . deallocating_end ( ) }
1470
- None
1471
- } else {
1472
- this. remaining_length -= 1 ;
1473
- Some ( unsafe { this. front . deallocating_next_unchecked ( ) } )
1474
- }
1475
- }
1476
-
1477
- struct DropGuard < ' a , K , V > ( & ' a mut Dropper < K , V > ) ;
1454
+ struct DropGuard < ' a , K , V > ( & ' a mut IntoIter < K , V > ) ;
1478
1455
1479
1456
impl < ' a , K , V > Drop for DropGuard < ' a , K , V > {
1480
1457
fn drop ( & mut self ) {
1481
1458
// Continue the same loop we perform below. This only runs when unwinding, so we
1482
1459
// don't have to care about panics this time (they'll abort).
1483
- while let Some ( kv) = next_or_end ( & mut self . 0 ) {
1484
- kv. drop_key_val ( ) ;
1460
+ while let Some ( kv) = self . 0 . dying_next ( ) {
1461
+ // SAFETY: we consume the dying handle immediately.
1462
+ unsafe { kv. drop_key_val ( ) } ;
1485
1463
}
1486
1464
}
1487
1465
}
1488
1466
1489
- while let Some ( kv) = next_or_end ( self ) {
1467
+ while let Some ( kv) = self . dying_next ( ) {
1490
1468
let guard = DropGuard ( self ) ;
1491
- kv. drop_key_val ( ) ;
1469
+ // SAFETY: we don't touch the tree before consuming the dying handle.
1470
+ unsafe { kv. drop_key_val ( ) } ;
1492
1471
mem:: forget ( guard) ;
1493
1472
}
1494
1473
}
1495
1474
}
1496
1475
1497
- #[ stable( feature = "btree_drop" , since = "1.7.0" ) ]
1498
- impl < K , V > Drop for IntoIter < K , V > {
1499
- fn drop ( & mut self ) {
1500
- if let Some ( front) = self . range . take_front ( ) {
1501
- Dropper { front, remaining_length : self . length } ;
1476
+ impl < K , V > IntoIter < K , V > {
1477
+ /// Core of a `next` method returning a dying KV handle,
1478
+ /// invalidated by further calls to this function and some others.
1479
+ fn dying_next (
1480
+ & mut self ,
1481
+ ) -> Option < Handle < NodeRef < marker:: Dying , K , V , marker:: LeafOrInternal > , marker:: KV > > {
1482
+ if self . length == 0 {
1483
+ self . range . deallocating_end ( ) ;
1484
+ None
1485
+ } else {
1486
+ self . length -= 1 ;
1487
+ Some ( unsafe { self . range . deallocating_next_unchecked ( ) } )
1488
+ }
1489
+ }
1490
+
1491
+ /// Core of a `next_back` method returning a dying KV handle,
1492
+ /// invalidated by further calls to this function and some others.
1493
+ fn dying_next_back (
1494
+ & mut self ,
1495
+ ) -> Option < Handle < NodeRef < marker:: Dying , K , V , marker:: LeafOrInternal > , marker:: KV > > {
1496
+ if self . length == 0 {
1497
+ self . range . deallocating_end ( ) ;
1498
+ None
1499
+ } else {
1500
+ self . length -= 1 ;
1501
+ Some ( unsafe { self . range . deallocating_next_back_unchecked ( ) } )
1502
1502
}
1503
1503
}
1504
1504
}
@@ -1508,13 +1508,8 @@ impl<K, V> Iterator for IntoIter<K, V> {
1508
1508
type Item = ( K , V ) ;
1509
1509
1510
1510
fn next ( & mut self ) -> Option < ( K , V ) > {
1511
- if self . length == 0 {
1512
- None
1513
- } else {
1514
- self . length -= 1 ;
1515
- let kv = unsafe { self . range . deallocating_next_unchecked ( ) } ;
1516
- Some ( kv. into_key_val ( ) )
1517
- }
1511
+ // SAFETY: we consume the dying handle immediately.
1512
+ self . dying_next ( ) . map ( unsafe { |kv| kv. into_key_val ( ) } )
1518
1513
}
1519
1514
1520
1515
fn size_hint ( & self ) -> ( usize , Option < usize > ) {
@@ -1525,13 +1520,8 @@ impl<K, V> Iterator for IntoIter<K, V> {
1525
1520
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
1526
1521
impl < K , V > DoubleEndedIterator for IntoIter < K , V > {
1527
1522
fn next_back ( & mut self ) -> Option < ( K , V ) > {
1528
- if self . length == 0 {
1529
- None
1530
- } else {
1531
- self . length -= 1 ;
1532
- let kv = unsafe { self . range . deallocating_next_back_unchecked ( ) } ;
1533
- Some ( kv. into_key_val ( ) )
1534
- }
1523
+ // SAFETY: we consume the dying handle immediately.
1524
+ self . dying_next_back ( ) . map ( unsafe { |kv| kv. into_key_val ( ) } )
1535
1525
}
1536
1526
}
1537
1527
0 commit comments