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(allocator_internals)]
|
||||
#![feature(on_unimplemented)]
|
||||
#![feature(exact_chunks)]
|
||||
|
||||
#![cfg_attr(not(test), feature(fused, fn_traits, placement_new_protocol, swap_with_slice, i128))]
|
||||
#![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};
|
||||
#[unstable(feature = "slice_get_slice", issue = "35729")]
|
||||
pub use core::slice::SliceIndex;
|
||||
#[unstable(feature = "exact_chunks", issue = "47115")]
|
||||
pub use core::slice::{ExactChunks, ExactChunksMut};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Basic slice extension methods
|
||||
@ -611,6 +613,9 @@ impl<T> [T] {
|
||||
/// not divide the length of the slice, then the last chunk will
|
||||
/// 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 if `chunk_size` is 0.
|
||||
@ -631,11 +636,44 @@ impl<T> [T] {
|
||||
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.
|
||||
/// 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
|
||||
/// 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 if `chunk_size` is 0.
|
||||
@ -660,6 +698,42 @@ impl<T> [T] {
|
||||
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.
|
||||
///
|
||||
/// The first will contain all indices from `[0, mid)` (excluding
|
||||
|
@ -30,6 +30,7 @@
|
||||
#![feature(string_retain)]
|
||||
#![feature(unboxed_closures)]
|
||||
#![feature(unicode)]
|
||||
#![feature(exact_chunks)]
|
||||
|
||||
extern crate alloc_system;
|
||||
extern crate std_unicode;
|
||||
|
@ -945,6 +945,30 @@ fn test_chunksator_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]
|
||||
fn test_reverse_part() {
|
||||
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];
|
||||
assert!(v == result);
|
||||
assert_eq!(v, result);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -1171,7 +1195,7 @@ fn test_mut_chunks_rev() {
|
||||
}
|
||||
}
|
||||
let result = [2, 2, 2, 1, 1, 1, 0];
|
||||
assert!(v == result);
|
||||
assert_eq!(v, result);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -1181,6 +1205,38 @@ fn test_mut_chunks_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]
|
||||
fn test_mut_last() {
|
||||
let mut x = [1, 2, 3, 4, 5];
|
||||
|
@ -104,6 +104,9 @@ pub trait SliceExt {
|
||||
#[stable(feature = "core", since = "1.6.0")]
|
||||
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")]
|
||||
fn get<I>(&self, index: I) -> Option<&I::Output>
|
||||
where I: SliceIndex<Self>;
|
||||
@ -181,6 +184,9 @@ pub trait SliceExt {
|
||||
#[stable(feature = "core", since = "1.6.0")]
|
||||
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")]
|
||||
fn swap(&mut self, a: usize, b: usize);
|
||||
|
||||
@ -356,6 +362,14 @@ impl<T> SliceExt for [T] {
|
||||
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]
|
||||
fn get<I>(&self, index: I) -> Option<&I::Output>
|
||||
where I: SliceIndex<[T]>
|
||||
@ -539,6 +553,14 @@ impl<T> SliceExt for [T] {
|
||||
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]
|
||||
fn swap(&mut self, a: usize, b: usize) {
|
||||
unsafe {
|
||||
@ -2378,6 +2400,209 @@ unsafe impl<'a, T> TrustedRandomAccess for ChunksMut<'a, T> {
|
||||
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
|
||||
//
|
||||
|
@ -42,6 +42,7 @@
|
||||
#![feature(try_from)]
|
||||
#![feature(try_trait)]
|
||||
#![feature(unique)]
|
||||
#![feature(exact_chunks)]
|
||||
|
||||
extern crate core;
|
||||
extern crate test;
|
||||
|
@ -117,12 +117,12 @@ fn test_chunks_count() {
|
||||
fn test_chunks_nth() {
|
||||
let v: &[i32] = &[0, 1, 2, 3, 4, 5];
|
||||
let mut c = v.chunks(2);
|
||||
assert_eq!(c.nth(1).unwrap()[1], 3);
|
||||
assert_eq!(c.next().unwrap()[0], 4);
|
||||
assert_eq!(c.nth(1).unwrap(), &[2, 3]);
|
||||
assert_eq!(c.next().unwrap(), &[4, 5]);
|
||||
|
||||
let v2: &[i32] = &[0, 1, 2, 3, 4];
|
||||
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);
|
||||
}
|
||||
|
||||
@ -168,12 +168,12 @@ fn test_chunks_mut_count() {
|
||||
fn test_chunks_mut_nth() {
|
||||
let v: &mut [i32] = &mut [0, 1, 2, 3, 4, 5];
|
||||
let mut c = v.chunks_mut(2);
|
||||
assert_eq!(c.nth(1).unwrap()[1], 3);
|
||||
assert_eq!(c.next().unwrap()[0], 4);
|
||||
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];
|
||||
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);
|
||||
}
|
||||
|
||||
@ -181,11 +181,11 @@ fn test_chunks_mut_nth() {
|
||||
fn test_chunks_mut_last() {
|
||||
let v: &mut [i32] = &mut [0, 1, 2, 3, 4, 5];
|
||||
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 c2 = v2.chunks_mut(2);
|
||||
assert_eq!(c2.last().unwrap()[0], 4);
|
||||
assert_eq!(c2.last().unwrap(), &[4]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -202,6 +202,110 @@ fn test_chunks_mut_zip() {
|
||||
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]
|
||||
fn test_windows_count() {
|
||||
let v: &[i32] = &[0, 1, 2, 3, 4, 5];
|
||||
|
@ -37,7 +37,7 @@ use rustc_typeck as typeck;
|
||||
use rustc_privacy;
|
||||
use rustc_plugin::registry::Registry;
|
||||
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 super::Compilation;
|
||||
use ::DefaultTransCrate;
|
||||
@ -852,10 +852,6 @@ pub fn phase_2_configure_and_expand<F>(sess: &Session,
|
||||
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,
|
||||
"AST validation",
|
||||
|| 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| {
|
||||
k.check_name("cfg")
|
||||
}).and_then(|a| a.meta_item_list());
|
||||
let cfg = cfg.map(|list| {
|
||||
list[0].meta_item().unwrap().clone()
|
||||
});
|
||||
let cfg = if let Some(list) = cfg {
|
||||
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()
|
||||
.map(|it| self.tcx.hir.local_def_id(it.id))
|
||||
.collect();
|
||||
|
@ -149,6 +149,9 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
||||
ExprKind::Continue(Some(ident)) => {
|
||||
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 loops;
|
||||
mod mir_stats;
|
||||
pub mod no_asm;
|
||||
pub mod static_recursion;
|
||||
|
||||
#[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.
|
||||
///
|
||||
/// 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;
|
||||
///
|
||||
/// let ten = 10.0f32;
|
||||
/// let two = 2.0f32;
|
||||
/// let five = 5.0f32;
|
||||
///
|
||||
/// // log10(10) - 1 == 0
|
||||
/// let abs_difference_10 = (ten.log(10.0) - 1.0).abs();
|
||||
/// // log5(5) - 1 == 0
|
||||
/// let abs_difference = (five.log(5.0) - 1.0).abs();
|
||||
///
|
||||
/// // log2(2) - 1 == 0
|
||||
/// let abs_difference_2 = (two.log(2.0) - 1.0).abs();
|
||||
///
|
||||
/// assert!(abs_difference_10 <= f32::EPSILON);
|
||||
/// assert!(abs_difference_2 <= f32::EPSILON);
|
||||
/// assert!(abs_difference <= f32::EPSILON);
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[inline]
|
||||
|
@ -432,18 +432,17 @@ impl f64 {
|
||||
|
||||
/// 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 two = 2.0_f64;
|
||||
/// let five = 5.0_f64;
|
||||
///
|
||||
/// // log10(10) - 1 == 0
|
||||
/// let abs_difference_10 = (ten.log(10.0) - 1.0).abs();
|
||||
/// // log5(5) - 1 == 0
|
||||
/// let abs_difference = (five.log(5.0) - 1.0).abs();
|
||||
///
|
||||
/// // log2(2) - 1 == 0
|
||||
/// let abs_difference_2 = (two.log(2.0) - 1.0).abs();
|
||||
///
|
||||
/// assert!(abs_difference_10 < 1e-10);
|
||||
/// assert!(abs_difference_2 < 1e-10);
|
||||
/// assert!(abs_difference < 1e-10);
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[inline]
|
||||
|
@ -345,8 +345,8 @@ impl<R: Seek> Seek for BufReader<R> {
|
||||
///
|
||||
/// let mut stream = TcpStream::connect("127.0.0.1:34254").unwrap();
|
||||
///
|
||||
/// for i in 1..10 {
|
||||
/// stream.write(&[i]).unwrap();
|
||||
/// for i in 0..10 {
|
||||
/// 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());
|
||||
///
|
||||
/// for i in 1..10 {
|
||||
/// stream.write(&[i]).unwrap();
|
||||
/// for i in 0..10 {
|
||||
/// stream.write(&[i+1]).unwrap();
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
|
@ -62,12 +62,18 @@ pub type Result<T> = result::Result<T, Error>;
|
||||
/// [`Write`]: ../io/trait.Write.html
|
||||
/// [`Seek`]: ../io/trait.Seek.html
|
||||
/// [`ErrorKind`]: enum.ErrorKind.html
|
||||
#[derive(Debug)]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct Error {
|
||||
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 {
|
||||
Os(i32),
|
||||
Simple(ErrorKind),
|
||||
@ -511,10 +517,12 @@ impl Error {
|
||||
impl fmt::Debug for Repr {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||
match *self {
|
||||
Repr::Os(ref code) =>
|
||||
fmt.debug_struct("Os").field("code", code)
|
||||
.field("message", &sys::os::error_string(*code)).finish(),
|
||||
Repr::Custom(ref c) => fmt.debug_tuple("Custom").field(c).finish(),
|
||||
Repr::Os(code) =>
|
||||
fmt.debug_struct("Os")
|
||||
.field("code", &code)
|
||||
.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(),
|
||||
}
|
||||
}
|
||||
@ -559,17 +567,36 @@ fn _assert_error_is_sync_send() {
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::{Error, ErrorKind};
|
||||
use super::{Error, ErrorKind, Repr, Custom};
|
||||
use error;
|
||||
use fmt;
|
||||
use sys::os::error_string;
|
||||
use sys::decode_error_kind;
|
||||
|
||||
#[test]
|
||||
fn test_debug_error() {
|
||||
let code = 6;
|
||||
let msg = error_string(code);
|
||||
let err = Error { repr: super::Repr::Os(code) };
|
||||
let expected = format!("Error {{ repr: Os {{ code: {:?}, message: {:?} }} }}", code, msg);
|
||||
let kind = decode_error_kind(code);
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
16
src/test/compile-fail/issue-43925.rs
Normal file
16
src/test/compile-fail/issue-43925.rs
Normal file
@ -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() {}
|
14
src/test/compile-fail/issue-43926.rs
Normal file
14
src/test/compile-fail/issue-43926.rs
Normal file
@ -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
src/test/ui-fulldeps/update-references.sh
Normal file → Executable file
0
src/test/ui-fulldeps/update-references.sh
Normal file → Executable file
30
src/test/ui/nll/borrowed-referent-issue-38899.rs
Normal file
30
src/test/ui/nll/borrowed-referent-issue-38899.rs
Normal file
@ -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() {}
|
11
src/test/ui/nll/borrowed-referent-issue-38899.stderr
Normal file
11
src/test/ui/nll/borrowed-referent-issue-38899.stderr
Normal file
@ -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
|
||||
|
21
src/test/ui/nll/return-ref-mut-issue-46557.rs
Normal file
21
src/test/ui/nll/return-ref-mut-issue-46557.rs
Normal file
@ -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() {}
|
13
src/test/ui/nll/return-ref-mut-issue-46557.stderr
Normal file
13
src/test/ui/nll/return-ref-mut-issue-46557.stderr
Normal file
@ -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
|
||||
.iter()
|
||||
.filter(|&(_, ref f)| f.level == Status::Unstable)
|
||||
.map(|(name, _)| name.to_owned())
|
||||
.map(|(name, _)| name.replace('_', "-"))
|
||||
.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"))
|
||||
.filter(dir_entry_is_file)
|
||||
.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()
|
||||
}
|
||||
|
||||
|
@ -53,9 +53,9 @@ fn set_to_summary_str(set: &BTreeSet<String>, dir: &str
|
||||
set
|
||||
.iter()
|
||||
.map(|ref n| format!(" - [{}]({}/{}.md)",
|
||||
n,
|
||||
n.replace('-', "_"),
|
||||
dir,
|
||||
n.replace('_', "-")))
|
||||
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);
|
||||
t!(fs::create_dir_all(&out));
|
||||
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 feature = &features[&feature_name];
|
||||
let feature = &features[&feature_name_underscore];
|
||||
|
||||
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 {
|
||||
generate_stub_no_issue(&out_file_path, &feature_name);
|
||||
generate_stub_no_issue(&out_file_path, &feature_name_underscore);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user