@@ -359,6 +359,74 @@ impl<T: Ord, A: Allocator> DerefMut for PeekMut<'_, T, A> {
359359}
360360
361361impl < ' a , T : Ord , A : Allocator > PeekMut < ' a , T , A > {
362+ /// Sifts the current element to its new position.
363+ ///
364+ /// Afterwards refers to the new element. Returns if the element changed.
365+ ///
366+ /// ## Examples
367+ ///
368+ /// The condition can be used to upper bound all elements in the heap. When only few elements
369+ /// are affected, the heap's sort ensures this is faster than a reconstruction from the raw
370+ /// element list and requires no additional allocation.
371+ ///
372+ /// ```
373+ /// #![feature(binary_heap_peek_mut_refresh)]
374+ /// use std::collections::BinaryHeap;
375+ ///
376+ /// let mut heap: BinaryHeap<u32> = (0..128).collect();
377+ /// let mut peek = heap.peek_mut().unwrap();
378+ ///
379+ /// loop {
380+ /// *peek = 99;
381+ ///
382+ /// if !peek.refresh() {
383+ /// break;
384+ /// }
385+ /// }
386+ ///
387+ /// // Post condition, this is now an upper bound.
388+ /// assert!(*peek < 100);
389+ /// ```
390+ ///
391+ /// When the element remains the maximum after modification, the peek remains unchanged:
392+ ///
393+ /// ```
394+ /// #![feature(binary_heap_peek_mut_refresh)]
395+ /// use std::collections::BinaryHeap;
396+ ///
397+ /// let mut heap: BinaryHeap<u32> = [1, 2, 3].into();
398+ /// let mut peek = heap.peek_mut().unwrap();
399+ ///
400+ /// assert_eq!(*peek, 3);
401+ /// *peek = 42;
402+ ///
403+ /// // When we refresh, the peek is updated to the new maximum.
404+ /// assert!(!peek.refresh(), "42 is even larger than 3");
405+ /// assert_eq!(*peek, 42);
406+ /// ```
407+ #[ unstable( feature = "binary_heap_peek_mut_refresh" , issue = "138355" ) ]
408+ #[ must_use = "is equivalent to dropping and getting a new PeekMut except for return information" ]
409+ pub fn refresh ( & mut self ) -> bool {
410+ // The length of the underlying heap is unchanged by sifting down. The value stored for leak
411+ // amplification thus remains accurate. We erase the leak amplification firstly because the
412+ // operation is then equivalent to constructing a new PeekMut and secondly this avoids any
413+ // future complication where original_len being non-empty would be interpreted as the heap
414+ // having been leak amplified instead of checking the heap itself.
415+ if let Some ( original_len) = self . original_len . take ( ) {
416+ // SAFETY: This is how many elements were in the Vec at the time of
417+ // the BinaryHeap::peek_mut call.
418+ unsafe { self . heap . data . set_len ( original_len. get ( ) ) } ;
419+
420+ // The length of the heap did not change by sifting, upholding our own invariants.
421+
422+ // SAFETY: PeekMut is only instantiated for non-empty heaps.
423+ ( unsafe { self . heap . sift_down ( 0 ) } ) != 0
424+ } else {
425+ // The element was not modified.
426+ false
427+ }
428+ }
429+
362430 /// Removes the peeked value from the heap and returns it.
363431 #[ stable( feature = "binary_heap_peek_mut_pop" , since = "1.18.0" ) ]
364432 pub fn pop ( mut this : PeekMut < ' a , T , A > ) -> T {
@@ -670,6 +738,8 @@ impl<T: Ord, A: Allocator> BinaryHeap<T, A> {
670738 /// # Safety
671739 ///
672740 /// The caller must guarantee that `pos < self.len()`.
741+ ///
742+ /// Returns the new position of the element.
673743 unsafe fn sift_up ( & mut self , start : usize , pos : usize ) -> usize {
674744 // Take out the value at `pos` and create a hole.
675745 // SAFETY: The caller guarantees that pos < self.len()
@@ -696,10 +766,12 @@ impl<T: Ord, A: Allocator> BinaryHeap<T, A> {
696766 /// Take an element at `pos` and move it down the heap,
697767 /// while its children are larger.
698768 ///
769+ /// Returns the new position of the element.
770+ ///
699771 /// # Safety
700772 ///
701773 /// The caller must guarantee that `pos < end <= self.len()`.
702- unsafe fn sift_down_range ( & mut self , pos : usize , end : usize ) {
774+ unsafe fn sift_down_range ( & mut self , pos : usize , end : usize ) -> usize {
703775 // SAFETY: The caller guarantees that pos < end <= self.len().
704776 let mut hole = unsafe { Hole :: new ( & mut self . data , pos) } ;
705777 let mut child = 2 * hole. pos ( ) + 1 ;
@@ -719,7 +791,7 @@ impl<T: Ord, A: Allocator> BinaryHeap<T, A> {
719791 // SAFETY: child is now either the old child or the old child+1
720792 // We already proven that both are < self.len() and != hole.pos()
721793 if hole. element ( ) >= unsafe { hole. get ( child) } {
722- return ;
794+ return hole . pos ( ) ;
723795 }
724796
725797 // SAFETY: same as above.
@@ -734,16 +806,18 @@ impl<T: Ord, A: Allocator> BinaryHeap<T, A> {
734806 // child == 2 * hole.pos() + 1 != hole.pos().
735807 unsafe { hole. move_to ( child) } ;
736808 }
809+
810+ hole. pos ( )
737811 }
738812
739813 /// # Safety
740814 ///
741815 /// The caller must guarantee that `pos < self.len()`.
742- unsafe fn sift_down ( & mut self , pos : usize ) {
816+ unsafe fn sift_down ( & mut self , pos : usize ) -> usize {
743817 let len = self . len ( ) ;
744818 // SAFETY: pos < len is guaranteed by the caller and
745819 // obviously len = self.len() <= self.len().
746- unsafe { self . sift_down_range ( pos, len) } ;
820+ unsafe { self . sift_down_range ( pos, len) }
747821 }
748822
749823 /// Take an element at `pos` and move it all the way down the heap,
0 commit comments