Skip to content

Commit b54770c

Browse files
committed
Auto merge of #31696 - apasel422:placement, r=pnkfelix
CC #30172. r? @pnkfelix CC @nagisa
2 parents f4046de + 895ab4f commit b54770c

File tree

2 files changed

+150
-2
lines changed

2 files changed

+150
-2
lines changed

src/libcollections/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@
4545
#![feature(nonzero)]
4646
#![feature(num_bits_bytes)]
4747
#![feature(pattern)]
48+
#![feature(placement_in)]
49+
#![feature(placement_new_protocol)]
4850
#![feature(shared)]
4951
#![feature(slice_bytes)]
5052
#![feature(slice_patterns)]

src/libcollections/linked_list.rs

+148-2
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,14 @@
2121

2222
#![stable(feature = "rust1", since = "1.0.0")]
2323

24-
use alloc::boxed::Box;
24+
use alloc::boxed::{Box, IntermediateBox};
2525
use core::cmp::Ordering;
2626
use core::fmt;
2727
use core::hash::{Hasher, Hash};
2828
use core::iter::FromIterator;
2929
use core::mem;
30-
use core::ptr::Shared;
30+
use core::ops::{BoxPlace, InPlace, Place, Placer};
31+
use core::ptr::{self, Shared};
3132

3233
/// A doubly-linked list.
3334
#[stable(feature = "rust1", since = "1.0.0")]
@@ -660,6 +661,56 @@ impl<T> LinkedList<T> {
660661

661662
second_part
662663
}
664+
665+
/// Returns a place for insertion at the front of the list.
666+
///
667+
/// Using this method with placement syntax is equivalent to [`push_front`]
668+
/// (#method.push_front), but may be more efficient.
669+
///
670+
/// # Examples
671+
///
672+
/// ```
673+
/// #![feature(collection_placement)]
674+
/// #![feature(placement_in_syntax)]
675+
///
676+
/// use std::collections::LinkedList;
677+
///
678+
/// let mut list = LinkedList::new();
679+
/// list.front_place() <- 2;
680+
/// list.front_place() <- 4;
681+
/// assert!(list.iter().eq(&[4, 2]));
682+
/// ```
683+
#[unstable(feature = "collection_placement",
684+
reason = "method name and placement protocol are subject to change",
685+
issue = "30172")]
686+
pub fn front_place(&mut self) -> FrontPlace<T> {
687+
FrontPlace { list: self, node: IntermediateBox::make_place() }
688+
}
689+
690+
/// Returns a place for insertion at the back of the list.
691+
///
692+
/// Using this method with placement syntax is equivalent to [`push_back`](#method.push_back),
693+
/// but may be more efficient.
694+
///
695+
/// # Examples
696+
///
697+
/// ```
698+
/// #![feature(collection_placement)]
699+
/// #![feature(placement_in_syntax)]
700+
///
701+
/// use std::collections::LinkedList;
702+
///
703+
/// let mut list = LinkedList::new();
704+
/// list.back_place() <- 2;
705+
/// list.back_place() <- 4;
706+
/// assert!(list.iter().eq(&[2, 4]));
707+
/// ```
708+
#[unstable(feature = "collection_placement",
709+
reason = "method name and placement protocol are subject to change",
710+
issue = "30172")]
711+
pub fn back_place(&mut self) -> BackPlace<T> {
712+
BackPlace { list: self, node: IntermediateBox::make_place() }
713+
}
663714
}
664715

665716
#[stable(feature = "rust1", since = "1.0.0")]
@@ -984,6 +1035,101 @@ impl<A: Hash> Hash for LinkedList<A> {
9841035
}
9851036
}
9861037

1038+
unsafe fn finalize<T>(node: IntermediateBox<Node<T>>) -> Box<Node<T>> {
1039+
let mut node = node.finalize();
1040+
ptr::write(&mut node.next, None);
1041+
ptr::write(&mut node.prev, Rawlink::none());
1042+
node
1043+
}
1044+
1045+
/// A place for insertion at the front of a `LinkedList`.
1046+
///
1047+
/// See [`LinkedList::front_place`](struct.LinkedList.html#method.front_place) for details.
1048+
#[must_use = "places do nothing unless written to with `<-` syntax"]
1049+
#[unstable(feature = "collection_placement",
1050+
reason = "struct name and placement protocol are subject to change",
1051+
issue = "30172")]
1052+
pub struct FrontPlace<'a, T: 'a> {
1053+
list: &'a mut LinkedList<T>,
1054+
node: IntermediateBox<Node<T>>,
1055+
}
1056+
1057+
#[unstable(feature = "collection_placement",
1058+
reason = "placement protocol is subject to change",
1059+
issue = "30172")]
1060+
impl<'a, T> Placer<T> for FrontPlace<'a, T> {
1061+
type Place = Self;
1062+
1063+
fn make_place(self) -> Self {
1064+
self
1065+
}
1066+
}
1067+
1068+
#[unstable(feature = "collection_placement",
1069+
reason = "placement protocol is subject to change",
1070+
issue = "30172")]
1071+
impl<'a, T> Place<T> for FrontPlace<'a, T> {
1072+
fn pointer(&mut self) -> *mut T {
1073+
unsafe { &mut (*self.node.pointer()).value }
1074+
}
1075+
}
1076+
1077+
#[unstable(feature = "collection_placement",
1078+
reason = "placement protocol is subject to change",
1079+
issue = "30172")]
1080+
impl<'a, T> InPlace<T> for FrontPlace<'a, T> {
1081+
type Owner = ();
1082+
1083+
unsafe fn finalize(self) {
1084+
let FrontPlace { list, node } = self;
1085+
list.push_front_node(finalize(node));
1086+
}
1087+
}
1088+
1089+
/// A place for insertion at the back of a `LinkedList`.
1090+
///
1091+
/// See [`LinkedList::back_place`](struct.LinkedList.html#method.back_place) for details.
1092+
#[must_use = "places do nothing unless written to with `<-` syntax"]
1093+
#[unstable(feature = "collection_placement",
1094+
reason = "struct name and placement protocol are subject to change",
1095+
issue = "30172")]
1096+
pub struct BackPlace<'a, T: 'a> {
1097+
list: &'a mut LinkedList<T>,
1098+
node: IntermediateBox<Node<T>>,
1099+
}
1100+
1101+
#[unstable(feature = "collection_placement",
1102+
reason = "placement protocol is subject to change",
1103+
issue = "30172")]
1104+
impl<'a, T> Placer<T> for BackPlace<'a, T> {
1105+
type Place = Self;
1106+
1107+
fn make_place(self) -> Self {
1108+
self
1109+
}
1110+
}
1111+
1112+
#[unstable(feature = "collection_placement",
1113+
reason = "placement protocol is subject to change",
1114+
issue = "30172")]
1115+
impl<'a, T> Place<T> for BackPlace<'a, T> {
1116+
fn pointer(&mut self) -> *mut T {
1117+
unsafe { &mut (*self.node.pointer()).value }
1118+
}
1119+
}
1120+
1121+
#[unstable(feature = "collection_placement",
1122+
reason = "placement protocol is subject to change",
1123+
issue = "30172")]
1124+
impl<'a, T> InPlace<T> for BackPlace<'a, T> {
1125+
type Owner = ();
1126+
1127+
unsafe fn finalize(self) {
1128+
let BackPlace { list, node } = self;
1129+
list.push_back_node(finalize(node));
1130+
}
1131+
}
1132+
9871133
// Ensure that `LinkedList` and its read-only iterators are covariant in their type parameters.
9881134
#[allow(dead_code)]
9891135
fn assert_covariance() {

0 commit comments

Comments
 (0)