@@ -1253,7 +1253,6 @@ impl<K, V, A: Allocator + Clone> BTreeMap<K, V, A> {
12531253 /// Similar to [`insert`], though, the key is not overwritten,
12541254 /// which matters for types that can be `==` without being identical.
12551255 ///
1256- ///
12571256 /// [`insert`]: BTreeMap::insert
12581257 /// [`append`]: BTreeMap::append
12591258 ///
@@ -1311,19 +1310,28 @@ impl<K, V, A: Allocator + Clone> BTreeMap<K, V, A> {
13111310 let mut self_cursor = self . lower_bound_mut ( Bound :: Included ( & first_other_key) ) ;
13121311
13131312 if let Some ( ( self_key, _) ) = self_cursor. peek_next ( ) {
1314- match K :: cmp ( & first_other_key , self_key ) {
1313+ match K :: cmp ( self_key , & first_other_key ) {
13151314 Ordering :: Equal => {
1316- self_cursor. with_next ( |self_key, self_val| {
1317- conflict ( self_key, self_val, first_other_val)
1318- } ) ;
1315+ // if `f` unwinds, the next entry is already removed leaving
1316+ // the tree in valid state.
1317+ // FIXME: Once `MaybeDangling` is implemented, we can optimize
1318+ // this through using a drop handler and transmutating CursorMutKey<K, V>
1319+ // to CursorMutKey<ManuallyDrop<K>, ManuallyDrop<V>> (see PR #152418)
1320+ if let Some ( ( k, v) ) = self_cursor. remove_next ( ) {
1321+ // SAFETY: we remove the K, V out of the next entry,
1322+ // apply 'f' to get a new (K, V), and insert it back
1323+ // into the next entry that the cursor is pointing at
1324+ let v = conflict ( & k, v, first_other_val) ;
1325+ unsafe { self_cursor. insert_after_unchecked ( k, v) } ;
1326+ }
13191327 }
1320- Ordering :: Less =>
1328+ Ordering :: Greater =>
13211329 // SAFETY: we know our other_key's ordering is less than self_key,
13221330 // so inserting before will guarantee sorted order
13231331 unsafe {
13241332 self_cursor. insert_before_unchecked ( first_other_key, first_other_val) ;
13251333 } ,
1326- Ordering :: Greater => {
1334+ Ordering :: Less => {
13271335 unreachable ! ( "Cursor's peek_next should return None." ) ;
13281336 }
13291337 }
@@ -1338,22 +1346,31 @@ impl<K, V, A: Allocator + Clone> BTreeMap<K, V, A> {
13381346 for ( other_key, other_val) in other_iter {
13391347 loop {
13401348 if let Some ( ( self_key, _) ) = self_cursor. peek_next ( ) {
1341- match K :: cmp ( & other_key , self_key ) {
1349+ match K :: cmp ( self_key , & other_key ) {
13421350 Ordering :: Equal => {
1343- self_cursor. with_next ( |self_key, self_val| {
1344- conflict ( self_key, self_val, other_val)
1345- } ) ;
1351+ // if `f` unwinds, the next entry is already removed leaving
1352+ // the tree in valid state.
1353+ // FIXME: Once `MaybeDangling` is implemented, we can optimize
1354+ // this through using a drop handler and transmutating CursorMutKey<K, V>
1355+ // to CursorMutKey<ManuallyDrop<K>, ManuallyDrop<V>> (see PR #152418)
1356+ if let Some ( ( k, v) ) = self_cursor. remove_next ( ) {
1357+ // SAFETY: we remove the K, V out of the next entry,
1358+ // apply 'f' to get a new (K, V), and insert it back
1359+ // into the next entry that the cursor is pointing at
1360+ let v = conflict ( & k, v, other_val) ;
1361+ unsafe { self_cursor. insert_after_unchecked ( k, v) } ;
1362+ }
13461363 break ;
13471364 }
1348- Ordering :: Less => {
1349- // SAFETY: we know our other_key 's ordering is less than self_key ,
1365+ Ordering :: Greater => {
1366+ // SAFETY: we know our self_key 's ordering is greater than other_key ,
13501367 // so inserting before will guarantee sorted order
13511368 unsafe {
13521369 self_cursor. insert_before_unchecked ( other_key, other_val) ;
13531370 }
13541371 break ;
13551372 }
1356- Ordering :: Greater => {
1373+ Ordering :: Less => {
13571374 // FIXME: instead of doing a linear search here,
13581375 // this can be optimized to search the tree by starting
13591376 // from self_cursor and going towards the root and then
@@ -1363,6 +1380,11 @@ impl<K, V, A: Allocator + Clone> BTreeMap<K, V, A> {
13631380 }
13641381 }
13651382 } else {
1383+ // FIXME: If we get here, that means all of other's keys are greater than
1384+ // self's keys. For performance, this should really do a bulk insertion of items
1385+ // from other_iter into the end of self `BTreeMap`. Maybe this should be
1386+ // a method for Cursor*?
1387+
13661388 // SAFETY: reaching here means our cursor is at the end
13671389 // self BTreeMap so we just insert other_key here
13681390 unsafe {
@@ -3396,37 +3418,6 @@ impl<'a, K, V, A> CursorMutKey<'a, K, V, A> {
33963418
33973419// Now the tree editing operations
33983420impl < ' a , K : Ord , V , A : Allocator + Clone > CursorMutKey < ' a , K , V , A > {
3399- /// Calls a function with ownership of the next element's key and
3400- /// and value and expects it to return a value to write
3401- /// back to the next element's key and value. The cursor is not
3402- /// advanced forward.
3403- ///
3404- /// If the cursor is at the end of the map then the function is not called
3405- /// and this essentially does not do anything.
3406- ///
3407- /// # Safety
3408- ///
3409- /// You must ensure that the `BTreeMap` invariants are maintained.
3410- /// Specifically:
3411- ///
3412- /// * The next element's key must be unique in the tree.
3413- /// * All keys in the tree must remain in sorted order.
3414- #[ allow( dead_code) ] /* This function exists for consistency with CursorMut */
3415- pub ( super ) fn with_next ( & mut self , f : impl FnOnce ( K , V ) -> ( K , V ) ) {
3416- // if `f` unwinds, the next entry is already removed leaving
3417- // the tree in valid state.
3418- // FIXME: Once `MaybeDangling` is implemented, we can optimize
3419- // this through using a drop handler and transmutating CursorMutKey<K, V>
3420- // to CursorMutKey<ManuallyDrop<K>, ManuallyDrop<V>> (see PR #152418)
3421- if let Some ( ( k, v) ) = self . remove_next ( ) {
3422- // SAFETY: we remove the K, V out of the next entry,
3423- // apply 'f' to get a new (K, V), and insert it back
3424- // into the next entry that the cursor is pointing at
3425- let ( k, v) = f ( k, v) ;
3426- unsafe { self . insert_after_unchecked ( k, v) } ;
3427- }
3428- }
3429-
34303421 /// Inserts a new key-value pair into the map in the gap that the
34313422 /// cursor is currently pointing to.
34323423 ///
@@ -3632,29 +3623,6 @@ impl<'a, K: Ord, V, A: Allocator + Clone> CursorMutKey<'a, K, V, A> {
36323623}
36333624
36343625impl < ' a , K : Ord , V , A : Allocator + Clone > CursorMut < ' a , K , V , A > {
3635- /// Calls a function with a reference to the next element's key and
3636- /// ownership of its value. The function is expected to return a value
3637- /// to write back to the next element's value. The cursor is not
3638- /// advanced forward.
3639- ///
3640- /// If the cursor is at the end of the map then the function is not called
3641- /// and this essentially does not do anything.
3642- pub ( super ) fn with_next ( & mut self , f : impl FnOnce ( & K , V ) -> V ) {
3643- // FIXME: This can be optimized to not do all the removing/reinserting
3644- // logic by using ptr::read, calling `f`, and then using ptr::write.
3645- // if `f` unwinds, then we need to remove the entry while being careful to
3646- // not cause UB by moving or dropping the already-dropped `V`
3647- // for the entry. Some implementation ideas:
3648- // https://github.com/rust-lang/rust/pull/152418#discussion_r2800232576
3649- if let Some ( ( k, v) ) = self . remove_next ( ) {
3650- // SAFETY: we remove the K, V out of the next entry,
3651- // apply 'f' to get a new V, and insert (K, V) back
3652- // into the next entry that the cursor is pointing at
3653- let v = f ( & k, v) ;
3654- unsafe { self . insert_after_unchecked ( k, v) } ;
3655- }
3656- }
3657-
36583626 /// Inserts a new key-value pair into the map in the gap that the
36593627 /// cursor is currently pointing to.
36603628 ///
0 commit comments