diff --git a/RELEASES.md b/RELEASES.md index 9bc750ddef5db..b40897a7509fa 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -1,3 +1,124 @@ +Version 1.30.0 (2018-10-25) +========================== + +Language +-------- +- [Procedural macros are now available.][52081] These kinds of macros allow for + more powerful code generation, there is a [new chapter available][proc-macros] + in Rust Programming Language book that goes further in depth. +- [You can now use keywords as identifiers using the raw identifiers + syntax (`r#`).][53236] e.g. `let r#bool = true;` +- [Using anonymous parameters in traits is now deprecated with a warning and + will be a hard error in the 2018 edition.][53272] +- [You can now use `crate` in paths.][54404] This allows you to refer to the + crate root in the path. e.g. `use crate::foo;` refers to `foo` in `src/lib.rs`. +- [Using a external crate now no longer requires being prefixed with `::`.][54404] + e.g. previously using a external crate in a module without a use statement + required `let json = ::serde_json::from_str(foo);` can now be written + as `let json = serde_json::from_str(foo);`. +- [You can now apply the `#[used]` attribute to static items to prevent the + compiler from optimising them away even if they appear to be unused.][51363] + e.g. `#[used] static FOO: u32 = 1;` +- [You can now import and reexport macros from other crates with the `use` + syntax.][50911] Macros exported with `#[macro_export]` are now placed into + the root module of the crate. If your macro relies on calling other local + macros it is recommended to export with the + `#[macro_export(local_inner_macros)]` attribute so that users won't have to + import those macros. +- [`mod.rs` files are now optional.][54146] Previously if you had a `foo` module + with a `bar` submodule, you would have `src/foo/mod.rs` and `src/foo/bar.rs`. + Now you can have `src/foo.rs` and `src/foo/bar.rs` to achieve the same effect. +- [You can now catch visibility keywords (e.g. `pub`, `pub(crate)`) in macros + using the `vis` specifier.][53370] +- [Non-macro attributes now allow all forms of literals not just + strings.][53044] e.g. Previously you would write `#[attr("true")]` you can now + write `#[attr(true)]`. +- [You can now specify a function to handle a panic in the Rust runtime with the + `#[panic_handler]` attribute.][51366] + +Compiler +-------- +- [Added the `riscv32imc-unknown-none-elf` target.][53822] +- [Added the `aarch64-unknown-netbsd` target][53165] + +Libraries +--------- +- [`ManuallyDrop` now allows the inner type to be unsized.][53033] + +Stabilized APIs +--------------- +- [`Ipv4Addr::BROADCAST`] +- [`Ipv4Addr::LOCALHOST`] +- [`Ipv4Addr::UNSPECIFIED`] +- [`Ipv6Addr::LOCALHOST`] +- [`Ipv6Addr::UNSPECIFIED`] +- [`Iterator::find_map`] + + The following methods are a replacement methods for `trim_left`, `trim_right`, + `trim_left_matches`, and `trim_right_matches`. Which will be deprecated + in 1.33.0. +- [`str::trim_end_matches`] +- [`str::trim_end`] +- [`str::trim_start_matches`] +- [`str::trim_start`] + +Cargo +---- +- [`cargo run` doesn't require specifying a package in workspaces.][cargo/5877] +- [`cargo doc` now supports `--message-format=json`.][cargo/5878] This is + equivalent to calling `rustdoc --error-format=json`. +- [You can specify which edition to create a project in cargo + with `cargo new --edition`.][cargo/5984] Currently only `2015` is a + valid option. +- [Cargo will now provide a progress bar for builds.][cargo/5995] + +Misc +---- +- [`rustdoc` allows you to specify what edition to treat your code as with the + `--edition` option.][54057] +- [`rustdoc` now has the `--color` (Specify whether to output color) and + `--error-format` (Specify error format e.g. `json`) options.][53003] +- [We now distribute a `rust-gdbgui` script that invokes `gdbgui` with Rust + debug symbols.][53774] +- [Attributes from Rust tools such as `rustfmt` or `clippy` are now + available.][53459] e.g. `#[rustfmt::skip]` will skip formatting the next item. + +[50911]: https://github.com/rust-lang/rust/pull/50911/ +[51363]: https://github.com/rust-lang/rust/pull/51363/ +[51366]: https://github.com/rust-lang/rust/pull/51366/ +[52081]: https://github.com/rust-lang/rust/pull/52081/ +[53003]: https://github.com/rust-lang/rust/pull/53003/ +[53033]: https://github.com/rust-lang/rust/pull/53033/ +[53044]: https://github.com/rust-lang/rust/pull/53044/ +[53165]: https://github.com/rust-lang/rust/pull/53165/ +[53213]: https://github.com/rust-lang/rust/pull/53213/ +[53236]: https://github.com/rust-lang/rust/pull/53236/ +[53272]: https://github.com/rust-lang/rust/pull/53272/ +[53370]: https://github.com/rust-lang/rust/pull/53370/ +[53459]: https://github.com/rust-lang/rust/pull/53459/ +[53774]: https://github.com/rust-lang/rust/pull/53774/ +[53822]: https://github.com/rust-lang/rust/pull/53822/ +[54057]: https://github.com/rust-lang/rust/pull/54057/ +[54146]: https://github.com/rust-lang/rust/pull/54146/ +[54404]: https://github.com/rust-lang/rust/pull/54404/ +[cargo/5877]: https://github.com/rust-lang/cargo/pull/5877/ +[cargo/5878]: https://github.com/rust-lang/cargo/pull/5878/ +[cargo/5984]: https://github.com/rust-lang/cargo/pull/5984/ +[cargo/5995]: https://github.com/rust-lang/cargo/pull/5995/ +[proc-macros]: https://doc.rust-lang.org/book/2018-edition/ch19-06-macros.html + +[`Ipv4Addr::BROADCAST`]: https://doc.rust-lang.org/nightly/std/net/struct.Ipv4Addr.html#associatedconstant.BROADCAST +[`Ipv4Addr::LOCALHOST`]: https://doc.rust-lang.org/nightly/std/net/struct.Ipv4Addr.html#associatedconstant.LOCALHOST +[`Ipv4Addr::UNSPECIFIED`]: https://doc.rust-lang.org/nightly/std/net/struct.Ipv4Addr.html#associatedconstant.UNSPECIFIED +[`Ipv6Addr::LOCALHOST`]: https://doc.rust-lang.org/nightly/std/net/struct.Ipv6Addr.html#associatedconstant.LOCALHOST +[`Ipv6Addr::UNSPECIFIED`]: https://doc.rust-lang.org/nightly/std/net/struct.Ipv6Addr.html#associatedconstant.UNSPECIFIED +[`Iterator::find_map`]: https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.find_map +[`str::trim_end_matches`]: https://doc.rust-lang.org/nightly/std/primitive.str.html#method.trim_end_matches +[`str::trim_end`]: https://doc.rust-lang.org/nightly/std/primitive.str.html#method.trim_end +[`str::trim_start_matches`]: https://doc.rust-lang.org/nightly/std/primitive.str.html#method.trim_start_matches +[`str::trim_start`]: https://doc.rust-lang.org/nightly/std/primitive.str.html#method.trim_start + + Version 1.29.2 (2018-10-11) =========================== @@ -6,6 +127,7 @@ Version 1.29.2 (2018-10-11) [54639]: https://github.com/rust-lang/rust/pull/54639 + Version 1.29.1 (2018-09-25) =========================== @@ -19,6 +141,7 @@ Security Notes Thank you to Scott McMurray for responsibily disclosing this vulnerability to us. + Version 1.29.0 (2018-09-13) ========================== @@ -73,7 +196,10 @@ Compatibility Notes Consider using the `home_dir` function from https://crates.io/crates/dirs instead. - [`rustc` will no longer silently ignore invalid data in target spec.][52330] +- [`cfg` attributes and `--cfg` command line flags are now more + strictly validated.][53893] +[53893]: https://github.com/rust-lang/rust/pull/53893/ [52861]: https://github.com/rust-lang/rust/pull/52861/ [52656]: https://github.com/rust-lang/rust/pull/52656/ [52239]: https://github.com/rust-lang/rust/pull/52239/ diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index 0cad471d9a1d5..84ca7c4fec9e5 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -115,12 +115,10 @@ #![feature(unsize)] #![feature(allocator_internals)] #![feature(on_unimplemented)] -#![feature(chunks_exact)] #![feature(rustc_const_unstable)] #![feature(const_vec_new)] #![feature(slice_partition_dedup)] #![feature(maybe_uninit)] -#![feature(rchunks)] // Allow testing this library diff --git a/src/liballoc/slice.rs b/src/liballoc/slice.rs index 2628757b503c1..1eaff7410ea6b 100644 --- a/src/liballoc/slice.rs +++ b/src/liballoc/slice.rs @@ -123,9 +123,9 @@ pub use core::slice::{from_raw_parts, from_raw_parts_mut}; pub use core::slice::{from_ref, from_mut}; #[stable(feature = "slice_get_slice", since = "1.28.0")] pub use core::slice::SliceIndex; -#[unstable(feature = "chunks_exact", issue = "47115")] +#[stable(feature = "chunks_exact", since = "1.31.0")] pub use core::slice::{ChunksExact, ChunksExactMut}; -#[unstable(feature = "rchunks", issue = "55177")] +#[stable(feature = "rchunks", since = "1.31.0")] pub use core::slice::{RChunks, RChunksMut, RChunksExact, RChunksExactMut}; //////////////////////////////////////////////////////////////////////////////// diff --git a/src/liballoc/tests/lib.rs b/src/liballoc/tests/lib.rs index 62c84c9e0864e..6d1cfb10859d4 100644 --- a/src/liballoc/tests/lib.rs +++ b/src/liballoc/tests/lib.rs @@ -19,8 +19,6 @@ #![feature(str_escape)] #![feature(try_reserve)] #![feature(unboxed_closures)] -#![feature(chunks_exact)] -#![feature(rchunks)] #![feature(repeat_generic_slice)] extern crate alloc_system; diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index 62f60034352a7..8a6b212020b4e 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -713,8 +713,6 @@ impl [T] { /// # Examples /// /// ``` - /// #![feature(chunks_exact)] - /// /// let slice = ['l', 'o', 'r', 'e', 'm']; /// let mut iter = slice.chunks_exact(2); /// assert_eq!(iter.next().unwrap(), &['l', 'o']); @@ -725,7 +723,7 @@ impl [T] { /// /// [`chunks`]: #method.chunks /// [`rchunks_exact`]: #method.rchunks_exact - #[unstable(feature = "chunks_exact", issue = "47115")] + #[stable(feature = "chunks_exact", since = "1.31.0")] #[inline] pub fn chunks_exact(&self, chunk_size: usize) -> ChunksExact { assert!(chunk_size != 0); @@ -756,8 +754,6 @@ impl [T] { /// # Examples /// /// ``` - /// #![feature(chunks_exact)] - /// /// let v = &mut [0, 0, 0, 0, 0]; /// let mut count = 1; /// @@ -772,7 +768,7 @@ impl [T] { /// /// [`chunks_mut`]: #method.chunks_mut /// [`rchunks_exact_mut`]: #method.rchunks_exact_mut - #[unstable(feature = "chunks_exact", issue = "47115")] + #[stable(feature = "chunks_exact", since = "1.31.0")] #[inline] pub fn chunks_exact_mut(&mut self, chunk_size: usize) -> ChunksExactMut { assert!(chunk_size != 0); @@ -799,8 +795,6 @@ impl [T] { /// # Examples /// /// ``` - /// #![feature(rchunks)] - /// /// let slice = ['l', 'o', 'r', 'e', 'm']; /// let mut iter = slice.rchunks(2); /// assert_eq!(iter.next().unwrap(), &['e', 'm']); @@ -811,7 +805,7 @@ impl [T] { /// /// [`rchunks_exact`]: #method.rchunks_exact /// [`chunks`]: #method.chunks - #[unstable(feature = "rchunks", issue = "55177")] + #[stable(feature = "rchunks", since = "1.31.0")] #[inline] pub fn rchunks(&self, chunk_size: usize) -> RChunks { assert!(chunk_size != 0); @@ -835,8 +829,6 @@ impl [T] { /// # Examples /// /// ``` - /// #![feature(rchunks)] - /// /// let v = &mut [0, 0, 0, 0, 0]; /// let mut count = 1; /// @@ -851,7 +843,7 @@ impl [T] { /// /// [`rchunks_exact_mut`]: #method.rchunks_exact_mut /// [`chunks_mut`]: #method.chunks_mut - #[unstable(feature = "rchunks", issue = "55177")] + #[stable(feature = "rchunks", since = "1.31.0")] #[inline] pub fn rchunks_mut(&mut self, chunk_size: usize) -> RChunksMut { assert!(chunk_size != 0); @@ -879,8 +871,6 @@ impl [T] { /// # Examples /// /// ``` - /// #![feature(rchunks)] - /// /// let slice = ['l', 'o', 'r', 'e', 'm']; /// let mut iter = slice.rchunks_exact(2); /// assert_eq!(iter.next().unwrap(), &['e', 'm']); @@ -891,7 +881,7 @@ impl [T] { /// /// [`rchunks`]: #method.rchunks /// [`chunks_exact`]: #method.chunks_exact - #[unstable(feature = "rchunks", issue = "55177")] + #[stable(feature = "rchunks", since = "1.31.0")] #[inline] pub fn rchunks_exact(&self, chunk_size: usize) -> RChunksExact { assert!(chunk_size != 0); @@ -921,8 +911,6 @@ impl [T] { /// # Examples /// /// ``` - /// #![feature(rchunks)] - /// /// let v = &mut [0, 0, 0, 0, 0]; /// let mut count = 1; /// @@ -937,7 +925,7 @@ impl [T] { /// /// [`rchunks_mut`]: #method.rchunks_mut /// [`chunks_exact_mut`]: #method.chunks_exact_mut - #[unstable(feature = "rchunks", issue = "55177")] + #[stable(feature = "rchunks", since = "1.31.0")] #[inline] pub fn rchunks_exact_mut(&mut self, chunk_size: usize) -> RChunksExactMut { assert!(chunk_size != 0); @@ -4022,25 +4010,25 @@ unsafe impl<'a, T> TrustedRandomAccess for ChunksMut<'a, T> { /// [`remainder`]: ../../std/slice/struct.ChunksExact.html#method.remainder /// [slices]: ../../std/primitive.slice.html #[derive(Debug)] -#[unstable(feature = "chunks_exact", issue = "47115")] +#[stable(feature = "chunks_exact", since = "1.31.0")] pub struct ChunksExact<'a, T:'a> { v: &'a [T], rem: &'a [T], chunk_size: usize } -#[unstable(feature = "chunks_exact", issue = "47115")] impl<'a, T> ChunksExact<'a, T> { /// Return the remainder of the original slice that is not going to be /// returned by the iterator. The returned slice has at most `chunk_size-1` /// elements. + #[stable(feature = "chunks_exact", since = "1.31.0")] pub fn remainder(&self) -> &'a [T] { self.rem } } // FIXME(#26925) Remove in favor of `#[derive(Clone)]` -#[unstable(feature = "chunks_exact", issue = "47115")] +#[stable(feature = "chunks_exact", since = "1.31.0")] impl Clone for ChunksExact<'_, T> { fn clone(&self) -> Self { ChunksExact { @@ -4051,7 +4039,7 @@ impl Clone for ChunksExact<'_, T> { } } -#[unstable(feature = "chunks_exact", issue = "47115")] +#[stable(feature = "chunks_exact", since = "1.31.0")] impl<'a, T> Iterator for ChunksExact<'a, T> { type Item = &'a [T]; @@ -4096,7 +4084,7 @@ impl<'a, T> Iterator for ChunksExact<'a, T> { } } -#[unstable(feature = "chunks_exact", issue = "47115")] +#[stable(feature = "chunks_exact", since = "1.31.0")] impl<'a, T> DoubleEndedIterator for ChunksExact<'a, T> { #[inline] fn next_back(&mut self) -> Option<&'a [T]> { @@ -4110,7 +4098,7 @@ impl<'a, T> DoubleEndedIterator for ChunksExact<'a, T> { } } -#[unstable(feature = "chunks_exact", issue = "47115")] +#[stable(feature = "chunks_exact", since = "1.31.0")] impl ExactSizeIterator for ChunksExact<'_, T> { fn is_empty(&self) -> bool { self.v.is_empty() @@ -4120,11 +4108,11 @@ impl ExactSizeIterator for ChunksExact<'_, T> { #[unstable(feature = "trusted_len", issue = "37572")] unsafe impl TrustedLen for ChunksExact<'_, T> {} -#[unstable(feature = "chunks_exact", issue = "47115")] +#[stable(feature = "chunks_exact", since = "1.31.0")] impl FusedIterator for ChunksExact<'_, T> {} #[doc(hidden)] -#[unstable(feature = "chunks_exact", issue = "47115")] +#[stable(feature = "chunks_exact", since = "1.31.0")] unsafe impl<'a, T> TrustedRandomAccess for ChunksExact<'a, T> { unsafe fn get_unchecked(&mut self, i: usize) -> &'a [T] { let start = i * self.chunk_size; @@ -4146,24 +4134,24 @@ unsafe impl<'a, T> TrustedRandomAccess for ChunksExact<'a, T> { /// [`into_remainder`]: ../../std/slice/struct.ChunksExactMut.html#method.into_remainder /// [slices]: ../../std/primitive.slice.html #[derive(Debug)] -#[unstable(feature = "chunks_exact", issue = "47115")] +#[stable(feature = "chunks_exact", since = "1.31.0")] pub struct ChunksExactMut<'a, T:'a> { v: &'a mut [T], rem: &'a mut [T], chunk_size: usize } -#[unstable(feature = "chunks_exact", issue = "47115")] impl<'a, T> ChunksExactMut<'a, T> { /// Return the remainder of the original slice that is not going to be /// returned by the iterator. The returned slice has at most `chunk_size-1` /// elements. + #[stable(feature = "chunks_exact", since = "1.31.0")] pub fn into_remainder(self) -> &'a mut [T] { self.rem } } -#[unstable(feature = "chunks_exact", issue = "47115")] +#[stable(feature = "chunks_exact", since = "1.31.0")] impl<'a, T> Iterator for ChunksExactMut<'a, T> { type Item = &'a mut [T]; @@ -4210,7 +4198,7 @@ impl<'a, T> Iterator for ChunksExactMut<'a, T> { } } -#[unstable(feature = "chunks_exact", issue = "47115")] +#[stable(feature = "chunks_exact", since = "1.31.0")] impl<'a, T> DoubleEndedIterator for ChunksExactMut<'a, T> { #[inline] fn next_back(&mut self) -> Option<&'a mut [T]> { @@ -4226,7 +4214,7 @@ impl<'a, T> DoubleEndedIterator for ChunksExactMut<'a, T> { } } -#[unstable(feature = "chunks_exact", issue = "47115")] +#[stable(feature = "chunks_exact", since = "1.31.0")] impl ExactSizeIterator for ChunksExactMut<'_, T> { fn is_empty(&self) -> bool { self.v.is_empty() @@ -4236,11 +4224,11 @@ impl ExactSizeIterator for ChunksExactMut<'_, T> { #[unstable(feature = "trusted_len", issue = "37572")] unsafe impl TrustedLen for ChunksExactMut<'_, T> {} -#[unstable(feature = "chunks_exact", issue = "47115")] +#[stable(feature = "chunks_exact", since = "1.31.0")] impl FusedIterator for ChunksExactMut<'_, T> {} #[doc(hidden)] -#[unstable(feature = "chunks_exact", issue = "47115")] +#[stable(feature = "chunks_exact", since = "1.31.0")] unsafe impl<'a, T> TrustedRandomAccess for ChunksExactMut<'a, T> { unsafe fn get_unchecked(&mut self, i: usize) -> &'a mut [T] { let start = i * self.chunk_size; @@ -4260,14 +4248,14 @@ unsafe impl<'a, T> TrustedRandomAccess for ChunksExactMut<'a, T> { /// [`rchunks`]: ../../std/primitive.slice.html#method.rchunks /// [slices]: ../../std/primitive.slice.html #[derive(Debug)] -#[unstable(feature = "rchunks", issue = "55177")] +#[stable(feature = "rchunks", since = "1.31.0")] pub struct RChunks<'a, T:'a> { v: &'a [T], chunk_size: usize } // FIXME(#26925) Remove in favor of `#[derive(Clone)]` -#[unstable(feature = "rchunks", issue = "55177")] +#[stable(feature = "rchunks", since = "1.31.0")] impl<'a, T> Clone for RChunks<'a, T> { fn clone(&self) -> RChunks<'a, T> { RChunks { @@ -4277,7 +4265,7 @@ impl<'a, T> Clone for RChunks<'a, T> { } } -#[unstable(feature = "rchunks", issue = "55177")] +#[stable(feature = "rchunks", since = "1.31.0")] impl<'a, T> Iterator for RChunks<'a, T> { type Item = &'a [T]; @@ -4341,7 +4329,7 @@ impl<'a, T> Iterator for RChunks<'a, T> { } } -#[unstable(feature = "rchunks", issue = "55177")] +#[stable(feature = "rchunks", since = "1.31.0")] impl<'a, T> DoubleEndedIterator for RChunks<'a, T> { #[inline] fn next_back(&mut self) -> Option<&'a [T]> { @@ -4357,17 +4345,17 @@ impl<'a, T> DoubleEndedIterator for RChunks<'a, T> { } } -#[unstable(feature = "rchunks", issue = "55177")] +#[stable(feature = "rchunks", since = "1.31.0")] impl<'a, T> ExactSizeIterator for RChunks<'a, T> {} #[unstable(feature = "trusted_len", issue = "37572")] unsafe impl<'a, T> TrustedLen for RChunks<'a, T> {} -#[unstable(feature = "rchunks", issue = "55177")] +#[stable(feature = "rchunks", since = "1.31.0")] impl<'a, T> FusedIterator for RChunks<'a, T> {} #[doc(hidden)] -#[unstable(feature = "rchunks", issue = "55177")] +#[stable(feature = "rchunks", since = "1.31.0")] unsafe impl<'a, T> TrustedRandomAccess for RChunks<'a, T> { unsafe fn get_unchecked(&mut self, i: usize) -> &'a [T] { let end = self.v.len() - i * self.chunk_size; @@ -4391,13 +4379,13 @@ unsafe impl<'a, T> TrustedRandomAccess for RChunks<'a, T> { /// [`rchunks_mut`]: ../../std/primitive.slice.html#method.rchunks_mut /// [slices]: ../../std/primitive.slice.html #[derive(Debug)] -#[unstable(feature = "rchunks", issue = "55177")] +#[stable(feature = "rchunks", since = "1.31.0")] pub struct RChunksMut<'a, T:'a> { v: &'a mut [T], chunk_size: usize } -#[unstable(feature = "rchunks", issue = "55177")] +#[stable(feature = "rchunks", since = "1.31.0")] impl<'a, T> Iterator for RChunksMut<'a, T> { type Item = &'a mut [T]; @@ -4465,7 +4453,7 @@ impl<'a, T> Iterator for RChunksMut<'a, T> { } } -#[unstable(feature = "rchunks", issue = "55177")] +#[stable(feature = "rchunks", since = "1.31.0")] impl<'a, T> DoubleEndedIterator for RChunksMut<'a, T> { #[inline] fn next_back(&mut self) -> Option<&'a mut [T]> { @@ -4482,17 +4470,17 @@ impl<'a, T> DoubleEndedIterator for RChunksMut<'a, T> { } } -#[unstable(feature = "rchunks", issue = "55177")] +#[stable(feature = "rchunks", since = "1.31.0")] impl<'a, T> ExactSizeIterator for RChunksMut<'a, T> {} #[unstable(feature = "trusted_len", issue = "37572")] unsafe impl<'a, T> TrustedLen for RChunksMut<'a, T> {} -#[unstable(feature = "rchunks", issue = "55177")] +#[stable(feature = "rchunks", since = "1.31.0")] impl<'a, T> FusedIterator for RChunksMut<'a, T> {} #[doc(hidden)] -#[unstable(feature = "rchunks", issue = "55177")] +#[stable(feature = "rchunks", since = "1.31.0")] unsafe impl<'a, T> TrustedRandomAccess for RChunksMut<'a, T> { unsafe fn get_unchecked(&mut self, i: usize) -> &'a mut [T] { let end = self.v.len() - i * self.chunk_size; @@ -4518,25 +4506,25 @@ unsafe impl<'a, T> TrustedRandomAccess for RChunksMut<'a, T> { /// [`remainder`]: ../../std/slice/struct.ChunksExact.html#method.remainder /// [slices]: ../../std/primitive.slice.html #[derive(Debug)] -#[unstable(feature = "rchunks", issue = "55177")] +#[stable(feature = "rchunks", since = "1.31.0")] pub struct RChunksExact<'a, T:'a> { v: &'a [T], rem: &'a [T], chunk_size: usize } -#[unstable(feature = "rchunks", issue = "55177")] impl<'a, T> RChunksExact<'a, T> { /// Return the remainder of the original slice that is not going to be /// returned by the iterator. The returned slice has at most `chunk_size-1` /// elements. + #[stable(feature = "rchunks", since = "1.31.0")] pub fn remainder(&self) -> &'a [T] { self.rem } } // FIXME(#26925) Remove in favor of `#[derive(Clone)]` -#[unstable(feature = "rchunks", issue = "55177")] +#[stable(feature = "rchunks", since = "1.31.0")] impl<'a, T> Clone for RChunksExact<'a, T> { fn clone(&self) -> RChunksExact<'a, T> { RChunksExact { @@ -4547,7 +4535,7 @@ impl<'a, T> Clone for RChunksExact<'a, T> { } } -#[unstable(feature = "rchunks", issue = "55177")] +#[stable(feature = "rchunks", since = "1.31.0")] impl<'a, T> Iterator for RChunksExact<'a, T> { type Item = &'a [T]; @@ -4592,7 +4580,7 @@ impl<'a, T> Iterator for RChunksExact<'a, T> { } } -#[unstable(feature = "rchunks", issue = "55177")] +#[stable(feature = "rchunks", since = "1.31.0")] impl<'a, T> DoubleEndedIterator for RChunksExact<'a, T> { #[inline] fn next_back(&mut self) -> Option<&'a [T]> { @@ -4606,7 +4594,7 @@ impl<'a, T> DoubleEndedIterator for RChunksExact<'a, T> { } } -#[unstable(feature = "rchunks", issue = "55177")] +#[stable(feature = "rchunks", since = "1.31.0")] impl<'a, T> ExactSizeIterator for RChunksExact<'a, T> { fn is_empty(&self) -> bool { self.v.is_empty() @@ -4616,11 +4604,11 @@ impl<'a, T> ExactSizeIterator for RChunksExact<'a, T> { #[unstable(feature = "trusted_len", issue = "37572")] unsafe impl<'a, T> TrustedLen for RChunksExact<'a, T> {} -#[unstable(feature = "rchunks", issue = "55177")] +#[stable(feature = "rchunks", since = "1.31.0")] impl<'a, T> FusedIterator for RChunksExact<'a, T> {} #[doc(hidden)] -#[unstable(feature = "rchunks", issue = "55177")] +#[stable(feature = "rchunks", since = "1.31.0")] unsafe impl<'a, T> TrustedRandomAccess for RChunksExact<'a, T> { unsafe fn get_unchecked(&mut self, i: usize) -> &'a [T] { let end = self.v.len() - i * self.chunk_size; @@ -4643,24 +4631,24 @@ unsafe impl<'a, T> TrustedRandomAccess for RChunksExact<'a, T> { /// [`into_remainder`]: ../../std/slice/struct.ChunksExactMut.html#method.into_remainder /// [slices]: ../../std/primitive.slice.html #[derive(Debug)] -#[unstable(feature = "rchunks", issue = "55177")] +#[stable(feature = "rchunks", since = "1.31.0")] pub struct RChunksExactMut<'a, T:'a> { v: &'a mut [T], rem: &'a mut [T], chunk_size: usize } -#[unstable(feature = "rchunks", issue = "55177")] impl<'a, T> RChunksExactMut<'a, T> { /// Return the remainder of the original slice that is not going to be /// returned by the iterator. The returned slice has at most `chunk_size-1` /// elements. + #[stable(feature = "rchunks", since = "1.31.0")] pub fn into_remainder(self) -> &'a mut [T] { self.rem } } -#[unstable(feature = "rchunks", issue = "55177")] +#[stable(feature = "rchunks", since = "1.31.0")] impl<'a, T> Iterator for RChunksExactMut<'a, T> { type Item = &'a mut [T]; @@ -4709,7 +4697,7 @@ impl<'a, T> Iterator for RChunksExactMut<'a, T> { } } -#[unstable(feature = "rchunks", issue = "55177")] +#[stable(feature = "rchunks", since = "1.31.0")] impl<'a, T> DoubleEndedIterator for RChunksExactMut<'a, T> { #[inline] fn next_back(&mut self) -> Option<&'a mut [T]> { @@ -4724,7 +4712,7 @@ impl<'a, T> DoubleEndedIterator for RChunksExactMut<'a, T> { } } -#[unstable(feature = "rchunks", issue = "55177")] +#[stable(feature = "rchunks", since = "1.31.0")] impl<'a, T> ExactSizeIterator for RChunksExactMut<'a, T> { fn is_empty(&self) -> bool { self.v.is_empty() @@ -4734,11 +4722,11 @@ impl<'a, T> ExactSizeIterator for RChunksExactMut<'a, T> { #[unstable(feature = "trusted_len", issue = "37572")] unsafe impl<'a, T> TrustedLen for RChunksExactMut<'a, T> {} -#[unstable(feature = "rchunks", issue = "55177")] +#[stable(feature = "rchunks", since = "1.31.0")] impl<'a, T> FusedIterator for RChunksExactMut<'a, T> {} #[doc(hidden)] -#[unstable(feature = "rchunks", issue = "55177")] +#[stable(feature = "rchunks", since = "1.31.0")] unsafe impl<'a, T> TrustedRandomAccess for RChunksExactMut<'a, T> { unsafe fn get_unchecked(&mut self, i: usize) -> &'a mut [T] { let end = self.v.len() - i * self.chunk_size; diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs index e889d484353a5..965bd545eed59 100644 --- a/src/libcore/tests/lib.rs +++ b/src/libcore/tests/lib.rs @@ -34,8 +34,6 @@ #![feature(trusted_len)] #![feature(try_from)] #![feature(try_trait)] -#![feature(chunks_exact)] -#![feature(rchunks)] #![feature(align_offset)] #![feature(reverse_bits)] #![feature(inner_deref)] diff --git a/src/librustc/ty/cast.rs b/src/librustc/ty/cast.rs index c0861abb774de..ab82f28c8bff4 100644 --- a/src/librustc/ty/cast.rs +++ b/src/librustc/ty/cast.rs @@ -58,6 +58,8 @@ pub enum CastKind { } impl<'tcx> CastTy<'tcx> { + /// Returns `Some` for integral/pointer casts. + /// casts like unsizing casts will return `None` pub fn from_ty(t: Ty<'tcx>) -> Option> { match t.sty { ty::Bool => Some(CastTy::Int(IntTy::Bool)), diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs index 76717548521b7..4cf2072e792ca 100644 --- a/src/librustc_lint/unused.rs +++ b/src/librustc_lint/unused.rs @@ -276,10 +276,13 @@ impl UnusedParens { cx: &EarlyContext, value: &ast::Expr, msg: &str, - struct_lit_needs_parens: bool) { + followed_by_block: bool) { if let ast::ExprKind::Paren(ref inner) = value.node { - let necessary = struct_lit_needs_parens && - parser::contains_exterior_struct_lit(&inner); + let necessary = followed_by_block && if let ast::ExprKind::Ret(_) = inner.node { + true + } else { + parser::contains_exterior_struct_lit(&inner) + }; if !necessary { let pattern = pprust::expr_to_string(value); Self::remove_outer_parens(cx, value.span, &pattern, msg); @@ -343,7 +346,7 @@ impl LintPass for UnusedParens { impl EarlyLintPass for UnusedParens { fn check_expr(&mut self, cx: &EarlyContext, e: &ast::Expr) { use syntax::ast::ExprKind::*; - let (value, msg, struct_lit_needs_parens) = match e.node { + let (value, msg, followed_by_block) = match e.node { If(ref cond, ..) => (cond, "`if` condition", true), While(ref cond, ..) => (cond, "`while` condition", true), IfLet(_, ref cond, ..) => (cond, "`if let` head expression", true), @@ -380,7 +383,7 @@ impl EarlyLintPass for UnusedParens { return; } }; - self.check_unused_parens_expr(cx, &value, msg, struct_lit_needs_parens); + self.check_unused_parens_expr(cx, &value, msg, followed_by_block); } fn check_pat(&mut self, cx: &EarlyContext, p: &ast::Pat) { diff --git a/src/librustc_mir/borrow_check/nll/region_infer/mod.rs b/src/librustc_mir/borrow_check/nll/region_infer/mod.rs index dd8a7f19a63bd..0fabcfe456449 100644 --- a/src/librustc_mir/borrow_check/nll/region_infer/mod.rs +++ b/src/librustc_mir/borrow_check/nll/region_infer/mod.rs @@ -1268,7 +1268,7 @@ pub trait ClosureRegionRequirementsExt<'gcx, 'tcx> { tcx: TyCtxt<'_, 'gcx, 'tcx>, location: Location, closure_def_id: DefId, - closure_substs: ty::ClosureSubsts<'tcx>, + closure_substs: &'tcx ty::subst::Substs<'tcx>, ) -> Vec>; fn subst_closure_mapping( @@ -1299,23 +1299,19 @@ impl<'gcx, 'tcx> ClosureRegionRequirementsExt<'gcx, 'tcx> for ClosureRegionRequi tcx: TyCtxt<'_, 'gcx, 'tcx>, location: Location, closure_def_id: DefId, - closure_substs: ty::ClosureSubsts<'tcx>, + closure_substs: &'tcx ty::subst::Substs<'tcx>, ) -> Vec> { debug!( "apply_requirements(location={:?}, closure_def_id={:?}, closure_substs={:?})", location, closure_def_id, closure_substs ); - // Get Tu. - let user_closure_ty = tcx.mk_closure(closure_def_id, closure_substs); - debug!("apply_requirements: user_closure_ty={:?}", user_closure_ty); - - // Extract the values of the free regions in `user_closure_ty` + // Extract the values of the free regions in `closure_substs` // into a vector. These are the regions that we will be // relating to one another. let closure_mapping = &UniversalRegions::closure_mapping( tcx, - user_closure_ty, + closure_substs, self.num_external_vids, tcx.closure_base_def_id(closure_def_id), ); diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs index 1e79bc272e4c0..c5758cde9494d 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -42,7 +42,7 @@ use rustc::traits::query::type_op::custom::CustomTypeOp; use rustc::traits::query::{Fallible, NoSolution}; use rustc::traits::{ObligationCause, PredicateObligations}; use rustc::ty::fold::TypeFoldable; -use rustc::ty::subst::{Subst, UnpackedKind}; +use rustc::ty::subst::{Subst, Substs, UnpackedKind}; use rustc::ty::{self, RegionVid, ToPolyTraitRef, Ty, TyCtxt, TyKind}; use std::rc::Rc; use std::{fmt, iter}; @@ -2075,12 +2075,9 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { // desugaring. A closure gets desugared to a struct, and // these extra requirements are basically like where // clauses on the struct. - AggregateKind::Closure(def_id, substs) => { - self.prove_closure_bounds(tcx, *def_id, *substs, location) - } - - AggregateKind::Generator(def_id, substs, _) => { - tcx.predicates_of(*def_id).instantiate(tcx, substs.substs) + AggregateKind::Closure(def_id, ty::ClosureSubsts { substs }) + | AggregateKind::Generator(def_id, ty::GeneratorSubsts { substs }, _) => { + self.prove_closure_bounds(tcx, *def_id, substs, location) } AggregateKind::Array(_) | AggregateKind::Tuple => ty::InstantiatedPredicates::empty(), @@ -2096,7 +2093,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { &mut self, tcx: TyCtxt<'a, 'gcx, 'tcx>, def_id: DefId, - substs: ty::ClosureSubsts<'tcx>, + substs: &'tcx Substs<'tcx>, location: Location, ) -> ty::InstantiatedPredicates<'tcx> { if let Some(closure_region_requirements) = @@ -2155,7 +2152,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { ); } - tcx.predicates_of(def_id).instantiate(tcx, substs.substs) + tcx.predicates_of(def_id).instantiate(tcx, substs) } fn prove_trait_ref( diff --git a/src/librustc_mir/borrow_check/nll/universal_regions.rs b/src/librustc_mir/borrow_check/nll/universal_regions.rs index eb6f1a0677b2c..c54a4f96b7dcf 100644 --- a/src/librustc_mir/borrow_check/nll/universal_regions.rs +++ b/src/librustc_mir/borrow_check/nll/universal_regions.rs @@ -232,13 +232,13 @@ impl<'tcx> UniversalRegions<'tcx> { /// `V[1]: V[2]`. pub fn closure_mapping( tcx: TyCtxt<'_, '_, 'tcx>, - closure_ty: Ty<'tcx>, + closure_substs: &'tcx Substs<'tcx>, expected_num_vars: usize, closure_base_def_id: DefId, ) -> IndexVec> { let mut region_mapping = IndexVec::with_capacity(expected_num_vars); region_mapping.push(tcx.types.re_static); - tcx.for_each_free_region(&closure_ty, |fr| { + tcx.for_each_free_region(&closure_substs, |fr| { region_mapping.push(fr); }); diff --git a/src/librustc_mir/transform/qualify_min_const_fn.rs b/src/librustc_mir/transform/qualify_min_const_fn.rs index aa559c96ec668..52c557b83d591 100644 --- a/src/librustc_mir/transform/qualify_min_const_fn.rs +++ b/src/librustc_mir/transform/qualify_min_const_fn.rs @@ -148,7 +148,7 @@ fn check_rvalue( Rvalue::Len(place) | Rvalue::Discriminant(place) | Rvalue::Ref(_, _, place) => { check_place(tcx, mir, place, span, PlaceMode::Read) } - Rvalue::Cast(_, operand, cast_ty) => { + Rvalue::Cast(CastKind::Misc, operand, cast_ty) => { use rustc::ty::cast::CastTy; let cast_in = CastTy::from_ty(operand.ty(mir, tcx)).expect("bad input type for cast"); let cast_out = CastTy::from_ty(cast_ty).expect("bad output type for cast"); @@ -163,6 +163,16 @@ fn check_rvalue( _ => check_operand(tcx, mir, operand, span), } } + Rvalue::Cast(CastKind::UnsafeFnPointer, _, _) | + Rvalue::Cast(CastKind::ClosureFnPointer, _, _) | + Rvalue::Cast(CastKind::ReifyFnPointer, _, _) => Err(( + span, + "function pointer casts are not allowed in const fn".into(), + )), + Rvalue::Cast(CastKind::Unsize, _, _) => Err(( + span, + "unsizing casts are not allowed in const fn".into(), + )), // binops are fine on integers Rvalue::BinaryOp(_, lhs, rhs) | Rvalue::CheckedBinaryOp(_, lhs, rhs) => { check_operand(tcx, mir, lhs, span)?; @@ -177,8 +187,11 @@ fn check_rvalue( )) } } - // checked by regular const fn checks - Rvalue::NullaryOp(..) => Ok(()), + Rvalue::NullaryOp(NullOp::SizeOf, _) => Ok(()), + Rvalue::NullaryOp(NullOp::Box, _) => Err(( + span, + "heap allocations are not allowed in const fn".into(), + )), Rvalue::UnaryOp(_, operand) => { let ty = operand.ty(mir, tcx); if ty.is_integral() || ty.is_bool() { diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 25a7ff9cd3f56..e2f5829d14ff7 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -139,7 +139,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> { let prefix_iter = || parent_prefix.iter().cloned() .chain(use_tree.prefix.segments.iter().map(|seg| seg.ident)); - let prefix_start = prefix_iter().nth(0); + let prefix_start = prefix_iter().next(); let starts_with_non_keyword = prefix_start.map_or(false, |ident| { !ident.is_path_segment_keyword() }); @@ -1048,13 +1048,10 @@ impl<'a, 'b, 'cl> Visitor<'a> for BuildReducedGraphVisitor<'a, 'b, 'cl> { fn visit_token(&mut self, t: Token) { if let Token::Interpolated(nt) = t { - match nt.0 { - token::NtExpr(ref expr) => { - if let ast::ExprKind::Mac(..) = expr.node { - self.visit_invoc(expr.id); - } + if let token::NtExpr(ref expr) = nt.0 { + if let ast::ExprKind::Mac(..) = expr.node { + self.visit_invoc(expr.id); } - _ => {} } } } diff --git a/src/librustc_resolve/check_unused.rs b/src/librustc_resolve/check_unused.rs index de9481579e2f4..6f3135b37cf05 100644 --- a/src/librustc_resolve/check_unused.rs +++ b/src/librustc_resolve/check_unused.rs @@ -109,7 +109,7 @@ impl<'a, 'b, 'cl> Visitor<'a> for UnusedImportCheckVisitor<'a, 'b, 'cl> { self.item_span }; - if items.len() == 0 { + if items.is_empty() { self.unused_imports .entry(self.base_id) .or_default() @@ -170,7 +170,7 @@ pub fn check_crate(resolver: &mut Resolver, krate: &ast::Crate) { for (id, spans) in &visitor.unused_imports { let len = spans.len(); - let mut spans = spans.values().map(|s| *s).collect::>(); + let mut spans = spans.values().cloned().collect::>(); spans.sort(); let ms = MultiSpan::from_spans(spans.clone()); let mut span_snippets = spans.iter() @@ -183,7 +183,7 @@ pub fn check_crate(resolver: &mut Resolver, krate: &ast::Crate) { span_snippets.sort(); let msg = format!("unused import{}{}", if len > 1 { "s" } else { "" }, - if span_snippets.len() > 0 { + if !span_snippets.is_empty() { format!(": {}", span_snippets.join(", ")) } else { String::new() diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index ac0616e50b091..bf3fbdc2c5ad5 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -1633,19 +1633,17 @@ impl<'a, 'crateloader> Resolver<'a, 'crateloader> { *def = module.def().unwrap(), PathResult::NonModule(path_res) if path_res.unresolved_segments() == 0 => *def = path_res.base_def(), - PathResult::NonModule(..) => match self.resolve_path( - None, - &path, - None, - true, - span, - CrateLint::No, - ) { - PathResult::Failed(span, msg, _) => { + PathResult::NonModule(..) => + if let PathResult::Failed(span, msg, _) = self.resolve_path( + None, + &path, + None, + true, + span, + CrateLint::No, + ) { error_callback(self, span, ResolutionError::FailedToResolve(&msg)); - } - _ => {} - }, + }, PathResult::Module(ModuleOrUniformRoot::UniformRoot(_)) | PathResult::Indeterminate => unreachable!(), PathResult::Failed(span, msg, _) => { @@ -2357,7 +2355,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { span: prefix.span.to(use_tree.prefix.span), }; - if items.len() == 0 { + if items.is_empty() { // Resolve prefix of an import with empty braces (issue #28388). self.smart_resolve_path_with_crate_lint( id, @@ -2696,7 +2694,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { let map_j = self.binding_mode_map(&q); for (&key, &binding_i) in &map_i { - if map_j.len() == 0 { // Account for missing bindings when + if map_j.is_empty() { // Account for missing bindings when let binding_error = missing_vars // map_j has none. .entry(key.name) .or_insert(BindingError { @@ -2757,9 +2755,8 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { // This has to happen *after* we determine which pat_idents are variants self.check_consistent_bindings(&arm.pats); - match arm.guard { - Some(ast::Guard::If(ref expr)) => self.visit_expr(expr), - _ => {} + if let Some(ast::Guard::If(ref expr)) = arm.guard { + self.visit_expr(expr) } self.visit_expr(&arm.body); @@ -3000,14 +2997,14 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { // Make the base error. let expected = source.descr_expected(); let path_str = names_to_string(path); - let item_str = path[path.len() - 1]; + let item_str = path.last().unwrap(); let code = source.error_code(def.is_some()); let (base_msg, fallback_label, base_span) = if let Some(def) = def { (format!("expected {}, found {} `{}`", expected, def.kind_name(), path_str), format!("not a {}", expected), span) } else { - let item_span = path[path.len() - 1].span; + let item_span = path.last().unwrap().span; let (mod_prefix, mod_str) = if path.len() == 1 { (String::new(), "this scope".to_string()) } else if path.len() == 2 && path[0].name == keywords::CrateRoot.name() { @@ -3030,10 +3027,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { let mut err = this.session.struct_span_err_with_code(base_span, &base_msg, code); // Emit help message for fake-self from other languages like `this`(javascript) - let fake_self: Vec = ["this", "my"].iter().map( - |s| Ident::from_str(*s) - ).collect(); - if fake_self.contains(&item_str) + if ["this", "my"].contains(&&*item_str.as_str()) && this.self_value_is_available(path[0].span, span) { err.span_suggestion_with_applicability( span, @@ -3374,7 +3368,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { ); } break; - } else if snippet.trim().len() != 0 { + } else if !snippet.trim().is_empty() { debug!("tried to find type ascription `:` token, couldn't find it"); break; } @@ -3936,7 +3930,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { } _ => {} } - return def; + def } fn lookup_assoc_candidate(&mut self, @@ -4386,10 +4380,9 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { where FilterFn: Fn(Def) -> bool { let mut candidates = Vec::new(); - let mut worklist = Vec::new(); let mut seen_modules = FxHashSet(); let not_local_module = crate_name != keywords::Crate.ident(); - worklist.push((start_module, Vec::::new(), not_local_module)); + let mut worklist = vec![(start_module, Vec::::new(), not_local_module)]; while let Some((in_module, path_segments, @@ -4476,33 +4469,24 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { -> Vec where FilterFn: Fn(Def) -> bool { - let mut suggestions = vec![]; - - suggestions.extend( - self.lookup_import_candidates_from_module( - lookup_name, namespace, self.graph_root, keywords::Crate.ident(), &filter_fn - ) - ); + let mut suggestions = self.lookup_import_candidates_from_module( + lookup_name, namespace, self.graph_root, keywords::Crate.ident(), &filter_fn); if self.session.rust_2018() { let extern_prelude_names = self.extern_prelude.clone(); for &name in extern_prelude_names.iter() { let ident = Ident::with_empty_ctxt(name); - match self.crate_loader.maybe_process_path_extern(name, ident.span) { - Some(crate_id) => { - let crate_root = self.get_module(DefId { - krate: crate_id, - index: CRATE_DEF_INDEX, - }); - self.populate_module_if_necessary(&crate_root); + if let Some(crate_id) = self.crate_loader.maybe_process_path_extern(name, + ident.span) + { + let crate_root = self.get_module(DefId { + krate: crate_id, + index: CRATE_DEF_INDEX, + }); + self.populate_module_if_necessary(&crate_root); - suggestions.extend( - self.lookup_import_candidates_from_module( - lookup_name, namespace, crate_root, ident, &filter_fn - ) - ); - } - None => {} + suggestions.extend(self.lookup_import_candidates_from_module( + lookup_name, namespace, crate_root, ident, &filter_fn)); } } } @@ -4515,9 +4499,8 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { -> Option<(Module<'a>, ImportSuggestion)> { let mut result = None; - let mut worklist = Vec::new(); let mut seen_modules = FxHashSet(); - worklist.push((self.graph_root, Vec::new())); + let mut worklist = vec![(self.graph_root, Vec::new())]; while let Some((in_module, path_segments)) = worklist.pop() { // abort if the module is already found diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 6c57e6c88abeb..28284a45bcdd5 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -203,9 +203,7 @@ impl<'a, 'crateloader: 'a> base::Resolver for Resolver<'a, 'crateloader> { self.current_module = invocation.module.get(); self.current_module.unresolved_invocations.borrow_mut().remove(&mark); self.current_module.unresolved_invocations.borrow_mut().extend(derives); - for &derive in derives { - self.invocations.insert(derive, invocation); - } + self.invocations.extend(derives.iter().map(|&derive| (derive, invocation))); let mut visitor = BuildReducedGraphVisitor { resolver: self, current_legacy_scope: invocation.parent_legacy_scope.get(), @@ -277,11 +275,12 @@ impl<'a, 'crateloader: 'a> base::Resolver for Resolver<'a, 'crateloader> { if traits.is_empty() { attrs.remove(i); } else { - let mut tokens = Vec::new(); + let mut tokens = Vec::with_capacity(traits.len() - 1); for (j, path) in traits.iter().enumerate() { if j > 0 { tokens.push(TokenTree::Token(attrs[i].span, Token::Comma).into()); } + tokens.reserve((path.segments.len() * 2).saturating_sub(1)); for (k, segment) in path.segments.iter().enumerate() { if k > 0 { tokens.push(TokenTree::Token(path.span, Token::ModSep).into()); diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index 48f312ce9f27d..d5d772e135914 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -672,7 +672,7 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> { }; let has_explicit_self = - import.module_path.len() > 0 && + !import.module_path.is_empty() && import.module_path[0].name == keywords::SelfValue.name(); self.per_ns(|_, ns| { @@ -703,9 +703,8 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> { if let SingleImport { source, ref result, .. } = import.subclass { if source.name == "self" { // Silence `unresolved import` error if E0429 is already emitted - match result.value_ns.get() { - Err(Determined) => continue, - _ => {}, + if let Err(Determined) = result.value_ns.get() { + continue; } } } @@ -822,20 +821,19 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> { fn throw_unresolved_import_error(&self, error_vec: Vec<(Span, String, String)>, span: Option) { let max_span_label_msg_count = 10; // upper limit on number of span_label message. - let (span,msg) = match error_vec.is_empty() { - true => (span.unwrap(), "unresolved import".to_string()), - false => { - let span = MultiSpan::from_spans(error_vec.clone().into_iter() - .map(|elem: (Span, String, String)| { elem.0 } - ).collect()); - let path_vec: Vec = error_vec.clone().into_iter() - .map(|elem: (Span, String, String)| { format!("`{}`", elem.1) } - ).collect(); - let path = path_vec.join(", "); - let msg = format!("unresolved import{} {}", - if path_vec.len() > 1 { "s" } else { "" }, path); - (span, msg) - } + let (span, msg) = if error_vec.is_empty() { + (span.unwrap(), "unresolved import".to_string()) + } else { + let span = MultiSpan::from_spans(error_vec.clone().into_iter() + .map(|elem: (Span, String, String)| { elem.0 }) + .collect()); + let path_vec: Vec = error_vec.clone().into_iter() + .map(|elem: (Span, String, String)| { format!("`{}`", elem.1) }) + .collect(); + let path = path_vec.join(", "); + let msg = format!("unresolved import{} {}", + if path_vec.len() > 1 { "s" } else { "" }, path); + (span, msg) }; let mut err = struct_span_err!(self.resolver.session, span, E0432, "{}", &msg); for span_error in error_vec.into_iter().take(max_span_label_msg_count) { @@ -1026,9 +1024,8 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> { if all_ns_err { let mut all_ns_failed = true; self.per_ns(|this, ns| if !type_ns_only || ns == TypeNS { - match this.resolve_ident_in_module(module, ident, ns, record_used, span) { - Ok(_) => all_ns_failed = false, - _ => {} + if this.resolve_ident_in_module(module, ident, ns, record_used, span).is_ok() { + all_ns_failed = false; } }); @@ -1247,65 +1244,62 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> { } } - match binding.kind { - NameBindingKind::Import { binding: orig_binding, directive, .. } => { - if ns == TypeNS && orig_binding.is_variant() && - !orig_binding.vis.is_at_least(binding.vis, &*self) { - let msg = match directive.subclass { - ImportDirectiveSubclass::SingleImport { .. } => { - format!("variant `{}` is private and cannot be re-exported", - ident) - }, - ImportDirectiveSubclass::GlobImport { .. } => { - let msg = "enum is private and its variants \ - cannot be re-exported".to_owned(); - let error_id = (DiagnosticMessageId::ErrorId(0), // no code?! - Some(binding.span), - msg.clone()); - let fresh = self.session.one_time_diagnostics - .borrow_mut().insert(error_id); - if !fresh { - continue; - } - msg - }, - ref s @ _ => bug!("unexpected import subclass {:?}", s) - }; - let mut err = self.session.struct_span_err(binding.span, &msg); - - let imported_module = match directive.imported_module.get() { - Some(ModuleOrUniformRoot::Module(module)) => module, - _ => bug!("module should exist"), - }; - let resolutions = imported_module.parent.expect("parent should exist") - .resolutions.borrow(); - let enum_path_segment_index = directive.module_path.len() - 1; - let enum_ident = directive.module_path[enum_path_segment_index]; - - let enum_resolution = resolutions.get(&(enum_ident, TypeNS)) - .expect("resolution should exist"); - let enum_span = enum_resolution.borrow() - .binding.expect("binding should exist") - .span; - let enum_def_span = self.session.source_map().def_span(enum_span); - let enum_def_snippet = self.session.source_map() - .span_to_snippet(enum_def_span).expect("snippet should exist"); - // potentially need to strip extant `crate`/`pub(path)` for suggestion - let after_vis_index = enum_def_snippet.find("enum") - .expect("`enum` keyword should exist in snippet"); - let suggestion = format!("pub {}", - &enum_def_snippet[after_vis_index..]); - - self.session - .diag_span_suggestion_once(&mut err, - DiagnosticMessageId::ErrorId(0), - enum_def_span, - "consider making the enum public", - suggestion); - err.emit(); - } + if let NameBindingKind::Import { binding: orig_binding, directive, .. } = binding.kind { + if ns == TypeNS && orig_binding.is_variant() && + !orig_binding.vis.is_at_least(binding.vis, &*self) { + let msg = match directive.subclass { + ImportDirectiveSubclass::SingleImport { .. } => { + format!("variant `{}` is private and cannot be re-exported", + ident) + }, + ImportDirectiveSubclass::GlobImport { .. } => { + let msg = "enum is private and its variants \ + cannot be re-exported".to_owned(); + let error_id = (DiagnosticMessageId::ErrorId(0), // no code?! + Some(binding.span), + msg.clone()); + let fresh = self.session.one_time_diagnostics + .borrow_mut().insert(error_id); + if !fresh { + continue; + } + msg + }, + ref s @ _ => bug!("unexpected import subclass {:?}", s) + }; + let mut err = self.session.struct_span_err(binding.span, &msg); + + let imported_module = match directive.imported_module.get() { + Some(ModuleOrUniformRoot::Module(module)) => module, + _ => bug!("module should exist"), + }; + let resolutions = imported_module.parent.expect("parent should exist") + .resolutions.borrow(); + let enum_path_segment_index = directive.module_path.len() - 1; + let enum_ident = directive.module_path[enum_path_segment_index]; + + let enum_resolution = resolutions.get(&(enum_ident, TypeNS)) + .expect("resolution should exist"); + let enum_span = enum_resolution.borrow() + .binding.expect("binding should exist") + .span; + let enum_def_span = self.session.source_map().def_span(enum_span); + let enum_def_snippet = self.session.source_map() + .span_to_snippet(enum_def_span).expect("snippet should exist"); + // potentially need to strip extant `crate`/`pub(path)` for suggestion + let after_vis_index = enum_def_snippet.find("enum") + .expect("`enum` keyword should exist in snippet"); + let suggestion = format!("pub {}", + &enum_def_snippet[after_vis_index..]); + + self.session + .diag_span_suggestion_once(&mut err, + DiagnosticMessageId::ErrorId(0), + enum_def_span, + "consider making the enum public", + suggestion); + err.emit(); } - _ => {} } } diff --git a/src/libstd/f32.rs b/src/libstd/f32.rs index 8e8340b3ed901..c3f225d1eb013 100644 --- a/src/libstd/f32.rs +++ b/src/libstd/f32.rs @@ -198,6 +198,35 @@ impl f32 { } } + /// Returns a number composed of the magnitude of one number and the sign of + /// another. + /// + /// Equal to `self` if the sign of `self` and `y` are the same, otherwise + /// equal to `-y`. If `self` is a `NAN`, then a `NAN` with the sign of `y` + /// is returned. + /// + /// # Examples + /// + /// ``` + /// #![feature(copysign)] + /// use std::f32; + /// + /// let f = 3.5_f32; + /// + /// assert_eq!(f.copysign(0.42), 3.5_f32); + /// assert_eq!(f.copysign(-0.42), -3.5_f32); + /// assert_eq!((-f).copysign(0.42), 3.5_f32); + /// assert_eq!((-f).copysign(-0.42), -3.5_f32); + /// + /// assert!(f32::NAN.copysign(1.0).is_nan()); + /// ``` + #[inline] + #[must_use] + #[unstable(feature="copysign", issue="55169")] + pub fn copysign(self, y: f32) -> f32 { + unsafe { intrinsics::copysignf32(self, y) } + } + /// Fused multiply-add. Computes `(self * a) + b` with only one rounding /// error, yielding a more accurate result than an unfused multiply-add. /// diff --git a/src/libstd/f64.rs b/src/libstd/f64.rs index 6880294afcaaf..da062dda77a47 100644 --- a/src/libstd/f64.rs +++ b/src/libstd/f64.rs @@ -176,6 +176,35 @@ impl f64 { } } + /// Returns a number composed of the magnitude of one number and the sign of + /// another. + /// + /// Equal to `self` if the sign of `self` and `y` are the same, otherwise + /// equal to `-y`. If `self` is a `NAN`, then a `NAN` with the sign of `y` + /// is returned. + /// + /// # Examples + /// + /// ``` + /// #![feature(copysign)] + /// use std::f64; + /// + /// let f = 3.5_f64; + /// + /// assert_eq!(f.copysign(0.42), 3.5_f64); + /// assert_eq!(f.copysign(-0.42), -3.5_f64); + /// assert_eq!((-f).copysign(0.42), 3.5_f64); + /// assert_eq!((-f).copysign(-0.42), -3.5_f64); + /// + /// assert!(f64::NAN.copysign(1.0).is_nan()); + /// ``` + #[inline] + #[must_use] + #[unstable(feature="copysign", issue="55169")] + pub fn copysign(self, y: f64) -> f64 { + unsafe { intrinsics::copysignf64(self, y) } + } + /// Fused multiply-add. Computes `(self * a) + b` with only one rounding /// error, yielding a more accurate result than an unfused multiply-add. /// diff --git a/src/test/ui/consts/min_const_fn/bad_const_fn_body_ice.rs b/src/test/ui/consts/min_const_fn/bad_const_fn_body_ice.rs new file mode 100644 index 0000000000000..3e42cb8c1b074 --- /dev/null +++ b/src/test/ui/consts/min_const_fn/bad_const_fn_body_ice.rs @@ -0,0 +1,5 @@ +const fn foo(a: i32) -> Vec { + vec![1, 2, 3] //~ ERROR heap allocations are not allowed in const fn +} + +fn main() {} diff --git a/src/test/ui/consts/min_const_fn/bad_const_fn_body_ice.stderr b/src/test/ui/consts/min_const_fn/bad_const_fn_body_ice.stderr new file mode 100644 index 0000000000000..f6b704370b6f2 --- /dev/null +++ b/src/test/ui/consts/min_const_fn/bad_const_fn_body_ice.stderr @@ -0,0 +1,10 @@ +error: heap allocations are not allowed in const fn + --> $DIR/bad_const_fn_body_ice.rs:2:5 + | +LL | vec![1, 2, 3] //~ ERROR heap allocations are not allowed in const fn + | ^^^^^^^^^^^^^ + | + = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +error: aborting due to previous error + diff --git a/src/test/ui/consts/min_const_fn/cast_errors.rs b/src/test/ui/consts/min_const_fn/cast_errors.rs new file mode 100644 index 0000000000000..8648cd35387ce --- /dev/null +++ b/src/test/ui/consts/min_const_fn/cast_errors.rs @@ -0,0 +1,14 @@ +fn main() {} + +const fn unsize(x: &[u8; 3]) -> &[u8] { x } +//~^ ERROR unsizing casts are not allowed in const fn +const fn closure() -> fn() { || {} } +//~^ ERROR function pointers in const fn are unstable +const fn closure2() { + (|| {}) as fn(); +//~^ ERROR function pointers in const fn are unstable +} +const fn reify(f: fn()) -> unsafe fn() { f } +//~^ ERROR function pointers in const fn are unstable +const fn reify2() { main as unsafe fn(); } +//~^ ERROR function pointers in const fn are unstable diff --git a/src/test/ui/consts/min_const_fn/cast_errors.stderr b/src/test/ui/consts/min_const_fn/cast_errors.stderr new file mode 100644 index 0000000000000..ba980b7aacb6c --- /dev/null +++ b/src/test/ui/consts/min_const_fn/cast_errors.stderr @@ -0,0 +1,32 @@ +error: unsizing casts are not allowed in const fn + --> $DIR/cast_errors.rs:3:41 + | +LL | const fn unsize(x: &[u8; 3]) -> &[u8] { x } + | ^ + +error: function pointers in const fn are unstable + --> $DIR/cast_errors.rs:5:23 + | +LL | const fn closure() -> fn() { || {} } + | ^^^^ + +error: function pointers in const fn are unstable + --> $DIR/cast_errors.rs:8:5 + | +LL | (|| {}) as fn(); + | ^^^^^^^^^^^^^^^ + +error: function pointers in const fn are unstable + --> $DIR/cast_errors.rs:11:28 + | +LL | const fn reify(f: fn()) -> unsafe fn() { f } + | ^^^^^^^^^^^ + +error: function pointers in const fn are unstable + --> $DIR/cast_errors.rs:13:21 + | +LL | const fn reify2() { main as unsafe fn(); } + | ^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 5 previous errors + diff --git a/src/test/ui/generator/generator-region-requirements.ast.stderr b/src/test/ui/generator/generator-region-requirements.ast.stderr new file mode 100644 index 0000000000000..6a423aea7eceb --- /dev/null +++ b/src/test/ui/generator/generator-region-requirements.ast.stderr @@ -0,0 +1,12 @@ +error[E0621]: explicit lifetime required in the type of `x` + --> $DIR/generator-region-requirements.rs:15:51 + | +LL | fn dangle(x: &mut i32) -> &'static mut i32 { + | -------- help: add explicit lifetime `'static` to the type of `x`: `&'static mut i32` +... +LL | GeneratorState::Complete(c) => return c, + | ^ lifetime `'static` required + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0621`. diff --git a/src/test/ui/generator/generator-region-requirements.nll.stderr b/src/test/ui/generator/generator-region-requirements.nll.stderr new file mode 100644 index 0000000000000..5d1050dc3526e --- /dev/null +++ b/src/test/ui/generator/generator-region-requirements.nll.stderr @@ -0,0 +1,12 @@ +error[E0621]: explicit lifetime required in the type of `x` + --> $DIR/generator-region-requirements.rs:11:9 + | +LL | fn dangle(x: &mut i32) -> &'static mut i32 { + | -------- help: add explicit lifetime `'static` to the type of `x`: `&'static mut i32` +... +LL | x + | ^ lifetime `'static` required + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0621`. diff --git a/src/test/ui/generator/generator-region-requirements.rs b/src/test/ui/generator/generator-region-requirements.rs new file mode 100644 index 0000000000000..59e7841309c57 --- /dev/null +++ b/src/test/ui/generator/generator-region-requirements.rs @@ -0,0 +1,21 @@ +// revisions: ast nll +// ignore-compare-mode-nll + +#![feature(generators, generator_trait)] +#![cfg_attr(nll, feature(nll))] +use std::ops::{Generator, GeneratorState}; + +fn dangle(x: &mut i32) -> &'static mut i32 { + let mut g = || { + yield; + x + }; + loop { + match unsafe { g.resume() } { + GeneratorState::Complete(c) => return c, + GeneratorState::Yielded(_) => (), + } + } +} + +fn main() {} diff --git a/src/test/ui/lint/no-unused-parens-return-block.rs b/src/test/ui/lint/no-unused-parens-return-block.rs new file mode 100644 index 0000000000000..37dc519a20401 --- /dev/null +++ b/src/test/ui/lint/no-unused-parens-return-block.rs @@ -0,0 +1,9 @@ +// run-pass + +#![deny(unused_parens)] +#![allow(unreachable_code)] + +fn main() { + match (return) {} // ok + if (return) {} // ok +}