Skip to content

Commit

Permalink
Auto merge of #31696 - apasel422:placement, r=pnkfelix
Browse files Browse the repository at this point in the history
  • Loading branch information
bors committed Feb 17, 2016
2 parents f4046de + 895ab4f commit b54770c
Show file tree
Hide file tree
Showing 2 changed files with 150 additions and 2 deletions.
2 changes: 2 additions & 0 deletions src/libcollections/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@
#![feature(nonzero)]
#![feature(num_bits_bytes)]
#![feature(pattern)]
#![feature(placement_in)]
#![feature(placement_new_protocol)]
#![feature(shared)]
#![feature(slice_bytes)]
#![feature(slice_patterns)]
Expand Down
150 changes: 148 additions & 2 deletions src/libcollections/linked_list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,14 @@

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

use alloc::boxed::Box;
use alloc::boxed::{Box, IntermediateBox};
use core::cmp::Ordering;
use core::fmt;
use core::hash::{Hasher, Hash};
use core::iter::FromIterator;
use core::mem;
use core::ptr::Shared;
use core::ops::{BoxPlace, InPlace, Place, Placer};
use core::ptr::{self, Shared};

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

second_part
}

/// Returns a place for insertion at the front of the list.
///
/// Using this method with placement syntax is equivalent to [`push_front`]
/// (#method.push_front), but may be more efficient.
///
/// # Examples
///
/// ```
/// #![feature(collection_placement)]
/// #![feature(placement_in_syntax)]
///
/// use std::collections::LinkedList;
///
/// let mut list = LinkedList::new();
/// list.front_place() <- 2;
/// list.front_place() <- 4;
/// assert!(list.iter().eq(&[4, 2]));
/// ```
#[unstable(feature = "collection_placement",
reason = "method name and placement protocol are subject to change",
issue = "30172")]
pub fn front_place(&mut self) -> FrontPlace<T> {
FrontPlace { list: self, node: IntermediateBox::make_place() }
}

/// Returns a place for insertion at the back of the list.
///
/// Using this method with placement syntax is equivalent to [`push_back`](#method.push_back),
/// but may be more efficient.
///
/// # Examples
///
/// ```
/// #![feature(collection_placement)]
/// #![feature(placement_in_syntax)]
///
/// use std::collections::LinkedList;
///
/// let mut list = LinkedList::new();
/// list.back_place() <- 2;
/// list.back_place() <- 4;
/// assert!(list.iter().eq(&[2, 4]));
/// ```
#[unstable(feature = "collection_placement",
reason = "method name and placement protocol are subject to change",
issue = "30172")]
pub fn back_place(&mut self) -> BackPlace<T> {
BackPlace { list: self, node: IntermediateBox::make_place() }
}
}

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

unsafe fn finalize<T>(node: IntermediateBox<Node<T>>) -> Box<Node<T>> {
let mut node = node.finalize();
ptr::write(&mut node.next, None);
ptr::write(&mut node.prev, Rawlink::none());
node
}

/// A place for insertion at the front of a `LinkedList`.
///
/// See [`LinkedList::front_place`](struct.LinkedList.html#method.front_place) for details.
#[must_use = "places do nothing unless written to with `<-` syntax"]
#[unstable(feature = "collection_placement",
reason = "struct name and placement protocol are subject to change",
issue = "30172")]
pub struct FrontPlace<'a, T: 'a> {
list: &'a mut LinkedList<T>,
node: IntermediateBox<Node<T>>,
}

#[unstable(feature = "collection_placement",
reason = "placement protocol is subject to change",
issue = "30172")]
impl<'a, T> Placer<T> for FrontPlace<'a, T> {
type Place = Self;

fn make_place(self) -> Self {
self
}
}

#[unstable(feature = "collection_placement",
reason = "placement protocol is subject to change",
issue = "30172")]
impl<'a, T> Place<T> for FrontPlace<'a, T> {
fn pointer(&mut self) -> *mut T {
unsafe { &mut (*self.node.pointer()).value }
}
}

#[unstable(feature = "collection_placement",
reason = "placement protocol is subject to change",
issue = "30172")]
impl<'a, T> InPlace<T> for FrontPlace<'a, T> {
type Owner = ();

unsafe fn finalize(self) {
let FrontPlace { list, node } = self;
list.push_front_node(finalize(node));
}
}

/// A place for insertion at the back of a `LinkedList`.
///
/// See [`LinkedList::back_place`](struct.LinkedList.html#method.back_place) for details.
#[must_use = "places do nothing unless written to with `<-` syntax"]
#[unstable(feature = "collection_placement",
reason = "struct name and placement protocol are subject to change",
issue = "30172")]
pub struct BackPlace<'a, T: 'a> {
list: &'a mut LinkedList<T>,
node: IntermediateBox<Node<T>>,
}

#[unstable(feature = "collection_placement",
reason = "placement protocol is subject to change",
issue = "30172")]
impl<'a, T> Placer<T> for BackPlace<'a, T> {
type Place = Self;

fn make_place(self) -> Self {
self
}
}

#[unstable(feature = "collection_placement",
reason = "placement protocol is subject to change",
issue = "30172")]
impl<'a, T> Place<T> for BackPlace<'a, T> {
fn pointer(&mut self) -> *mut T {
unsafe { &mut (*self.node.pointer()).value }
}
}

#[unstable(feature = "collection_placement",
reason = "placement protocol is subject to change",
issue = "30172")]
impl<'a, T> InPlace<T> for BackPlace<'a, T> {
type Owner = ();

unsafe fn finalize(self) {
let BackPlace { list, node } = self;
list.push_back_node(finalize(node));
}
}

// Ensure that `LinkedList` and its read-only iterators are covariant in their type parameters.
#[allow(dead_code)]
fn assert_covariance() {
Expand Down

0 comments on commit b54770c

Please sign in to comment.