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:
bors 2018-01-15 12:46:10 +00:00
commit 57850e5360
30 changed files with 660 additions and 212 deletions

View File

@ -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))]

View File

@ -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

View File

@ -30,6 +30,7 @@
#![feature(string_retain)]
#![feature(unboxed_closures)]
#![feature(unicode)]
#![feature(exact_chunks)]
extern crate alloc_system;
extern crate std_unicode;

View File

@ -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];

View File

@ -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
//

View File

@ -42,6 +42,7 @@
#![feature(try_from)]
#![feature(try_trait)]
#![feature(unique)]
#![feature(exact_chunks)]
extern crate core;
extern crate test;

View File

@ -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];

View File

@ -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));

View File

@ -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();

View File

@ -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");
}
_ => {}
}

View File

@ -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

View File

@ -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)
}
}

View File

@ -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]

View File

@ -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]

View File

@ -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();
/// }
/// ```
///

View File

@ -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);
}

View File

@ -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);
}
}

View 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() {}

View 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
View File

View 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() {}

View 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

View 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() {}

View 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

View File

@ -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()
}

View File

@ -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);
}
}
}