Auto merge of #47445 - kennytm:rollup, r=kennytm
Rollup of 10 pull requests - Successful merges: #47120, #47126, #47277, #47330, #47368, #47372, #47414, #47417, #47432, #47443 - Failed merges: #47334
This commit is contained in:
commit
57850e5360
|
@ -124,6 +124,7 @@
|
||||||
#![feature(unsize)]
|
#![feature(unsize)]
|
||||||
#![feature(allocator_internals)]
|
#![feature(allocator_internals)]
|
||||||
#![feature(on_unimplemented)]
|
#![feature(on_unimplemented)]
|
||||||
|
#![feature(exact_chunks)]
|
||||||
|
|
||||||
#![cfg_attr(not(test), feature(fused, fn_traits, placement_new_protocol, swap_with_slice, i128))]
|
#![cfg_attr(not(test), feature(fused, fn_traits, placement_new_protocol, swap_with_slice, i128))]
|
||||||
#![cfg_attr(test, feature(test, box_heap))]
|
#![cfg_attr(test, feature(test, box_heap))]
|
||||||
|
|
|
@ -123,6 +123,8 @@ pub use core::slice::{from_raw_parts, from_raw_parts_mut};
|
||||||
pub use core::slice::{from_ref, from_ref_mut};
|
pub use core::slice::{from_ref, from_ref_mut};
|
||||||
#[unstable(feature = "slice_get_slice", issue = "35729")]
|
#[unstable(feature = "slice_get_slice", issue = "35729")]
|
||||||
pub use core::slice::SliceIndex;
|
pub use core::slice::SliceIndex;
|
||||||
|
#[unstable(feature = "exact_chunks", issue = "47115")]
|
||||||
|
pub use core::slice::{ExactChunks, ExactChunksMut};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// Basic slice extension methods
|
// Basic slice extension methods
|
||||||
|
@ -611,6 +613,9 @@ impl<T> [T] {
|
||||||
/// not divide the length of the slice, then the last chunk will
|
/// not divide the length of the slice, then the last chunk will
|
||||||
/// not have length `chunk_size`.
|
/// not have length `chunk_size`.
|
||||||
///
|
///
|
||||||
|
/// See [`exact_chunks`] for a variant of this iterator that returns chunks
|
||||||
|
/// of always exactly `chunk_size` elements.
|
||||||
|
///
|
||||||
/// # Panics
|
/// # Panics
|
||||||
///
|
///
|
||||||
/// Panics if `chunk_size` is 0.
|
/// Panics if `chunk_size` is 0.
|
||||||
|
@ -631,11 +636,44 @@ impl<T> [T] {
|
||||||
core_slice::SliceExt::chunks(self, chunk_size)
|
core_slice::SliceExt::chunks(self, chunk_size)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns an iterator over `chunk_size` elements of the slice at a
|
||||||
|
/// time. The chunks are slices and do not overlap. If `chunk_size` does
|
||||||
|
/// not divide the length of the slice, then the last up to `chunk_size-1`
|
||||||
|
/// elements will be omitted.
|
||||||
|
///
|
||||||
|
/// Due to each chunk having exactly `chunk_size` elements, the compiler
|
||||||
|
/// can often optimize the resulting code better than in the case of
|
||||||
|
/// [`chunks`].
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
///
|
||||||
|
/// Panics if `chunk_size` is 0.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// #![feature(exact_chunks)]
|
||||||
|
///
|
||||||
|
/// let slice = ['l', 'o', 'r', 'e', 'm'];
|
||||||
|
/// let mut iter = slice.exact_chunks(2);
|
||||||
|
/// assert_eq!(iter.next().unwrap(), &['l', 'o']);
|
||||||
|
/// assert_eq!(iter.next().unwrap(), &['r', 'e']);
|
||||||
|
/// assert!(iter.next().is_none());
|
||||||
|
/// ```
|
||||||
|
#[unstable(feature = "exact_chunks", issue = "47115")]
|
||||||
|
#[inline]
|
||||||
|
pub fn exact_chunks(&self, chunk_size: usize) -> ExactChunks<T> {
|
||||||
|
core_slice::SliceExt::exact_chunks(self, chunk_size)
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns an iterator over `chunk_size` elements of the slice at a time.
|
/// Returns an iterator over `chunk_size` elements of the slice at a time.
|
||||||
/// The chunks are mutable slices, and do not overlap. If `chunk_size` does
|
/// The chunks are mutable slices, and do not overlap. If `chunk_size` does
|
||||||
/// not divide the length of the slice, then the last chunk will not
|
/// not divide the length of the slice, then the last chunk will not
|
||||||
/// have length `chunk_size`.
|
/// have length `chunk_size`.
|
||||||
///
|
///
|
||||||
|
/// See [`exact_chunks_mut`] for a variant of this iterator that returns chunks
|
||||||
|
/// of always exactly `chunk_size` elements.
|
||||||
|
///
|
||||||
/// # Panics
|
/// # Panics
|
||||||
///
|
///
|
||||||
/// Panics if `chunk_size` is 0.
|
/// Panics if `chunk_size` is 0.
|
||||||
|
@ -660,6 +698,42 @@ impl<T> [T] {
|
||||||
core_slice::SliceExt::chunks_mut(self, chunk_size)
|
core_slice::SliceExt::chunks_mut(self, chunk_size)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns an iterator over `chunk_size` elements of the slice at a time.
|
||||||
|
/// The chunks are mutable slices, and do not overlap. If `chunk_size` does
|
||||||
|
/// not divide the length of the slice, then the last up to `chunk_size-1`
|
||||||
|
/// elements will be omitted.
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// Due to each chunk having exactly `chunk_size` elements, the compiler
|
||||||
|
/// can often optimize the resulting code better than in the case of
|
||||||
|
/// [`chunks_mut`].
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
///
|
||||||
|
/// Panics if `chunk_size` is 0.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// #![feature(exact_chunks)]
|
||||||
|
///
|
||||||
|
/// let v = &mut [0, 0, 0, 0, 0];
|
||||||
|
/// let mut count = 1;
|
||||||
|
///
|
||||||
|
/// for chunk in v.exact_chunks_mut(2) {
|
||||||
|
/// for elem in chunk.iter_mut() {
|
||||||
|
/// *elem += count;
|
||||||
|
/// }
|
||||||
|
/// count += 1;
|
||||||
|
/// }
|
||||||
|
/// assert_eq!(v, &[1, 1, 2, 2, 0]);
|
||||||
|
/// ```
|
||||||
|
#[unstable(feature = "exact_chunks", issue = "47115")]
|
||||||
|
#[inline]
|
||||||
|
pub fn exact_chunks_mut(&mut self, chunk_size: usize) -> ExactChunksMut<T> {
|
||||||
|
core_slice::SliceExt::exact_chunks_mut(self, chunk_size)
|
||||||
|
}
|
||||||
|
|
||||||
/// Divides one slice into two at an index.
|
/// Divides one slice into two at an index.
|
||||||
///
|
///
|
||||||
/// The first will contain all indices from `[0, mid)` (excluding
|
/// The first will contain all indices from `[0, mid)` (excluding
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
#![feature(string_retain)]
|
#![feature(string_retain)]
|
||||||
#![feature(unboxed_closures)]
|
#![feature(unboxed_closures)]
|
||||||
#![feature(unicode)]
|
#![feature(unicode)]
|
||||||
|
#![feature(exact_chunks)]
|
||||||
|
|
||||||
extern crate alloc_system;
|
extern crate alloc_system;
|
||||||
extern crate std_unicode;
|
extern crate std_unicode;
|
||||||
|
|
|
@ -945,6 +945,30 @@ fn test_chunksator_0() {
|
||||||
let _it = v.chunks(0);
|
let _it = v.chunks(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_exact_chunksator() {
|
||||||
|
let v = &[1, 2, 3, 4, 5];
|
||||||
|
|
||||||
|
assert_eq!(v.exact_chunks(2).len(), 2);
|
||||||
|
|
||||||
|
let chunks: &[&[_]] = &[&[1, 2], &[3, 4]];
|
||||||
|
assert_eq!(v.exact_chunks(2).collect::<Vec<_>>(), chunks);
|
||||||
|
let chunks: &[&[_]] = &[&[1, 2, 3]];
|
||||||
|
assert_eq!(v.exact_chunks(3).collect::<Vec<_>>(), chunks);
|
||||||
|
let chunks: &[&[_]] = &[];
|
||||||
|
assert_eq!(v.exact_chunks(6).collect::<Vec<_>>(), chunks);
|
||||||
|
|
||||||
|
let chunks: &[&[_]] = &[&[3, 4], &[1, 2]];
|
||||||
|
assert_eq!(v.exact_chunks(2).rev().collect::<Vec<_>>(), chunks);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[should_panic]
|
||||||
|
fn test_exact_chunksator_0() {
|
||||||
|
let v = &[1, 2, 3, 4];
|
||||||
|
let _it = v.exact_chunks(0);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_reverse_part() {
|
fn test_reverse_part() {
|
||||||
let mut values = [1, 2, 3, 4, 5];
|
let mut values = [1, 2, 3, 4, 5];
|
||||||
|
@ -1159,7 +1183,7 @@ fn test_mut_chunks() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let result = [0, 0, 0, 1, 1, 1, 2];
|
let result = [0, 0, 0, 1, 1, 1, 2];
|
||||||
assert!(v == result);
|
assert_eq!(v, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -1171,7 +1195,7 @@ fn test_mut_chunks_rev() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let result = [2, 2, 2, 1, 1, 1, 0];
|
let result = [2, 2, 2, 1, 1, 1, 0];
|
||||||
assert!(v == result);
|
assert_eq!(v, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -1181,6 +1205,38 @@ fn test_mut_chunks_0() {
|
||||||
let _it = v.chunks_mut(0);
|
let _it = v.chunks_mut(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_mut_exact_chunks() {
|
||||||
|
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() {
|
||||||
|
for x in chunk {
|
||||||
|
*x = i as u8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let result = [0, 0, 0, 1, 1, 1, 6];
|
||||||
|
assert_eq!(v, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_mut_exact_chunks_rev() {
|
||||||
|
let mut v = [0, 1, 2, 3, 4, 5, 6];
|
||||||
|
for (i, chunk) in v.exact_chunks_mut(3).rev().enumerate() {
|
||||||
|
for x in chunk {
|
||||||
|
*x = i as u8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let result = [1, 1, 1, 0, 0, 0, 6];
|
||||||
|
assert_eq!(v, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[should_panic]
|
||||||
|
fn test_mut_exact_chunks_0() {
|
||||||
|
let mut v = [1, 2, 3, 4];
|
||||||
|
let _it = v.exact_chunks_mut(0);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_mut_last() {
|
fn test_mut_last() {
|
||||||
let mut x = [1, 2, 3, 4, 5];
|
let mut x = [1, 2, 3, 4, 5];
|
||||||
|
|
|
@ -104,6 +104,9 @@ pub trait SliceExt {
|
||||||
#[stable(feature = "core", since = "1.6.0")]
|
#[stable(feature = "core", since = "1.6.0")]
|
||||||
fn chunks(&self, size: usize) -> Chunks<Self::Item>;
|
fn chunks(&self, size: usize) -> Chunks<Self::Item>;
|
||||||
|
|
||||||
|
#[unstable(feature = "exact_chunks", issue = "47115")]
|
||||||
|
fn exact_chunks(&self, size: usize) -> ExactChunks<Self::Item>;
|
||||||
|
|
||||||
#[stable(feature = "core", since = "1.6.0")]
|
#[stable(feature = "core", since = "1.6.0")]
|
||||||
fn get<I>(&self, index: I) -> Option<&I::Output>
|
fn get<I>(&self, index: I) -> Option<&I::Output>
|
||||||
where I: SliceIndex<Self>;
|
where I: SliceIndex<Self>;
|
||||||
|
@ -181,6 +184,9 @@ pub trait SliceExt {
|
||||||
#[stable(feature = "core", since = "1.6.0")]
|
#[stable(feature = "core", since = "1.6.0")]
|
||||||
fn chunks_mut(&mut self, chunk_size: usize) -> ChunksMut<Self::Item>;
|
fn chunks_mut(&mut self, chunk_size: usize) -> ChunksMut<Self::Item>;
|
||||||
|
|
||||||
|
#[unstable(feature = "exact_chunks", issue = "47115")]
|
||||||
|
fn exact_chunks_mut(&mut self, size: usize) -> ExactChunksMut<Self::Item>;
|
||||||
|
|
||||||
#[stable(feature = "core", since = "1.6.0")]
|
#[stable(feature = "core", since = "1.6.0")]
|
||||||
fn swap(&mut self, a: usize, b: usize);
|
fn swap(&mut self, a: usize, b: usize);
|
||||||
|
|
||||||
|
@ -356,6 +362,14 @@ impl<T> SliceExt for [T] {
|
||||||
Chunks { v: self, chunk_size: chunk_size }
|
Chunks { v: self, chunk_size: chunk_size }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn exact_chunks(&self, chunk_size: usize) -> ExactChunks<T> {
|
||||||
|
assert!(chunk_size != 0);
|
||||||
|
let rem = self.len() % chunk_size;
|
||||||
|
let len = self.len() - rem;
|
||||||
|
ExactChunks { v: &self[..len], chunk_size: chunk_size}
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn get<I>(&self, index: I) -> Option<&I::Output>
|
fn get<I>(&self, index: I) -> Option<&I::Output>
|
||||||
where I: SliceIndex<[T]>
|
where I: SliceIndex<[T]>
|
||||||
|
@ -539,6 +553,14 @@ impl<T> SliceExt for [T] {
|
||||||
ChunksMut { v: self, chunk_size: chunk_size }
|
ChunksMut { v: self, chunk_size: chunk_size }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn exact_chunks_mut(&mut self, chunk_size: usize) -> ExactChunksMut<T> {
|
||||||
|
assert!(chunk_size != 0);
|
||||||
|
let rem = self.len() % chunk_size;
|
||||||
|
let len = self.len() - rem;
|
||||||
|
ExactChunksMut { v: &mut self[..len], chunk_size: chunk_size}
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn swap(&mut self, a: usize, b: usize) {
|
fn swap(&mut self, a: usize, b: usize) {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -2378,6 +2400,209 @@ unsafe impl<'a, T> TrustedRandomAccess for ChunksMut<'a, T> {
|
||||||
fn may_have_side_effect() -> bool { false }
|
fn may_have_side_effect() -> bool { false }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// An iterator over a slice in (non-overlapping) chunks (`chunk_size` elements at a
|
||||||
|
/// time).
|
||||||
|
///
|
||||||
|
/// When the slice len is not evenly divided by the chunk size, the last
|
||||||
|
/// up to `chunk_size-1` elements will be omitted.
|
||||||
|
///
|
||||||
|
/// This struct is created by the [`exact_chunks`] method on [slices].
|
||||||
|
///
|
||||||
|
/// [`exact_chunks`]: ../../std/primitive.slice.html#method.exact_chunks
|
||||||
|
/// [slices]: ../../std/primitive.slice.html
|
||||||
|
#[derive(Debug)]
|
||||||
|
#[unstable(feature = "exact_chunks", issue = "47115")]
|
||||||
|
pub struct ExactChunks<'a, T:'a> {
|
||||||
|
v: &'a [T],
|
||||||
|
chunk_size: usize
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME(#26925) Remove in favor of `#[derive(Clone)]`
|
||||||
|
#[unstable(feature = "exact_chunks", issue = "47115")]
|
||||||
|
impl<'a, T> Clone for ExactChunks<'a, T> {
|
||||||
|
fn clone(&self) -> ExactChunks<'a, T> {
|
||||||
|
ExactChunks {
|
||||||
|
v: self.v,
|
||||||
|
chunk_size: self.chunk_size,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unstable(feature = "exact_chunks", issue = "47115")]
|
||||||
|
impl<'a, T> Iterator for ExactChunks<'a, T> {
|
||||||
|
type Item = &'a [T];
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn next(&mut self) -> Option<&'a [T]> {
|
||||||
|
if self.v.len() < self.chunk_size {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
let (fst, snd) = self.v.split_at(self.chunk_size);
|
||||||
|
self.v = snd;
|
||||||
|
Some(fst)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||||
|
let n = self.v.len() / self.chunk_size;
|
||||||
|
(n, Some(n))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn count(self) -> usize {
|
||||||
|
self.len()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn nth(&mut self, n: usize) -> Option<Self::Item> {
|
||||||
|
let (start, overflow) = n.overflowing_mul(self.chunk_size);
|
||||||
|
if start >= self.v.len() || overflow {
|
||||||
|
self.v = &[];
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
let (_, snd) = self.v.split_at(start);
|
||||||
|
self.v = snd;
|
||||||
|
self.next()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn last(mut self) -> Option<Self::Item> {
|
||||||
|
self.next_back()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unstable(feature = "exact_chunks", issue = "47115")]
|
||||||
|
impl<'a, T> DoubleEndedIterator for ExactChunks<'a, T> {
|
||||||
|
#[inline]
|
||||||
|
fn next_back(&mut self) -> Option<&'a [T]> {
|
||||||
|
if self.v.len() < self.chunk_size {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
let (fst, snd) = self.v.split_at(self.v.len() - self.chunk_size);
|
||||||
|
self.v = fst;
|
||||||
|
Some(snd)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unstable(feature = "exact_chunks", issue = "47115")]
|
||||||
|
impl<'a, T> ExactSizeIterator for ExactChunks<'a, T> {
|
||||||
|
fn is_empty(&self) -> bool {
|
||||||
|
self.v.is_empty()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unstable(feature = "fused", issue = "35602")]
|
||||||
|
impl<'a, T> FusedIterator for ExactChunks<'a, T> {}
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
unsafe impl<'a, T> TrustedRandomAccess for ExactChunks<'a, T> {
|
||||||
|
unsafe fn get_unchecked(&mut self, i: usize) -> &'a [T] {
|
||||||
|
let start = i * self.chunk_size;
|
||||||
|
from_raw_parts(self.v.as_ptr().offset(start as isize), self.chunk_size)
|
||||||
|
}
|
||||||
|
fn may_have_side_effect() -> bool { false }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// An iterator over a slice in (non-overlapping) mutable chunks (`chunk_size`
|
||||||
|
/// elements at a time). When the slice len is not evenly divided by the chunk
|
||||||
|
/// size, the last up to `chunk_size-1` elements will be omitted.
|
||||||
|
///
|
||||||
|
/// This struct is created by the [`exact_chunks_mut`] method on [slices].
|
||||||
|
///
|
||||||
|
/// [`exact_chunks_mut`]: ../../std/primitive.slice.html#method.exact_chunks_mut
|
||||||
|
/// [slices]: ../../std/primitive.slice.html
|
||||||
|
#[derive(Debug)]
|
||||||
|
#[unstable(feature = "exact_chunks", issue = "47115")]
|
||||||
|
pub struct ExactChunksMut<'a, T:'a> {
|
||||||
|
v: &'a mut [T],
|
||||||
|
chunk_size: usize
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unstable(feature = "exact_chunks", issue = "47115")]
|
||||||
|
impl<'a, T> Iterator for ExactChunksMut<'a, T> {
|
||||||
|
type Item = &'a mut [T];
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn next(&mut self) -> Option<&'a mut [T]> {
|
||||||
|
if self.v.len() < self.chunk_size {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
let tmp = mem::replace(&mut self.v, &mut []);
|
||||||
|
let (head, tail) = tmp.split_at_mut(self.chunk_size);
|
||||||
|
self.v = tail;
|
||||||
|
Some(head)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||||
|
let n = self.v.len() / self.chunk_size;
|
||||||
|
(n, Some(n))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn count(self) -> usize {
|
||||||
|
self.len()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn nth(&mut self, n: usize) -> Option<&'a mut [T]> {
|
||||||
|
let (start, overflow) = n.overflowing_mul(self.chunk_size);
|
||||||
|
if start >= self.v.len() || overflow {
|
||||||
|
self.v = &mut [];
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
let tmp = mem::replace(&mut self.v, &mut []);
|
||||||
|
let (_, snd) = tmp.split_at_mut(start);
|
||||||
|
self.v = snd;
|
||||||
|
self.next()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn last(mut self) -> Option<Self::Item> {
|
||||||
|
self.next_back()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unstable(feature = "exact_chunks", issue = "47115")]
|
||||||
|
impl<'a, T> DoubleEndedIterator for ExactChunksMut<'a, T> {
|
||||||
|
#[inline]
|
||||||
|
fn next_back(&mut self) -> Option<&'a mut [T]> {
|
||||||
|
if self.v.len() < self.chunk_size {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
let tmp = mem::replace(&mut self.v, &mut []);
|
||||||
|
let tmp_len = tmp.len();
|
||||||
|
let (head, tail) = tmp.split_at_mut(tmp_len - self.chunk_size);
|
||||||
|
self.v = head;
|
||||||
|
Some(tail)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unstable(feature = "exact_chunks", issue = "47115")]
|
||||||
|
impl<'a, T> ExactSizeIterator for ExactChunksMut<'a, T> {
|
||||||
|
fn is_empty(&self) -> bool {
|
||||||
|
self.v.is_empty()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unstable(feature = "fused", issue = "35602")]
|
||||||
|
impl<'a, T> FusedIterator for ExactChunksMut<'a, T> {}
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
unsafe impl<'a, T> TrustedRandomAccess for ExactChunksMut<'a, T> {
|
||||||
|
unsafe fn get_unchecked(&mut self, i: usize) -> &'a mut [T] {
|
||||||
|
let start = i * self.chunk_size;
|
||||||
|
from_raw_parts_mut(self.v.as_mut_ptr().offset(start as isize), self.chunk_size)
|
||||||
|
}
|
||||||
|
fn may_have_side_effect() -> bool { false }
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Free functions
|
// Free functions
|
||||||
//
|
//
|
||||||
|
|
|
@ -42,6 +42,7 @@
|
||||||
#![feature(try_from)]
|
#![feature(try_from)]
|
||||||
#![feature(try_trait)]
|
#![feature(try_trait)]
|
||||||
#![feature(unique)]
|
#![feature(unique)]
|
||||||
|
#![feature(exact_chunks)]
|
||||||
|
|
||||||
extern crate core;
|
extern crate core;
|
||||||
extern crate test;
|
extern crate test;
|
||||||
|
|
|
@ -117,12 +117,12 @@ fn test_chunks_count() {
|
||||||
fn test_chunks_nth() {
|
fn test_chunks_nth() {
|
||||||
let v: &[i32] = &[0, 1, 2, 3, 4, 5];
|
let v: &[i32] = &[0, 1, 2, 3, 4, 5];
|
||||||
let mut c = v.chunks(2);
|
let mut c = v.chunks(2);
|
||||||
assert_eq!(c.nth(1).unwrap()[1], 3);
|
assert_eq!(c.nth(1).unwrap(), &[2, 3]);
|
||||||
assert_eq!(c.next().unwrap()[0], 4);
|
assert_eq!(c.next().unwrap(), &[4, 5]);
|
||||||
|
|
||||||
let v2: &[i32] = &[0, 1, 2, 3, 4];
|
let v2: &[i32] = &[0, 1, 2, 3, 4];
|
||||||
let mut c2 = v2.chunks(3);
|
let mut c2 = v2.chunks(3);
|
||||||
assert_eq!(c2.nth(1).unwrap()[1], 4);
|
assert_eq!(c2.nth(1).unwrap(), &[3, 4]);
|
||||||
assert_eq!(c2.next(), None);
|
assert_eq!(c2.next(), None);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -168,12 +168,12 @@ fn test_chunks_mut_count() {
|
||||||
fn test_chunks_mut_nth() {
|
fn test_chunks_mut_nth() {
|
||||||
let v: &mut [i32] = &mut [0, 1, 2, 3, 4, 5];
|
let v: &mut [i32] = &mut [0, 1, 2, 3, 4, 5];
|
||||||
let mut c = v.chunks_mut(2);
|
let mut c = v.chunks_mut(2);
|
||||||
assert_eq!(c.nth(1).unwrap()[1], 3);
|
assert_eq!(c.nth(1).unwrap(), &[2, 3]);
|
||||||
assert_eq!(c.next().unwrap()[0], 4);
|
assert_eq!(c.next().unwrap(), &[4, 5]);
|
||||||
|
|
||||||
let v2: &mut [i32] = &mut [0, 1, 2, 3, 4];
|
let v2: &mut [i32] = &mut [0, 1, 2, 3, 4];
|
||||||
let mut c2 = v2.chunks_mut(3);
|
let mut c2 = v2.chunks_mut(3);
|
||||||
assert_eq!(c2.nth(1).unwrap()[1], 4);
|
assert_eq!(c2.nth(1).unwrap(), &[3, 4]);
|
||||||
assert_eq!(c2.next(), None);
|
assert_eq!(c2.next(), None);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -181,11 +181,11 @@ fn test_chunks_mut_nth() {
|
||||||
fn test_chunks_mut_last() {
|
fn test_chunks_mut_last() {
|
||||||
let v: &mut [i32] = &mut [0, 1, 2, 3, 4, 5];
|
let v: &mut [i32] = &mut [0, 1, 2, 3, 4, 5];
|
||||||
let c = v.chunks_mut(2);
|
let c = v.chunks_mut(2);
|
||||||
assert_eq!(c.last().unwrap()[1], 5);
|
assert_eq!(c.last().unwrap(), &[4, 5]);
|
||||||
|
|
||||||
let v2: &mut [i32] = &mut [0, 1, 2, 3, 4];
|
let v2: &mut [i32] = &mut [0, 1, 2, 3, 4];
|
||||||
let c2 = v2.chunks_mut(2);
|
let c2 = v2.chunks_mut(2);
|
||||||
assert_eq!(c2.last().unwrap()[0], 4);
|
assert_eq!(c2.last().unwrap(), &[4]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -202,6 +202,110 @@ fn test_chunks_mut_zip() {
|
||||||
assert_eq!(v1, [13, 14, 19, 20, 14]);
|
assert_eq!(v1, [13, 14, 19, 20, 14]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_exact_chunks_count() {
|
||||||
|
let v: &[i32] = &[0, 1, 2, 3, 4, 5];
|
||||||
|
let c = v.exact_chunks(3);
|
||||||
|
assert_eq!(c.count(), 2);
|
||||||
|
|
||||||
|
let v2: &[i32] = &[0, 1, 2, 3, 4];
|
||||||
|
let c2 = v2.exact_chunks(2);
|
||||||
|
assert_eq!(c2.count(), 2);
|
||||||
|
|
||||||
|
let v3: &[i32] = &[];
|
||||||
|
let c3 = v3.exact_chunks(2);
|
||||||
|
assert_eq!(c3.count(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_exact_chunks_nth() {
|
||||||
|
let v: &[i32] = &[0, 1, 2, 3, 4, 5];
|
||||||
|
let mut c = v.exact_chunks(2);
|
||||||
|
assert_eq!(c.nth(1).unwrap(), &[2, 3]);
|
||||||
|
assert_eq!(c.next().unwrap(), &[4, 5]);
|
||||||
|
|
||||||
|
let v2: &[i32] = &[0, 1, 2, 3, 4, 5, 6];
|
||||||
|
let mut c2 = v2.exact_chunks(3);
|
||||||
|
assert_eq!(c2.nth(1).unwrap(), &[3, 4, 5]);
|
||||||
|
assert_eq!(c2.next(), None);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_exact_chunks_last() {
|
||||||
|
let v: &[i32] = &[0, 1, 2, 3, 4, 5];
|
||||||
|
let c = v.exact_chunks(2);
|
||||||
|
assert_eq!(c.last().unwrap(), &[4, 5]);
|
||||||
|
|
||||||
|
let v2: &[i32] = &[0, 1, 2, 3, 4];
|
||||||
|
let c2 = v2.exact_chunks(2);
|
||||||
|
assert_eq!(c2.last().unwrap(), &[2, 3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_exact_chunks_zip() {
|
||||||
|
let v1: &[i32] = &[0, 1, 2, 3, 4];
|
||||||
|
let v2: &[i32] = &[6, 7, 8, 9, 10];
|
||||||
|
|
||||||
|
let res = v1.exact_chunks(2)
|
||||||
|
.zip(v2.exact_chunks(2))
|
||||||
|
.map(|(a, b)| a.iter().sum::<i32>() + b.iter().sum::<i32>())
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
assert_eq!(res, vec![14, 22]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_exact_chunks_mut_count() {
|
||||||
|
let v: &mut [i32] = &mut [0, 1, 2, 3, 4, 5];
|
||||||
|
let c = v.exact_chunks_mut(3);
|
||||||
|
assert_eq!(c.count(), 2);
|
||||||
|
|
||||||
|
let v2: &mut [i32] = &mut [0, 1, 2, 3, 4];
|
||||||
|
let c2 = v2.exact_chunks_mut(2);
|
||||||
|
assert_eq!(c2.count(), 2);
|
||||||
|
|
||||||
|
let v3: &mut [i32] = &mut [];
|
||||||
|
let c3 = v3.exact_chunks_mut(2);
|
||||||
|
assert_eq!(c3.count(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_exact_chunks_mut_nth() {
|
||||||
|
let v: &mut [i32] = &mut [0, 1, 2, 3, 4, 5];
|
||||||
|
let mut c = v.exact_chunks_mut(2);
|
||||||
|
assert_eq!(c.nth(1).unwrap(), &[2, 3]);
|
||||||
|
assert_eq!(c.next().unwrap(), &[4, 5]);
|
||||||
|
|
||||||
|
let v2: &mut [i32] = &mut [0, 1, 2, 3, 4, 5, 6];
|
||||||
|
let mut c2 = v2.exact_chunks_mut(3);
|
||||||
|
assert_eq!(c2.nth(1).unwrap(), &[3, 4, 5]);
|
||||||
|
assert_eq!(c2.next(), None);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_exact_chunks_mut_last() {
|
||||||
|
let v: &mut [i32] = &mut [0, 1, 2, 3, 4, 5];
|
||||||
|
let c = v.exact_chunks_mut(2);
|
||||||
|
assert_eq!(c.last().unwrap(), &[4, 5]);
|
||||||
|
|
||||||
|
let v2: &mut [i32] = &mut [0, 1, 2, 3, 4];
|
||||||
|
let c2 = v2.exact_chunks_mut(2);
|
||||||
|
assert_eq!(c2.last().unwrap(), &[2, 3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_exact_chunks_mut_zip() {
|
||||||
|
let v1: &mut [i32] = &mut [0, 1, 2, 3, 4];
|
||||||
|
let v2: &[i32] = &[6, 7, 8, 9, 10];
|
||||||
|
|
||||||
|
for (a, b) in v1.exact_chunks_mut(2).zip(v2.exact_chunks(2)) {
|
||||||
|
let sum = b.iter().sum::<i32>();
|
||||||
|
for v in a {
|
||||||
|
*v += sum;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert_eq!(v1, [13, 14, 19, 20, 4]);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_windows_count() {
|
fn test_windows_count() {
|
||||||
let v: &[i32] = &[0, 1, 2, 3, 4, 5];
|
let v: &[i32] = &[0, 1, 2, 3, 4, 5];
|
||||||
|
|
|
@ -37,7 +37,7 @@ use rustc_typeck as typeck;
|
||||||
use rustc_privacy;
|
use rustc_privacy;
|
||||||
use rustc_plugin::registry::Registry;
|
use rustc_plugin::registry::Registry;
|
||||||
use rustc_plugin as plugin;
|
use rustc_plugin as plugin;
|
||||||
use rustc_passes::{self, ast_validation, no_asm, loops, consts, static_recursion, hir_stats};
|
use rustc_passes::{self, ast_validation, loops, consts, static_recursion, hir_stats};
|
||||||
use rustc_const_eval::{self, check_match};
|
use rustc_const_eval::{self, check_match};
|
||||||
use super::Compilation;
|
use super::Compilation;
|
||||||
use ::DefaultTransCrate;
|
use ::DefaultTransCrate;
|
||||||
|
@ -852,10 +852,6 @@ pub fn phase_2_configure_and_expand<F>(sess: &Session,
|
||||||
println!("{}", json::as_json(&krate));
|
println!("{}", json::as_json(&krate));
|
||||||
}
|
}
|
||||||
|
|
||||||
time(time_passes,
|
|
||||||
"checking for inline asm in case the target doesn't support it",
|
|
||||||
|| no_asm::check_crate(sess, &krate));
|
|
||||||
|
|
||||||
time(time_passes,
|
time(time_passes,
|
||||||
"AST validation",
|
"AST validation",
|
||||||
|| ast_validation::check_crate(sess, &krate));
|
|| ast_validation::check_crate(sess, &krate));
|
||||||
|
|
|
@ -92,9 +92,19 @@ impl<'a, 'tcx> ItemLikeVisitor<'tcx> for Collector<'a, 'tcx> {
|
||||||
let cfg = items.iter().find(|k| {
|
let cfg = items.iter().find(|k| {
|
||||||
k.check_name("cfg")
|
k.check_name("cfg")
|
||||||
}).and_then(|a| a.meta_item_list());
|
}).and_then(|a| a.meta_item_list());
|
||||||
let cfg = cfg.map(|list| {
|
let cfg = if let Some(list) = cfg {
|
||||||
list[0].meta_item().unwrap().clone()
|
if list.is_empty() {
|
||||||
});
|
self.tcx.sess.span_err(m.span(), "`cfg()` must have an argument");
|
||||||
|
return;
|
||||||
|
} else if let cfg @ Some(..) = list[0].meta_item() {
|
||||||
|
cfg.cloned()
|
||||||
|
} else {
|
||||||
|
self.tcx.sess.span_err(list[0].span(), "invalid argument for `cfg(..)`");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
let foreign_items = fm.items.iter()
|
let foreign_items = fm.items.iter()
|
||||||
.map(|it| self.tcx.hir.local_def_id(it.id))
|
.map(|it| self.tcx.hir.local_def_id(it.id))
|
||||||
.collect();
|
.collect();
|
||||||
|
|
|
@ -149,6 +149,9 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
||||||
ExprKind::Continue(Some(ident)) => {
|
ExprKind::Continue(Some(ident)) => {
|
||||||
self.check_label(ident.node, ident.span);
|
self.check_label(ident.node, ident.span);
|
||||||
}
|
}
|
||||||
|
ExprKind::InlineAsm(..) if !self.session.target.target.options.allow_asm => {
|
||||||
|
span_err!(self.session, expr.span, E0472, "asm! is unsupported on this target");
|
||||||
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -42,7 +42,6 @@ pub mod consts;
|
||||||
pub mod hir_stats;
|
pub mod hir_stats;
|
||||||
pub mod loops;
|
pub mod loops;
|
||||||
mod mir_stats;
|
mod mir_stats;
|
||||||
pub mod no_asm;
|
|
||||||
pub mod static_recursion;
|
pub mod static_recursion;
|
||||||
|
|
||||||
#[cfg(not(stage0))] // remove after the next snapshot
|
#[cfg(not(stage0))] // remove after the next snapshot
|
||||||
|
|
|
@ -1,47 +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.
|
|
||||||
|
|
||||||
/// Run over the whole crate and check for ExprInlineAsm.
|
|
||||||
/// Inline asm isn't allowed on virtual ISA based targets, so we reject it
|
|
||||||
/// here.
|
|
||||||
|
|
||||||
use rustc::session::Session;
|
|
||||||
|
|
||||||
use syntax::ast;
|
|
||||||
use syntax::visit::Visitor;
|
|
||||||
use syntax::visit;
|
|
||||||
|
|
||||||
pub fn check_crate(sess: &Session, krate: &ast::Crate) {
|
|
||||||
if sess.target.target.options.allow_asm {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
visit::walk_crate(&mut CheckNoAsm { sess: sess }, krate);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
|
||||||
struct CheckNoAsm<'a> {
|
|
||||||
sess: &'a Session,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> Visitor<'a> for CheckNoAsm<'a> {
|
|
||||||
fn visit_expr(&mut self, e: &'a ast::Expr) {
|
|
||||||
match e.node {
|
|
||||||
ast::ExprKind::InlineAsm(_) => {
|
|
||||||
span_err!(self.sess,
|
|
||||||
e.span,
|
|
||||||
E0472,
|
|
||||||
"asm! is unsupported on this target")
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
visit::walk_expr(self, e)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -472,20 +472,19 @@ impl f32 {
|
||||||
|
|
||||||
/// Returns the logarithm of the number with respect to an arbitrary base.
|
/// Returns the logarithm of the number with respect to an arbitrary base.
|
||||||
///
|
///
|
||||||
|
/// The result may not be correctly rounded owing to implementation details;
|
||||||
|
/// `self.log2()` can produce more accurate results for base 2, and
|
||||||
|
/// `self.log10()` can produce more accurate results for base 10.
|
||||||
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use std::f32;
|
/// use std::f32;
|
||||||
///
|
///
|
||||||
/// let ten = 10.0f32;
|
/// let five = 5.0f32;
|
||||||
/// let two = 2.0f32;
|
|
||||||
///
|
///
|
||||||
/// // log10(10) - 1 == 0
|
/// // log5(5) - 1 == 0
|
||||||
/// let abs_difference_10 = (ten.log(10.0) - 1.0).abs();
|
/// let abs_difference = (five.log(5.0) - 1.0).abs();
|
||||||
///
|
///
|
||||||
/// // log2(2) - 1 == 0
|
/// assert!(abs_difference <= f32::EPSILON);
|
||||||
/// let abs_difference_2 = (two.log(2.0) - 1.0).abs();
|
|
||||||
///
|
|
||||||
/// assert!(abs_difference_10 <= f32::EPSILON);
|
|
||||||
/// assert!(abs_difference_2 <= f32::EPSILON);
|
|
||||||
/// ```
|
/// ```
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|
|
@ -432,18 +432,17 @@ impl f64 {
|
||||||
|
|
||||||
/// Returns the logarithm of the number with respect to an arbitrary base.
|
/// Returns the logarithm of the number with respect to an arbitrary base.
|
||||||
///
|
///
|
||||||
|
/// The result may not be correctly rounded owing to implementation details;
|
||||||
|
/// `self.log2()` can produce more accurate results for base 2, and
|
||||||
|
/// `self.log10()` can produce more accurate results for base 10.
|
||||||
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// let ten = 10.0_f64;
|
/// let five = 5.0_f64;
|
||||||
/// let two = 2.0_f64;
|
|
||||||
///
|
///
|
||||||
/// // log10(10) - 1 == 0
|
/// // log5(5) - 1 == 0
|
||||||
/// let abs_difference_10 = (ten.log(10.0) - 1.0).abs();
|
/// let abs_difference = (five.log(5.0) - 1.0).abs();
|
||||||
///
|
///
|
||||||
/// // log2(2) - 1 == 0
|
/// assert!(abs_difference < 1e-10);
|
||||||
/// let abs_difference_2 = (two.log(2.0) - 1.0).abs();
|
|
||||||
///
|
|
||||||
/// assert!(abs_difference_10 < 1e-10);
|
|
||||||
/// assert!(abs_difference_2 < 1e-10);
|
|
||||||
/// ```
|
/// ```
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|
|
@ -345,8 +345,8 @@ impl<R: Seek> Seek for BufReader<R> {
|
||||||
///
|
///
|
||||||
/// let mut stream = TcpStream::connect("127.0.0.1:34254").unwrap();
|
/// let mut stream = TcpStream::connect("127.0.0.1:34254").unwrap();
|
||||||
///
|
///
|
||||||
/// for i in 1..10 {
|
/// for i in 0..10 {
|
||||||
/// stream.write(&[i]).unwrap();
|
/// stream.write(&[i+1]).unwrap();
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
|
@ -361,8 +361,8 @@ impl<R: Seek> Seek for BufReader<R> {
|
||||||
///
|
///
|
||||||
/// let mut stream = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap());
|
/// let mut stream = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap());
|
||||||
///
|
///
|
||||||
/// for i in 1..10 {
|
/// for i in 0..10 {
|
||||||
/// stream.write(&[i]).unwrap();
|
/// stream.write(&[i+1]).unwrap();
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
|
|
|
@ -62,12 +62,18 @@ pub type Result<T> = result::Result<T, Error>;
|
||||||
/// [`Write`]: ../io/trait.Write.html
|
/// [`Write`]: ../io/trait.Write.html
|
||||||
/// [`Seek`]: ../io/trait.Seek.html
|
/// [`Seek`]: ../io/trait.Seek.html
|
||||||
/// [`ErrorKind`]: enum.ErrorKind.html
|
/// [`ErrorKind`]: enum.ErrorKind.html
|
||||||
#[derive(Debug)]
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub struct Error {
|
pub struct Error {
|
||||||
repr: Repr,
|
repr: Repr,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
impl fmt::Debug for Error {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
fmt::Debug::fmt(&self.repr, f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
enum Repr {
|
enum Repr {
|
||||||
Os(i32),
|
Os(i32),
|
||||||
Simple(ErrorKind),
|
Simple(ErrorKind),
|
||||||
|
@ -511,10 +517,12 @@ impl Error {
|
||||||
impl fmt::Debug for Repr {
|
impl fmt::Debug for Repr {
|
||||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||||
match *self {
|
match *self {
|
||||||
Repr::Os(ref code) =>
|
Repr::Os(code) =>
|
||||||
fmt.debug_struct("Os").field("code", code)
|
fmt.debug_struct("Os")
|
||||||
.field("message", &sys::os::error_string(*code)).finish(),
|
.field("code", &code)
|
||||||
Repr::Custom(ref c) => fmt.debug_tuple("Custom").field(c).finish(),
|
.field("kind", &sys::decode_error_kind(code))
|
||||||
|
.field("message", &sys::os::error_string(code)).finish(),
|
||||||
|
Repr::Custom(ref c) => fmt::Debug::fmt(&c, fmt),
|
||||||
Repr::Simple(kind) => fmt.debug_tuple("Kind").field(&kind).finish(),
|
Repr::Simple(kind) => fmt.debug_tuple("Kind").field(&kind).finish(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -559,17 +567,36 @@ fn _assert_error_is_sync_send() {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use super::{Error, ErrorKind};
|
use super::{Error, ErrorKind, Repr, Custom};
|
||||||
use error;
|
use error;
|
||||||
use fmt;
|
use fmt;
|
||||||
use sys::os::error_string;
|
use sys::os::error_string;
|
||||||
|
use sys::decode_error_kind;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_debug_error() {
|
fn test_debug_error() {
|
||||||
let code = 6;
|
let code = 6;
|
||||||
let msg = error_string(code);
|
let msg = error_string(code);
|
||||||
let err = Error { repr: super::Repr::Os(code) };
|
let kind = decode_error_kind(code);
|
||||||
let expected = format!("Error {{ repr: Os {{ code: {:?}, message: {:?} }} }}", code, msg);
|
let err = Error {
|
||||||
|
repr: Repr::Custom(box Custom {
|
||||||
|
kind: ErrorKind::InvalidInput,
|
||||||
|
error: box Error {
|
||||||
|
repr: super::Repr::Os(code)
|
||||||
|
},
|
||||||
|
})
|
||||||
|
};
|
||||||
|
let expected = format!(
|
||||||
|
"Custom {{ \
|
||||||
|
kind: InvalidInput, \
|
||||||
|
error: Os {{ \
|
||||||
|
code: {:?}, \
|
||||||
|
kind: {:?}, \
|
||||||
|
message: {:?} \
|
||||||
|
}} \
|
||||||
|
}}",
|
||||||
|
code, kind, msg
|
||||||
|
);
|
||||||
assert_eq!(format!("{:?}", err), expected);
|
assert_eq!(format!("{:?}", err), expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,108 +0,0 @@
|
||||||
// Copyright 2013 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.
|
|
||||||
|
|
||||||
//! A wrapper around any Read to treat it as an RNG.
|
|
||||||
|
|
||||||
#![allow(dead_code)]
|
|
||||||
|
|
||||||
use io::prelude::*;
|
|
||||||
use rand::Rng;
|
|
||||||
|
|
||||||
/// An RNG that reads random bytes straight from a `Read`. This will
|
|
||||||
/// work best with an infinite reader, but this is not required.
|
|
||||||
///
|
|
||||||
/// # Panics
|
|
||||||
///
|
|
||||||
/// It will panic if it there is insufficient data to fulfill a request.
|
|
||||||
pub struct ReaderRng<R> {
|
|
||||||
reader: R
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<R: Read> ReaderRng<R> {
|
|
||||||
/// Create a new `ReaderRng` from a `Read`.
|
|
||||||
pub fn new(r: R) -> ReaderRng<R> {
|
|
||||||
ReaderRng {
|
|
||||||
reader: r
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<R: Read> Rng for ReaderRng<R> {
|
|
||||||
fn next_u32(&mut self) -> u32 {
|
|
||||||
// This is designed for speed: reading a LE integer on a LE
|
|
||||||
// platform just involves blitting the bytes into the memory
|
|
||||||
// of the u32, similarly for BE on BE; avoiding byteswapping.
|
|
||||||
let mut bytes = [0; 4];
|
|
||||||
self.fill_bytes(&mut bytes);
|
|
||||||
unsafe { *(bytes.as_ptr() as *const u32) }
|
|
||||||
}
|
|
||||||
fn next_u64(&mut self) -> u64 {
|
|
||||||
// see above for explanation.
|
|
||||||
let mut bytes = [0; 8];
|
|
||||||
self.fill_bytes(&mut bytes);
|
|
||||||
unsafe { *(bytes.as_ptr() as *const u64) }
|
|
||||||
}
|
|
||||||
fn fill_bytes(&mut self, mut v: &mut [u8]) {
|
|
||||||
while !v.is_empty() {
|
|
||||||
let t = v;
|
|
||||||
match self.reader.read(t) {
|
|
||||||
Ok(0) => panic!("ReaderRng.fill_bytes: EOF reached"),
|
|
||||||
Ok(n) => v = t.split_at_mut(n).1,
|
|
||||||
Err(e) => panic!("ReaderRng.fill_bytes: {}", e),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use super::ReaderRng;
|
|
||||||
use rand::Rng;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_reader_rng_u64() {
|
|
||||||
// transmute from the target to avoid endianness concerns.
|
|
||||||
let v = &[0, 0, 0, 0, 0, 0, 0, 1,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 2,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 3][..];
|
|
||||||
let mut rng = ReaderRng::new(v);
|
|
||||||
|
|
||||||
assert_eq!(rng.next_u64(), 1u64.to_be());
|
|
||||||
assert_eq!(rng.next_u64(), 2u64.to_be());
|
|
||||||
assert_eq!(rng.next_u64(), 3u64.to_be());
|
|
||||||
}
|
|
||||||
#[test]
|
|
||||||
fn test_reader_rng_u32() {
|
|
||||||
let v = &[0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 3][..];
|
|
||||||
let mut rng = ReaderRng::new(v);
|
|
||||||
|
|
||||||
assert_eq!(rng.next_u32(), 1u32.to_be());
|
|
||||||
assert_eq!(rng.next_u32(), 2u32.to_be());
|
|
||||||
assert_eq!(rng.next_u32(), 3u32.to_be());
|
|
||||||
}
|
|
||||||
#[test]
|
|
||||||
fn test_reader_rng_fill_bytes() {
|
|
||||||
let v = [1, 2, 3, 4, 5, 6, 7, 8];
|
|
||||||
let mut w = [0; 8];
|
|
||||||
|
|
||||||
let mut rng = ReaderRng::new(&v[..]);
|
|
||||||
rng.fill_bytes(&mut w);
|
|
||||||
|
|
||||||
assert!(v == w);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
#[should_panic]
|
|
||||||
fn test_reader_rng_insufficient_bytes() {
|
|
||||||
let mut rng = ReaderRng::new(&[][..]);
|
|
||||||
let mut v = [0; 3];
|
|
||||||
rng.fill_bytes(&mut v);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
// Copyright 2018 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(attr_literals)]
|
||||||
|
|
||||||
|
#[link(name="foo", cfg("rlib"))] //~ ERROR invalid argument for `cfg(..)`
|
||||||
|
extern {}
|
||||||
|
|
||||||
|
fn main() {}
|
|
@ -0,0 +1,14 @@
|
||||||
|
// Copyright 2018 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.
|
||||||
|
|
||||||
|
#[link(name="foo", cfg())] //~ ERROR `cfg()` must have an argument
|
||||||
|
extern {}
|
||||||
|
|
||||||
|
fn main() {}
|
|
@ -0,0 +1,30 @@
|
||||||
|
// Copyright 2018 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.
|
||||||
|
|
||||||
|
// Regression test for issue #38899
|
||||||
|
|
||||||
|
#![feature(nll)]
|
||||||
|
#![allow(dead_code)]
|
||||||
|
|
||||||
|
pub struct Block<'a> {
|
||||||
|
current: &'a u8,
|
||||||
|
unrelated: &'a u8,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn bump<'a>(mut block: &mut Block<'a>) {
|
||||||
|
let x = &mut block;
|
||||||
|
println!("{}", x.current);
|
||||||
|
let p: &'a u8 = &*block.current;
|
||||||
|
//~^ ERROR cannot borrow `*block.current` as immutable because it is also borrowed as mutable
|
||||||
|
drop(x);
|
||||||
|
drop(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
|
@ -0,0 +1,11 @@
|
||||||
|
error[E0502]: cannot borrow `*block.current` as immutable because it is also borrowed as mutable
|
||||||
|
--> $DIR/borrowed-referent-issue-38899.rs:24:21
|
||||||
|
|
|
||||||
|
22 | let x = &mut block;
|
||||||
|
| ---------- mutable borrow occurs here
|
||||||
|
23 | println!("{}", x.current);
|
||||||
|
24 | let p: &'a u8 = &*block.current;
|
||||||
|
| ^^^^^^^^^^^^^^^ immutable borrow occurs here
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
// Copyright 2018 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.
|
||||||
|
|
||||||
|
// Regression test for issue #46557
|
||||||
|
|
||||||
|
#![feature(nll)]
|
||||||
|
#![allow(dead_code)]
|
||||||
|
|
||||||
|
fn gimme_static_mut() -> &'static mut u32 {
|
||||||
|
let ref mut x = 1234543; //~ ERROR borrowed value does not live long enough [E0597]
|
||||||
|
x
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
|
@ -0,0 +1,13 @@
|
||||||
|
error[E0597]: borrowed value does not live long enough
|
||||||
|
--> $DIR/return-ref-mut-issue-46557.rs:17:21
|
||||||
|
|
|
||||||
|
17 | let ref mut x = 1234543; //~ ERROR borrowed value does not live long enough [E0597]
|
||||||
|
| ^^^^^^^ temporary value does not live long enough
|
||||||
|
18 | x
|
||||||
|
19 | }
|
||||||
|
| - temporary value only lives until here
|
||||||
|
|
|
||||||
|
= note: borrowed value must be valid for lifetime '_#2r...
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
|
@ -49,7 +49,7 @@ pub fn collect_unstable_feature_names(features: &Features) -> BTreeSet<String> {
|
||||||
features
|
features
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|&(_, ref f)| f.level == Status::Unstable)
|
.filter(|&(_, ref f)| f.level == Status::Unstable)
|
||||||
.map(|(name, _)| name.to_owned())
|
.map(|(name, _)| name.replace('_', "-"))
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,7 +60,7 @@ pub fn collect_unstable_book_section_file_names(dir: &path::Path) -> BTreeSet<St
|
||||||
.map(|entry| entry.expect("could not read directory entry"))
|
.map(|entry| entry.expect("could not read directory entry"))
|
||||||
.filter(dir_entry_is_file)
|
.filter(dir_entry_is_file)
|
||||||
.map(|entry| entry.file_name().into_string().unwrap())
|
.map(|entry| entry.file_name().into_string().unwrap())
|
||||||
.map(|n| n.trim_right_matches(".md").replace('-', "_"))
|
.map(|n| n.trim_right_matches(".md").to_owned())
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -53,9 +53,9 @@ fn set_to_summary_str(set: &BTreeSet<String>, dir: &str
|
||||||
set
|
set
|
||||||
.iter()
|
.iter()
|
||||||
.map(|ref n| format!(" - [{}]({}/{}.md)",
|
.map(|ref n| format!(" - [{}]({}/{}.md)",
|
||||||
n,
|
n.replace('-', "_"),
|
||||||
dir,
|
dir,
|
||||||
n.replace('_', "-")))
|
n))
|
||||||
.fold("".to_owned(), |s, a| s + &a + "\n")
|
.fold("".to_owned(), |s, a| s + &a + "\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,14 +96,17 @@ fn generate_unstable_book_files(src :&Path, out: &Path, features :&Features) {
|
||||||
let unstable_section_file_names = collect_unstable_book_section_file_names(src);
|
let unstable_section_file_names = collect_unstable_book_section_file_names(src);
|
||||||
t!(fs::create_dir_all(&out));
|
t!(fs::create_dir_all(&out));
|
||||||
for feature_name in &unstable_features - &unstable_section_file_names {
|
for feature_name in &unstable_features - &unstable_section_file_names {
|
||||||
let file_name = format!("{}.md", feature_name.replace('_', "-"));
|
let feature_name_underscore = feature_name.replace('-', "_");
|
||||||
|
let file_name = format!("{}.md", feature_name);
|
||||||
let out_file_path = out.join(&file_name);
|
let out_file_path = out.join(&file_name);
|
||||||
let feature = &features[&feature_name];
|
let feature = &features[&feature_name_underscore];
|
||||||
|
|
||||||
if has_valid_tracking_issue(&feature) {
|
if has_valid_tracking_issue(&feature) {
|
||||||
generate_stub_issue(&out_file_path, &feature_name, feature.tracking_issue.unwrap());
|
generate_stub_issue(&out_file_path,
|
||||||
|
&feature_name_underscore,
|
||||||
|
feature.tracking_issue.unwrap());
|
||||||
} else {
|
} else {
|
||||||
generate_stub_no_issue(&out_file_path, &feature_name);
|
generate_stub_no_issue(&out_file_path, &feature_name_underscore);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue