@@ -161,9 +161,7 @@ pub struct BTreeMap<K, V> {
161161#[ stable( feature = "btree_drop" , since = "1.7.0" ) ]
162162unsafe impl < #[ may_dangle] K , #[ may_dangle] V > Drop for BTreeMap < K , V > {
163163 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 ( ) )
167165 }
168166}
169167
@@ -352,14 +350,6 @@ impl<K: fmt::Debug, V: fmt::Debug> fmt::Debug for IntoIter<K, V> {
352350 }
353351}
354352
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-
363353/// An iterator over the keys of a `BTreeMap`.
364354///
365355/// This `struct` is created by the [`keys`] method on [`BTreeMap`]. See its
@@ -1458,47 +1448,57 @@ impl<K, V> IntoIterator for BTreeMap<K, V> {
14581448 }
14591449}
14601450
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 > {
14621453 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 > ) ;
14781455
14791456 impl < ' a , K , V > Drop for DropGuard < ' a , K , V > {
14801457 fn drop ( & mut self ) {
14811458 // Continue the same loop we perform below. This only runs when unwinding, so we
14821459 // 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 ( ) } ;
14851463 }
14861464 }
14871465 }
14881466
1489- while let Some ( kv) = next_or_end ( self ) {
1467+ while let Some ( kv) = self . dying_next ( ) {
14901468 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 ( ) } ;
14921471 mem:: forget ( guard) ;
14931472 }
14941473 }
14951474}
14961475
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 ( ) } )
15021502 }
15031503 }
15041504}
@@ -1508,13 +1508,8 @@ impl<K, V> Iterator for IntoIter<K, V> {
15081508 type Item = ( K , V ) ;
15091509
15101510 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 ( ) } )
15181513 }
15191514
15201515 fn size_hint ( & self ) -> ( usize , Option < usize > ) {
@@ -1525,13 +1520,8 @@ impl<K, V> Iterator for IntoIter<K, V> {
15251520#[ stable( feature = "rust1" , since = "1.0.0" ) ]
15261521impl < K , V > DoubleEndedIterator for IntoIter < K , V > {
15271522 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 ( ) } )
15351525 }
15361526}
15371527
0 commit comments