Auto merge of #47413 - GuillaumeGomez:unstable-error-code, r=estebank
Add error code for unstable feature errors
Fixes #47397.
diff --git a/.gitmodules b/.gitmodules
index 373ca90..ffa7b32 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -48,3 +48,6 @@
[submodule "src/binaryen"]
path = src/binaryen
url = https://github.com/alexcrichton/binaryen.git
+[submodule "src/doc/rust-by-example"]
+ path = src/doc/rust-by-example
+ url = https://github.com/rust-lang/rust-by-example
diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs
index a660b5c..8e35ecc 100644
--- a/src/bootstrap/builder.rs
+++ b/src/bootstrap/builder.rs
@@ -258,7 +258,7 @@
Kind::Bench => describe!(check::Crate, check::CrateLibrustc),
Kind::Doc => describe!(doc::UnstableBook, doc::UnstableBookGen, doc::TheBook,
doc::Standalone, doc::Std, doc::Test, doc::Rustc, doc::ErrorIndex, doc::Nomicon,
- doc::Reference, doc::Rustdoc, doc::CargoBook),
+ doc::Reference, doc::Rustdoc, doc::RustByExample, doc::CargoBook),
Kind::Dist => describe!(dist::Docs, dist::Mingw, dist::Rustc, dist::DebuggerScripts,
dist::Std, dist::Analysis, dist::Src, dist::PlainSourceTarball, dist::Cargo,
dist::Rls, dist::Rustfmt, dist::Extended, dist::HashSign,
diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs
index 178d60d..d66c01e 100644
--- a/src/bootstrap/doc.rs
+++ b/src/bootstrap/doc.rs
@@ -12,7 +12,7 @@
//!
//! This module implements generation for all bits and pieces of documentation
//! for the Rust project. This notably includes suites like the rust book, the
-//! nomicon, standalone documentation, etc.
+//! nomicon, rust by example, standalone documentation, etc.
//!
//! Everything here is basically just a shim around calling either `rustbook` or
//! `rustdoc`.
@@ -69,6 +69,7 @@
Nomicon, "src/doc/nomicon", "nomicon";
Reference, "src/doc/reference", "reference";
Rustdoc, "src/doc/rustdoc", "rustdoc";
+ RustByExample, "src/doc/rust-by-example", "rust-by-example";
);
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example
new file mode 160000
index 0000000..4ebb816
--- /dev/null
+++ b/src/doc/rust-by-example
@@ -0,0 +1 @@
+Subproject commit 4ebb8169dfe569b3dcbeab560607800bb717978a
diff --git a/src/doc/unstable-book/src/language-features/crate_in_paths.md b/src/doc/unstable-book/src/language-features/crate-in-paths.md
similarity index 100%
rename from src/doc/unstable-book/src/language-features/crate_in_paths.md
rename to src/doc/unstable-book/src/language-features/crate-in-paths.md
diff --git a/src/doc/unstable-book/src/language-features/extern_absolute_paths.md b/src/doc/unstable-book/src/language-features/extern-absolute-paths.md
similarity index 100%
rename from src/doc/unstable-book/src/language-features/extern_absolute_paths.md
rename to src/doc/unstable-book/src/language-features/extern-absolute-paths.md
diff --git a/src/doc/unstable-book/src/language-features/extern_in_paths.md b/src/doc/unstable-book/src/language-features/extern-in-paths.md
similarity index 100%
rename from src/doc/unstable-book/src/language-features/extern_in_paths.md
rename to src/doc/unstable-book/src/language-features/extern-in-paths.md
diff --git a/src/doc/unstable-book/src/language-features/match_default_bindings.md b/src/doc/unstable-book/src/language-features/match-default-bindings.md
similarity index 100%
rename from src/doc/unstable-book/src/language-features/match_default_bindings.md
rename to src/doc/unstable-book/src/language-features/match-default-bindings.md
diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs
index 3cc3ea4..d8ce286 100644
--- a/src/liballoc/lib.rs
+++ b/src/liballoc/lib.rs
@@ -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))]
diff --git a/src/liballoc/slice.rs b/src/liballoc/slice.rs
index 2c7bdc4..861f72b 100644
--- a/src/liballoc/slice.rs
+++ b/src/liballoc/slice.rs
@@ -123,6 +123,8 @@
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 @@
/// 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 @@
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 @@
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
diff --git a/src/liballoc/tests/lib.rs b/src/liballoc/tests/lib.rs
index f1e9588..eee229b 100644
--- a/src/liballoc/tests/lib.rs
+++ b/src/liballoc/tests/lib.rs
@@ -30,6 +30,7 @@
#![feature(string_retain)]
#![feature(unboxed_closures)]
#![feature(unicode)]
+#![feature(exact_chunks)]
extern crate alloc_system;
extern crate std_unicode;
diff --git a/src/liballoc/tests/slice.rs b/src/liballoc/tests/slice.rs
index 49bdc9e..1a9d26f 100644
--- a/src/liballoc/tests/slice.rs
+++ b/src/liballoc/tests/slice.rs
@@ -946,6 +946,30 @@
}
#[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];
values[1..4].reverse();
@@ -1159,7 +1183,7 @@
}
}
let result = [0, 0, 0, 1, 1, 1, 2];
- assert!(v == result);
+ assert_eq!(v, result);
}
#[test]
@@ -1171,7 +1195,7 @@
}
}
let result = [2, 2, 2, 1, 1, 1, 0];
- assert!(v == result);
+ assert_eq!(v, result);
}
#[test]
@@ -1182,6 +1206,38 @@
}
#[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];
let h = x.last_mut();
diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs
index e6b7931..48e8266 100644
--- a/src/libcore/slice/mod.rs
+++ b/src/libcore/slice/mod.rs
@@ -104,6 +104,9 @@
#[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 @@
#[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);
@@ -357,6 +363,14 @@
}
#[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]>
{
@@ -540,6 +554,14 @@
}
#[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 {
// Can't take two mutable loans from one vector, so instead just cast
@@ -2378,6 +2400,209 @@
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
//
diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs
index c4b85b8..2c00095 100644
--- a/src/libcore/tests/lib.rs
+++ b/src/libcore/tests/lib.rs
@@ -42,6 +42,7 @@
#![feature(try_from)]
#![feature(try_trait)]
#![feature(unique)]
+#![feature(exact_chunks)]
extern crate core;
extern crate test;
diff --git a/src/libcore/tests/slice.rs b/src/libcore/tests/slice.rs
index 40e5fe5..f7a4a71 100644
--- a/src/libcore/tests/slice.rs
+++ b/src/libcore/tests/slice.rs
@@ -117,12 +117,12 @@
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_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_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]
@@ -203,6 +203,110 @@
}
#[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];
let c = v.windows(3);
diff --git a/src/librustc/infer/error_reporting/nice_region_error/named_anon_conflict.rs b/src/librustc/infer/error_reporting/nice_region_error/named_anon_conflict.rs
index 9d0ddfd..5617c77 100644
--- a/src/librustc/infer/error_reporting/nice_region_error/named_anon_conflict.rs
+++ b/src/librustc/infer/error_reporting/nice_region_error/named_anon_conflict.rs
@@ -118,4 +118,17 @@
.emit();
return Some(ErrorReported);
}
+
+ // This method returns whether the given Region is Named
+ pub(super) fn is_named_region(&self, region: ty::Region<'tcx>) -> bool {
+ match *region {
+ ty::ReStatic => true,
+ ty::ReFree(ref free_region) => match free_region.bound_region {
+ ty::BrNamed(..) => true,
+ _ => false,
+ },
+ ty::ReEarlyBound(_) => true,
+ _ => false,
+ }
+ }
}
diff --git a/src/librustc/infer/error_reporting/nice_region_error/util.rs b/src/librustc/infer/error_reporting/nice_region_error/util.rs
index f8b6f7d..8aadec6 100644
--- a/src/librustc/infer/error_reporting/nice_region_error/util.rs
+++ b/src/librustc/infer/error_reporting/nice_region_error/util.rs
@@ -198,16 +198,4 @@
}
false
}
-
- // This method returns whether the given Region is Named
- pub(super) fn is_named_region(&self, region: Region<'tcx>) -> bool {
- match *region {
- ty::ReFree(ref free_region) => match free_region.bound_region {
- ty::BrNamed(..) => true,
- _ => false,
- },
- ty::ReEarlyBound(_) => true,
- _ => false,
- }
- }
}
diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs
index 73c1b69..33234ff 100644
--- a/src/librustc_driver/driver.rs
+++ b/src/librustc_driver/driver.rs
@@ -37,7 +37,7 @@
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;
@@ -853,10 +853,6 @@
}
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));
diff --git a/src/librustc_metadata/native_libs.rs b/src/librustc_metadata/native_libs.rs
index cc332ac..c0ce32c 100644
--- a/src/librustc_metadata/native_libs.rs
+++ b/src/librustc_metadata/native_libs.rs
@@ -92,9 +92,19 @@
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();
diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs
index dd7e6a5..3f49128 100644
--- a/src/librustc_passes/ast_validation.rs
+++ b/src/librustc_passes/ast_validation.rs
@@ -149,6 +149,9 @@
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");
+ }
_ => {}
}
diff --git a/src/librustc_passes/lib.rs b/src/librustc_passes/lib.rs
index 754c3bb..73c71ec 100644
--- a/src/librustc_passes/lib.rs
+++ b/src/librustc_passes/lib.rs
@@ -42,7 +42,6 @@
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
diff --git a/src/librustc_passes/no_asm.rs b/src/librustc_passes/no_asm.rs
deleted file mode 100644
index 4dbf57a..0000000
--- a/src/librustc_passes/no_asm.rs
+++ /dev/null
@@ -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)
- }
-}
diff --git a/src/libstd/f32.rs b/src/libstd/f32.rs
index 6d76c7e..5e5695f 100644
--- a/src/libstd/f32.rs
+++ b/src/libstd/f32.rs
@@ -472,20 +472,19 @@
/// 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]
diff --git a/src/libstd/f64.rs b/src/libstd/f64.rs
index dee9566..e4eea74 100644
--- a/src/libstd/f64.rs
+++ b/src/libstd/f64.rs
@@ -432,18 +432,17 @@
/// 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]
diff --git a/src/libstd/io/buffered.rs b/src/libstd/io/buffered.rs
index 16fbf0c..4e7db5f 100644
--- a/src/libstd/io/buffered.rs
+++ b/src/libstd/io/buffered.rs
@@ -345,8 +345,8 @@
///
/// 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 @@
///
/// 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();
/// }
/// ```
///
diff --git a/src/libstd/io/error.rs b/src/libstd/io/error.rs
index bb9383d..f0b41f3 100644
--- a/src/libstd/io/error.rs
+++ b/src/libstd/io/error.rs
@@ -62,12 +62,18 @@
/// [`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 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 @@
#[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);
}
diff --git a/src/libstd/rand/reader.rs b/src/libstd/rand/reader.rs
deleted file mode 100644
index 08bc809..0000000
--- a/src/libstd/rand/reader.rs
+++ /dev/null
@@ -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);
- }
-}
diff --git a/src/test/compile-fail/closure-bounds-static-cant-capture-borrowed.rs b/src/test/compile-fail/closure-bounds-static-cant-capture-borrowed.rs
index 513a17e..1ffba68 100644
--- a/src/test/compile-fail/closure-bounds-static-cant-capture-borrowed.rs
+++ b/src/test/compile-fail/closure-bounds-static-cant-capture-borrowed.rs
@@ -13,7 +13,7 @@
fn foo(x: &()) {
bar(|| {
- //~^ ERROR does not fulfill
+ //~^ ERROR explicit lifetime required in the type of `x` [E0621]
let _ = x;
})
}
diff --git a/src/test/compile-fail/impl-trait/must_outlive_least_region_or_bound.rs b/src/test/compile-fail/impl-trait/must_outlive_least_region_or_bound.rs
index 837160b..0eb99ca 100644
--- a/src/test/compile-fail/impl-trait/must_outlive_least_region_or_bound.rs
+++ b/src/test/compile-fail/impl-trait/must_outlive_least_region_or_bound.rs
@@ -13,7 +13,7 @@
use std::fmt::Debug;
fn elided(x: &i32) -> impl Copy { x }
-//~^ ERROR cannot infer an appropriate lifetime
+//~^ ERROR explicit lifetime required in the type of `x` [E0621]
fn explicit<'a>(x: &'a i32) -> impl Copy { x }
//~^ ERROR cannot infer an appropriate lifetime
diff --git a/src/test/compile-fail/issue-16922.rs b/src/test/compile-fail/issue-16922.rs
index b525d5f..1768c83 100644
--- a/src/test/compile-fail/issue-16922.rs
+++ b/src/test/compile-fail/issue-16922.rs
@@ -12,7 +12,7 @@
fn foo<T: Any>(value: &T) -> Box<Any> {
Box::new(value) as Box<Any>
- //~^ ERROR: cannot infer an appropriate lifetime
+ //~^ ERROR explicit lifetime required in the type of `value` [E0621]
}
fn main() {
diff --git a/src/test/compile-fail/issue-43925.rs b/src/test/compile-fail/issue-43925.rs
new file mode 100644
index 0000000..8ad5764
--- /dev/null
+++ b/src/test/compile-fail/issue-43925.rs
@@ -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() {}
diff --git a/src/test/compile-fail/issue-43926.rs b/src/test/compile-fail/issue-43926.rs
new file mode 100644
index 0000000..5d510b6
--- /dev/null
+++ b/src/test/compile-fail/issue-43926.rs
@@ -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() {}
diff --git a/src/test/compile-fail/object-lifetime-default-from-box-error.rs b/src/test/compile-fail/object-lifetime-default-from-box-error.rs
index c50f425..b253612 100644
--- a/src/test/compile-fail/object-lifetime-default-from-box-error.rs
+++ b/src/test/compile-fail/object-lifetime-default-from-box-error.rs
@@ -25,7 +25,7 @@
// `Box<SomeTrait>` defaults to a `'static` bound, so this return
// is illegal.
- ss.r //~ ERROR cannot infer an appropriate lifetime
+ ss.r //~ ERROR explicit lifetime required in the type of `ss` [E0621]
}
fn store(ss: &mut SomeStruct, b: Box<SomeTrait>) {
diff --git a/src/test/compile-fail/region-object-lifetime-in-coercion.rs b/src/test/compile-fail/region-object-lifetime-in-coercion.rs
index 687b2c3..5bf397a 100644
--- a/src/test/compile-fail/region-object-lifetime-in-coercion.rs
+++ b/src/test/compile-fail/region-object-lifetime-in-coercion.rs
@@ -16,20 +16,20 @@
fn a(v: &[u8]) -> Box<Foo + 'static> {
let x: Box<Foo + 'static> = Box::new(v);
- //~^ ERROR cannot infer an appropriate lifetime due to conflicting
+ //~^ ERROR explicit lifetime required in the type of `v` [E0621]
x
}
fn b(v: &[u8]) -> Box<Foo + 'static> {
Box::new(v)
- //~^ ERROR cannot infer an appropriate lifetime due to conflicting
+ //~^ ERROR explicit lifetime required in the type of `v` [E0621]
}
fn c(v: &[u8]) -> Box<Foo> {
// same as previous case due to RFC 599
Box::new(v)
- //~^ ERROR cannot infer an appropriate lifetime due to conflicting
+ //~^ ERROR explicit lifetime required in the type of `v` [E0621]
}
fn d<'a,'b>(v: &'a [u8]) -> Box<Foo+'b> {
diff --git a/src/test/compile-fail/regions-proc-bound-capture.rs b/src/test/compile-fail/regions-proc-bound-capture.rs
index 17fd55b..dd7b2bf 100644
--- a/src/test/compile-fail/regions-proc-bound-capture.rs
+++ b/src/test/compile-fail/regions-proc-bound-capture.rs
@@ -16,7 +16,7 @@
fn static_proc(x: &isize) -> Box<FnMut()->(isize) + 'static> {
// This is illegal, because the region bound on `proc` is 'static.
- Box::new(move|| { *x }) //~ ERROR cannot infer an appropriate lifetime
+ Box::new(move|| { *x }) //~ ERROR explicit lifetime required in the type of `x` [E0621]
}
fn main() { }
diff --git a/src/test/compile-fail/regions-static-bound.rs b/src/test/compile-fail/regions-static-bound.rs
index a217cc9..13f9309 100644
--- a/src/test/compile-fail/regions-static-bound.rs
+++ b/src/test/compile-fail/regions-static-bound.rs
@@ -22,12 +22,12 @@
}
fn error(u: &(), v: &()) {
- static_id(&u); //[ll]~ ERROR cannot infer an appropriate lifetime
+ static_id(&u); //[ll]~ ERROR explicit lifetime required in the type of `u` [E0621]
//[nll]~^ WARNING not reporting region error due to -Znll
- //[nll]~| ERROR free region `` does not outlive free region `'static`
- static_id_indirect(&v); //[ll]~ ERROR cannot infer an appropriate lifetime
+ //[nll]~| ERROR explicit lifetime required in the type of `u` [E0621]
+ static_id_indirect(&v); //[ll]~ ERROR explicit lifetime required in the type of `v` [E0621]
//[nll]~^ WARNING not reporting region error due to -Znll
- //[nll]~| ERROR free region `` does not outlive free region `'static`
+ //[nll]~| ERROR explicit lifetime required in the type of `v` [E0621]
}
fn main() {}
diff --git a/src/test/ui-fulldeps/update-references.sh b/src/test/ui-fulldeps/update-references.sh
old mode 100644
new mode 100755
diff --git a/src/test/ui/issue-46983.rs b/src/test/ui/issue-46983.rs
new file mode 100644
index 0000000..ebbd474
--- /dev/null
+++ b/src/test/ui/issue-46983.rs
@@ -0,0 +1,18 @@
+// Copyright 2017 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(nll)]
+
+fn foo(x: &u32) -> &'static u32 {
+ &*x
+ //~^ ERROR explicit lifetime required in the type of `x` [E0621]
+}
+
+fn main() {}
diff --git a/src/test/ui/issue-46983.stderr b/src/test/ui/issue-46983.stderr
new file mode 100644
index 0000000..ac8417a
--- /dev/null
+++ b/src/test/ui/issue-46983.stderr
@@ -0,0 +1,10 @@
+error[E0621]: explicit lifetime required in the type of `x`
+ --> $DIR/issue-46983.rs:14:5
+ |
+13 | fn foo(x: &u32) -> &'static u32 {
+ | - consider changing the type of `x` to `&'static u32`
+14 | &*x
+ | ^^^ lifetime `'static` required
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/nll/borrowed-referent-issue-38899.rs b/src/test/ui/nll/borrowed-referent-issue-38899.rs
new file mode 100644
index 0000000..d7c1585
--- /dev/null
+++ b/src/test/ui/nll/borrowed-referent-issue-38899.rs
@@ -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() {}
diff --git a/src/test/ui/nll/borrowed-referent-issue-38899.stderr b/src/test/ui/nll/borrowed-referent-issue-38899.stderr
new file mode 100644
index 0000000..3031fec
--- /dev/null
+++ b/src/test/ui/nll/borrowed-referent-issue-38899.stderr
@@ -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
+
diff --git a/src/test/ui/nll/closure-requirements/region-lbr-anon-does-not-outlive-static.rs b/src/test/ui/nll/closure-requirements/region-lbr-anon-does-not-outlive-static.rs
index 3f56dfe..ac21fe2 100644
--- a/src/test/ui/nll/closure-requirements/region-lbr-anon-does-not-outlive-static.rs
+++ b/src/test/ui/nll/closure-requirements/region-lbr-anon-does-not-outlive-static.rs
@@ -18,7 +18,7 @@
fn foo(x: &u32) -> &'static u32 {
&*x
//~^ WARN not reporting region error due to -Znll
- //~| ERROR does not outlive free region
+ //~| ERROR explicit lifetime required in the type of `x`
}
fn main() { }
diff --git a/src/test/ui/nll/closure-requirements/region-lbr-anon-does-not-outlive-static.stderr b/src/test/ui/nll/closure-requirements/region-lbr-anon-does-not-outlive-static.stderr
index 6648e38..2a1122c 100644
--- a/src/test/ui/nll/closure-requirements/region-lbr-anon-does-not-outlive-static.stderr
+++ b/src/test/ui/nll/closure-requirements/region-lbr-anon-does-not-outlive-static.stderr
@@ -4,11 +4,13 @@
19 | &*x
| ^^^
-error: free region `ReFree(DefId(0/0:3 ~ region_lbr_anon_does_not_outlive_static[317d]::foo[0]), BrAnon(0))` does not outlive free region `ReStatic`
+error[E0621]: explicit lifetime required in the type of `x`
--> $DIR/region-lbr-anon-does-not-outlive-static.rs:19:5
|
+18 | fn foo(x: &u32) -> &'static u32 {
+ | - consider changing the type of `x` to `&ReStatic u32`
19 | &*x
- | ^^^
+ | ^^^ lifetime `ReStatic` required
error: aborting due to previous error
diff --git a/src/test/ui/nll/guarantor-issue-46974.rs b/src/test/ui/nll/guarantor-issue-46974.rs
index 57ecddb..09ce42ce 100644
--- a/src/test/ui/nll/guarantor-issue-46974.rs
+++ b/src/test/ui/nll/guarantor-issue-46974.rs
@@ -22,7 +22,7 @@
fn bar(s: &Box<(i32,)>) -> &'static i32 {
// FIXME(#46983): error message should be better
- &s.0 //~ ERROR free region `` does not outlive free region `'static`
+ &s.0 //~ ERROR explicit lifetime required in the type of `s` [E0621]
}
fn main() {
diff --git a/src/test/ui/nll/guarantor-issue-46974.stderr b/src/test/ui/nll/guarantor-issue-46974.stderr
index 68cc87e..4f0bd88 100644
--- a/src/test/ui/nll/guarantor-issue-46974.stderr
+++ b/src/test/ui/nll/guarantor-issue-46974.stderr
@@ -7,11 +7,14 @@
19 | *s = (2,); //~ ERROR cannot assign to `*s`
| ^^^^^^^^^ assignment to borrowed `*s` occurs here
-error: free region `` does not outlive free region `'static`
+error[E0621]: explicit lifetime required in the type of `s`
--> $DIR/guarantor-issue-46974.rs:25:5
|
-25 | &s.0 //~ ERROR free region `` does not outlive free region `'static`
- | ^^^^
+23 | fn bar(s: &Box<(i32,)>) -> &'static i32 {
+ | - consider changing the type of `s` to `&'static std::boxed::Box<(i32,)>`
+24 | // FIXME(#46983): error message should be better
+25 | &s.0 //~ ERROR explicit lifetime required in the type of `s` [E0621]
+ | ^^^^ lifetime `'static` required
error: aborting due to 2 previous errors
diff --git a/src/test/ui/nll/return-ref-mut-issue-46557.rs b/src/test/ui/nll/return-ref-mut-issue-46557.rs
new file mode 100644
index 0000000..79150f3
--- /dev/null
+++ b/src/test/ui/nll/return-ref-mut-issue-46557.rs
@@ -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() {}
diff --git a/src/test/ui/nll/return-ref-mut-issue-46557.stderr b/src/test/ui/nll/return-ref-mut-issue-46557.stderr
new file mode 100644
index 0000000..763e2bf
--- /dev/null
+++ b/src/test/ui/nll/return-ref-mut-issue-46557.stderr
@@ -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
+
diff --git a/src/tools/tidy/src/unstable_book.rs b/src/tools/tidy/src/unstable_book.rs
index a4a35a7..6ffe78e 100644
--- a/src/tools/tidy/src/unstable_book.rs
+++ b/src/tools/tidy/src/unstable_book.rs
@@ -49,7 +49,7 @@
features
.iter()
.filter(|&(_, ref f)| f.level == Status::Unstable)
- .map(|(name, _)| name.to_owned())
+ .map(|(name, _)| name.replace('_', "-"))
.collect()
}
@@ -60,7 +60,7 @@
.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()
}
diff --git a/src/tools/unstable-book-gen/src/main.rs b/src/tools/unstable-book-gen/src/main.rs
index f66a185..f66144f 100644
--- a/src/tools/unstable-book-gen/src/main.rs
+++ b/src/tools/unstable-book-gen/src/main.rs
@@ -53,9 +53,9 @@
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 @@
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);
}
}
}