43 changes: 20 additions & 23 deletions src/liballoc/collections/btree/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
// This implies that even an empty internal node has at least one edge.

use core::marker::PhantomData;
use core::mem;
use core::mem::{self, MaybeUninit};
use core::ptr::{self, Unique, NonNull};
use core::slice;

Expand All @@ -58,9 +58,6 @@ pub const CAPACITY: usize = 2 * B - 1;
/// these should always be put behind pointers, and specifically behind `BoxedNode` in the owned
/// case.
///
/// See also rust-lang/rfcs#197, which would make this structure significantly more safe by
/// avoiding accidentally dropping unused and uninitialized keys and values.
///
/// We put the metadata first so that its position is the same for every `K` and `V`, in order
/// to statically allocate a single dummy node to avoid allocations. This struct is `repr(C)` to
/// prevent them from being reordered.
Expand All @@ -73,7 +70,7 @@ struct LeafNode<K, V> {
/// This node's index into the parent node's `edges` array.
/// `*node.parent.edges[node.parent_idx]` should be the same thing as `node`.
/// This is only guaranteed to be initialized when `parent` is nonnull.
parent_idx: u16,
parent_idx: MaybeUninit<u16>,

/// The number of keys and values this node stores.
///
Expand All @@ -83,8 +80,8 @@ struct LeafNode<K, V> {

/// The arrays storing the actual data of the node. Only the first `len` elements of each
/// array are initialized and valid.
keys: [K; CAPACITY],
vals: [V; CAPACITY],
keys: MaybeUninit<[K; CAPACITY]>,
vals: MaybeUninit<[V; CAPACITY]>,
}

impl<K, V> LeafNode<K, V> {
Expand All @@ -94,10 +91,10 @@ impl<K, V> LeafNode<K, V> {
LeafNode {
// As a general policy, we leave fields uninitialized if they can be, as this should
// be both slightly faster and easier to track in Valgrind.
keys: mem::uninitialized(),
vals: mem::uninitialized(),
keys: MaybeUninit::uninitialized(),
vals: MaybeUninit::uninitialized(),
parent: ptr::null(),
parent_idx: mem::uninitialized(),
parent_idx: MaybeUninit::uninitialized(),
len: 0
}
}
Expand All @@ -115,10 +112,10 @@ unsafe impl Sync for LeafNode<(), ()> {}
// ever take a pointer past the first key.
static EMPTY_ROOT_NODE: LeafNode<(), ()> = LeafNode {
parent: ptr::null(),
parent_idx: 0,
parent_idx: MaybeUninit::uninitialized(),
len: 0,
keys: [(); CAPACITY],
vals: [(); CAPACITY],
keys: MaybeUninit::uninitialized(),
vals: MaybeUninit::uninitialized(),
};

/// The underlying representation of internal nodes. As with `LeafNode`s, these should be hidden
Expand Down Expand Up @@ -430,7 +427,7 @@ impl<BorrowType, K, V, Type> NodeRef<BorrowType, K, V, Type> {
root: self.root,
_marker: PhantomData
},
idx: self.as_leaf().parent_idx as usize,
idx: unsafe { usize::from(*self.as_leaf().parent_idx.get_ref()) },
_marker: PhantomData
})
} else {
Expand Down Expand Up @@ -567,7 +564,7 @@ impl<'a, K: 'a, V: 'a, Type> NodeRef<marker::Immut<'a>, K, V, Type> {
// the node, which is allowed by LLVM.
unsafe {
slice::from_raw_parts(
self.as_leaf().keys.as_ptr(),
self.as_leaf().keys.as_ptr() as *const K,
self.len()
)
}
Expand All @@ -578,7 +575,7 @@ impl<'a, K: 'a, V: 'a, Type> NodeRef<marker::Immut<'a>, K, V, Type> {
debug_assert!(!self.is_shared_root());
unsafe {
slice::from_raw_parts(
self.as_leaf().vals.as_ptr(),
self.as_leaf().vals.as_ptr() as *const V,
self.len()
)
}
Expand All @@ -605,7 +602,7 @@ impl<'a, K: 'a, V: 'a, Type> NodeRef<marker::Mut<'a>, K, V, Type> {
} else {
unsafe {
slice::from_raw_parts_mut(
&mut self.as_leaf_mut().keys as *mut [K] as *mut K,
self.as_leaf_mut().keys.get_mut() as *mut [K] as *mut K,
self.len()
)
}
Expand All @@ -616,7 +613,7 @@ impl<'a, K: 'a, V: 'a, Type> NodeRef<marker::Mut<'a>, K, V, Type> {
debug_assert!(!self.is_shared_root());
unsafe {
slice::from_raw_parts_mut(
&mut self.as_leaf_mut().vals as *mut [V] as *mut V,
self.as_leaf_mut().vals.get_mut() as *mut [V] as *mut V,
self.len()
)
}
Expand Down Expand Up @@ -1013,7 +1010,7 @@ impl<'a, K, V> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Internal>, marker::
let ptr = self.node.as_internal_mut() as *mut _;
let mut child = self.descend();
child.as_leaf_mut().parent = ptr;
child.as_leaf_mut().parent_idx = idx;
child.as_leaf_mut().parent_idx.set(idx);
}

/// Unsafely asserts to the compiler some static information about whether the underlying
Expand Down Expand Up @@ -1152,12 +1149,12 @@ impl<'a, K, V> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, marker::KV>

ptr::copy_nonoverlapping(
self.node.keys().as_ptr().add(self.idx + 1),
new_node.keys.as_mut_ptr(),
new_node.keys.as_mut_ptr() as *mut K,
new_len
);
ptr::copy_nonoverlapping(
self.node.vals().as_ptr().add(self.idx + 1),
new_node.vals.as_mut_ptr(),
new_node.vals.as_mut_ptr() as *mut V,
new_len
);

Expand Down Expand Up @@ -1210,12 +1207,12 @@ impl<'a, K, V> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Internal>, marker::

ptr::copy_nonoverlapping(
self.node.keys().as_ptr().add(self.idx + 1),
new_node.data.keys.as_mut_ptr(),
new_node.data.keys.as_mut_ptr() as *mut K,
new_len
);
ptr::copy_nonoverlapping(
self.node.vals().as_ptr().add(self.idx + 1),
new_node.data.vals.as_mut_ptr(),
new_node.data.vals.as_mut_ptr() as *mut V,
new_len
);
ptr::copy_nonoverlapping(
Expand Down
52 changes: 5 additions & 47 deletions src/liballoc/collections/vec_deque.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@

use core::cmp::Ordering;
use core::fmt;
use core::isize;
use core::iter::{repeat, FromIterator, FusedIterator};
use core::mem;
use core::ops::Bound::{Excluded, Included, Unbounded};
Expand Down Expand Up @@ -203,33 +202,6 @@ impl<T> VecDeque<T> {
len);
}

/// Copies all values from `src` to the back of `self`, wrapping around if needed.
///
/// # Safety
///
/// The capacity must be sufficient to hold self.len() + src.len() elements.
/// If so, this function never panics.
#[inline]
unsafe fn copy_slice(&mut self, src: &[T]) {
/// This is guaranteed by `RawVec`.
debug_assert!(self.capacity() <= isize::MAX as usize);

let expected_new_len = self.len() + src.len();
debug_assert!(self.capacity() >= expected_new_len);

let dst_high_ptr = self.ptr().add(self.head);
let dst_high_len = self.cap() - self.head;

let split = cmp::min(src.len(), dst_high_len);
let (src_high, src_low) = src.split_at(split);

ptr::copy_nonoverlapping(src_high.as_ptr(), dst_high_ptr, src_high.len());
ptr::copy_nonoverlapping(src_low.as_ptr(), self.ptr(), src_low.len());

self.head = self.wrap_add(self.head, src.len());
debug_assert!(self.len() == expected_new_len);
}

/// Copies a potentially wrapping block of memory len long from src to dest.
/// (abs(dst - src) + len) must be no larger than cap() (There must be at
/// most one continuous overlapping region between src and dest).
Expand Down Expand Up @@ -1052,7 +1024,7 @@ impl<T> VecDeque<T> {
iter: Iter {
tail: drain_tail,
head: drain_head,
ring: unsafe { self.buffer_as_slice() },
ring: unsafe { self.buffer_as_mut_slice() },
},
}
}
Expand Down Expand Up @@ -1862,22 +1834,8 @@ impl<T> VecDeque<T> {
#[inline]
#[stable(feature = "append", since = "1.4.0")]
pub fn append(&mut self, other: &mut Self) {
unsafe {
// Guarantees there is space in `self` for `other`.
self.reserve(other.len());

{
let (src_high, src_low) = other.as_slices();

// This is only safe because copy_slice never panics when capacity is sufficient.
self.copy_slice(src_low);
self.copy_slice(src_high);
}

// Some values now exist in both `other` and `self` but are made inaccessible
// in`other`.
other.tail = other.head;
}
// naive impl
self.extend(other.drain(..));
}

/// Retains only the elements specified by the predicate.
Expand Down Expand Up @@ -2635,8 +2593,8 @@ impl<T> From<VecDeque<T>> for Vec<T> {
let mut right_offset = 0;
for i in left_edge..right_edge {
right_offset = (i - left_edge) % (cap - right_edge);
let src = right_edge + right_offset;
ptr::swap(buf.add(i), buf.add(src));
let src: isize = (right_edge + right_offset) as isize;
ptr::swap(buf.add(i), buf.offset(src));
}
let n_ops = right_edge - left_edge;
left_edge += n_ops;
Expand Down
5 changes: 2 additions & 3 deletions src/liballoc/fmt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@
//! Additionally, the return value of this function is [`fmt::Result`] which is a
//! type alias of [`Result`]`<(), `[`std::fmt::Error`]`>`. Formatting implementations
//! should ensure that they propagate errors from the [`Formatter`][`Formatter`] (e.g., when
//! calling [`write!`]) however, they should never return errors spuriously. That
//! calling [`write!`]). However, they should never return errors spuriously. That
//! is, a formatting implementation must and may only return an error if the
//! passed-in [`Formatter`] returns an error. This is because, contrary to what
//! the function signature might suggest, string formatting is an infallible
Expand Down Expand Up @@ -335,8 +335,7 @@
//!
//! Each argument being formatted can be transformed by a number of formatting
//! parameters (corresponding to `format_spec` in the syntax above). These
//! parameters affect the string representation of what's being formatted. This
//! syntax draws heavily from Python's, so it may seem a bit familiar.
//! parameters affect the string representation of what's being formatted.
//!
//! ## Fill/Alignment
//!
Expand Down
9 changes: 4 additions & 5 deletions src/liballoc/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,6 @@

#![cfg_attr(not(test), feature(fn_traits))]
#![cfg_attr(not(test), feature(generator_trait))]
#![cfg_attr(not(stage0), feature(nll))]
#![cfg_attr(test, feature(test))]

#![feature(allocator_api)]
Expand All @@ -87,8 +86,7 @@
#![feature(box_syntax)]
#![feature(cfg_target_has_atomic)]
#![feature(coerce_unsized)]
#![cfg_attr(stage0, feature(const_fn))]
#![cfg_attr(not(stage0), feature(min_const_fn))]
#![cfg_attr(stage0, feature(min_const_fn))]
#![feature(core_intrinsics)]
#![feature(custom_attribute)]
#![feature(dropck_eyepatch)]
Expand All @@ -99,6 +97,7 @@
#![feature(lang_items)]
#![feature(libc)]
#![feature(needs_allocator)]
#![feature(nll)]
#![feature(optin_builtin_traits)]
#![feature(pattern)]
#![feature(pin)]
Expand All @@ -116,9 +115,10 @@
#![feature(unsize)]
#![feature(allocator_internals)]
#![feature(on_unimplemented)]
#![feature(exact_chunks)]
#![feature(rustc_const_unstable)]
#![feature(const_vec_new)]
#![feature(slice_partition_dedup)]
#![feature(maybe_uninit)]

// Allow testing this library

Expand Down Expand Up @@ -160,7 +160,6 @@ pub mod collections;
pub mod sync;
pub mod rc;
pub mod raw_vec;
pub mod pin;
pub mod prelude;
pub mod borrow;
pub mod fmt;
Expand Down
302 changes: 0 additions & 302 deletions src/liballoc/pin.rs

This file was deleted.

16 changes: 11 additions & 5 deletions src/liballoc/rc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@
//!
//! `Rc<T>` automatically dereferences to `T` (via the [`Deref`] trait),
//! so you can call `T`'s methods on a value of type [`Rc<T>`][`Rc`]. To avoid name
//! clashes with `T`'s methods, the methods of [`Rc<T>`][`Rc`] itself are [associated
//! functions][assoc], called using function-like syntax:
//! clashes with `T`'s methods, the methods of [`Rc<T>`][`Rc`] itself are associated
//! functions, called using function-like syntax:
//!
//! ```
//! use std::rc::Rc;
Expand Down Expand Up @@ -234,7 +234,6 @@
//! [downgrade]: struct.Rc.html#method.downgrade
//! [upgrade]: struct.Weak.html#method.upgrade
//! [`None`]: ../../std/option/enum.Option.html#variant.None
//! [assoc]: ../../book/first-edition/method-syntax.html#associated-functions
//! [mutability]: ../../std/cell/index.html#introducing-mutability-inside-of-something-immutable

#![stable(feature = "rust1", since = "1.0.0")]
Expand All @@ -256,6 +255,7 @@ use core::marker::{Unpin, Unsize, PhantomData};
use core::mem::{self, align_of_val, forget, size_of_val};
use core::ops::Deref;
use core::ops::CoerceUnsized;
use core::pin::Pin;
use core::ptr::{self, NonNull};
use core::convert::From;
use core::usize;
Expand All @@ -281,6 +281,7 @@ struct RcBox<T: ?Sized> {
/// type `T`.
///
/// [get_mut]: #method.get_mut
#[cfg_attr(all(not(stage0), not(test)), lang = "rc")]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Rc<T: ?Sized> {
ptr: NonNull<RcBox<T>>,
Expand Down Expand Up @@ -321,6 +322,11 @@ impl<T> Rc<T> {
}
}

#[unstable(feature = "pin", issue = "49150")]
pub fn pinned(value: T) -> Pin<Rc<T>> {
unsafe { Pin::new_unchecked(Rc::new(value)) }
}

/// Returns the contained value, if the `Rc` has exactly one strong reference.
///
/// Otherwise, an [`Err`][result] is returned with the same `Rc` that was
Expand Down Expand Up @@ -860,7 +866,7 @@ impl<T: ?Sized> Clone for Rc<T> {
///
/// let five = Rc::new(5);
///
/// Rc::clone(&five);
/// let _ = Rc::clone(&five);
/// ```
#[inline]
fn clone(&self) -> Rc<T> {
Expand Down Expand Up @@ -1297,7 +1303,7 @@ impl<T: ?Sized> Clone for Weak<T> {
///
/// let weak_five = Rc::downgrade(&Rc::new(5));
///
/// Weak::clone(&weak_five);
/// let _ = Weak::clone(&weak_five);
/// ```
#[inline]
fn clone(&self) -> Weak<T> {
Expand Down
22 changes: 19 additions & 3 deletions src/liballoc/slice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -123,8 +123,10 @@ pub use core::slice::{from_raw_parts, from_raw_parts_mut};
pub use core::slice::{from_ref, from_mut};
#[stable(feature = "slice_get_slice", since = "1.28.0")]
pub use core::slice::SliceIndex;
#[unstable(feature = "exact_chunks", issue = "47115")]
pub use core::slice::{ExactChunks, ExactChunksMut};
#[stable(feature = "chunks_exact", since = "1.31.0")]
pub use core::slice::{ChunksExact, ChunksExactMut};
#[stable(feature = "rchunks", since = "1.31.0")]
pub use core::slice::{RChunks, RChunksMut, RChunksExact, RChunksExactMut};

////////////////////////////////////////////////////////////////////////////////
// Basic slice extension methods
Expand Down Expand Up @@ -392,6 +394,10 @@ impl<T> [T] {

/// Creates a vector by repeating a slice `n` times.
///
/// # Panics
///
/// This function will panic if the capacity would overflow.
///
/// # Examples
///
/// Basic usage:
Expand All @@ -403,6 +409,16 @@ impl<T> [T] {
/// assert_eq!([1, 2].repeat(3), vec![1, 2, 1, 2, 1, 2]);
/// }
/// ```
///
/// A panic upon overflow:
///
/// ```should_panic
/// #![feature(repeat_generic_slice)]
/// fn main() {
/// // this will panic at runtime
/// b"0123456789abcdef".repeat(usize::max_value());
/// }
/// ```
#[unstable(feature = "repeat_generic_slice",
reason = "it's on str, why not on slice?",
issue = "48784")]
Expand All @@ -417,7 +433,7 @@ impl<T> [T] {
// and `rem` is the remaining part of `n`.

// Using `Vec` to access `set_len()`.
let mut buf = Vec::with_capacity(self.len() * n);
let mut buf = Vec::with_capacity(self.len().checked_mul(n).expect("capacity overflow"));

// `2^expn` repetition is done by doubling `buf` `expn`-times.
buf.extend(self);
Expand Down
14 changes: 14 additions & 0 deletions src/liballoc/str.rs
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,7 @@ impl Borrow<str> for String {
#[stable(feature = "rust1", since = "1.0.0")]
impl ToOwned for str {
type Owned = String;
#[inline]
fn to_owned(&self) -> String {
unsafe { String::from_utf8_unchecked(self.as_bytes().to_owned()) }
}
Expand Down Expand Up @@ -515,6 +516,10 @@ impl str {

/// Creates a new [`String`] by repeating a string `n` times.
///
/// # Panics
///
/// This function will panic if the capacity would overflow.
///
/// [`String`]: string/struct.String.html
///
/// # Examples
Expand All @@ -524,6 +529,15 @@ impl str {
/// ```
/// assert_eq!("abc".repeat(4), String::from("abcabcabcabc"));
/// ```
///
/// A panic upon overflow:
///
/// ```should_panic
/// fn main() {
/// // this will panic at runtime
/// "0123456789abcdef".repeat(usize::max_value());
/// }
/// ```
#[stable(feature = "repeat_str", since = "1.16.0")]
pub fn repeat(&self, n: usize) -> String {
unsafe { String::from_utf8_unchecked(self.as_bytes().repeat(n)) }
Expand Down
1 change: 1 addition & 0 deletions src/liballoc/string.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2196,6 +2196,7 @@ impl AsRef<[u8]> for String {

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a> From<&'a str> for String {
#[inline]
fn from(s: &'a str) -> String {
s.to_owned()
}
Expand Down
16 changes: 11 additions & 5 deletions src/liballoc/sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ use core::intrinsics::abort;
use core::mem::{self, align_of_val, size_of_val};
use core::ops::Deref;
use core::ops::CoerceUnsized;
use core::pin::Pin;
use core::ptr::{self, NonNull};
use core::marker::{Unpin, Unsize, PhantomData};
use core::hash::{Hash, Hasher};
Expand Down Expand Up @@ -119,8 +120,8 @@ const MAX_REFCOUNT: usize = (isize::MAX) as usize;
///
/// `Arc<T>` automatically dereferences to `T` (via the [`Deref`][deref] trait),
/// so you can call `T`'s methods on a value of type `Arc<T>`. To avoid name
/// clashes with `T`'s methods, the methods of `Arc<T>` itself are [associated
/// functions][assoc], called using function-like syntax:
/// clashes with `T`'s methods, the methods of `Arc<T>` itself are associated
/// functions, called using function-like syntax:
///
/// ```
/// use std::sync::Arc;
Expand All @@ -145,7 +146,6 @@ const MAX_REFCOUNT: usize = (isize::MAX) as usize;
/// [downgrade]: struct.Arc.html#method.downgrade
/// [upgrade]: struct.Weak.html#method.upgrade
/// [`None`]: ../../std/option/enum.Option.html#variant.None
/// [assoc]: ../../book/first-edition/method-syntax.html#associated-functions
/// [`RefCell<T>`]: ../../std/cell/struct.RefCell.html
/// [`std::sync`]: ../../std/sync/index.html
/// [`Arc::clone(&from)`]: #method.clone
Expand Down Expand Up @@ -198,6 +198,7 @@ const MAX_REFCOUNT: usize = (isize::MAX) as usize;
/// counting in general.
///
/// [rc_examples]: ../../std/rc/index.html#examples
#[cfg_attr(all(not(stage0), not(test)), lang = "arc")]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Arc<T: ?Sized> {
ptr: NonNull<ArcInner<T>>,
Expand Down Expand Up @@ -297,6 +298,11 @@ impl<T> Arc<T> {
Arc { ptr: Box::into_raw_non_null(x), phantom: PhantomData }
}

#[unstable(feature = "pin", issue = "49150")]
pub fn pinned(data: T) -> Pin<Arc<T>> {
unsafe { Pin::new_unchecked(Arc::new(data)) }
}

/// Returns the contained value, if the `Arc` has exactly one strong reference.
///
/// Otherwise, an [`Err`][result] is returned with the same `Arc` that was
Expand Down Expand Up @@ -706,7 +712,7 @@ impl<T: ?Sized> Clone for Arc<T> {
///
/// let five = Arc::new(5);
///
/// Arc::clone(&five);
/// let _ = Arc::clone(&five);
/// ```
#[inline]
fn clone(&self) -> Arc<T> {
Expand Down Expand Up @@ -1128,7 +1134,7 @@ impl<T: ?Sized> Clone for Weak<T> {
///
/// let weak_five = Arc::downgrade(&Arc::new(5));
///
/// Weak::clone(&weak_five);
/// let _ = Weak::clone(&weak_five);
/// ```
#[inline]
fn clone(&self) -> Weak<T> {
Expand Down
4 changes: 1 addition & 3 deletions src/liballoc/tests/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,14 @@
#![feature(allocator_api)]
#![feature(alloc_system)]
#![feature(box_syntax)]
#![cfg_attr(stage0, feature(const_fn))]
#![cfg_attr(not(stage0), feature(min_const_fn))]
#![cfg_attr(stage0, feature(min_const_fn))]
#![feature(drain_filter)]
#![feature(exact_size_is_empty)]
#![feature(pattern)]
#![feature(slice_sort_by_cached_key)]
#![feature(str_escape)]
#![feature(try_reserve)]
#![feature(unboxed_closures)]
#![feature(exact_chunks)]
#![feature(repeat_generic_slice)]

extern crate alloc_system;
Expand Down
144 changes: 128 additions & 16 deletions src/liballoc/tests/slice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -975,27 +975,75 @@ fn test_chunksator_0() {
}

#[test]
fn test_exact_chunksator() {
fn test_chunks_exactator() {
let v = &[1, 2, 3, 4, 5];

assert_eq!(v.exact_chunks(2).len(), 2);
assert_eq!(v.chunks_exact(2).len(), 2);

let chunks: &[&[_]] = &[&[1, 2], &[3, 4]];
assert_eq!(v.exact_chunks(2).collect::<Vec<_>>(), chunks);
assert_eq!(v.chunks_exact(2).collect::<Vec<_>>(), chunks);
let chunks: &[&[_]] = &[&[1, 2, 3]];
assert_eq!(v.exact_chunks(3).collect::<Vec<_>>(), chunks);
assert_eq!(v.chunks_exact(3).collect::<Vec<_>>(), chunks);
let chunks: &[&[_]] = &[];
assert_eq!(v.exact_chunks(6).collect::<Vec<_>>(), chunks);
assert_eq!(v.chunks_exact(6).collect::<Vec<_>>(), chunks);

let chunks: &[&[_]] = &[&[3, 4], &[1, 2]];
assert_eq!(v.exact_chunks(2).rev().collect::<Vec<_>>(), chunks);
assert_eq!(v.chunks_exact(2).rev().collect::<Vec<_>>(), chunks);
}

#[test]
#[should_panic]
fn test_exact_chunksator_0() {
fn test_chunks_exactator_0() {
let v = &[1, 2, 3, 4];
let _it = v.exact_chunks(0);
let _it = v.chunks_exact(0);
}

#[test]
fn test_rchunksator() {
let v = &[1, 2, 3, 4, 5];

assert_eq!(v.rchunks(2).len(), 3);

let chunks: &[&[_]] = &[&[4, 5], &[2, 3], &[1]];
assert_eq!(v.rchunks(2).collect::<Vec<_>>(), chunks);
let chunks: &[&[_]] = &[&[3, 4, 5], &[1, 2]];
assert_eq!(v.rchunks(3).collect::<Vec<_>>(), chunks);
let chunks: &[&[_]] = &[&[1, 2, 3, 4, 5]];
assert_eq!(v.rchunks(6).collect::<Vec<_>>(), chunks);

let chunks: &[&[_]] = &[&[1], &[2, 3], &[4, 5]];
assert_eq!(v.rchunks(2).rev().collect::<Vec<_>>(), chunks);
}

#[test]
#[should_panic]
fn test_rchunksator_0() {
let v = &[1, 2, 3, 4];
let _it = v.rchunks(0);
}

#[test]
fn test_rchunks_exactator() {
let v = &[1, 2, 3, 4, 5];

assert_eq!(v.rchunks_exact(2).len(), 2);

let chunks: &[&[_]] = &[&[4, 5], &[2, 3]];
assert_eq!(v.rchunks_exact(2).collect::<Vec<_>>(), chunks);
let chunks: &[&[_]] = &[&[3, 4, 5]];
assert_eq!(v.rchunks_exact(3).collect::<Vec<_>>(), chunks);
let chunks: &[&[_]] = &[];
assert_eq!(v.rchunks_exact(6).collect::<Vec<_>>(), chunks);

let chunks: &[&[_]] = &[&[2, 3], &[4, 5]];
assert_eq!(v.rchunks_exact(2).rev().collect::<Vec<_>>(), chunks);
}

#[test]
#[should_panic]
fn test_rchunks_exactator_0() {
let v = &[1, 2, 3, 4];
let _it = v.rchunks_exact(0);
}

#[test]
Expand Down Expand Up @@ -1205,7 +1253,7 @@ fn test_get_mut() {
#[test]
fn test_mut_chunks() {
let mut v = [0, 1, 2, 3, 4, 5, 6];
assert_eq!(v.chunks_mut(2).len(), 4);
assert_eq!(v.chunks_mut(3).len(), 3);
for (i, chunk) in v.chunks_mut(3).enumerate() {
for x in chunk {
*x = i as u8;
Expand Down Expand Up @@ -1235,10 +1283,10 @@ fn test_mut_chunks_0() {
}

#[test]
fn test_mut_exact_chunks() {
fn test_mut_chunks_exact() {
let mut v = [0, 1, 2, 3, 4, 5, 6];
assert_eq!(v.exact_chunks_mut(2).len(), 3);
for (i, chunk) in v.exact_chunks_mut(3).enumerate() {
assert_eq!(v.chunks_exact_mut(3).len(), 2);
for (i, chunk) in v.chunks_exact_mut(3).enumerate() {
for x in chunk {
*x = i as u8;
}
Expand All @@ -1248,9 +1296,9 @@ fn test_mut_exact_chunks() {
}

#[test]
fn test_mut_exact_chunks_rev() {
fn test_mut_chunks_exact_rev() {
let mut v = [0, 1, 2, 3, 4, 5, 6];
for (i, chunk) in v.exact_chunks_mut(3).rev().enumerate() {
for (i, chunk) in v.chunks_exact_mut(3).rev().enumerate() {
for x in chunk {
*x = i as u8;
}
Expand All @@ -1261,9 +1309,73 @@ fn test_mut_exact_chunks_rev() {

#[test]
#[should_panic]
fn test_mut_exact_chunks_0() {
fn test_mut_chunks_exact_0() {
let mut v = [1, 2, 3, 4];
let _it = v.chunks_exact_mut(0);
}

#[test]
fn test_mut_rchunks() {
let mut v = [0, 1, 2, 3, 4, 5, 6];
assert_eq!(v.rchunks_mut(3).len(), 3);
for (i, chunk) in v.rchunks_mut(3).enumerate() {
for x in chunk {
*x = i as u8;
}
}
let result = [2, 1, 1, 1, 0, 0, 0];
assert_eq!(v, result);
}

#[test]
fn test_mut_rchunks_rev() {
let mut v = [0, 1, 2, 3, 4, 5, 6];
for (i, chunk) in v.rchunks_mut(3).rev().enumerate() {
for x in chunk {
*x = i as u8;
}
}
let result = [0, 1, 1, 1, 2, 2, 2];
assert_eq!(v, result);
}

#[test]
#[should_panic]
fn test_mut_rchunks_0() {
let mut v = [1, 2, 3, 4];
let _it = v.rchunks_mut(0);
}

#[test]
fn test_mut_rchunks_exact() {
let mut v = [0, 1, 2, 3, 4, 5, 6];
assert_eq!(v.rchunks_exact_mut(3).len(), 2);
for (i, chunk) in v.rchunks_exact_mut(3).enumerate() {
for x in chunk {
*x = i as u8;
}
}
let result = [0, 1, 1, 1, 0, 0, 0];
assert_eq!(v, result);
}

#[test]
fn test_mut_rchunks_exact_rev() {
let mut v = [0, 1, 2, 3, 4, 5, 6];
for (i, chunk) in v.rchunks_exact_mut(3).rev().enumerate() {
for x in chunk {
*x = i as u8;
}
}
let result = [0, 0, 0, 0, 1, 1, 1];
assert_eq!(v, result);
}

#[test]
#[should_panic]
fn test_mut_rchunks_exact_0() {
let mut v = [1, 2, 3, 4];
let _it = v.exact_chunks_mut(0);
let _it = v.rchunks_exact_mut(0);
}

#[test]
Expand Down
112 changes: 20 additions & 92 deletions src/liballoc/vec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,11 +120,17 @@ use raw_vec::RawVec;
/// assert_eq!(vec, [1, 2, 3, 4]);
/// ```
///
/// It can also initialize each element of a `Vec<T>` with a given value:
/// It can also initialize each element of a `Vec<T>` with a given value.
/// This may be more efficient than performing allocation and initialization
/// in separate steps, especially when initializing a vector of zeros:
///
/// ```
/// let vec = vec![0; 5];
/// assert_eq!(vec, [0, 0, 0, 0, 0]);
///
/// // The following is equivalent, but potentially slower:
/// let mut vec1 = Vec::with_capacity(5);
/// vec1.resize(5, 0);
/// ```
///
/// Use a `Vec<T>` as an efficient stack:
Expand Down Expand Up @@ -947,10 +953,9 @@ impl<T> Vec<T> {
/// Removes all but the first of consecutive elements in the vector satisfying a given equality
/// relation.
///
/// The `same_bucket` function is passed references to two elements from the vector, and
/// returns `true` if the elements compare equal, or `false` if they do not. The elements are
/// passed in opposite order from their order in the vector, so if `same_bucket(a, b)` returns
/// `true`, `a` is removed.
/// The `same_bucket` function is passed references to two elements from the vector and
/// must determine if the elements compare equal. The elements are passed in opposite order
/// from their order in the slice, so if `same_bucket(a, b)` returns `true`, `a` is removed.
///
/// If the vector is sorted, this removes all duplicates.
///
Expand All @@ -964,90 +969,12 @@ impl<T> Vec<T> {
/// assert_eq!(vec, ["foo", "bar", "baz", "bar"]);
/// ```
#[stable(feature = "dedup_by", since = "1.16.0")]
pub fn dedup_by<F>(&mut self, mut same_bucket: F) where F: FnMut(&mut T, &mut T) -> bool {
unsafe {
// Although we have a mutable reference to `self`, we cannot make
// *arbitrary* changes. The `same_bucket` calls could panic, so we
// must ensure that the vector is in a valid state at all time.
//
// The way that we handle this is by using swaps; we iterate
// over all the elements, swapping as we go so that at the end
// the elements we wish to keep are in the front, and those we
// wish to reject are at the back. We can then truncate the
// vector. This operation is still O(n).
//
// Example: We start in this state, where `r` represents "next
// read" and `w` represents "next_write`.
//
// r
// +---+---+---+---+---+---+
// | 0 | 1 | 1 | 2 | 3 | 3 |
// +---+---+---+---+---+---+
// w
//
// Comparing self[r] against self[w-1], this is not a duplicate, so
// we swap self[r] and self[w] (no effect as r==w) and then increment both
// r and w, leaving us with:
//
// r
// +---+---+---+---+---+---+
// | 0 | 1 | 1 | 2 | 3 | 3 |
// +---+---+---+---+---+---+
// w
//
// Comparing self[r] against self[w-1], this value is a duplicate,
// so we increment `r` but leave everything else unchanged:
//
// r
// +---+---+---+---+---+---+
// | 0 | 1 | 1 | 2 | 3 | 3 |
// +---+---+---+---+---+---+
// w
//
// Comparing self[r] against self[w-1], this is not a duplicate,
// so swap self[r] and self[w] and advance r and w:
//
// r
// +---+---+---+---+---+---+
// | 0 | 1 | 2 | 1 | 3 | 3 |
// +---+---+---+---+---+---+
// w
//
// Not a duplicate, repeat:
//
// r
// +---+---+---+---+---+---+
// | 0 | 1 | 2 | 3 | 1 | 3 |
// +---+---+---+---+---+---+
// w
//
// Duplicate, advance r. End of vec. Truncate to w.

let ln = self.len();
if ln <= 1 {
return;
}

// Avoid bounds checks by using raw pointers.
let p = self.as_mut_ptr();
let mut r: usize = 1;
let mut w: usize = 1;

while r < ln {
let p_r = p.add(r);
let p_wm1 = p.add(w - 1);
if !same_bucket(&mut *p_r, &mut *p_wm1) {
if r != w {
let p_w = p_wm1.offset(1);
mem::swap(&mut *p_r, &mut *p_w);
}
w += 1;
}
r += 1;
}

self.truncate(w);
}
pub fn dedup_by<F>(&mut self, same_bucket: F) where F: FnMut(&mut T, &mut T) -> bool {
let len = {
let (dedup, _) = self.as_mut_slice().partition_dedup_by(same_bucket);
dedup.len()
};
self.truncate(len);
}

/// Appends an element to the back of a collection.
Expand Down Expand Up @@ -1533,7 +1460,8 @@ impl<'a> Drop for SetLenOnDrop<'a> {
}

impl<T: PartialEq> Vec<T> {
/// Removes consecutive repeated elements in the vector.
/// Removes consecutive repeated elements in the vector according to the
/// [`PartialEq`] trait implementation.
///
/// If the vector is sorted, this removes all duplicates.
///
Expand Down Expand Up @@ -1900,12 +1828,12 @@ impl<T, I> SpecExtend<T, I> for Vec<T>
unsafe {
let mut ptr = self.as_mut_ptr().add(self.len());
let mut local_len = SetLenOnDrop::new(&mut self.len);
for element in iterator {
iterator.for_each(move |element| {
ptr::write(ptr, element);
ptr = ptr.offset(1);
// NB can't overflow since we would have had to alloc the address space
local_len.increment_len(1);
}
});
}
} else {
self.extend_desugared(iterator)
Expand Down
6 changes: 1 addition & 5 deletions src/liballoc_jemalloc/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
#![feature(core_intrinsics)]
#![feature(libc)]
#![feature(linkage)]
#![cfg_attr(not(stage0), feature(nll))]
#![feature(nll)]
#![feature(staged_api)]
#![feature(rustc_attrs)]
#![cfg_attr(dummy_jemalloc, allow(dead_code, unused_extern_crates))]
Expand Down Expand Up @@ -90,15 +90,13 @@ mod contents {
// ABI

#[rustc_std_internal_symbol]
#[cfg_attr(stage0, no_mangle)]
pub unsafe extern fn __rde_alloc(size: usize, align: usize) -> *mut u8 {
let flags = align_to_flags(align, size);
let ptr = mallocx(size as size_t, flags) as *mut u8;
ptr
}

#[rustc_std_internal_symbol]
#[cfg_attr(stage0, no_mangle)]
pub unsafe extern fn __rde_dealloc(ptr: *mut u8,
size: usize,
align: usize) {
Expand All @@ -107,7 +105,6 @@ mod contents {
}

#[rustc_std_internal_symbol]
#[cfg_attr(stage0, no_mangle)]
pub unsafe extern fn __rde_realloc(ptr: *mut u8,
_old_size: usize,
align: usize,
Expand All @@ -118,7 +115,6 @@ mod contents {
}

#[rustc_std_internal_symbol]
#[cfg_attr(stage0, no_mangle)]
pub unsafe extern fn __rde_alloc_zeroed(size: usize, align: usize) -> *mut u8 {
let ptr = if align <= MIN_ALIGN && align <= size {
calloc(size as size_t, 1) as *mut u8
Expand Down
55 changes: 53 additions & 2 deletions src/liballoc_system/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,13 @@

#![feature(allocator_api)]
#![feature(core_intrinsics)]
#![cfg_attr(not(stage0), feature(nll))]
#![feature(nll)]
#![feature(staged_api)]
#![feature(rustc_attrs)]
#![cfg_attr(
all(target_arch = "wasm32", not(target_os = "emscripten")),
feature(integer_atomics, stdsimd)
)]
#![cfg_attr(any(unix, target_os = "cloudabi", target_os = "redox"), feature(libc))]
#![rustc_alloc_kind = "lib"]

Expand Down Expand Up @@ -331,29 +335,76 @@ mod platform {
use core::alloc::{GlobalAlloc, Layout};
use System;

// No need for synchronization here as wasm is currently single-threaded
static mut DLMALLOC: dlmalloc::Dlmalloc = dlmalloc::DLMALLOC_INIT;

#[stable(feature = "alloc_system_type", since = "1.28.0")]
unsafe impl GlobalAlloc for System {
#[inline]
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
let _lock = lock::lock();
DLMALLOC.malloc(layout.size(), layout.align())
}

#[inline]
unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 {
let _lock = lock::lock();
DLMALLOC.calloc(layout.size(), layout.align())
}

#[inline]
unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
let _lock = lock::lock();
DLMALLOC.free(ptr, layout.size(), layout.align())
}

#[inline]
unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
let _lock = lock::lock();
DLMALLOC.realloc(ptr, layout.size(), layout.align(), new_size)
}
}

#[cfg(target_feature = "atomics")]
mod lock {
use core::arch::wasm32;
use core::sync::atomic::{AtomicI32, Ordering::SeqCst};

static LOCKED: AtomicI32 = AtomicI32::new(0);

pub struct DropLock;

pub fn lock() -> DropLock {
loop {
if LOCKED.swap(1, SeqCst) == 0 {
return DropLock
}
unsafe {
let r = wasm32::atomic::wait_i32(
&LOCKED as *const AtomicI32 as *mut i32,
1, // expected value
-1, // timeout
);
debug_assert!(r == 0 || r == 1);
}
}
}

impl Drop for DropLock {
fn drop(&mut self) {
let r = LOCKED.swap(0, SeqCst);
debug_assert_eq!(r, 1);
unsafe {
wasm32::atomic::wake(
&LOCKED as *const AtomicI32 as *mut i32,
1, // only one thread
);
}
}
}
}

#[cfg(not(target_feature = "atomics"))]
mod lock {
pub fn lock() {} // no atomics, no threads, that's easy!
}
}
56 changes: 24 additions & 32 deletions src/libarena/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
#![feature(alloc)]
#![feature(core_intrinsics)]
#![feature(dropck_eyepatch)]
#![cfg_attr(not(stage0), feature(nll))]
#![feature(nll)]
#![feature(raw_vec_internals)]
#![cfg_attr(test, feature(test))]

Expand Down Expand Up @@ -114,10 +114,9 @@ impl<T> TypedArenaChunk<T> {

const PAGE: usize = 4096;

impl<T> TypedArena<T> {
impl<T> Default for TypedArena<T> {
/// Creates a new `TypedArena`.
#[inline]
pub fn new() -> TypedArena<T> {
fn default() -> TypedArena<T> {
TypedArena {
// We set both `ptr` and `end` to 0 so that the first call to
// alloc() will trigger a grow().
Expand All @@ -127,7 +126,9 @@ impl<T> TypedArena<T> {
_own: PhantomData,
}
}
}

impl<T> TypedArena<T> {
/// Allocates an object in the `TypedArena`, returning a reference to it.
#[inline]
pub fn alloc(&self, object: T) -> &mut T {
Expand Down Expand Up @@ -296,15 +297,17 @@ pub struct DroplessArena {

unsafe impl Send for DroplessArena {}

impl DroplessArena {
pub fn new() -> DroplessArena {
impl Default for DroplessArena {
fn default() -> DroplessArena {
DroplessArena {
ptr: Cell::new(0 as *mut u8),
end: Cell::new(0 as *mut u8),
chunks: RefCell::new(vec![]),
chunks: Default::default(),
}
}
}

impl DroplessArena {
pub fn in_arena<T: ?Sized>(&self, ptr: *const T) -> bool {
let ptr = ptr as *const u8 as *mut u8;
for chunk in &*self.chunks.borrow() {
Expand Down Expand Up @@ -419,18 +422,13 @@ impl DroplessArena {
}
}

#[derive(Default)]
// FIXME(@Zoxc): this type is entirely unused in rustc
pub struct SyncTypedArena<T> {
lock: MTLock<TypedArena<T>>,
}

impl<T> SyncTypedArena<T> {
#[inline(always)]
pub fn new() -> SyncTypedArena<T> {
SyncTypedArena {
lock: MTLock::new(TypedArena::new())
}
}

#[inline(always)]
pub fn alloc(&self, object: T) -> &mut T {
// Extend the lifetime of the result since it's limited to the lock guard
Expand All @@ -452,18 +450,12 @@ impl<T> SyncTypedArena<T> {
}
}

#[derive(Default)]
pub struct SyncDroplessArena {
lock: MTLock<DroplessArena>,
}

impl SyncDroplessArena {
#[inline(always)]
pub fn new() -> SyncDroplessArena {
SyncDroplessArena {
lock: MTLock::new(DroplessArena::new())
}
}

#[inline(always)]
pub fn in_arena<T: ?Sized>(&self, ptr: *const T) -> bool {
self.lock.lock().in_arena(ptr)
Expand Down Expand Up @@ -508,7 +500,7 @@ mod tests {

#[test]
pub fn test_unused() {
let arena: TypedArena<Point> = TypedArena::new();
let arena: TypedArena<Point> = TypedArena::default();
assert!(arena.chunks.borrow().is_empty());
}

Expand Down Expand Up @@ -546,7 +538,7 @@ mod tests {
}
}

let arena = Wrap(TypedArena::new());
let arena = Wrap(TypedArena::default());

let result = arena.alloc_outer(|| Outer {
inner: arena.alloc_inner(|| Inner { value: 10 }),
Expand All @@ -557,15 +549,15 @@ mod tests {

#[test]
pub fn test_copy() {
let arena = TypedArena::new();
let arena = TypedArena::default();
for _ in 0..100000 {
arena.alloc(Point { x: 1, y: 2, z: 3 });
}
}

#[bench]
pub fn bench_copy(b: &mut Bencher) {
let arena = TypedArena::new();
let arena = TypedArena::default();
b.iter(|| arena.alloc(Point { x: 1, y: 2, z: 3 }))
}

Expand All @@ -584,7 +576,7 @@ mod tests {

#[test]
pub fn test_noncopy() {
let arena = TypedArena::new();
let arena = TypedArena::default();
for _ in 0..100000 {
arena.alloc(Noncopy {
string: "hello world".to_string(),
Expand All @@ -595,15 +587,15 @@ mod tests {

#[test]
pub fn test_typed_arena_zero_sized() {
let arena = TypedArena::new();
let arena = TypedArena::default();
for _ in 0..100000 {
arena.alloc(());
}
}

#[test]
pub fn test_typed_arena_clear() {
let mut arena = TypedArena::new();
let mut arena = TypedArena::default();
for _ in 0..10 {
arena.clear();
for _ in 0..10000 {
Expand All @@ -628,7 +620,7 @@ mod tests {
fn test_typed_arena_drop_count() {
let counter = Cell::new(0);
{
let arena: TypedArena<DropCounter> = TypedArena::new();
let arena: TypedArena<DropCounter> = TypedArena::default();
for _ in 0..100 {
// Allocate something with drop glue to make sure it doesn't leak.
arena.alloc(DropCounter { count: &counter });
Expand All @@ -640,7 +632,7 @@ mod tests {
#[test]
fn test_typed_arena_drop_on_clear() {
let counter = Cell::new(0);
let mut arena: TypedArena<DropCounter> = TypedArena::new();
let mut arena: TypedArena<DropCounter> = TypedArena::default();
for i in 0..10 {
for _ in 0..100 {
// Allocate something with drop glue to make sure it doesn't leak.
Expand All @@ -667,7 +659,7 @@ mod tests {
fn test_typed_arena_drop_small_count() {
DROP_COUNTER.with(|c| c.set(0));
{
let arena: TypedArena<SmallDroppable> = TypedArena::new();
let arena: TypedArena<SmallDroppable> = TypedArena::default();
for _ in 0..100 {
// Allocate something with drop glue to make sure it doesn't leak.
arena.alloc(SmallDroppable);
Expand All @@ -679,7 +671,7 @@ mod tests {

#[bench]
pub fn bench_noncopy(b: &mut Bencher) {
let arena = TypedArena::new();
let arena = TypedArena::default();
b.iter(|| {
arena.alloc(Noncopy {
string: "hello world".to_string(),
Expand Down
2 changes: 1 addition & 1 deletion src/libcore/alloc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -518,7 +518,7 @@ pub unsafe trait GlobalAlloc {
/// The block is described by the given `ptr` pointer and `layout`.
///
/// If this returns a non-null pointer, then ownership of the memory block
/// referenced by `ptr` has been transferred to this alloctor.
/// referenced by `ptr` has been transferred to this allocator.
/// The memory may or may not have been deallocated,
/// and should be considered unusable (unless of course it was
/// transferred back to the caller again via the return value of
Expand Down
6 changes: 3 additions & 3 deletions src/libcore/borrow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -226,16 +226,16 @@ impl<T: ?Sized> BorrowMut<T> for T {
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T: ?Sized> Borrow<T> for &'a T {
impl<T: ?Sized> Borrow<T> for &T {
fn borrow(&self) -> &T { &**self }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T: ?Sized> Borrow<T> for &'a mut T {
impl<T: ?Sized> Borrow<T> for &mut T {
fn borrow(&self) -> &T { &**self }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T: ?Sized> BorrowMut<T> for &'a mut T {
impl<T: ?Sized> BorrowMut<T> for &mut T {
fn borrow_mut(&mut self) -> &mut T { &mut **self }
}
18 changes: 9 additions & 9 deletions src/libcore/cell.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1092,7 +1092,7 @@ impl<'b> BorrowRef<'b> {
}
}

impl<'b> Drop for BorrowRef<'b> {
impl Drop for BorrowRef<'_> {
#[inline]
fn drop(&mut self) {
let borrow = self.borrow.get();
Expand All @@ -1101,9 +1101,9 @@ impl<'b> Drop for BorrowRef<'b> {
}
}

impl<'b> Clone for BorrowRef<'b> {
impl Clone for BorrowRef<'_> {
#[inline]
fn clone(&self) -> BorrowRef<'b> {
fn clone(&self) -> Self {
// Since this Ref exists, we know the borrow flag
// is a reading borrow.
let borrow = self.borrow.get();
Expand All @@ -1127,7 +1127,7 @@ pub struct Ref<'b, T: ?Sized + 'b> {
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'b, T: ?Sized> Deref for Ref<'b, T> {
impl<T: ?Sized> Deref for Ref<'_, T> {
type Target = T;

#[inline]
Expand Down Expand Up @@ -1219,7 +1219,7 @@ impl<'b, T: ?Sized> Ref<'b, T> {
impl<'b, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Ref<'b, U>> for Ref<'b, T> {}

#[stable(feature = "std_guard_impls", since = "1.20.0")]
impl<'a, T: ?Sized + fmt::Display> fmt::Display for Ref<'a, T> {
impl<T: ?Sized + fmt::Display> fmt::Display for Ref<'_, T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.value.fmt(f)
}
Expand Down Expand Up @@ -1305,7 +1305,7 @@ struct BorrowRefMut<'b> {
borrow: &'b Cell<BorrowFlag>,
}

impl<'b> Drop for BorrowRefMut<'b> {
impl Drop for BorrowRefMut<'_> {
#[inline]
fn drop(&mut self) {
let borrow = self.borrow.get();
Expand Down Expand Up @@ -1356,7 +1356,7 @@ pub struct RefMut<'b, T: ?Sized + 'b> {
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'b, T: ?Sized> Deref for RefMut<'b, T> {
impl<T: ?Sized> Deref for RefMut<'_, T> {
type Target = T;

#[inline]
Expand All @@ -1366,7 +1366,7 @@ impl<'b, T: ?Sized> Deref for RefMut<'b, T> {
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'b, T: ?Sized> DerefMut for RefMut<'b, T> {
impl<T: ?Sized> DerefMut for RefMut<'_, T> {
#[inline]
fn deref_mut(&mut self) -> &mut T {
self.value
Expand All @@ -1377,7 +1377,7 @@ impl<'b, T: ?Sized> DerefMut for RefMut<'b, T> {
impl<'b, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<RefMut<'b, U>> for RefMut<'b, T> {}

#[stable(feature = "std_guard_impls", since = "1.20.0")]
impl<'a, T: ?Sized + fmt::Display> fmt::Display for RefMut<'a, T> {
impl<T: ?Sized + fmt::Display> fmt::Display for RefMut<'_, T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.value.fmt(f)
}
Expand Down
32 changes: 28 additions & 4 deletions src/libcore/char/convert.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ use super::MAX;
/// Converts a `u32` to a `char`.
///
/// Note that all [`char`]s are valid [`u32`]s, and can be cast to one with
/// [`as`]:
/// `as`:
///
/// ```
/// let c = '💯';
Expand All @@ -34,7 +34,6 @@ use super::MAX;
///
/// [`char`]: ../../std/primitive.char.html
/// [`u32`]: ../../std/primitive.u32.html
/// [`as`]: ../../book/first-edition/casting-between-types.html#as
///
/// For an unsafe version of this function which ignores these checks, see
/// [`from_u32_unchecked`].
Expand Down Expand Up @@ -71,7 +70,7 @@ pub fn from_u32(i: u32) -> Option<char> {
/// Converts a `u32` to a `char`, ignoring validity.
///
/// Note that all [`char`]s are valid [`u32`]s, and can be cast to one with
/// [`as`]:
/// `as`:
///
/// ```
/// let c = '💯';
Expand All @@ -86,7 +85,6 @@ pub fn from_u32(i: u32) -> Option<char> {
///
/// [`char`]: ../../std/primitive.char.html
/// [`u32`]: ../../std/primitive.u32.html
/// [`as`]: ../../book/first-edition/casting-between-types.html#as
///
/// # Safety
///
Expand Down Expand Up @@ -115,6 +113,19 @@ pub unsafe fn from_u32_unchecked(i: u32) -> char {

#[stable(feature = "char_convert", since = "1.13.0")]
impl From<char> for u32 {
/// Converts a [`char`] into a [`u32`].
///
/// # Examples
///
/// ```
/// use std::mem;
///
/// fn main() {
/// let c = 'c';
/// let u = u32::from(c);
/// assert!(4 == mem::size_of_val(&u))
/// }
/// ```
#[inline]
fn from(c: char) -> Self {
c as u32
Expand All @@ -141,6 +152,19 @@ impl From<char> for u32 {
/// C0 and C1 control codes.
#[stable(feature = "char_convert", since = "1.13.0")]
impl From<u8> for char {
/// Converts a [`u8`] into a [`char`].
///
/// # Examples
///
/// ```
/// use std::mem;
///
/// fn main() {
/// let u = 32 as u8;
/// let c = char::from(u);
/// assert!(4 == mem::size_of_val(&c))
/// }
/// ```
#[inline]
fn from(i: u8) -> Self {
i as char
Expand Down
2 changes: 1 addition & 1 deletion src/libcore/clone.rs
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ mod impls {

// Shared references can be cloned, but mutable references *cannot*!
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T: ?Sized> Clone for &'a T {
impl<T: ?Sized> Clone for &T {
#[inline]
fn clone(&self) -> Self {
*self
Expand Down
12 changes: 6 additions & 6 deletions src/libcore/cmp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1033,12 +1033,12 @@ mod impls {
fn gt(&self, other: & &'b B) -> bool { PartialOrd::gt(*self, *other) }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, A: ?Sized> Ord for &'a A where A: Ord {
impl<A: ?Sized> Ord for &A where A: Ord {
#[inline]
fn cmp(&self, other: & &'a A) -> Ordering { Ord::cmp(*self, *other) }
fn cmp(&self, other: &Self) -> Ordering { Ord::cmp(*self, *other) }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, A: ?Sized> Eq for &'a A where A: Eq {}
impl<A: ?Sized> Eq for &A where A: Eq {}

// &mut pointers

Expand All @@ -1065,12 +1065,12 @@ mod impls {
fn gt(&self, other: &&'b mut B) -> bool { PartialOrd::gt(*self, *other) }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, A: ?Sized> Ord for &'a mut A where A: Ord {
impl<A: ?Sized> Ord for &mut A where A: Ord {
#[inline]
fn cmp(&self, other: &&'a mut A) -> Ordering { Ord::cmp(*self, *other) }
fn cmp(&self, other: &Self) -> Ordering { Ord::cmp(*self, *other) }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, A: ?Sized> Eq for &'a mut A where A: Eq {}
impl<A: ?Sized> Eq for &mut A where A: Eq {}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, 'b, A: ?Sized, B: ?Sized> PartialEq<&'b mut B> for &'a A where A: PartialEq<B> {
Expand Down
6 changes: 3 additions & 3 deletions src/libcore/convert.rs
Original file line number Diff line number Diff line change
Expand Up @@ -407,7 +407,7 @@ pub trait TryFrom<T>: Sized {

// As lifts over &
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T: ?Sized, U: ?Sized> AsRef<U> for &'a T where T: AsRef<U>
impl<T: ?Sized, U: ?Sized> AsRef<U> for &T where T: AsRef<U>
{
fn as_ref(&self) -> &U {
<T as AsRef<U>>::as_ref(*self)
Expand All @@ -416,7 +416,7 @@ impl<'a, T: ?Sized, U: ?Sized> AsRef<U> for &'a T where T: AsRef<U>

// As lifts over &mut
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T: ?Sized, U: ?Sized> AsRef<U> for &'a mut T where T: AsRef<U>
impl<T: ?Sized, U: ?Sized> AsRef<U> for &mut T where T: AsRef<U>
{
fn as_ref(&self) -> &U {
<T as AsRef<U>>::as_ref(*self)
Expand All @@ -433,7 +433,7 @@ impl<'a, T: ?Sized, U: ?Sized> AsRef<U> for &'a mut T where T: AsRef<U>

// AsMut lifts over &mut
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T: ?Sized, U: ?Sized> AsMut<U> for &'a mut T where T: AsMut<U>
impl<T: ?Sized, U: ?Sized> AsMut<U> for &mut T where T: AsMut<U>
{
fn as_mut(&mut self) -> &mut U {
(*self).as_mut()
Expand Down
2 changes: 1 addition & 1 deletion src/libcore/fmt/builders.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ impl<'a> PadAdapter<'a> {
}
}

impl<'a> fmt::Write for PadAdapter<'a> {
impl fmt::Write for PadAdapter<'_> {
fn write_str(&mut self, mut s: &str) -> fmt::Result {
while !s.is_empty() {
if self.on_newline {
Expand Down
31 changes: 15 additions & 16 deletions src/libcore/fmt/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,9 +96,8 @@ pub type Result = result::Result<(), Error>;
/// use std::fmt::{self, write};
///
/// let mut output = String::new();
/// match write(&mut output, format_args!("Hello {}!", "world")) {
/// Err(fmt::Error) => panic!("An error occurred"),
/// _ => (),
/// if let Err(fmt::Error) = write(&mut output, format_args!("Hello {}!", "world")) {
/// panic!("An error occurred");
/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
Expand Down Expand Up @@ -208,7 +207,7 @@ pub trait Write {
// requiring a `Sized` bound.
struct Adapter<'a,T: ?Sized +'a>(&'a mut T);

impl<'a, T: ?Sized> Write for Adapter<'a, T>
impl<T: ?Sized> Write for Adapter<'_, T>
where T: Write
{
fn write_str(&mut self, s: &str) -> Result {
Expand All @@ -229,7 +228,7 @@ pub trait Write {
}

#[stable(feature = "fmt_write_blanket_impl", since = "1.4.0")]
impl<'a, W: Write + ?Sized> Write for &'a mut W {
impl<W: Write + ?Sized> Write for &mut W {
fn write_str(&mut self, s: &str) -> Result {
(**self).write_str(s)
}
Expand Down Expand Up @@ -291,8 +290,8 @@ pub struct ArgumentV1<'a> {

#[unstable(feature = "fmt_internals", reason = "internal to format_args!",
issue = "0")]
impl<'a> Clone for ArgumentV1<'a> {
fn clone(&self) -> ArgumentV1<'a> {
impl Clone for ArgumentV1<'_> {
fn clone(&self) -> Self {
*self
}
}
Expand Down Expand Up @@ -436,14 +435,14 @@ pub struct Arguments<'a> {
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a> Debug for Arguments<'a> {
impl Debug for Arguments<'_> {
fn fmt(&self, fmt: &mut Formatter) -> Result {
Display::fmt(self, fmt)
}
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a> Display for Arguments<'a> {
impl Display for Arguments<'_> {
fn fmt(&self, fmt: &mut Formatter) -> Result {
write(fmt.buf, *self)
}
Expand Down Expand Up @@ -1884,7 +1883,7 @@ impl<'a> Formatter<'a> {
}

#[stable(since = "1.2.0", feature = "formatter_write")]
impl<'a> Write for Formatter<'a> {
impl Write for Formatter<'_> {
fn write_str(&mut self, s: &str) -> Result {
self.buf.write_str(s)
}
Expand All @@ -1911,11 +1910,11 @@ macro_rules! fmt_refs {
($($tr:ident),*) => {
$(
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T: ?Sized + $tr> $tr for &'a T {
impl<T: ?Sized + $tr> $tr for &T {
fn fmt(&self, f: &mut Formatter) -> Result { $tr::fmt(&**self, f) }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T: ?Sized + $tr> $tr for &'a mut T {
impl<T: ?Sized + $tr> $tr for &mut T {
fn fmt(&self, f: &mut Formatter) -> Result { $tr::fmt(&**self, f) }
}
)*
Expand Down Expand Up @@ -2039,14 +2038,14 @@ impl<T: ?Sized> Pointer for *mut T {
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T: ?Sized> Pointer for &'a T {
impl<T: ?Sized> Pointer for &T {
fn fmt(&self, f: &mut Formatter) -> Result {
Pointer::fmt(&(*self as *const T), f)
}
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T: ?Sized> Pointer for &'a mut T {
impl<T: ?Sized> Pointer for &mut T {
fn fmt(&self, f: &mut Formatter) -> Result {
Pointer::fmt(&(&**self as *const T), f)
}
Expand Down Expand Up @@ -2153,14 +2152,14 @@ impl<T: ?Sized + Debug> Debug for RefCell<T> {
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'b, T: ?Sized + Debug> Debug for Ref<'b, T> {
impl<T: ?Sized + Debug> Debug for Ref<'_, T> {
fn fmt(&self, f: &mut Formatter) -> Result {
Debug::fmt(&**self, f)
}
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'b, T: ?Sized + Debug> Debug for RefMut<'b, T> {
impl<T: ?Sized + Debug> Debug for RefMut<'_, T> {
fn fmt(&self, f: &mut Formatter) -> Result {
Debug::fmt(&*(self.deref()), f)
}
Expand Down
66 changes: 42 additions & 24 deletions src/libcore/future/future.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,10 @@
reason = "futures in libcore are unstable",
issue = "50547")]

use pin::PinMut;
use marker::Unpin;
use task::{self, Poll};
use ops;
use pin::Pin;
use task::{Poll, LocalWaker};

/// A future represents an asychronous computation.
///
Expand Down Expand Up @@ -49,28 +50,28 @@ pub trait Future {
///
/// Once a future has finished, clients should not `poll` it again.
///
/// When a future is not ready yet, `poll` returns
/// `Poll::Pending`. The future will *also* register the
/// interest of the current task in the value being produced. For example,
/// if the future represents the availability of data on a socket, then the
/// task is recorded so that when data arrives, it is woken up (via
/// [`cx.waker()`]). Once a task has been woken up,
/// it should attempt to `poll` the future again, which may or may not
/// produce a final value.
/// When a future is not ready yet, `poll` returns `Poll::Pending` and
/// stores a clone of the [`LocalWaker`] to be woken once the future can
/// make progress. For example, a future waiting for a socket to become
/// readable would call `.clone()` on the [`LocalWaker`] and store it.
/// When a signal arrives elsewhere indicating that the socket is readable,
/// `[LocalWaker::wake]` is called and the socket future's task is awoken.
/// Once a task has been woken up, it should attempt to `poll` the future
/// again, which may or may not produce a final value.
///
/// Note that if `Pending` is returned it only means that the *current* task
/// (represented by the argument `cx`) will receive a notification. Tasks
/// from previous calls to `poll` will *not* receive notifications.
/// Note that on multiple calls to `poll`, only the most recent
/// [`LocalWaker`] passed to `poll` should be scheduled to receive a
/// wakeup.
///
/// # Runtime characteristics
///
/// Futures alone are *inert*; they must be *actively* `poll`ed to make
/// progress, meaning that each time the current task is woken up, it should
/// actively re-`poll` pending futures that it still has an interest in.
///
/// The `poll` function is not called repeatedly in a tight loop for
/// futures, but only whenever the future itself is ready, as signaled via
/// the `Waker` inside `task::Context`. If you're familiar with the
/// The `poll` function is not called repeatedly in a tight loop-- instead,
/// it should only be called when the future indicates that it is ready to
/// make progress (by calling `wake()`). If you're familiar with the
/// `poll(2)` or `select(2)` syscalls on Unix it's worth noting that futures
/// typically do *not* suffer the same problems of "all wakeups must poll
/// all events"; they are more like `epoll(4)`.
Expand All @@ -82,6 +83,16 @@ pub trait Future {
/// thread pool (or something similar) to ensure that `poll` can return
/// quickly.
///
/// # [`LocalWaker`], [`Waker`] and thread-safety
///
/// The `poll` function takes a [`LocalWaker`], an object which knows how to
/// awaken the current task. [`LocalWaker`] is not `Send` nor `Sync`, so in
/// order to make thread-safe futures the [`LocalWaker::into_waker`] method
/// should be used to convert the [`LocalWaker`] into a thread-safe version.
/// [`LocalWaker::wake`] implementations have the ability to be more
/// efficient, however, so when thread safety is not necessary,
/// [`LocalWaker`] should be preferred.
///
/// # Panics
///
/// Once a future has completed (returned `Ready` from `poll`),
Expand All @@ -91,22 +102,29 @@ pub trait Future {
///
/// [`Poll::Pending`]: ../task/enum.Poll.html#variant.Pending
/// [`Poll::Ready(val)`]: ../task/enum.Poll.html#variant.Ready
/// [`cx.waker()`]: ../task/struct.Context.html#method.waker
fn poll(self: PinMut<Self>, cx: &mut task::Context) -> Poll<Self::Output>;
/// [`LocalWaker`]: ../task/struct.LocalWaker.html
/// [`LocalWaker::into_waker`]: ../task/struct.LocalWaker.html#method.into_waker
/// [`LocalWaker::wake`]: ../task/struct.LocalWaker.html#method.wake
/// [`Waker`]: ../task/struct.Waker.html
fn poll(self: Pin<&mut Self>, lw: &LocalWaker) -> Poll<Self::Output>;
}

impl<'a, F: ?Sized + Future + Unpin> Future for &'a mut F {
type Output = F::Output;

fn poll(mut self: PinMut<Self>, cx: &mut task::Context) -> Poll<Self::Output> {
F::poll(PinMut::new(&mut **self), cx)
fn poll(mut self: Pin<&mut Self>, lw: &LocalWaker) -> Poll<Self::Output> {
F::poll(Pin::new(&mut **self), lw)
}
}

impl<'a, F: ?Sized + Future> Future for PinMut<'a, F> {
type Output = F::Output;
impl<P> Future for Pin<P>
where
P: ops::DerefMut,
P::Target: Future,
{
type Output = <<P as ops::Deref>::Target as Future>::Output;

fn poll(mut self: PinMut<Self>, cx: &mut task::Context) -> Poll<Self::Output> {
F::poll((*self).reborrow(), cx)
fn poll(self: Pin<&mut Self>, lw: &LocalWaker) -> Poll<Self::Output> {
Pin::get_mut(self).as_mut().poll(lw)
}
}
182 changes: 0 additions & 182 deletions src/libcore/future/future_obj.rs

This file was deleted.

3 changes: 0 additions & 3 deletions src/libcore/future/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,3 @@

mod future;
pub use self::future::Future;

mod future_obj;
pub use self::future_obj::{FutureObj, LocalFutureObj, UnsafeFutureObj};
6 changes: 3 additions & 3 deletions src/libcore/hash/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -361,7 +361,7 @@ pub trait Hasher {
}

#[stable(feature = "indirect_hasher_impl", since = "1.22.0")]
impl<'a, H: Hasher + ?Sized> Hasher for &'a mut H {
impl<H: Hasher + ?Sized> Hasher for &mut H {
fn finish(&self) -> u64 {
(**self).finish()
}
Expand Down Expand Up @@ -669,14 +669,14 @@ mod impls {


#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T: ?Sized + Hash> Hash for &'a T {
impl<T: ?Sized + Hash> Hash for &T {
fn hash<H: Hasher>(&self, state: &mut H) {
(**self).hash(state);
}
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T: ?Sized + Hash> Hash for &'a mut T {
impl<T: ?Sized + Hash> Hash for &mut T {
fn hash<H: Hasher>(&self, state: &mut H) {
(**self).hash(state);
}
Expand Down
196 changes: 160 additions & 36 deletions src/libcore/intrinsics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -962,59 +962,127 @@ extern "rust-intrinsic" {
/// value is not necessarily valid to be used to actually access memory.
pub fn arith_offset<T>(dst: *const T, offset: isize) -> *const T;

/// Copies `count * size_of<T>` bytes from `src` to `dst`. The source
/// and destination may *not* overlap.
/// Copies `count * size_of::<T>()` bytes from `src` to `dst`. The source
/// and destination must *not* overlap.
///
/// `copy_nonoverlapping` is semantically equivalent to C's `memcpy`.
/// For regions of memory which might overlap, use [`copy`] instead.
///
/// `copy_nonoverlapping` is semantically equivalent to C's [`memcpy`], but
/// with the argument order swapped.
///
/// [`copy`]: ./fn.copy.html
/// [`memcpy`]: https://en.cppreference.com/w/c/string/byte/memcpy
///
/// # Safety
///
/// Beyond requiring that the program must be allowed to access both regions
/// of memory, it is Undefined Behavior for source and destination to
/// overlap. Care must also be taken with the ownership of `src` and
/// `dst`. This method semantically moves the values of `src` into `dst`.
/// However it does not drop the contents of `dst`, or prevent the contents
/// of `src` from being dropped or used.
/// Behavior is undefined if any of the following conditions are violated:
///
/// * `src` must be [valid] for reads of `count * size_of::<T>()` bytes.
///
/// * `dst` must be [valid] for writes of `count * size_of::<T>()` bytes.
///
/// * Both `src` and `dst` must be properly aligned.
///
/// * The region of memory beginning at `src` with a size of `count *
/// size_of::<T>()` bytes must *not* overlap with the region of memory
/// beginning at `dst` with the same size.
///
/// Like [`read`], `copy_nonoverlapping` creates a bitwise copy of `T`, regardless of
/// whether `T` is [`Copy`]. If `T` is not [`Copy`], using *both* the values
/// in the region beginning at `*src` and the region beginning at `*dst` can
/// [violate memory safety][read-ownership].
///
/// Note that even if the effectively copied size (`count * size_of::<T>()`) is
/// `0`, the pointers must be non-NULL and properly aligned.
///
/// [`Copy`]: ../marker/trait.Copy.html
/// [`read`]: ../ptr/fn.read.html
/// [read-ownership]: ../ptr/fn.read.html#ownership-of-the-returned-value
/// [valid]: ../ptr/index.html#safety
///
/// # Examples
///
/// A safe swap function:
/// Manually implement [`Vec::append`]:
///
/// ```
/// use std::mem;
/// use std::ptr;
///
/// # #[allow(dead_code)]
/// fn swap<T>(x: &mut T, y: &mut T) {
/// unsafe {
/// // Give ourselves some scratch space to work with
/// let mut t: T = mem::uninitialized();
/// /// Moves all the elements of `src` into `dst`, leaving `src` empty.
/// fn append<T>(dst: &mut Vec<T>, src: &mut Vec<T>) {
/// let src_len = src.len();
/// let dst_len = dst.len();
///
/// // Perform the swap, `&mut` pointers never alias
/// ptr::copy_nonoverlapping(x, &mut t, 1);
/// ptr::copy_nonoverlapping(y, x, 1);
/// ptr::copy_nonoverlapping(&t, y, 1);
/// // Ensure that `dst` has enough capacity to hold all of `src`.
/// dst.reserve(src_len);
///
/// // y and t now point to the same thing, but we need to completely forget `t`
/// // because it's no longer relevant.
/// mem::forget(t);
/// unsafe {
/// // The call to offset is always safe because `Vec` will never
/// // allocate more than `isize::MAX` bytes.
/// let dst_ptr = dst.as_mut_ptr().offset(dst_len as isize);
/// let src_ptr = src.as_ptr();
///
/// // Truncate `src` without dropping its contents. We do this first,
/// // to avoid problems in case something further down panics.
/// src.set_len(0);
///
/// // The two regions cannot overlap because mutable references do
/// // not alias, and two different vectors cannot own the same
/// // memory.
/// ptr::copy_nonoverlapping(src_ptr, dst_ptr, src_len);
///
/// // Notify `dst` that it now holds the contents of `src`.
/// dst.set_len(dst_len + src_len);
/// }
/// }
///
/// let mut a = vec!['r'];
/// let mut b = vec!['u', 's', 't'];
///
/// append(&mut a, &mut b);
///
/// assert_eq!(a, &['r', 'u', 's', 't']);
/// assert!(b.is_empty());
/// ```
///
/// [`Vec::append`]: ../../std/vec/struct.Vec.html#method.append
#[stable(feature = "rust1", since = "1.0.0")]
pub fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize);

/// Copies `count * size_of<T>` bytes from `src` to `dst`. The source
/// Copies `count * size_of::<T>()` bytes from `src` to `dst`. The source
/// and destination may overlap.
///
/// `copy` is semantically equivalent to C's `memmove`.
/// If the source and destination will *never* overlap,
/// [`copy_nonoverlapping`] can be used instead.
///
/// `copy` is semantically equivalent to C's [`memmove`], but with the argument
/// order swapped. Copying takes place as if the bytes were copied from `src`
/// to a temporary array and then copied from the array to `dst`.
///
/// [`copy_nonoverlapping`]: ./fn.copy_nonoverlapping.html
/// [`memmove`]: https://en.cppreference.com/w/c/string/byte/memmove
///
/// # Safety
///
/// Care must be taken with the ownership of `src` and `dst`.
/// This method semantically moves the values of `src` into `dst`.
/// However it does not drop the contents of `dst`, or prevent the contents of `src`
/// from being dropped or used.
/// Behavior is undefined if any of the following conditions are violated:
///
/// * `src` must be [valid] for reads of `count * size_of::<T>()` bytes.
///
/// * `dst` must be [valid] for writes of `count * size_of::<T>()` bytes.
///
/// * Both `src` and `dst` must be properly aligned.
///
/// Like [`read`], `copy` creates a bitwise copy of `T`, regardless of
/// whether `T` is [`Copy`]. If `T` is not [`Copy`], using both the values
/// in the region beginning at `*src` and the region beginning at `*dst` can
/// [violate memory safety][read-ownership].
///
/// Note that even if the effectively copied size (`count * size_of::<T>()`) is
/// `0`, the pointers must be non-NULL and properly aligned.
///
/// [`Copy`]: ../marker/trait.Copy.html
/// [`read`]: ../ptr/fn.read.html
/// [read-ownership]: ../ptr/fn.read.html#ownership-of-the-returned-value
/// [valid]: ../ptr/index.html#safety
///
/// # Examples
///
Expand All @@ -1031,24 +1099,80 @@ extern "rust-intrinsic" {
/// dst
/// }
/// ```
///
#[stable(feature = "rust1", since = "1.0.0")]
pub fn copy<T>(src: *const T, dst: *mut T, count: usize);

/// Invokes memset on the specified pointer, setting `count * size_of::<T>()`
/// bytes of memory starting at `dst` to `val`.
/// Sets `count * size_of::<T>()` bytes of memory starting at `dst` to
/// `val`.
///
/// `write_bytes` is similar to C's [`memset`], but sets `count *
/// size_of::<T>()` bytes to `val`.
///
/// [`memset`]: https://en.cppreference.com/w/c/string/byte/memset
///
/// # Safety
///
/// Behavior is undefined if any of the following conditions are violated:
///
/// * `dst` must be [valid] for writes of `count * size_of::<T>()` bytes.
///
/// * `dst` must be properly aligned.
///
/// Additionally, the caller must ensure that writing `count *
/// size_of::<T>()` bytes to the given region of memory results in a valid
/// value of `T`. Using a region of memory typed as a `T` that contains an
/// invalid value of `T` is undefined behavior.
///
/// Note that even if the effectively copied size (`count * size_of::<T>()`) is
/// `0`, the pointer must be non-NULL and properly aligned.
///
/// [valid]: ../ptr/index.html#safety
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// use std::ptr;
///
/// let mut vec = vec![0; 4];
/// let mut vec = vec![0u32; 4];
/// unsafe {
/// let vec_ptr = vec.as_mut_ptr();
/// ptr::write_bytes(vec_ptr, b'a', 2);
/// ptr::write_bytes(vec_ptr, 0xfe, 2);
/// }
/// assert_eq!(vec, [0xfefefefe, 0xfefefefe, 0, 0]);
/// ```
///
/// Creating an invalid value:
///
/// ```
/// use std::ptr;
///
/// let mut v = Box::new(0i32);
///
/// unsafe {
/// // Leaks the previously held value by overwriting the `Box<T>` with
/// // a null pointer.
/// ptr::write_bytes(&mut v as *mut Box<i32>, 0, 1);
/// }
/// assert_eq!(vec, [b'a', b'a', 0, 0]);
///
/// // At this point, using or dropping `v` results in undefined behavior.
/// // drop(v); // ERROR
///
/// // Even leaking `v` "uses" it, and hence is undefined behavior.
/// // mem::forget(v); // ERROR
///
/// // In fact, `v` is invalid according to basic type layout invariants, so *any*
/// // operation touching it is undefined behavior.
/// // let v2 = v; // ERROR
///
/// unsafe {
/// // Let us instead put in a valid value
/// ptr::write(&mut v as *mut Box<i32>, Box::new(42i32));
/// }
///
/// // Now the box is fine
/// assert_eq!(*v, 42);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn write_bytes<T>(dst: *mut T, val: u8, count: usize);
Expand All @@ -1066,7 +1190,7 @@ extern "rust-intrinsic" {
/// `min_align_of::<T>()`
///
/// The volatile parameter is set to `true`, so it will not be optimized out
/// unless size is equal to zero..
/// unless size is equal to zero.
pub fn volatile_copy_memory<T>(dst: *mut T, src: *const T, count: usize);
/// Equivalent to the appropriate `llvm.memset.p0i8.*` intrinsic, with a
/// size of `count` * `size_of::<T>()` and an alignment of
Expand Down
71 changes: 66 additions & 5 deletions src/libcore/iter/iterator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,72 @@ fn _assert_is_object_safe(_: &dyn Iterator<Item=()>) {}
/// [impl]: index.html#implementing-iterator
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_on_unimplemented(
on(
_Self="[std::ops::Range<Idx>; 1]",
label="if you meant to iterate between two values, remove the square brackets",
note="`[start..end]` is an array of one `Range`; you might have meant to have a `Range` \
without the brackets: `start..end`"
),
on(
_Self="[std::ops::RangeFrom<Idx>; 1]",
label="if you meant to iterate from a value onwards, remove the square brackets",
note="`[start..]` is an array of one `RangeFrom`; you might have meant to have a \
`RangeFrom` without the brackets: `start..`, keeping in mind that iterating over an \
unbounded iterator will run forever unless you `break` or `return` from within the \
loop"
),
on(
_Self="[std::ops::RangeTo<Idx>; 1]",
label="if you meant to iterate until a value, remove the square brackets and add a \
starting value",
note="`[..end]` is an array of one `RangeTo`; you might have meant to have a bounded \
`Range` without the brackets: `0..end`"
),
on(
_Self="[std::ops::RangeInclusive<Idx>; 1]",
label="if you meant to iterate between two values, remove the square brackets",
note="`[start..=end]` is an array of one `RangeInclusive`; you might have meant to have a \
`RangeInclusive` without the brackets: `start..=end`"
),
on(
_Self="[std::ops::RangeToInclusive<Idx>; 1]",
label="if you meant to iterate until a value (including it), remove the square brackets \
and add a starting value",
note="`[..=end]` is an array of one `RangeToInclusive`; you might have meant to have a \
bounded `RangeInclusive` without the brackets: `0..=end`"
),
on(
_Self="std::ops::RangeTo<Idx>",
label="if you meant to iterate until a value, add a starting value",
note="`..end` is a `RangeTo`, which cannot be iterated on; you might have meant to have a \
bounded `Range`: `0..end`"
),
on(
_Self="std::ops::RangeToInclusive<Idx>",
label="if you meant to iterate until a value (including it), add a starting value",
note="`..=end` is a `RangeToInclusive`, which cannot be iterated on; you might have meant \
to have a bounded `RangeInclusive`: `0..=end`"
),
on(
_Self="&str",
label="`{Self}` is not an iterator; try calling `.chars()` or `.bytes()`"
),
label="`{Self}` is not an iterator; maybe try calling `.iter()` or a similar method"
on(
_Self="std::string::String",
label="`{Self}` is not an iterator; try calling `.chars()` or `.bytes()`"
),
on(
_Self="[]",
label="borrow the array with `&` or call `.iter()` on it to iterate over it",
note="arrays are not an iterators, but slices like the following are: `&[1, 2, 3]`"
),
on(
_Self="{integral}",
note="if you want to iterate between `start` until a value `end`, use the exclusive range \
syntax `start..end` or the inclusive range syntax `start..=end`"
),
label="`{Self}` is not an iterator",
message="`{Self}` is not an iterator"
)]
#[doc(spotlight)]
pub trait Iterator {
Expand Down Expand Up @@ -471,7 +532,7 @@ pub trait Iterator {
/// If you're doing some sort of looping for a side effect, it's considered
/// more idiomatic to use [`for`] than `map()`.
///
/// [`for`]: ../../book/first-edition/loops.html#for
/// [`for`]: ../../book/ch03-05-control-flow.html#looping-through-a-collection-with-for
///
/// # Examples
///
Expand Down Expand Up @@ -519,7 +580,7 @@ pub trait Iterator {
/// cases `for_each` may also be faster than a loop, because it will use
/// internal iteration on adaptors like `Chain`.
///
/// [`for`]: ../../book/first-edition/loops.html#for
/// [`for`]: ../../book/ch03-05-control-flow.html#looping-through-a-collection-with-for
///
/// # Examples
///
Expand Down Expand Up @@ -1608,7 +1669,7 @@ pub trait Iterator {
/// use a `for` loop with a list of things to build up a result. Those
/// can be turned into `fold()`s:
///
/// [`for`]: ../../book/first-edition/loops.html#for
/// [`for`]: ../../book/ch03-05-control-flow.html#looping-through-a-collection-with-for
///
/// ```
/// let numbers = [1, 2, 3, 4, 5];
Expand Down Expand Up @@ -2557,7 +2618,7 @@ fn select_fold1<I, B, FProj, FCmp>(mut it: I,
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, I: Iterator + ?Sized> Iterator for &'a mut I {
impl<I: Iterator + ?Sized> Iterator for &mut I {
type Item = I::Item;
fn next(&mut self) -> Option<I::Item> { (**self).next() }
fn size_hint(&self) -> (usize, Option<usize>) { (**self).size_hint() }
Expand Down
84 changes: 8 additions & 76 deletions src/libcore/iter/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,7 @@
//! using it. The compiler will warn us about this kind of behavior:
//!
//! ```text
//! warning: unused result which must be used: iterator adaptors are lazy and
//! warning: unused result that must be used: iterator adaptors are lazy and
//! do nothing unless consumed
//! ```
//!
Expand Down Expand Up @@ -319,10 +319,9 @@
use cmp;
use fmt;
use iter_private::TrustedRandomAccess;
use ops::{self, Try};
use ops::Try;
use usize;
use intrinsics;
use mem;

#[stable(feature = "rust1", since = "1.0.0")]
pub use self::iterator::Iterator;
Expand Down Expand Up @@ -673,7 +672,12 @@ impl<I> Iterator for StepBy<I> where I: Iterator {

#[inline]
fn next(&mut self) -> Option<Self::Item> {
<Self as StepBySpecIterator>::spec_next(self)
if self.first_take {
self.first_take = false;
self.iter.next()
} else {
self.iter.nth(self.step)
}
}

#[inline]
Expand Down Expand Up @@ -733,78 +737,6 @@ impl<I> Iterator for StepBy<I> where I: Iterator {
}
}

// hidden trait for specializing iterator methods
// could be generalized but is currently only used for StepBy
trait StepBySpecIterator {
type Item;
fn spec_next(&mut self) -> Option<Self::Item>;
}

impl<I> StepBySpecIterator for StepBy<I>
where
I: Iterator,
{
type Item = I::Item;

#[inline]
default fn spec_next(&mut self) -> Option<I::Item> {
if self.first_take {
self.first_take = false;
self.iter.next()
} else {
self.iter.nth(self.step)
}
}
}

impl<T> StepBySpecIterator for StepBy<ops::Range<T>>
where
T: Step,
{
#[inline]
fn spec_next(&mut self) -> Option<Self::Item> {
self.first_take = false;
if !(self.iter.start < self.iter.end) {
return None;
}
// add 1 to self.step to get original step size back
// it was decremented for the general case on construction
if let Some(n) = self.iter.start.add_usize(self.step+1) {
let next = mem::replace(&mut self.iter.start, n);
Some(next)
} else {
let last = self.iter.start.clone();
self.iter.start = self.iter.end.clone();
Some(last)
}
}
}

impl<T> StepBySpecIterator for StepBy<ops::RangeInclusive<T>>
where
T: Step,
{
#[inline]
fn spec_next(&mut self) -> Option<Self::Item> {
self.first_take = false;
self.iter.compute_is_empty();
if self.iter.is_empty.unwrap_or_default() {
return None;
}
// add 1 to self.step to get original step size back
// it was decremented for the general case on construction
if let Some(n) = self.iter.start.add_usize(self.step+1) {
self.iter.is_empty = Some(!(n <= self.iter.end));
let next = mem::replace(&mut self.iter.start, n);
Some(next)
} else {
let last = self.iter.start.clone();
self.iter.is_empty = Some(true);
Some(last)
}
}
}

// StepBy can only make the iterator shorter, so the len will still fit.
#[stable(feature = "iterator_step_by", since = "1.28.0")]
impl<I> ExactSizeIterator for StepBy<I> where I: ExactSizeIterator {}
Expand Down
6 changes: 3 additions & 3 deletions src/libcore/iter/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -724,7 +724,7 @@ pub trait ExactSizeIterator: Iterator {
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, I: ExactSizeIterator + ?Sized> ExactSizeIterator for &'a mut I {
impl<I: ExactSizeIterator + ?Sized> ExactSizeIterator for &mut I {
fn len(&self) -> usize {
(**self).len()
}
Expand Down Expand Up @@ -974,7 +974,7 @@ impl<T, U, E> Product<Result<U, E>> for Result<T, E>
pub trait FusedIterator: Iterator {}

#[stable(feature = "fused", since = "1.26.0")]
impl<'a, I: FusedIterator + ?Sized> FusedIterator for &'a mut I {}
impl<I: FusedIterator + ?Sized> FusedIterator for &mut I {}

/// An iterator that reports an accurate length using size_hint.
///
Expand All @@ -999,4 +999,4 @@ impl<'a, I: FusedIterator + ?Sized> FusedIterator for &'a mut I {}
pub unsafe trait TrustedLen : Iterator {}

#[unstable(feature = "trusted_len", issue = "37572")]
unsafe impl<'a, I: TrustedLen + ?Sized> TrustedLen for &'a mut I {}
unsafe impl<I: TrustedLen + ?Sized> TrustedLen for &mut I {}
4 changes: 3 additions & 1 deletion src/libcore/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,11 +87,12 @@
#![feature(doc_spotlight)]
#![feature(extern_types)]
#![feature(fundamental)]
#![cfg_attr(stage0, feature(impl_header_lifetime_elision))]
#![feature(intrinsics)]
#![feature(lang_items)]
#![feature(link_llvm_intrinsics)]
#![feature(never_type)]
#![cfg_attr(not(stage0), feature(nll))]
#![feature(nll)]
#![feature(exhaustive_patterns)]
#![feature(macro_at_most_once_rep)]
#![feature(no_core)]
Expand All @@ -116,6 +117,7 @@
#![feature(powerpc_target_feature)]
#![feature(mips_target_feature)]
#![feature(aarch64_target_feature)]
#![feature(wasm_target_feature)]
#![feature(const_slice_len)]
#![feature(const_str_as_bytes)]
#![feature(const_str_len)]
Expand Down
19 changes: 10 additions & 9 deletions src/libcore/marker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ impl<T: ?Sized> !Send for *mut T { }
#[stable(feature = "rust1", since = "1.0.0")]
#[lang = "sized"]
#[rustc_on_unimplemented(
on(parent_trait="std::path::Path", label="borrow the `Path` instead"),
message="the size for values of type `{Self}` cannot be known at compilation time",
label="doesn't have a size known at compile-time",
note="to learn more, visit <https://doc.rust-lang.org/book/second-edition/\
Expand Down Expand Up @@ -584,9 +585,9 @@ impls! { PhantomData }

mod impls {
#[stable(feature = "rust1", since = "1.0.0")]
unsafe impl<'a, T: Sync + ?Sized> Send for &'a T {}
unsafe impl<T: Sync + ?Sized> Send for &T {}
#[stable(feature = "rust1", since = "1.0.0")]
unsafe impl<'a, T: Send + ?Sized> Send for &'a mut T {}
unsafe impl<T: Send + ?Sized> Send for &mut T {}
}

/// Compiler-internal trait used to determine whether a type contains
Expand All @@ -600,16 +601,16 @@ impl<T: ?Sized> !Freeze for UnsafeCell<T> {}
unsafe impl<T: ?Sized> Freeze for PhantomData<T> {}
unsafe impl<T: ?Sized> Freeze for *const T {}
unsafe impl<T: ?Sized> Freeze for *mut T {}
unsafe impl<'a, T: ?Sized> Freeze for &'a T {}
unsafe impl<'a, T: ?Sized> Freeze for &'a mut T {}
unsafe impl<T: ?Sized> Freeze for &T {}
unsafe impl<T: ?Sized> Freeze for &mut T {}

/// Types which can be safely moved after being pinned.
///
/// Since Rust itself has no notion of immovable types, and will consider moves to always be safe,
/// this trait cannot prevent types from moving by itself.
///
/// Instead it can be used to prevent moves through the type system,
/// by controlling the behavior of special pointer types like [`PinMut`],
/// by controlling the behavior of pointers wrapped in the [`Pin`] wrapper,
/// which "pin" the type in place by not allowing it to be moved out of them.
/// See the [`pin module`] documentation for more information on pinning.
///
Expand All @@ -621,10 +622,10 @@ unsafe impl<'a, T: ?Sized> Freeze for &'a mut T {}
/// ```rust
/// #![feature(pin)]
/// use std::mem::replace;
/// use std::pin::PinMut;
/// use std::pin::Pin;
///
/// let mut string = "this".to_string();
/// let mut pinned_string = PinMut::new(&mut string);
/// let mut pinned_string = Pin::new(&mut string);
///
/// // dereferencing the pointer mutably is only possible because String implements Unpin
/// replace(&mut *pinned_string, "other".to_string());
Expand All @@ -633,7 +634,7 @@ unsafe impl<'a, T: ?Sized> Freeze for &'a mut T {}
/// This trait is automatically implemented for almost every type.
///
/// [`replace`]: ../../std/mem/fn.replace.html
/// [`PinMut`]: ../pin/struct.PinMut.html
/// [`Pin`]: ../pin/struct.Pin.html
/// [`pin module`]: ../../std/pin/index.html
#[unstable(feature = "pin", issue = "49150")]
pub auto trait Unpin {}
Expand Down Expand Up @@ -689,6 +690,6 @@ mod copy_impls {

// Shared references can be copied, but mutable references *cannot*!
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T: ?Sized> Copy for &'a T {}
impl<T: ?Sized> Copy for &T {}

}
Loading