parent
5ee891cfea
commit
9b5859aea1
|
@ -1400,7 +1400,6 @@ nonblock_expr
|
|||
| BREAK lifetime { $$ = mk_node("ExprBreak", 1, $2); }
|
||||
| YIELD { $$ = mk_node("ExprYield", 0); }
|
||||
| YIELD expr { $$ = mk_node("ExprYield", 1, $2); }
|
||||
| nonblock_expr LARROW expr { $$ = mk_node("ExprInPlace", 2, $1, $3); }
|
||||
| nonblock_expr '=' expr { $$ = mk_node("ExprAssign", 2, $1, $3); }
|
||||
| nonblock_expr SHLEQ expr { $$ = mk_node("ExprAssignShl", 2, $1, $3); }
|
||||
| nonblock_expr SHREQ expr { $$ = mk_node("ExprAssignShr", 2, $1, $3); }
|
||||
|
@ -1463,7 +1462,6 @@ expr
|
|||
| BREAK ident { $$ = mk_node("ExprBreak", 1, $2); }
|
||||
| YIELD { $$ = mk_node("ExprYield", 0); }
|
||||
| YIELD expr { $$ = mk_node("ExprYield", 1, $2); }
|
||||
| expr LARROW expr { $$ = mk_node("ExprInPlace", 2, $1, $3); }
|
||||
| expr '=' expr { $$ = mk_node("ExprAssign", 2, $1, $3); }
|
||||
| expr SHLEQ expr { $$ = mk_node("ExprAssignShl", 2, $1, $3); }
|
||||
| expr SHREQ expr { $$ = mk_node("ExprAssignShr", 2, $1, $3); }
|
||||
|
@ -1527,7 +1525,6 @@ expr_nostruct
|
|||
| BREAK ident { $$ = mk_node("ExprBreak", 1, $2); }
|
||||
| YIELD { $$ = mk_node("ExprYield", 0); }
|
||||
| YIELD expr { $$ = mk_node("ExprYield", 1, $2); }
|
||||
| expr_nostruct LARROW expr_nostruct { $$ = mk_node("ExprInPlace", 2, $1, $3); }
|
||||
| expr_nostruct '=' expr_nostruct { $$ = mk_node("ExprAssign", 2, $1, $3); }
|
||||
| expr_nostruct SHLEQ expr_nostruct { $$ = mk_node("ExprAssignShl", 2, $1, $3); }
|
||||
| expr_nostruct SHREQ expr_nostruct { $$ = mk_node("ExprAssignShr", 2, $1, $3); }
|
||||
|
|
|
@ -155,7 +155,7 @@
|
|||
#![allow(missing_docs)]
|
||||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
|
||||
use core::ops::{Deref, DerefMut, Place, Placer, InPlace};
|
||||
use core::ops::{Deref, DerefMut};
|
||||
use core::iter::{FromIterator, FusedIterator};
|
||||
use core::mem::{swap, size_of};
|
||||
use core::ptr;
|
||||
|
@ -1195,67 +1195,3 @@ impl<'a, T: 'a + Ord + Copy> Extend<&'a T> for BinaryHeap<T> {
|
|||
self.extend(iter.into_iter().cloned());
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "collection_placement",
|
||||
reason = "placement protocol is subject to change",
|
||||
issue = "30172")]
|
||||
pub struct BinaryHeapPlace<'a, T: 'a>
|
||||
where T: Clone + Ord {
|
||||
heap: *mut BinaryHeap<T>,
|
||||
place: vec::PlaceBack<'a, T>,
|
||||
}
|
||||
|
||||
#[unstable(feature = "collection_placement",
|
||||
reason = "placement protocol is subject to change",
|
||||
issue = "30172")]
|
||||
impl<'a, T: Clone + Ord + fmt::Debug> fmt::Debug for BinaryHeapPlace<'a, T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.debug_tuple("BinaryHeapPlace")
|
||||
.field(&self.place)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "collection_placement",
|
||||
reason = "placement protocol is subject to change",
|
||||
issue = "30172")]
|
||||
impl<'a, T: 'a> Placer<T> for &'a mut BinaryHeap<T>
|
||||
where T: Clone + Ord {
|
||||
type Place = BinaryHeapPlace<'a, T>;
|
||||
|
||||
fn make_place(self) -> Self::Place {
|
||||
let ptr = self as *mut BinaryHeap<T>;
|
||||
let place = Placer::make_place(self.data.place_back());
|
||||
BinaryHeapPlace {
|
||||
heap: ptr,
|
||||
place,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "collection_placement",
|
||||
reason = "placement protocol is subject to change",
|
||||
issue = "30172")]
|
||||
unsafe impl<'a, T> Place<T> for BinaryHeapPlace<'a, T>
|
||||
where T: Clone + Ord {
|
||||
fn pointer(&mut self) -> *mut T {
|
||||
self.place.pointer()
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "collection_placement",
|
||||
reason = "placement protocol is subject to change",
|
||||
issue = "30172")]
|
||||
impl<'a, T> InPlace<T> for BinaryHeapPlace<'a, T>
|
||||
where T: Clone + Ord {
|
||||
type Owner = &'a T;
|
||||
|
||||
unsafe fn finalize(self) -> &'a T {
|
||||
self.place.finalize();
|
||||
|
||||
let heap: &mut BinaryHeap<T> = &mut *self.heap;
|
||||
let len = heap.len();
|
||||
let i = heap.sift_up(0, len - 1);
|
||||
heap.data.get_unchecked(i)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -55,7 +55,6 @@
|
|||
|
||||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
|
||||
use heap::Heap;
|
||||
use raw_vec::RawVec;
|
||||
|
||||
use core::any::Any;
|
||||
|
@ -63,47 +62,14 @@ use core::borrow;
|
|||
use core::cmp::Ordering;
|
||||
use core::fmt;
|
||||
use core::hash::{Hash, Hasher};
|
||||
use core::heap::{Alloc, Layout};
|
||||
use core::iter::FusedIterator;
|
||||
use core::marker::{self, Unpin, Unsize};
|
||||
use core::marker::{Unpin, Unsize};
|
||||
use core::mem::{self, Pin};
|
||||
use core::ops::{CoerceUnsized, Deref, DerefMut, Generator, GeneratorState};
|
||||
use core::ops::{BoxPlace, Boxed, InPlace, Place, Placer};
|
||||
use core::ptr::{self, NonNull, Unique};
|
||||
use core::convert::From;
|
||||
use str::from_boxed_utf8_unchecked;
|
||||
|
||||
/// A value that represents the heap. This is the default place that the `box`
|
||||
/// keyword allocates into when no place is supplied.
|
||||
///
|
||||
/// The following two examples are equivalent:
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(box_heap)]
|
||||
///
|
||||
/// #![feature(box_syntax, placement_in_syntax)]
|
||||
/// use std::boxed::HEAP;
|
||||
///
|
||||
/// fn main() {
|
||||
/// let foo: Box<i32> = in HEAP { 5 };
|
||||
/// let foo = box 5;
|
||||
/// }
|
||||
/// ```
|
||||
#[unstable(feature = "box_heap",
|
||||
reason = "may be renamed; uncertain about custom allocator design",
|
||||
issue = "27779")]
|
||||
pub const HEAP: ExchangeHeapSingleton = ExchangeHeapSingleton { _force_singleton: () };
|
||||
|
||||
/// This the singleton type used solely for `boxed::HEAP`.
|
||||
#[unstable(feature = "box_heap",
|
||||
reason = "may be renamed; uncertain about custom allocator design",
|
||||
issue = "27779")]
|
||||
#[allow(missing_debug_implementations)]
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct ExchangeHeapSingleton {
|
||||
_force_singleton: (),
|
||||
}
|
||||
|
||||
/// A pointer type for heap allocation.
|
||||
///
|
||||
/// See the [module-level documentation](../../std/boxed/index.html) for more.
|
||||
|
@ -112,121 +78,6 @@ pub struct ExchangeHeapSingleton {
|
|||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct Box<T: ?Sized>(Unique<T>);
|
||||
|
||||
/// `IntermediateBox` represents uninitialized backing storage for `Box`.
|
||||
///
|
||||
/// FIXME (pnkfelix): Ideally we would just reuse `Box<T>` instead of
|
||||
/// introducing a separate `IntermediateBox<T>`; but then you hit
|
||||
/// issues when you e.g. attempt to destructure an instance of `Box`,
|
||||
/// since it is a lang item and so it gets special handling by the
|
||||
/// compiler. Easier just to make this parallel type for now.
|
||||
///
|
||||
/// FIXME (pnkfelix): Currently the `box` protocol only supports
|
||||
/// creating instances of sized types. This IntermediateBox is
|
||||
/// designed to be forward-compatible with a future protocol that
|
||||
/// supports creating instances of unsized types; that is why the type
|
||||
/// parameter has the `?Sized` generalization marker, and is also why
|
||||
/// this carries an explicit size. However, it probably does not need
|
||||
/// to carry the explicit alignment; that is just a work-around for
|
||||
/// the fact that the `align_of` intrinsic currently requires the
|
||||
/// input type to be Sized (which I do not think is strictly
|
||||
/// necessary).
|
||||
#[unstable(feature = "placement_in",
|
||||
reason = "placement box design is still being worked out.",
|
||||
issue = "27779")]
|
||||
#[allow(missing_debug_implementations)]
|
||||
pub struct IntermediateBox<T: ?Sized> {
|
||||
ptr: *mut u8,
|
||||
layout: Layout,
|
||||
marker: marker::PhantomData<*mut T>,
|
||||
}
|
||||
|
||||
#[unstable(feature = "placement_in",
|
||||
reason = "placement box design is still being worked out.",
|
||||
issue = "27779")]
|
||||
unsafe impl<T> Place<T> for IntermediateBox<T> {
|
||||
fn pointer(&mut self) -> *mut T {
|
||||
self.ptr as *mut T
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn finalize<T>(b: IntermediateBox<T>) -> Box<T> {
|
||||
let p = b.ptr as *mut T;
|
||||
mem::forget(b);
|
||||
Box::from_raw(p)
|
||||
}
|
||||
|
||||
fn make_place<T>() -> IntermediateBox<T> {
|
||||
let layout = Layout::new::<T>();
|
||||
|
||||
let p = if layout.size() == 0 {
|
||||
mem::align_of::<T>() as *mut u8
|
||||
} else {
|
||||
unsafe {
|
||||
Heap.alloc(layout.clone()).unwrap_or_else(|err| {
|
||||
Heap.oom(err)
|
||||
})
|
||||
}
|
||||
};
|
||||
|
||||
IntermediateBox {
|
||||
ptr: p,
|
||||
layout,
|
||||
marker: marker::PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "placement_in",
|
||||
reason = "placement box design is still being worked out.",
|
||||
issue = "27779")]
|
||||
impl<T> BoxPlace<T> for IntermediateBox<T> {
|
||||
fn make_place() -> IntermediateBox<T> {
|
||||
make_place()
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "placement_in",
|
||||
reason = "placement box design is still being worked out.",
|
||||
issue = "27779")]
|
||||
impl<T> InPlace<T> for IntermediateBox<T> {
|
||||
type Owner = Box<T>;
|
||||
unsafe fn finalize(self) -> Box<T> {
|
||||
finalize(self)
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "placement_new_protocol", issue = "27779")]
|
||||
impl<T> Boxed for Box<T> {
|
||||
type Data = T;
|
||||
type Place = IntermediateBox<T>;
|
||||
unsafe fn finalize(b: IntermediateBox<T>) -> Box<T> {
|
||||
finalize(b)
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "placement_in",
|
||||
reason = "placement box design is still being worked out.",
|
||||
issue = "27779")]
|
||||
impl<T> Placer<T> for ExchangeHeapSingleton {
|
||||
type Place = IntermediateBox<T>;
|
||||
|
||||
fn make_place(self) -> IntermediateBox<T> {
|
||||
make_place()
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "placement_in",
|
||||
reason = "placement box design is still being worked out.",
|
||||
issue = "27779")]
|
||||
impl<T: ?Sized> Drop for IntermediateBox<T> {
|
||||
fn drop(&mut self) {
|
||||
if self.layout.size() > 0 {
|
||||
unsafe {
|
||||
Heap.dealloc(self.ptr, self.layout.clone())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Box<T> {
|
||||
/// Allocates memory on the heap and then places `x` into it.
|
||||
///
|
||||
|
|
|
@ -76,7 +76,6 @@
|
|||
#![deny(missing_debug_implementations)]
|
||||
|
||||
#![cfg_attr(test, allow(deprecated))] // rand
|
||||
#![cfg_attr(test, feature(placement_in))]
|
||||
#![cfg_attr(not(test), feature(core_float))]
|
||||
#![cfg_attr(not(test), feature(exact_size_is_empty))]
|
||||
#![cfg_attr(not(test), feature(generator_trait))]
|
||||
|
@ -108,8 +107,6 @@
|
|||
#![feature(optin_builtin_traits)]
|
||||
#![feature(pattern)]
|
||||
#![feature(pin)]
|
||||
#![feature(placement_in_syntax)]
|
||||
#![feature(placement_new_protocol)]
|
||||
#![feature(ptr_internals)]
|
||||
#![feature(rustc_attrs)]
|
||||
#![feature(slice_get_slice)]
|
||||
|
@ -128,8 +125,8 @@
|
|||
#![feature(pointer_methods)]
|
||||
#![feature(inclusive_range_fields)]
|
||||
|
||||
#![cfg_attr(not(test), feature(fn_traits, placement_new_protocol, swap_with_slice, i128))]
|
||||
#![cfg_attr(test, feature(test, box_heap))]
|
||||
#![cfg_attr(not(test), feature(fn_traits, swap_with_slice, i128))]
|
||||
#![cfg_attr(test, feature(test))]
|
||||
|
||||
// Allow testing this library
|
||||
|
||||
|
@ -159,13 +156,12 @@ pub mod heap;
|
|||
|
||||
// Need to conditionally define the mod from `boxed.rs` to avoid
|
||||
// duplicating the lang-items when building in test cfg; but also need
|
||||
// to allow code to have `use boxed::HEAP;`
|
||||
// and `use boxed::Box;` declarations.
|
||||
// to allow code to have `use boxed::Box;` declarations.
|
||||
#[cfg(not(test))]
|
||||
pub mod boxed;
|
||||
#[cfg(test)]
|
||||
mod boxed {
|
||||
pub use std::boxed::{Box, IntermediateBox, HEAP};
|
||||
pub use std::boxed::Box;
|
||||
}
|
||||
#[cfg(test)]
|
||||
mod boxed_test;
|
||||
|
|
|
@ -28,10 +28,9 @@ use core::hash::{Hasher, Hash};
|
|||
use core::iter::{FromIterator, FusedIterator};
|
||||
use core::marker::PhantomData;
|
||||
use core::mem;
|
||||
use core::ops::{BoxPlace, InPlace, Place, Placer};
|
||||
use core::ptr::{self, NonNull};
|
||||
use core::ptr::NonNull;
|
||||
|
||||
use boxed::{Box, IntermediateBox};
|
||||
use boxed::Box;
|
||||
use super::SpecExtend;
|
||||
|
||||
/// A doubly-linked list with owned nodes.
|
||||
|
@ -786,62 +785,6 @@ impl<T> LinkedList<T> {
|
|||
old_len: old_len,
|
||||
}
|
||||
}
|
||||
|
||||
/// 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")]
|
||||
|
@ -1242,123 +1185,6 @@ impl<T: Hash> Hash for LinkedList<T> {
|
|||
}
|
||||
}
|
||||
|
||||
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, 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 = "struct name and placement protocol are subject to change",
|
||||
issue = "30172")]
|
||||
impl<'a, T: 'a + fmt::Debug> fmt::Debug for FrontPlace<'a, T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.debug_tuple("FrontPlace")
|
||||
.field(&self.list)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
#[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")]
|
||||
unsafe impl<'a, T> Place<T> for FrontPlace<'a, T> {
|
||||
fn pointer(&mut self) -> *mut T {
|
||||
unsafe { &mut (*self.node.pointer()).element }
|
||||
}
|
||||
}
|
||||
|
||||
#[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 = "struct name and placement protocol are subject to change",
|
||||
issue = "30172")]
|
||||
impl<'a, T: 'a + fmt::Debug> fmt::Debug for BackPlace<'a, T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.debug_tuple("BackPlace")
|
||||
.field(&self.list)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
#[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")]
|
||||
unsafe impl<'a, T> Place<T> for BackPlace<'a, T> {
|
||||
fn pointer(&mut self) -> *mut T {
|
||||
unsafe { &mut (*self.node.pointer()).element }
|
||||
}
|
||||
}
|
||||
|
||||
#[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() {
|
||||
|
|
|
@ -278,26 +278,6 @@ fn test_extend_specialization() {
|
|||
assert_eq!(a.into_sorted_vec(), [-20, -10, 1, 2, 3, 3, 5, 43]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_placement() {
|
||||
let mut a = BinaryHeap::new();
|
||||
&mut a <- 2;
|
||||
&mut a <- 4;
|
||||
&mut a <- 3;
|
||||
assert_eq!(a.peek(), Some(&4));
|
||||
assert_eq!(a.len(), 3);
|
||||
&mut a <- 1;
|
||||
assert_eq!(a.into_sorted_vec(), vec![1, 2, 3, 4]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_placement_panic() {
|
||||
let mut heap = BinaryHeap::from(vec![1, 2, 3]);
|
||||
fn mkpanic() -> usize { panic!() }
|
||||
let _ = panic::catch_unwind(panic::AssertUnwindSafe(|| { &mut heap <- mkpanic(); }));
|
||||
assert_eq!(heap.len(), 3);
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
fn assert_covariance() {
|
||||
fn drain<'new>(d: Drain<'static, &'static str>) -> Drain<'new, &'new str> {
|
||||
|
|
|
@ -15,13 +15,11 @@
|
|||
#![feature(attr_literals)]
|
||||
#![feature(box_syntax)]
|
||||
#![cfg_attr(stage0, feature(inclusive_range_syntax))]
|
||||
#![feature(collection_placement)]
|
||||
#![feature(const_fn)]
|
||||
#![feature(drain_filter)]
|
||||
#![feature(exact_size_is_empty)]
|
||||
#![feature(iterator_step_by)]
|
||||
#![feature(pattern)]
|
||||
#![feature(placement_in_syntax)]
|
||||
#![feature(rand)]
|
||||
#![feature(slice_sort_by_cached_key)]
|
||||
#![feature(splice)]
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
use std::borrow::Cow;
|
||||
use std::mem::size_of;
|
||||
use std::{usize, isize, panic};
|
||||
use std::{usize, isize};
|
||||
use std::vec::{Drain, IntoIter};
|
||||
use std::collections::CollectionAllocErr::*;
|
||||
|
||||
|
@ -753,24 +753,6 @@ fn assert_covariance() {
|
|||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_placement() {
|
||||
let mut vec = vec![1];
|
||||
assert_eq!(vec.place_back() <- 2, &2);
|
||||
assert_eq!(vec.len(), 2);
|
||||
assert_eq!(vec.place_back() <- 3, &3);
|
||||
assert_eq!(vec.len(), 3);
|
||||
assert_eq!(&vec, &[1, 2, 3]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_placement_panic() {
|
||||
let mut vec = vec![1, 2, 3];
|
||||
fn mkpanic() -> usize { panic!() }
|
||||
let _ = panic::catch_unwind(panic::AssertUnwindSafe(|| { vec.place_back() <- mkpanic(); }));
|
||||
assert_eq!(vec.len(), 3);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_into_inner() {
|
||||
let vec = vec![1, 2, 3];
|
||||
|
|
|
@ -1004,28 +1004,6 @@ fn test_is_empty() {
|
|||
assert!(v.into_iter().is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_placement_in() {
|
||||
let mut buf: VecDeque<isize> = VecDeque::new();
|
||||
buf.place_back() <- 1;
|
||||
buf.place_back() <- 2;
|
||||
assert_eq!(buf, [1,2]);
|
||||
|
||||
buf.place_front() <- 3;
|
||||
buf.place_front() <- 4;
|
||||
assert_eq!(buf, [4,3,1,2]);
|
||||
|
||||
{
|
||||
let ptr_head = buf.place_front() <- 5;
|
||||
assert_eq!(*ptr_head, 5);
|
||||
}
|
||||
{
|
||||
let ptr_tail = buf.place_back() <- 6;
|
||||
assert_eq!(*ptr_tail, 6);
|
||||
}
|
||||
assert_eq!(buf, [5,4,3,1,2,6]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_reserve_exact_2() {
|
||||
// This is all the same as test_reserve
|
||||
|
|
|
@ -76,7 +76,7 @@ use core::mem;
|
|||
#[cfg(not(test))]
|
||||
use core::num::Float;
|
||||
use core::ops::Bound::{Excluded, Included, Unbounded};
|
||||
use core::ops::{InPlace, Index, IndexMut, Place, Placer, RangeBounds};
|
||||
use core::ops::{Index, IndexMut, RangeBounds};
|
||||
use core::ops;
|
||||
use core::ptr;
|
||||
use core::ptr::NonNull;
|
||||
|
@ -1065,29 +1065,6 @@ impl<T> Vec<T> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Returns a place for insertion at the back of the `Vec`.
|
||||
///
|
||||
/// Using this method with placement syntax is equivalent to [`push`](#method.push),
|
||||
/// but may be more efficient.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(collection_placement)]
|
||||
/// #![feature(placement_in_syntax)]
|
||||
///
|
||||
/// let mut vec = vec![1, 2];
|
||||
/// vec.place_back() <- 3;
|
||||
/// vec.place_back() <- 4;
|
||||
/// assert_eq!(&vec, &[1, 2, 3, 4]);
|
||||
/// ```
|
||||
#[unstable(feature = "collection_placement",
|
||||
reason = "placement protocol is subject to change",
|
||||
issue = "30172")]
|
||||
pub fn place_back(&mut self) -> PlaceBack<T> {
|
||||
PlaceBack { vec: self }
|
||||
}
|
||||
|
||||
/// Removes the last element from a vector and returns it, or [`None`] if it
|
||||
/// is empty.
|
||||
///
|
||||
|
@ -2492,57 +2469,6 @@ impl<'a, T> ExactSizeIterator for Drain<'a, T> {
|
|||
#[stable(feature = "fused", since = "1.26.0")]
|
||||
impl<'a, T> FusedIterator for Drain<'a, T> {}
|
||||
|
||||
/// A place for insertion at the back of a `Vec`.
|
||||
///
|
||||
/// See [`Vec::place_back`](struct.Vec.html#method.place_back) 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")]
|
||||
#[derive(Debug)]
|
||||
pub struct PlaceBack<'a, T: 'a> {
|
||||
vec: &'a mut Vec<T>,
|
||||
}
|
||||
|
||||
#[unstable(feature = "collection_placement",
|
||||
reason = "placement protocol is subject to change",
|
||||
issue = "30172")]
|
||||
impl<'a, T> Placer<T> for PlaceBack<'a, T> {
|
||||
type Place = PlaceBack<'a, T>;
|
||||
|
||||
fn make_place(self) -> Self {
|
||||
// This will panic or abort if we would allocate > isize::MAX bytes
|
||||
// or if the length increment would overflow for zero-sized types.
|
||||
if self.vec.len == self.vec.buf.cap() {
|
||||
self.vec.buf.double();
|
||||
}
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "collection_placement",
|
||||
reason = "placement protocol is subject to change",
|
||||
issue = "30172")]
|
||||
unsafe impl<'a, T> Place<T> for PlaceBack<'a, T> {
|
||||
fn pointer(&mut self) -> *mut T {
|
||||
unsafe { self.vec.as_mut_ptr().offset(self.vec.len as isize) }
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "collection_placement",
|
||||
reason = "placement protocol is subject to change",
|
||||
issue = "30172")]
|
||||
impl<'a, T> InPlace<T> for PlaceBack<'a, T> {
|
||||
type Owner = &'a mut T;
|
||||
|
||||
unsafe fn finalize(mut self) -> &'a mut T {
|
||||
let ptr = self.pointer();
|
||||
self.vec.len += 1;
|
||||
&mut *ptr
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// A splicing iterator for `Vec`.
|
||||
///
|
||||
/// This struct is created by the [`splice()`] method on [`Vec`]. See its
|
||||
|
|
|
@ -22,7 +22,7 @@ use core::fmt;
|
|||
use core::iter::{repeat, FromIterator, FusedIterator};
|
||||
use core::mem;
|
||||
use core::ops::Bound::{Excluded, Included, Unbounded};
|
||||
use core::ops::{Index, IndexMut, Place, Placer, InPlace, RangeBounds};
|
||||
use core::ops::{Index, IndexMut, RangeBounds};
|
||||
use core::ptr;
|
||||
use core::ptr::NonNull;
|
||||
use core::slice;
|
||||
|
@ -1885,56 +1885,6 @@ impl<T> VecDeque<T> {
|
|||
debug_assert!(!self.is_full());
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a place for insertion at the back of the `VecDeque`.
|
||||
///
|
||||
/// 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::VecDeque;
|
||||
///
|
||||
/// let mut buf = VecDeque::new();
|
||||
/// buf.place_back() <- 3;
|
||||
/// buf.place_back() <- 4;
|
||||
/// assert_eq!(&buf, &[3, 4]);
|
||||
/// ```
|
||||
#[unstable(feature = "collection_placement",
|
||||
reason = "placement protocol is subject to change",
|
||||
issue = "30172")]
|
||||
pub fn place_back(&mut self) -> PlaceBack<T> {
|
||||
PlaceBack { vec_deque: self }
|
||||
}
|
||||
|
||||
/// Returns a place for insertion at the front of the `VecDeque`.
|
||||
///
|
||||
/// 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::VecDeque;
|
||||
///
|
||||
/// let mut buf = VecDeque::new();
|
||||
/// buf.place_front() <- 3;
|
||||
/// buf.place_front() <- 4;
|
||||
/// assert_eq!(&buf, &[4, 3]);
|
||||
/// ```
|
||||
#[unstable(feature = "collection_placement",
|
||||
reason = "placement protocol is subject to change",
|
||||
issue = "30172")]
|
||||
pub fn place_front(&mut self) -> PlaceFront<T> {
|
||||
PlaceFront { vec_deque: self }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Clone> VecDeque<T> {
|
||||
|
@ -2662,98 +2612,6 @@ impl<T> From<VecDeque<T>> for Vec<T> {
|
|||
}
|
||||
}
|
||||
|
||||
/// A place for insertion at the back of a `VecDeque`.
|
||||
///
|
||||
/// See [`VecDeque::place_back`](struct.VecDeque.html#method.place_back) 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")]
|
||||
#[derive(Debug)]
|
||||
pub struct PlaceBack<'a, T: 'a> {
|
||||
vec_deque: &'a mut VecDeque<T>,
|
||||
}
|
||||
|
||||
#[unstable(feature = "collection_placement",
|
||||
reason = "placement protocol is subject to change",
|
||||
issue = "30172")]
|
||||
impl<'a, T> Placer<T> for PlaceBack<'a, T> {
|
||||
type Place = PlaceBack<'a, T>;
|
||||
|
||||
fn make_place(self) -> Self {
|
||||
self.vec_deque.grow_if_necessary();
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "collection_placement",
|
||||
reason = "placement protocol is subject to change",
|
||||
issue = "30172")]
|
||||
unsafe impl<'a, T> Place<T> for PlaceBack<'a, T> {
|
||||
fn pointer(&mut self) -> *mut T {
|
||||
unsafe { self.vec_deque.ptr().offset(self.vec_deque.head as isize) }
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "collection_placement",
|
||||
reason = "placement protocol is subject to change",
|
||||
issue = "30172")]
|
||||
impl<'a, T> InPlace<T> for PlaceBack<'a, T> {
|
||||
type Owner = &'a mut T;
|
||||
|
||||
unsafe fn finalize(self) -> &'a mut T {
|
||||
let head = self.vec_deque.head;
|
||||
self.vec_deque.head = self.vec_deque.wrap_add(head, 1);
|
||||
&mut *(self.vec_deque.ptr().offset(head as isize))
|
||||
}
|
||||
}
|
||||
|
||||
/// A place for insertion at the front of a `VecDeque`.
|
||||
///
|
||||
/// See [`VecDeque::place_front`](struct.VecDeque.html#method.place_front) 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")]
|
||||
#[derive(Debug)]
|
||||
pub struct PlaceFront<'a, T: 'a> {
|
||||
vec_deque: &'a mut VecDeque<T>,
|
||||
}
|
||||
|
||||
#[unstable(feature = "collection_placement",
|
||||
reason = "placement protocol is subject to change",
|
||||
issue = "30172")]
|
||||
impl<'a, T> Placer<T> for PlaceFront<'a, T> {
|
||||
type Place = PlaceFront<'a, T>;
|
||||
|
||||
fn make_place(self) -> Self {
|
||||
self.vec_deque.grow_if_necessary();
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "collection_placement",
|
||||
reason = "placement protocol is subject to change",
|
||||
issue = "30172")]
|
||||
unsafe impl<'a, T> Place<T> for PlaceFront<'a, T> {
|
||||
fn pointer(&mut self) -> *mut T {
|
||||
let tail = self.vec_deque.wrap_sub(self.vec_deque.tail, 1);
|
||||
unsafe { self.vec_deque.ptr().offset(tail as isize) }
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "collection_placement",
|
||||
reason = "placement protocol is subject to change",
|
||||
issue = "30172")]
|
||||
impl<'a, T> InPlace<T> for PlaceFront<'a, T> {
|
||||
type Owner = &'a mut T;
|
||||
|
||||
unsafe fn finalize(self) -> &'a mut T {
|
||||
self.vec_deque.tail = self.vec_deque.wrap_sub(self.vec_deque.tail, 1);
|
||||
&mut *(self.vec_deque.ptr().offset(self.vec_deque.tail as isize))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use test;
|
||||
|
|
|
@ -161,7 +161,6 @@ mod drop;
|
|||
mod function;
|
||||
mod generator;
|
||||
mod index;
|
||||
mod place;
|
||||
mod range;
|
||||
mod try;
|
||||
mod unsize;
|
||||
|
@ -200,8 +199,5 @@ pub use self::try::Try;
|
|||
#[unstable(feature = "generator_trait", issue = "43122")]
|
||||
pub use self::generator::{Generator, GeneratorState};
|
||||
|
||||
#[unstable(feature = "placement_new_protocol", issue = "27779")]
|
||||
pub use self::place::{Place, Placer, InPlace, Boxed, BoxPlace};
|
||||
|
||||
#[unstable(feature = "coerce_unsized", issue = "27732")]
|
||||
pub use self::unsize::CoerceUnsized;
|
||||
|
|
|
@ -1,143 +0,0 @@
|
|||
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
/// Both `PLACE <- EXPR` and `box EXPR` desugar into expressions
|
||||
/// that allocate an intermediate "place" that holds uninitialized
|
||||
/// state. The desugaring evaluates EXPR, and writes the result at
|
||||
/// the address returned by the `pointer` method of this trait.
|
||||
///
|
||||
/// A `Place` can be thought of as a special representation for a
|
||||
/// hypothetical `&uninit` reference (which Rust cannot currently
|
||||
/// express directly). That is, it represents a pointer to
|
||||
/// uninitialized storage.
|
||||
///
|
||||
/// The client is responsible for two steps: First, initializing the
|
||||
/// payload (it can access its address via `pointer`). Second,
|
||||
/// converting the agent to an instance of the owning pointer, via the
|
||||
/// appropriate `finalize` method (see the `InPlace`.
|
||||
///
|
||||
/// If evaluating EXPR fails, then it is up to the destructor for the
|
||||
/// implementation of Place to clean up any intermediate state
|
||||
/// (e.g. deallocate box storage, pop a stack, etc).
|
||||
#[unstable(feature = "placement_new_protocol", issue = "27779")]
|
||||
pub unsafe trait Place<Data: ?Sized> {
|
||||
/// Returns the address where the input value will be written.
|
||||
/// Note that the data at this address is generally uninitialized,
|
||||
/// and thus one should use `ptr::write` for initializing it.
|
||||
///
|
||||
/// This function must return a pointer through which a value
|
||||
/// of type `Data` can be written.
|
||||
fn pointer(&mut self) -> *mut Data;
|
||||
}
|
||||
|
||||
/// Interface to implementations of `PLACE <- EXPR`.
|
||||
///
|
||||
/// `PLACE <- EXPR` effectively desugars into:
|
||||
///
|
||||
/// ```
|
||||
/// # #![feature(placement_new_protocol, box_heap)]
|
||||
/// # use std::ops::{Placer, Place, InPlace};
|
||||
/// # #[allow(non_snake_case)]
|
||||
/// # fn main() {
|
||||
/// # let PLACE = std::boxed::HEAP;
|
||||
/// # let EXPR = 1;
|
||||
/// let p = PLACE;
|
||||
/// let mut place = Placer::make_place(p);
|
||||
/// let raw_place = Place::pointer(&mut place);
|
||||
/// let value = EXPR;
|
||||
/// unsafe {
|
||||
/// std::ptr::write(raw_place, value);
|
||||
/// InPlace::finalize(place)
|
||||
/// }
|
||||
/// # ; }
|
||||
/// ```
|
||||
///
|
||||
/// The type of `PLACE <- EXPR` is derived from the type of `PLACE`;
|
||||
/// if the type of `PLACE` is `P`, then the final type of the whole
|
||||
/// expression is `P::Place::Owner` (see the `InPlace` and `Boxed`
|
||||
/// traits).
|
||||
///
|
||||
/// Values for types implementing this trait usually are transient
|
||||
/// intermediate values (e.g. the return value of `Vec::emplace_back`)
|
||||
/// or `Copy`, since the `make_place` method takes `self` by value.
|
||||
#[unstable(feature = "placement_new_protocol", issue = "27779")]
|
||||
pub trait Placer<Data: ?Sized> {
|
||||
/// `Place` is the intermediate agent guarding the
|
||||
/// uninitialized state for `Data`.
|
||||
type Place: InPlace<Data>;
|
||||
|
||||
/// Creates a fresh place from `self`.
|
||||
fn make_place(self) -> Self::Place;
|
||||
}
|
||||
|
||||
/// Specialization of `Place` trait supporting `PLACE <- EXPR`.
|
||||
#[unstable(feature = "placement_new_protocol", issue = "27779")]
|
||||
pub trait InPlace<Data: ?Sized>: Place<Data> {
|
||||
/// `Owner` is the type of the end value of `PLACE <- EXPR`
|
||||
///
|
||||
/// Note that when `PLACE <- EXPR` is solely used for
|
||||
/// side-effecting an existing data-structure,
|
||||
/// e.g. `Vec::emplace_back`, then `Owner` need not carry any
|
||||
/// information at all (e.g. it can be the unit type `()` in that
|
||||
/// case).
|
||||
type Owner;
|
||||
|
||||
/// Converts self into the final value, shifting
|
||||
/// deallocation/cleanup responsibilities (if any remain), over to
|
||||
/// the returned instance of `Owner` and forgetting self.
|
||||
unsafe fn finalize(self) -> Self::Owner;
|
||||
}
|
||||
|
||||
/// Core trait for the `box EXPR` form.
|
||||
///
|
||||
/// `box EXPR` effectively desugars into:
|
||||
///
|
||||
/// ```
|
||||
/// # #![feature(placement_new_protocol)]
|
||||
/// # use std::ops::{BoxPlace, Place, Boxed};
|
||||
/// # #[allow(non_snake_case)]
|
||||
/// # fn main() {
|
||||
/// # let EXPR = 1;
|
||||
/// let mut place = BoxPlace::make_place();
|
||||
/// let raw_place = Place::pointer(&mut place);
|
||||
/// let value = EXPR;
|
||||
/// # let _: Box<_> =
|
||||
/// unsafe {
|
||||
/// ::std::ptr::write(raw_place, value);
|
||||
/// Boxed::finalize(place)
|
||||
/// }
|
||||
/// # ; }
|
||||
/// ```
|
||||
///
|
||||
/// The type of `box EXPR` is supplied from its surrounding
|
||||
/// context; in the above expansion, the result type `T` is used
|
||||
/// to determine which implementation of `Boxed` to use, and that
|
||||
/// `<T as Boxed>` in turn dictates determines which
|
||||
/// implementation of `BoxPlace` to use, namely:
|
||||
/// `<<T as Boxed>::Place as BoxPlace>`.
|
||||
#[unstable(feature = "placement_new_protocol", issue = "27779")]
|
||||
pub trait Boxed {
|
||||
/// The kind of data that is stored in this kind of box.
|
||||
type Data; /* (`Data` unused b/c cannot yet express below bound.) */
|
||||
/// The place that will negotiate the storage of the data.
|
||||
type Place: BoxPlace<Self::Data>;
|
||||
|
||||
/// Converts filled place into final owning value, shifting
|
||||
/// deallocation/cleanup responsibilities (if any remain), over to
|
||||
/// returned instance of `Self` and forgetting `filled`.
|
||||
unsafe fn finalize(filled: Self::Place) -> Self;
|
||||
}
|
||||
|
||||
/// Specialization of `Place` trait supporting `box EXPR`.
|
||||
#[unstable(feature = "placement_new_protocol", issue = "27779")]
|
||||
pub trait BoxPlace<Data: ?Sized> : Place<Data> {
|
||||
/// Creates a globally fresh place.
|
||||
fn make_place() -> Self;
|
||||
}
|
|
@ -2911,118 +2911,8 @@ impl<'a> LoweringContext<'a> {
|
|||
|
||||
fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
|
||||
let kind = match e.node {
|
||||
// Issue #22181:
|
||||
// Eventually a desugaring for `box EXPR`
|
||||
// (similar to the desugaring above for `in PLACE BLOCK`)
|
||||
// should go here, desugaring
|
||||
//
|
||||
// to:
|
||||
//
|
||||
// let mut place = BoxPlace::make_place();
|
||||
// let raw_place = Place::pointer(&mut place);
|
||||
// let value = $value;
|
||||
// unsafe {
|
||||
// ::std::ptr::write(raw_place, value);
|
||||
// Boxed::finalize(place)
|
||||
// }
|
||||
//
|
||||
// But for now there are type-inference issues doing that.
|
||||
ExprKind::Box(ref inner) => hir::ExprBox(P(self.lower_expr(inner))),
|
||||
|
||||
// Desugar ExprBox: `in (PLACE) EXPR`
|
||||
ExprKind::InPlace(ref placer, ref value_expr) => {
|
||||
// to:
|
||||
//
|
||||
// let p = PLACE;
|
||||
// let mut place = Placer::make_place(p);
|
||||
// let raw_place = Place::pointer(&mut place);
|
||||
// push_unsafe!({
|
||||
// std::intrinsics::move_val_init(raw_place, pop_unsafe!( EXPR ));
|
||||
// InPlace::finalize(place)
|
||||
// })
|
||||
let placer_expr = P(self.lower_expr(placer));
|
||||
let value_expr = P(self.lower_expr(value_expr));
|
||||
|
||||
let placer_ident = self.str_to_ident("placer");
|
||||
let place_ident = self.str_to_ident("place");
|
||||
let p_ptr_ident = self.str_to_ident("p_ptr");
|
||||
|
||||
let make_place = ["ops", "Placer", "make_place"];
|
||||
let place_pointer = ["ops", "Place", "pointer"];
|
||||
let move_val_init = ["intrinsics", "move_val_init"];
|
||||
let inplace_finalize = ["ops", "InPlace", "finalize"];
|
||||
|
||||
let unstable_span =
|
||||
self.allow_internal_unstable(CompilerDesugaringKind::BackArrow, e.span);
|
||||
let make_call = |this: &mut LoweringContext, p, args| {
|
||||
let path = P(this.expr_std_path(unstable_span, p, ThinVec::new()));
|
||||
P(this.expr_call(e.span, path, args))
|
||||
};
|
||||
|
||||
let mk_stmt_let = |this: &mut LoweringContext, bind, expr| {
|
||||
this.stmt_let(e.span, false, bind, expr)
|
||||
};
|
||||
|
||||
let mk_stmt_let_mut = |this: &mut LoweringContext, bind, expr| {
|
||||
this.stmt_let(e.span, true, bind, expr)
|
||||
};
|
||||
|
||||
// let placer = <placer_expr> ;
|
||||
let (s1, placer_binding) = { mk_stmt_let(self, placer_ident, placer_expr) };
|
||||
|
||||
// let mut place = Placer::make_place(placer);
|
||||
let (s2, place_binding) = {
|
||||
let placer = self.expr_ident(e.span, placer_ident, placer_binding);
|
||||
let call = make_call(self, &make_place, hir_vec![placer]);
|
||||
mk_stmt_let_mut(self, place_ident, call)
|
||||
};
|
||||
|
||||
// let p_ptr = Place::pointer(&mut place);
|
||||
let (s3, p_ptr_binding) = {
|
||||
let agent = P(self.expr_ident(e.span, place_ident, place_binding));
|
||||
let args = hir_vec![self.expr_mut_addr_of(e.span, agent)];
|
||||
let call = make_call(self, &place_pointer, args);
|
||||
mk_stmt_let(self, p_ptr_ident, call)
|
||||
};
|
||||
|
||||
// pop_unsafe!(EXPR));
|
||||
let pop_unsafe_expr = {
|
||||
self.signal_block_expr(
|
||||
hir_vec![],
|
||||
value_expr,
|
||||
e.span,
|
||||
hir::PopUnsafeBlock(hir::CompilerGenerated),
|
||||
ThinVec::new(),
|
||||
)
|
||||
};
|
||||
|
||||
// push_unsafe!({
|
||||
// std::intrinsics::move_val_init(raw_place, pop_unsafe!( EXPR ));
|
||||
// InPlace::finalize(place)
|
||||
// })
|
||||
let expr = {
|
||||
let ptr = self.expr_ident(e.span, p_ptr_ident, p_ptr_binding);
|
||||
let call_move_val_init = hir::StmtSemi(
|
||||
make_call(self, &move_val_init, hir_vec![ptr, pop_unsafe_expr]),
|
||||
self.next_id().node_id,
|
||||
);
|
||||
let call_move_val_init = respan(e.span, call_move_val_init);
|
||||
|
||||
let place = self.expr_ident(e.span, place_ident, place_binding);
|
||||
let call = make_call(self, &inplace_finalize, hir_vec![place]);
|
||||
P(self.signal_block_expr(
|
||||
hir_vec![call_move_val_init],
|
||||
call,
|
||||
e.span,
|
||||
hir::PushUnsafeBlock(hir::CompilerGenerated),
|
||||
ThinVec::new(),
|
||||
))
|
||||
};
|
||||
|
||||
let block = self.block_all(e.span, hir_vec![s1, s2, s3], Some(expr));
|
||||
hir::ExprBlock(P(block))
|
||||
}
|
||||
|
||||
ExprKind::Array(ref exprs) => {
|
||||
hir::ExprArray(exprs.iter().map(|x| self.lower_expr(x)).collect())
|
||||
}
|
||||
|
@ -4069,29 +3959,6 @@ impl<'a> LoweringContext<'a> {
|
|||
.resolve_str_path(span, self.crate_root, components, is_value)
|
||||
}
|
||||
|
||||
fn signal_block_expr(
|
||||
&mut self,
|
||||
stmts: hir::HirVec<hir::Stmt>,
|
||||
expr: P<hir::Expr>,
|
||||
span: Span,
|
||||
rule: hir::BlockCheckMode,
|
||||
attrs: ThinVec<Attribute>,
|
||||
) -> hir::Expr {
|
||||
let LoweredNodeId { node_id, hir_id } = self.next_id();
|
||||
|
||||
let block = P(hir::Block {
|
||||
rules: rule,
|
||||
span,
|
||||
id: node_id,
|
||||
hir_id,
|
||||
stmts,
|
||||
expr: Some(expr),
|
||||
targeted_by_break: false,
|
||||
recovered: false,
|
||||
});
|
||||
self.expr_block(block, attrs)
|
||||
}
|
||||
|
||||
fn ty_path(&mut self, id: LoweredNodeId, span: Span, qpath: hir::QPath) -> P<hir::Ty> {
|
||||
let mut id = id;
|
||||
let node = match qpath {
|
||||
|
|
|
@ -371,7 +371,6 @@ impl_stable_hash_for!(enum ::syntax_pos::hygiene::ExpnFormat {
|
|||
});
|
||||
|
||||
impl_stable_hash_for!(enum ::syntax_pos::hygiene::CompilerDesugaringKind {
|
||||
BackArrow,
|
||||
DotFill,
|
||||
QuestionMark
|
||||
});
|
||||
|
|
|
@ -301,7 +301,6 @@ impl EarlyLintPass for UnusedParens {
|
|||
Ret(Some(ref value)) => (value, "`return` value", false),
|
||||
Assign(_, ref value) => (value, "assigned value", false),
|
||||
AssignOp(.., ref value) => (value, "assigned value", false),
|
||||
InPlace(_, ref value) => (value, "emplacement value", false),
|
||||
// either function/method call, or something this lint doesn't care about
|
||||
ref call_or_other => {
|
||||
let args_to_check;
|
||||
|
|
|
@ -196,15 +196,16 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
|||
let mut values = Vec::with_capacity(used_variants);
|
||||
let tcx = self.hir.tcx();
|
||||
for (idx, discr) in adt_def.discriminants(tcx).enumerate() {
|
||||
target_blocks.place_back() <- if variants.contains(idx) {
|
||||
target_blocks.push(if variants.contains(idx) {
|
||||
values.push(discr.val);
|
||||
*(targets.place_back() <- self.cfg.start_new_block())
|
||||
targets.push(self.cfg.start_new_block());
|
||||
*targets.last().unwrap()
|
||||
} else {
|
||||
if otherwise_block.is_none() {
|
||||
otherwise_block = Some(self.cfg.start_new_block());
|
||||
}
|
||||
otherwise_block.unwrap()
|
||||
};
|
||||
});
|
||||
}
|
||||
if let Some(otherwise_block) = otherwise_block {
|
||||
targets.push(otherwise_block);
|
||||
|
|
|
@ -34,8 +34,6 @@ Rust MIR: a lowered representation of Rust. Also: an experiment!
|
|||
#![feature(exhaustive_patterns)]
|
||||
#![feature(range_contains)]
|
||||
#![feature(rustc_diagnostic_macros)]
|
||||
#![feature(placement_in_syntax)]
|
||||
#![feature(collection_placement)]
|
||||
#![feature(nonzero)]
|
||||
#![cfg_attr(stage0, feature(underscore_lifetimes))]
|
||||
#![cfg_attr(stage0, feature(never_type))]
|
||||
|
|
|
@ -721,16 +721,6 @@ fn main() {
|
|||
```
|
||||
"##,
|
||||
|
||||
E0066: r##"
|
||||
Box placement expressions (like C++'s "placement new") do not yet support any
|
||||
place expression except the exchange heap (i.e. `std::boxed::HEAP`).
|
||||
Furthermore, the syntax is changing to use `in` instead of `box`. See [RFC 470]
|
||||
and [RFC 809] for more details.
|
||||
|
||||
[RFC 470]: https://github.com/rust-lang/rfcs/pull/470
|
||||
[RFC 809]: https://github.com/rust-lang/rfcs/blob/master/text/0809-box-and-in-for-stdlib.md
|
||||
"##,
|
||||
|
||||
E0067: r##"
|
||||
The left-hand side of a compound assignment expression must be a place
|
||||
expression. A place expression represents a memory location and includes
|
||||
|
|
|
@ -22,8 +22,7 @@ use fmt::{self, Debug};
|
|||
use hash::{Hash, Hasher, BuildHasher, SipHasher13};
|
||||
use iter::{FromIterator, FusedIterator};
|
||||
use mem::{self, replace};
|
||||
use ops::{Deref, Index, InPlace, Place, Placer};
|
||||
use ptr;
|
||||
use ops::{Deref, Index};
|
||||
use sys;
|
||||
|
||||
use super::table::{self, Bucket, EmptyBucket, FullBucket, FullBucketMut, RawTable, SafeHash};
|
||||
|
@ -2043,80 +2042,6 @@ impl<'a, K, V> fmt::Debug for Drain<'a, K, V>
|
|||
}
|
||||
}
|
||||
|
||||
/// A place for insertion to a `Entry`.
|
||||
///
|
||||
/// See [`HashMap::entry`](struct.HashMap.html#method.entry) for details.
|
||||
#[must_use = "places do nothing unless written to with `<-` syntax"]
|
||||
#[unstable(feature = "collection_placement",
|
||||
reason = "struct name and placement protocol is subject to change",
|
||||
issue = "30172")]
|
||||
pub struct EntryPlace<'a, K: 'a, V: 'a> {
|
||||
bucket: FullBucketMut<'a, K, V>,
|
||||
}
|
||||
|
||||
#[unstable(feature = "collection_placement",
|
||||
reason = "struct name and placement protocol is subject to change",
|
||||
issue = "30172")]
|
||||
impl<'a, K: 'a + Debug, V: 'a + Debug> Debug for EntryPlace<'a, K, V> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.debug_struct("EntryPlace")
|
||||
.field("key", self.bucket.read().0)
|
||||
.field("value", self.bucket.read().1)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "collection_placement",
|
||||
reason = "struct name and placement protocol is subject to change",
|
||||
issue = "30172")]
|
||||
impl<'a, K, V> Drop for EntryPlace<'a, K, V> {
|
||||
fn drop(&mut self) {
|
||||
// Inplacement insertion failed. Only key need to drop.
|
||||
// The value is failed to insert into map.
|
||||
unsafe { self.bucket.remove_key() };
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "collection_placement",
|
||||
reason = "placement protocol is subject to change",
|
||||
issue = "30172")]
|
||||
impl<'a, K, V> Placer<V> for Entry<'a, K, V> {
|
||||
type Place = EntryPlace<'a, K, V>;
|
||||
|
||||
fn make_place(self) -> EntryPlace<'a, K, V> {
|
||||
let b = match self {
|
||||
Occupied(mut o) => {
|
||||
unsafe { ptr::drop_in_place(o.elem.read_mut().1); }
|
||||
o.elem
|
||||
}
|
||||
Vacant(v) => {
|
||||
unsafe { v.insert_key() }
|
||||
}
|
||||
};
|
||||
EntryPlace { bucket: b }
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "collection_placement",
|
||||
reason = "placement protocol is subject to change",
|
||||
issue = "30172")]
|
||||
unsafe impl<'a, K, V> Place<V> for EntryPlace<'a, K, V> {
|
||||
fn pointer(&mut self) -> *mut V {
|
||||
self.bucket.read_mut().1
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "collection_placement",
|
||||
reason = "placement protocol is subject to change",
|
||||
issue = "30172")]
|
||||
impl<'a, K, V> InPlace<V> for EntryPlace<'a, K, V> {
|
||||
type Owner = ();
|
||||
|
||||
unsafe fn finalize(self) {
|
||||
mem::forget(self);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, K, V> Entry<'a, K, V> {
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
/// Ensures a value is in the entry by inserting the default if empty, and returns
|
||||
|
@ -2539,26 +2464,6 @@ impl<'a, K: 'a, V: 'a> VacantEntry<'a, K, V> {
|
|||
};
|
||||
b.into_mut_refs().1
|
||||
}
|
||||
|
||||
// Only used for InPlacement insert. Avoid unnecessary value copy.
|
||||
// The value remains uninitialized.
|
||||
unsafe fn insert_key(self) -> FullBucketMut<'a, K, V> {
|
||||
match self.elem {
|
||||
NeqElem(mut bucket, disp) => {
|
||||
if disp >= DISPLACEMENT_THRESHOLD {
|
||||
bucket.table_mut().set_tag(true);
|
||||
}
|
||||
let uninit = mem::uninitialized();
|
||||
robin_hood(bucket, disp, self.hash, self.key, uninit)
|
||||
},
|
||||
NoElem(mut bucket, disp) => {
|
||||
if disp >= DISPLACEMENT_THRESHOLD {
|
||||
bucket.table_mut().set_tag(true);
|
||||
}
|
||||
bucket.put_key(self.hash, self.key)
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
|
@ -2823,7 +2728,6 @@ mod test_map {
|
|||
use super::RandomState;
|
||||
use cell::RefCell;
|
||||
use rand::{thread_rng, Rng};
|
||||
use panic;
|
||||
use realstd::collections::CollectionAllocErr::*;
|
||||
use realstd::mem::size_of;
|
||||
use realstd::usize;
|
||||
|
@ -3709,59 +3613,6 @@ mod test_map {
|
|||
panic!("Adaptive early resize failed");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_placement_in() {
|
||||
let mut map = HashMap::new();
|
||||
map.extend((0..10).map(|i| (i, i)));
|
||||
|
||||
map.entry(100) <- 100;
|
||||
assert_eq!(map[&100], 100);
|
||||
|
||||
map.entry(0) <- 10;
|
||||
assert_eq!(map[&0], 10);
|
||||
|
||||
assert_eq!(map.len(), 11);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_placement_panic() {
|
||||
let mut map = HashMap::new();
|
||||
map.extend((0..10).map(|i| (i, i)));
|
||||
|
||||
fn mkpanic() -> usize { panic!() }
|
||||
|
||||
// modify existing key
|
||||
// when panic happens, previous key is removed.
|
||||
let _ = panic::catch_unwind(panic::AssertUnwindSafe(|| { map.entry(0) <- mkpanic(); }));
|
||||
assert_eq!(map.len(), 9);
|
||||
assert!(!map.contains_key(&0));
|
||||
|
||||
// add new key
|
||||
let _ = panic::catch_unwind(panic::AssertUnwindSafe(|| { map.entry(100) <- mkpanic(); }));
|
||||
assert_eq!(map.len(), 9);
|
||||
assert!(!map.contains_key(&100));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_placement_drop() {
|
||||
// correctly drop
|
||||
struct TestV<'a>(&'a mut bool);
|
||||
impl<'a> Drop for TestV<'a> {
|
||||
fn drop(&mut self) {
|
||||
if !*self.0 { panic!("value double drop!"); } // no double drop
|
||||
*self.0 = false;
|
||||
}
|
||||
}
|
||||
|
||||
fn makepanic<'a>() -> TestV<'a> { panic!() }
|
||||
|
||||
let mut can_drop = true;
|
||||
let mut hm = HashMap::new();
|
||||
hm.insert(0, TestV(&mut can_drop));
|
||||
let _ = panic::catch_unwind(panic::AssertUnwindSafe(|| { hm.entry(0) <- makepanic(); }));
|
||||
assert_eq!(hm.len(), 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_try_reserve() {
|
||||
|
||||
|
|
|
@ -486,21 +486,6 @@ impl<K, V, M> EmptyBucket<K, V, M>
|
|||
table: self.table,
|
||||
}
|
||||
}
|
||||
|
||||
/// Puts given key, remain value uninitialized.
|
||||
/// It is only used for inplacement insertion.
|
||||
pub unsafe fn put_key(mut self, hash: SafeHash, key: K) -> FullBucket<K, V, M> {
|
||||
*self.raw.hash() = hash.inspect();
|
||||
let pair_ptr = self.raw.pair();
|
||||
ptr::write(&mut (*pair_ptr).0, key);
|
||||
|
||||
self.table.borrow_table_mut().size += 1;
|
||||
|
||||
FullBucket {
|
||||
raw: self.raw,
|
||||
table: self.table,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<K, V, M: Deref<Target = RawTable<K, V>>> FullBucket<K, V, M> {
|
||||
|
@ -576,17 +561,6 @@ impl<'t, K, V> FullBucket<K, V, &'t mut RawTable<K, V>> {
|
|||
v)
|
||||
}
|
||||
}
|
||||
|
||||
/// Remove this bucket's `key` from the hashtable.
|
||||
/// Only used for inplacement insertion.
|
||||
/// NOTE: `Value` is uninitialized when this function is called, don't try to drop the `Value`.
|
||||
pub unsafe fn remove_key(&mut self) {
|
||||
self.table.size -= 1;
|
||||
|
||||
*self.raw.hash() = EMPTY_BUCKET;
|
||||
let pair_ptr = self.raw.pair();
|
||||
ptr::drop_in_place(&mut (*pair_ptr).0); // only drop key
|
||||
}
|
||||
}
|
||||
|
||||
// This use of `Put` is misleading and restrictive, but safe and sufficient for our use cases
|
||||
|
|
|
@ -290,7 +290,6 @@
|
|||
#![feature(panic_internals)]
|
||||
#![feature(panic_unwind)]
|
||||
#![feature(peek)]
|
||||
#![feature(placement_in_syntax)]
|
||||
#![feature(placement_new_protocol)]
|
||||
#![feature(prelude_import)]
|
||||
#![feature(ptr_internals)]
|
||||
|
|
|
@ -1011,7 +1011,6 @@ impl Expr {
|
|||
pub fn precedence(&self) -> ExprPrecedence {
|
||||
match self.node {
|
||||
ExprKind::Box(_) => ExprPrecedence::Box,
|
||||
ExprKind::InPlace(..) => ExprPrecedence::InPlace,
|
||||
ExprKind::Array(_) => ExprPrecedence::Array,
|
||||
ExprKind::Call(..) => ExprPrecedence::Call,
|
||||
ExprKind::MethodCall(..) => ExprPrecedence::MethodCall,
|
||||
|
@ -1071,8 +1070,6 @@ pub enum RangeLimits {
|
|||
pub enum ExprKind {
|
||||
/// A `box x` expression.
|
||||
Box(P<Expr>),
|
||||
/// First expr is the place; second expr is the value.
|
||||
InPlace(P<Expr>, P<Expr>),
|
||||
/// An array (`[a, b, c, d]`)
|
||||
Array(Vec<P<Expr>>),
|
||||
/// A function call
|
||||
|
|
|
@ -146,7 +146,6 @@ declare_features! (
|
|||
(active, rustc_diagnostic_macros, "1.0.0", None, None),
|
||||
(active, rustc_const_unstable, "1.0.0", None, None),
|
||||
(active, box_syntax, "1.0.0", Some(27779), None),
|
||||
(active, placement_in_syntax, "1.0.0", Some(27779), None),
|
||||
(active, unboxed_closures, "1.0.0", Some(29625), None),
|
||||
|
||||
(active, fundamental, "1.0.0", Some(29635), None),
|
||||
|
@ -1287,9 +1286,6 @@ pub const EXPLAIN_VIS_MATCHER: &'static str =
|
|||
pub const EXPLAIN_LIFETIME_MATCHER: &'static str =
|
||||
":lifetime fragment specifier is experimental and subject to change";
|
||||
|
||||
pub const EXPLAIN_PLACEMENT_IN: &'static str =
|
||||
"placement-in expression syntax is experimental and subject to change.";
|
||||
|
||||
pub const EXPLAIN_UNSIZED_TUPLE_COERCION: &'static str =
|
||||
"Unsized tuple coercion is not stable enough for use and is subject to change";
|
||||
|
||||
|
@ -1636,9 +1632,6 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
|
|||
gate_feature_post!(&self, type_ascription, e.span,
|
||||
"type ascription is experimental");
|
||||
}
|
||||
ast::ExprKind::InPlace(..) => {
|
||||
gate_feature_post!(&self, placement_in_syntax, e.span, EXPLAIN_PLACEMENT_IN);
|
||||
}
|
||||
ast::ExprKind::Yield(..) => {
|
||||
gate_feature_post!(&self, generators,
|
||||
e.span,
|
||||
|
|
|
@ -1167,9 +1167,6 @@ pub fn noop_fold_expr<T: Folder>(Expr {id, node, span, attrs}: Expr, folder: &mu
|
|||
ExprKind::Box(e) => {
|
||||
ExprKind::Box(folder.fold_expr(e))
|
||||
}
|
||||
ExprKind::InPlace(p, e) => {
|
||||
ExprKind::InPlace(folder.fold_expr(p), folder.fold_expr(e))
|
||||
}
|
||||
ExprKind::Array(exprs) => {
|
||||
ExprKind::Array(folder.fold_exprs(exprs))
|
||||
}
|
||||
|
|
|
@ -2850,17 +2850,6 @@ impl<'a> Parser<'a> {
|
|||
let (span, e) = self.interpolated_or_expr_span(e)?;
|
||||
(lo.to(span), ExprKind::AddrOf(m, e))
|
||||
}
|
||||
token::Ident(..) if self.token.is_keyword(keywords::In) => {
|
||||
self.bump();
|
||||
let place = self.parse_expr_res(
|
||||
Restrictions::NO_STRUCT_LITERAL,
|
||||
None,
|
||||
)?;
|
||||
let blk = self.parse_block()?;
|
||||
let span = blk.span;
|
||||
let blk_expr = self.mk_expr(span, ExprKind::Block(blk), ThinVec::new());
|
||||
(lo.to(span), ExprKind::InPlace(place, blk_expr))
|
||||
}
|
||||
token::Ident(..) if self.token.is_keyword(keywords::Box) => {
|
||||
self.bump();
|
||||
let e = self.parse_prefix_expr(None);
|
||||
|
@ -3023,8 +3012,6 @@ impl<'a> Parser<'a> {
|
|||
}
|
||||
AssocOp::Assign =>
|
||||
self.mk_expr(span, ExprKind::Assign(lhs, rhs), ThinVec::new()),
|
||||
AssocOp::Inplace =>
|
||||
self.mk_expr(span, ExprKind::InPlace(lhs, rhs), ThinVec::new()),
|
||||
AssocOp::AssignOp(k) => {
|
||||
let aop = match k {
|
||||
token::Plus => BinOpKind::Add,
|
||||
|
|
|
@ -1877,16 +1877,6 @@ impl<'a> State<'a> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn print_expr_in_place(&mut self,
|
||||
place: &ast::Expr,
|
||||
expr: &ast::Expr) -> io::Result<()> {
|
||||
let prec = AssocOp::Inplace.precedence() as i8;
|
||||
self.print_expr_maybe_paren(place, prec + 1)?;
|
||||
self.s.space()?;
|
||||
self.word_space("<-")?;
|
||||
self.print_expr_maybe_paren(expr, prec)
|
||||
}
|
||||
|
||||
fn print_expr_vec(&mut self, exprs: &[P<ast::Expr>],
|
||||
attrs: &[Attribute]) -> io::Result<()> {
|
||||
self.ibox(INDENT_UNIT)?;
|
||||
|
@ -2056,9 +2046,6 @@ impl<'a> State<'a> {
|
|||
self.word_space("box")?;
|
||||
self.print_expr_maybe_paren(expr, parser::PREC_PREFIX)?;
|
||||
}
|
||||
ast::ExprKind::InPlace(ref place, ref expr) => {
|
||||
self.print_expr_in_place(place, expr)?;
|
||||
}
|
||||
ast::ExprKind::Array(ref exprs) => {
|
||||
self.print_expr_vec(&exprs[..], attrs)?;
|
||||
}
|
||||
|
|
|
@ -56,8 +56,6 @@ pub enum AssocOp {
|
|||
GreaterEqual,
|
||||
/// `=`
|
||||
Assign,
|
||||
/// `<-`
|
||||
Inplace,
|
||||
/// `?=` where ? is one of the BinOpToken
|
||||
AssignOp(BinOpToken),
|
||||
/// `as`
|
||||
|
@ -86,7 +84,6 @@ impl AssocOp {
|
|||
use self::AssocOp::*;
|
||||
match *t {
|
||||
Token::BinOpEq(k) => Some(AssignOp(k)),
|
||||
Token::LArrow => Some(Inplace),
|
||||
Token::Eq => Some(Assign),
|
||||
Token::BinOp(BinOpToken::Star) => Some(Multiply),
|
||||
Token::BinOp(BinOpToken::Slash) => Some(Divide),
|
||||
|
@ -156,7 +153,6 @@ impl AssocOp {
|
|||
LAnd => 6,
|
||||
LOr => 5,
|
||||
DotDot | DotDotEq => 4,
|
||||
Inplace => 3,
|
||||
Assign | AssignOp(_) => 2,
|
||||
}
|
||||
}
|
||||
|
@ -166,7 +162,7 @@ impl AssocOp {
|
|||
use self::AssocOp::*;
|
||||
// NOTE: it is a bug to have an operators that has same precedence but different fixities!
|
||||
match *self {
|
||||
Inplace | Assign | AssignOp(_) => Fixity::Right,
|
||||
Assign | AssignOp(_) => Fixity::Right,
|
||||
As | Multiply | Divide | Modulus | Add | Subtract | ShiftLeft | ShiftRight | BitAnd |
|
||||
BitXor | BitOr | Less | Greater | LessEqual | GreaterEqual | Equal | NotEqual |
|
||||
LAnd | LOr | Colon => Fixity::Left,
|
||||
|
@ -178,7 +174,7 @@ impl AssocOp {
|
|||
use self::AssocOp::*;
|
||||
match *self {
|
||||
Less | Greater | LessEqual | GreaterEqual | Equal | NotEqual => true,
|
||||
Inplace | Assign | AssignOp(_) | As | Multiply | Divide | Modulus | Add | Subtract |
|
||||
Assign | AssignOp(_) | As | Multiply | Divide | Modulus | Add | Subtract |
|
||||
ShiftLeft | ShiftRight | BitAnd | BitXor | BitOr | LAnd | LOr |
|
||||
DotDot | DotDotEq | Colon => false
|
||||
}
|
||||
|
@ -187,7 +183,7 @@ impl AssocOp {
|
|||
pub fn is_assign_like(&self) -> bool {
|
||||
use self::AssocOp::*;
|
||||
match *self {
|
||||
Assign | AssignOp(_) | Inplace => true,
|
||||
Assign | AssignOp(_) => true,
|
||||
Less | Greater | LessEqual | GreaterEqual | Equal | NotEqual | As | Multiply | Divide |
|
||||
Modulus | Add | Subtract | ShiftLeft | ShiftRight | BitAnd | BitXor | BitOr | LAnd |
|
||||
LOr | DotDot | DotDotEq | Colon => false
|
||||
|
@ -215,7 +211,7 @@ impl AssocOp {
|
|||
BitOr => Some(BinOpKind::BitOr),
|
||||
LAnd => Some(BinOpKind::And),
|
||||
LOr => Some(BinOpKind::Or),
|
||||
Inplace | Assign | AssignOp(_) | As | DotDot | DotDotEq | Colon => None
|
||||
Assign | AssignOp(_) | As | DotDot | DotDotEq | Colon => None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -242,7 +238,6 @@ pub enum ExprPrecedence {
|
|||
|
||||
Binary(BinOpKind),
|
||||
|
||||
InPlace,
|
||||
Cast,
|
||||
Type,
|
||||
|
||||
|
@ -310,7 +305,6 @@ impl ExprPrecedence {
|
|||
|
||||
// Binop-like expr kinds, handled by `AssocOp`.
|
||||
ExprPrecedence::Binary(op) => AssocOp::from_ast_binop(op).precedence() as i8,
|
||||
ExprPrecedence::InPlace => AssocOp::Inplace.precedence() as i8,
|
||||
ExprPrecedence::Cast => AssocOp::As.precedence() as i8,
|
||||
ExprPrecedence::Type => AssocOp::Colon.precedence() as i8,
|
||||
|
||||
|
|
|
@ -654,10 +654,6 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) {
|
|||
ExprKind::Box(ref subexpression) => {
|
||||
visitor.visit_expr(subexpression)
|
||||
}
|
||||
ExprKind::InPlace(ref place, ref subexpression) => {
|
||||
visitor.visit_expr(place);
|
||||
visitor.visit_expr(subexpression)
|
||||
}
|
||||
ExprKind::Array(ref subexpressions) => {
|
||||
walk_list!(visitor, visit_expr, subexpressions);
|
||||
}
|
||||
|
|
|
@ -430,7 +430,6 @@ pub enum ExpnFormat {
|
|||
/// The kind of compiler desugaring.
|
||||
#[derive(Clone, Hash, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)]
|
||||
pub enum CompilerDesugaringKind {
|
||||
BackArrow,
|
||||
DotFill,
|
||||
QuestionMark,
|
||||
}
|
||||
|
@ -439,7 +438,6 @@ impl CompilerDesugaringKind {
|
|||
pub fn as_symbol(&self) -> Symbol {
|
||||
use CompilerDesugaringKind::*;
|
||||
let s = match *self {
|
||||
BackArrow => "<-",
|
||||
DotFill => "...",
|
||||
QuestionMark => "?",
|
||||
};
|
||||
|
|
|
@ -1,17 +0,0 @@
|
|||
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![feature(box_syntax)]
|
||||
#![feature(placement_in_syntax)]
|
||||
|
||||
fn main() {
|
||||
() <- 0;
|
||||
//~^ ERROR: `(): std::ops::Placer<_>` is not satisfied
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// Check that placement in respects unsafe code checks.
|
||||
|
||||
#![feature(box_heap)]
|
||||
#![feature(placement_in_syntax)]
|
||||
|
||||
fn main() {
|
||||
use std::boxed::HEAP;
|
||||
|
||||
let p: *const i32 = &42;
|
||||
let _ = HEAP <- *p; //~ ERROR requires unsafe
|
||||
|
||||
let p: *const _ = &HEAP;
|
||||
let _ = *p <- 42; //~ ERROR requires unsafe
|
||||
}
|
|
@ -1,21 +0,0 @@
|
|||
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// Check that placement in respects unstable code checks.
|
||||
|
||||
#![feature(placement_in_syntax)]
|
||||
|
||||
fn main() {
|
||||
use std::boxed::HEAP; //~ ERROR use of unstable library feature
|
||||
|
||||
let _ = HEAP <- { //~ ERROR use of unstable library feature
|
||||
HEAP //~ ERROR use of unstable library feature
|
||||
};
|
||||
}
|
|
@ -13,10 +13,9 @@
|
|||
fn that_odd_parse() {
|
||||
// following lines below parse and must not fail
|
||||
x = if c { a } else { b }();
|
||||
x <- if c { a } else { b }[n];
|
||||
x = if true { 1 } else { 0 } as *mut _;
|
||||
// however this does not parse and probably should fail to retain compat?
|
||||
// NB: `..` here is arbitrary, failure happens/should happen ∀ops that aren’t `=` or `<-`
|
||||
// NB: `..` here is arbitrary, failure happens/should happen ∀ops that aren’t `=`
|
||||
// see assoc-oddities-2 and assoc-oddities-3
|
||||
..if c { a } else { b }[n]; //~ ERROR expected one of
|
||||
}
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
|
||||
#![feature(custom_attribute)]
|
||||
#![feature(box_syntax)]
|
||||
#![feature(placement_in_syntax)]
|
||||
#![feature(stmt_expr_attributes)]
|
||||
|
||||
fn main() { }
|
||||
|
|
|
@ -126,16 +126,6 @@ fn run() {
|
|||
check_expr_attrs("#[attr] box 0", outer);
|
||||
reject_expr_parse("box #![attr] 0");
|
||||
|
||||
check_expr_attrs("#[attr] 0 <- #[attr] 0", none);
|
||||
check_expr_attrs("#[attr] (0 <- 0)", outer);
|
||||
reject_expr_parse("0 #[attr] <- 0");
|
||||
reject_expr_parse("0 <- #![attr] 0");
|
||||
|
||||
check_expr_attrs("in #[attr] 0 {#[attr] 0}", none);
|
||||
check_expr_attrs("#[attr] (in 0 {0})", outer);
|
||||
reject_expr_parse("in 0 #[attr] {0}");
|
||||
reject_expr_parse("in 0 {#![attr] 0}");
|
||||
|
||||
check_expr_attrs("#[attr] [#![attr]]", both);
|
||||
check_expr_attrs("#[attr] [#![attr] 0]", both);
|
||||
check_expr_attrs("#[attr] [#![attr] 0; 0]", both);
|
||||
|
|
|
@ -84,18 +84,11 @@ fn iter_exprs(depth: usize, f: &mut FnMut(P<Expr>)) {
|
|||
|
||||
let mut g = |e| f(expr(e));
|
||||
|
||||
for kind in 0 .. 17 {
|
||||
for kind in 0 .. 16 {
|
||||
match kind {
|
||||
0 => iter_exprs(depth - 1, &mut |e| g(ExprKind::Box(e))),
|
||||
1 => {
|
||||
// Note that for binary expressions, we explore each side separately. The
|
||||
// parenthesization decisions for the LHS and RHS should be independent, and this
|
||||
// way produces `O(n)` results instead of `O(n^2)`.
|
||||
iter_exprs(depth - 1, &mut |e| g(ExprKind::InPlace(e, make_x())));
|
||||
iter_exprs(depth - 1, &mut |e| g(ExprKind::InPlace(make_x(), e)));
|
||||
},
|
||||
2 => iter_exprs(depth - 1, &mut |e| g(ExprKind::Call(e, vec![]))),
|
||||
3 => {
|
||||
1 => iter_exprs(depth - 1, &mut |e| g(ExprKind::Call(e, vec![]))),
|
||||
2 => {
|
||||
let seg = PathSegment {
|
||||
identifier: Ident::from_str("x"),
|
||||
span: DUMMY_SP,
|
||||
|
@ -107,25 +100,25 @@ fn iter_exprs(depth: usize, f: &mut FnMut(P<Expr>)) {
|
|||
iter_exprs(depth - 1, &mut |e| g(ExprKind::MethodCall(
|
||||
seg.clone(), vec![make_x(), e])));
|
||||
},
|
||||
4 => {
|
||||
3 => {
|
||||
let op = Spanned { span: DUMMY_SP, node: BinOpKind::Add };
|
||||
iter_exprs(depth - 1, &mut |e| g(ExprKind::Binary(op, e, make_x())));
|
||||
iter_exprs(depth - 1, &mut |e| g(ExprKind::Binary(op, make_x(), e)));
|
||||
},
|
||||
5 => {
|
||||
4 => {
|
||||
let op = Spanned { span: DUMMY_SP, node: BinOpKind::Mul };
|
||||
iter_exprs(depth - 1, &mut |e| g(ExprKind::Binary(op, e, make_x())));
|
||||
iter_exprs(depth - 1, &mut |e| g(ExprKind::Binary(op, make_x(), e)));
|
||||
},
|
||||
6 => {
|
||||
5 => {
|
||||
let op = Spanned { span: DUMMY_SP, node: BinOpKind::Shl };
|
||||
iter_exprs(depth - 1, &mut |e| g(ExprKind::Binary(op, e, make_x())));
|
||||
iter_exprs(depth - 1, &mut |e| g(ExprKind::Binary(op, make_x(), e)));
|
||||
},
|
||||
7 => {
|
||||
6 => {
|
||||
iter_exprs(depth - 1, &mut |e| g(ExprKind::Unary(UnOp::Deref, e)));
|
||||
},
|
||||
8 => {
|
||||
7 => {
|
||||
let block = P(Block {
|
||||
stmts: Vec::new(),
|
||||
id: DUMMY_NODE_ID,
|
||||
|
@ -135,7 +128,7 @@ fn iter_exprs(depth: usize, f: &mut FnMut(P<Expr>)) {
|
|||
});
|
||||
iter_exprs(depth - 1, &mut |e| g(ExprKind::If(e, block.clone(), None)));
|
||||
},
|
||||
9 => {
|
||||
8 => {
|
||||
let decl = P(FnDecl {
|
||||
inputs: vec![],
|
||||
output: FunctionRetTy::Default(DUMMY_SP),
|
||||
|
@ -148,28 +141,28 @@ fn iter_exprs(depth: usize, f: &mut FnMut(P<Expr>)) {
|
|||
e,
|
||||
DUMMY_SP)));
|
||||
},
|
||||
10 => {
|
||||
9 => {
|
||||
iter_exprs(depth - 1, &mut |e| g(ExprKind::Assign(e, make_x())));
|
||||
iter_exprs(depth - 1, &mut |e| g(ExprKind::Assign(make_x(), e)));
|
||||
},
|
||||
11 => {
|
||||
10 => {
|
||||
let ident = Spanned { span: DUMMY_SP, node: Ident::from_str("f") };
|
||||
iter_exprs(depth - 1, &mut |e| g(ExprKind::Field(e, ident)));
|
||||
},
|
||||
12 => {
|
||||
11 => {
|
||||
iter_exprs(depth - 1, &mut |e| g(ExprKind::Range(
|
||||
Some(e), Some(make_x()), RangeLimits::HalfOpen)));
|
||||
iter_exprs(depth - 1, &mut |e| g(ExprKind::Range(
|
||||
Some(make_x()), Some(e), RangeLimits::HalfOpen)));
|
||||
},
|
||||
13 => {
|
||||
12 => {
|
||||
iter_exprs(depth - 1, &mut |e| g(ExprKind::AddrOf(Mutability::Immutable, e)));
|
||||
},
|
||||
14 => {
|
||||
13 => {
|
||||
g(ExprKind::Ret(None));
|
||||
iter_exprs(depth - 1, &mut |e| g(ExprKind::Ret(Some(e))));
|
||||
},
|
||||
15 => {
|
||||
14 => {
|
||||
let seg = PathSegment {
|
||||
identifier: Ident::from_str("S"),
|
||||
span: DUMMY_SP,
|
||||
|
@ -181,7 +174,7 @@ fn iter_exprs(depth: usize, f: &mut FnMut(P<Expr>)) {
|
|||
};
|
||||
g(ExprKind::Struct(path, vec![], Some(make_x())));
|
||||
},
|
||||
16 => {
|
||||
15 => {
|
||||
iter_exprs(depth - 1, &mut |e| g(ExprKind::Try(e)));
|
||||
},
|
||||
_ => panic!("bad counter value in iter_exprs"),
|
||||
|
|
|
@ -14,16 +14,11 @@
|
|||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
#![allow(dead_code, unused_variables)]
|
||||
#![feature(box_syntax, box_heap)]
|
||||
#![feature(placement_in_syntax)]
|
||||
|
||||
// during check-pretty, the expanded code needs to opt into these
|
||||
// features
|
||||
#![feature(placement_new_protocol, core_intrinsics)]
|
||||
#![feature(box_syntax)]
|
||||
|
||||
// Tests that the new `box` syntax works with unique pointers.
|
||||
|
||||
use std::boxed::{Box, HEAP};
|
||||
use std::boxed::Box;
|
||||
|
||||
struct Structure {
|
||||
x: isize,
|
||||
|
@ -31,7 +26,6 @@ struct Structure {
|
|||
}
|
||||
|
||||
pub fn main() {
|
||||
let x: Box<isize> = in HEAP { 2 };
|
||||
let y: Box<isize> = box 2;
|
||||
let b: Box<isize> = box (1 + 2);
|
||||
let c = box (3 + 4);
|
||||
|
|
|
@ -1,37 +0,0 @@
|
|||
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![allow(dead_code, unused_variables)]
|
||||
#![feature(box_heap)]
|
||||
#![feature(placement_in_syntax)]
|
||||
|
||||
// Tests that the new `in` syntax works with unique pointers.
|
||||
//
|
||||
// Compare with new-box-syntax.rs
|
||||
|
||||
use std::boxed::{Box, HEAP};
|
||||
|
||||
struct Structure {
|
||||
x: isize,
|
||||
y: isize,
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
let x: Box<isize> = in HEAP { 2 };
|
||||
let b: Box<isize> = in HEAP { 1 + 2 };
|
||||
let c = in HEAP { 3 + 4 };
|
||||
|
||||
let s: Box<Structure> = in HEAP {
|
||||
Structure {
|
||||
x: 3,
|
||||
y: 4,
|
||||
}
|
||||
};
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// gate-test-placement_in_syntax
|
||||
|
||||
// Check that `in PLACE { EXPR }` is feature-gated.
|
||||
//
|
||||
// See also feature-gate-box-expr.rs
|
||||
//
|
||||
// (Note that the two tests are separated since the checks appear to
|
||||
// be performed at distinct phases, with an abort_if_errors call
|
||||
// separating them.)
|
||||
|
||||
fn main() {
|
||||
use std::boxed::HEAP;
|
||||
|
||||
let x = HEAP <- 'c'; //~ ERROR placement-in expression syntax is experimental
|
||||
println!("x: {}", x);
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
error[E0658]: placement-in expression syntax is experimental and subject to change. (see issue #27779)
|
||||
--> $DIR/feature-gate-placement-expr.rs:24:13
|
||||
|
|
||||
LL | let x = HEAP <- 'c'; //~ ERROR placement-in expression syntax is experimental
|
||||
| ^^^^^^^^^^^
|
||||
|
|
||||
= help: add #![feature(placement_in_syntax)] to the crate attributes to enable
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
Loading…
Reference in New Issue