Skip to content

Commit a52da95

Browse files
committed
Auto merge of #39062 - martinhath:placement-in-binaryheap, r=nagisa
Implement placement-in protocol for `BinaryHeap` Related to #30172, and loosley based on #38551. At the moment, this PR is in a pretty rough state, but I wanted to get some feedback to see if I'm going in the right direction. I hope the Mentor label of #30172 is still applicable, even though it's a year old 😄
2 parents b7ca2b9 + 90fbe15 commit a52da95

File tree

2 files changed

+77
-2
lines changed

2 files changed

+77
-2
lines changed

src/libcollections/binary_heap.rs

+56-2
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@
151151
#![allow(missing_docs)]
152152
#![stable(feature = "rust1", since = "1.0.0")]
153153

154-
use core::ops::{Deref, DerefMut};
154+
use core::ops::{Deref, DerefMut, Place, Placer, InPlace};
155155
use core::iter::{FromIterator, FusedIterator};
156156
use core::mem::{swap, size_of};
157157
use core::ptr;
@@ -673,7 +673,7 @@ impl<T: Ord> BinaryHeap<T> {
673673
// the hole is filled back at the end of its scope, even on panic.
674674
// Using a hole reduces the constant factor compared to using swaps,
675675
// which involves twice as many moves.
676-
fn sift_up(&mut self, start: usize, pos: usize) {
676+
fn sift_up(&mut self, start: usize, pos: usize) -> usize {
677677
unsafe {
678678
// Take out the value at `pos` and create a hole.
679679
let mut hole = Hole::new(&mut self.data, pos);
@@ -685,6 +685,7 @@ impl<T: Ord> BinaryHeap<T> {
685685
}
686686
hole.move_to(parent);
687687
}
688+
hole.pos()
688689
}
689690
}
690691

@@ -1189,3 +1190,56 @@ impl<'a, T: 'a + Ord + Copy> Extend<&'a T> for BinaryHeap<T> {
11891190
self.extend(iter.into_iter().cloned());
11901191
}
11911192
}
1193+
1194+
#[unstable(feature = "collection_placement",
1195+
reason = "placement protocol is subject to change",
1196+
issue = "30172")]
1197+
pub struct BinaryHeapPlace<'a, T: 'a>
1198+
where T: Clone + Ord {
1199+
heap: *mut BinaryHeap<T>,
1200+
place: vec::PlaceBack<'a, T>,
1201+
}
1202+
1203+
#[unstable(feature = "collection_placement",
1204+
reason = "placement protocol is subject to change",
1205+
issue = "30172")]
1206+
impl<'a, T: 'a> Placer<T> for &'a mut BinaryHeap<T>
1207+
where T: Clone + Ord {
1208+
type Place = BinaryHeapPlace<'a, T>;
1209+
1210+
fn make_place(self) -> Self::Place {
1211+
let ptr = self as *mut BinaryHeap<T>;
1212+
let place = Placer::make_place(self.data.place_back());
1213+
BinaryHeapPlace {
1214+
heap: ptr,
1215+
place: place,
1216+
}
1217+
}
1218+
}
1219+
1220+
#[unstable(feature = "collection_placement",
1221+
reason = "placement protocol is subject to change",
1222+
issue = "30172")]
1223+
impl<'a, T> Place<T> for BinaryHeapPlace<'a, T>
1224+
where T: Clone + Ord {
1225+
fn pointer(&mut self) -> *mut T {
1226+
self.place.pointer()
1227+
}
1228+
}
1229+
1230+
#[unstable(feature = "collection_placement",
1231+
reason = "placement protocol is subject to change",
1232+
issue = "30172")]
1233+
impl<'a, T> InPlace<T> for BinaryHeapPlace<'a, T>
1234+
where T: Clone + Ord {
1235+
type Owner = &'a T;
1236+
1237+
unsafe fn finalize(self) -> &'a T {
1238+
self.place.finalize();
1239+
1240+
let heap: &mut BinaryHeap<T> = &mut *self.heap;
1241+
let len = heap.len();
1242+
let i = heap.sift_up(0, len - 1);
1243+
heap.data.get_unchecked(i)
1244+
}
1245+
}

src/libcollectionstest/binary_heap.rs

+21
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
use std::panic;
1112
use std::collections::BinaryHeap;
1213
use std::collections::binary_heap::{Drain, PeekMut};
1314

@@ -310,6 +311,26 @@ fn test_extend_specialization() {
310311
assert_eq!(a.into_sorted_vec(), [-20, -10, 1, 2, 3, 3, 5, 43]);
311312
}
312313

314+
#[test]
315+
fn test_placement() {
316+
let mut a = BinaryHeap::new();
317+
&mut a <- 2;
318+
&mut a <- 4;
319+
&mut a <- 3;
320+
assert_eq!(a.peek(), Some(&4));
321+
assert_eq!(a.len(), 3);
322+
&mut a <- 1;
323+
assert_eq!(a.into_sorted_vec(), vec![1, 2, 3, 4]);
324+
}
325+
326+
#[test]
327+
fn test_placement_panic() {
328+
let mut heap = BinaryHeap::from(vec![1, 2, 3]);
329+
fn mkpanic() -> usize { panic!() }
330+
let _ = panic::catch_unwind(panic::AssertUnwindSafe(|| { &mut heap <- mkpanic(); }));
331+
assert_eq!(heap.len(), 3);
332+
}
333+
313334
#[allow(dead_code)]
314335
fn assert_covariance() {
315336
fn drain<'new>(d: Drain<'static, &'static str>) -> Drain<'new, &'new str> {

0 commit comments

Comments
 (0)