]> git.lizzy.rs Git - rust.git/commitdiff
Rollup merge of #55013 - matthewjasper:propagate-generator-bounds, r=nikomatsakis
authorkennytm <kennytm@gmail.com>
Fri, 19 Oct 2018 08:48:36 +0000 (16:48 +0800)
committerkennytm <kennytm@gmail.com>
Fri, 19 Oct 2018 08:48:36 +0000 (16:48 +0800)
[NLL] Propagate bounds from generators

This used to only be done for closures.

36 files changed:
RELEASES.md
src/liballoc/lib.rs
src/liballoc/slice.rs
src/liballoc/tests/lib.rs
src/libcore/marker.rs
src/libcore/slice/mod.rs
src/libcore/tests/lib.rs
src/librustc/traits/error_reporting.rs
src/librustc/ty/cast.rs
src/librustc_borrowck/borrowck/check_loans.rs
src/librustc_lint/unused.rs
src/librustc_mir/borrow_check/error_reporting.rs
src/librustc_mir/transform/qualify_min_const_fn.rs
src/librustc_mir/util/borrowck_errors.rs
src/librustc_resolve/build_reduced_graph.rs
src/librustc_resolve/check_unused.rs
src/librustc_resolve/lib.rs
src/librustc_resolve/macros.rs
src/librustc_resolve/resolve_imports.rs
src/libstd/f32.rs
src/libstd/f64.rs
src/test/ui/closure_context/issue-42065.nll.stderr [deleted file]
src/test/ui/consts/min_const_fn/bad_const_fn_body_ice.rs [new file with mode: 0644]
src/test/ui/consts/min_const_fn/bad_const_fn_body_ice.stderr [new file with mode: 0644]
src/test/ui/consts/min_const_fn/cast_errors.rs [new file with mode: 0644]
src/test/ui/consts/min_const_fn/cast_errors.stderr [new file with mode: 0644]
src/test/ui/error-codes/E0277.stderr
src/test/ui/generator/borrowing.nll.stderr
src/test/ui/generator/dropck.nll.stderr
src/test/ui/generator/yield-while-iterating.nll.stderr
src/test/ui/generator/yield-while-ref-reborrowed.nll.stderr
src/test/ui/lint/no-unused-parens-return-block.rs [new file with mode: 0644]
src/test/ui/suggestions/path-by-value.rs [new file with mode: 0644]
src/test/ui/suggestions/path-by-value.stderr [new file with mode: 0644]
src/test/ui/unboxed-closures/unboxed-closures-infer-fnonce-call-twice.nll.stderr [deleted file]
src/test/ui/unboxed-closures/unboxed-closures-infer-fnonce-move-call-twice.nll.stderr [deleted file]

index 9bc750ddef5dbf317b172f935cc7cdf9e0425b63..b40897a7509fa8e81a252589d0d5ff88398a8cc4 100644 (file)
@@ -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/
index 0cad471d9a1d51fda7aa77b88c924768241e39e2..84ca7c4fec9e5d4f154b4fe98a6aaea545887844 100644 (file)
 #![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
 
index 2628757b503c147b58b459cda3c9f552ed778d69..1eaff7410ea6b2e5fda3e6871b144bfd34704479 100644 (file)
 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};
 
 ////////////////////////////////////////////////////////////////////////////////
index 62c84c9e0864eeb5e4839a3b8e71498826da65ec..6d1cfb10859d4bc4ee433c9247c66dbcbad1c088 100644 (file)
@@ -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;
index 266c6913747f123544e31909c81a06e106b428b4..662a8ddd96862d0e70bca2281b8cccc7e207c568 100644 (file)
@@ -92,6 +92,7 @@ impl<T: ?Sized> !Send for *mut T { }
 #[stable(feature = "rust1", since = "1.0.0")]
 #[lang = "sized"]
 #[rustc_on_unimplemented(
+    on(parent_trait="std::path::Path", label="borrow the `Path` instead"),
     message="the size for values of type `{Self}` cannot be known at compilation time",
     label="doesn't have a size known at compile-time",
     note="to learn more, visit <https://doc.rust-lang.org/book/second-edition/\
index 62f60034352a784e923665ec5e4e5e84b24c9c46..8a6b212020b4e4a0d74f661d675a604bafce40b1 100644 (file)
@@ -713,8 +713,6 @@ pub fn chunks_mut(&mut self, chunk_size: usize) -> ChunksMut<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 @@ pub fn chunks_mut(&mut self, chunk_size: usize) -> ChunksMut<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<T> {
         assert!(chunk_size != 0);
@@ -756,8 +754,6 @@ pub fn chunks_exact(&self, chunk_size: usize) -> ChunksExact<T> {
     /// # Examples
     ///
     /// ```
-    /// #![feature(chunks_exact)]
-    ///
     /// let v = &mut [0, 0, 0, 0, 0];
     /// let mut count = 1;
     ///
@@ -772,7 +768,7 @@ pub fn chunks_exact(&self, chunk_size: usize) -> ChunksExact<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<T> {
         assert!(chunk_size != 0);
@@ -799,8 +795,6 @@ pub fn chunks_exact_mut(&mut self, chunk_size: usize) -> ChunksExactMut<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 @@ pub fn chunks_exact_mut(&mut self, chunk_size: usize) -> ChunksExactMut<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<T> {
         assert!(chunk_size != 0);
@@ -835,8 +829,6 @@ pub fn rchunks(&self, chunk_size: usize) -> RChunks<T> {
     /// # Examples
     ///
     /// ```
-    /// #![feature(rchunks)]
-    ///
     /// let v = &mut [0, 0, 0, 0, 0];
     /// let mut count = 1;
     ///
@@ -851,7 +843,7 @@ pub fn rchunks(&self, chunk_size: usize) -> RChunks<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<T> {
         assert!(chunk_size != 0);
@@ -879,8 +871,6 @@ pub fn rchunks_mut(&mut self, chunk_size: usize) -> RChunksMut<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 @@ pub fn rchunks_mut(&mut self, chunk_size: usize) -> RChunksMut<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<T> {
         assert!(chunk_size != 0);
@@ -921,8 +911,6 @@ pub fn rchunks_exact(&self, chunk_size: usize) -> RChunksExact<T> {
     /// # Examples
     ///
     /// ```
-    /// #![feature(rchunks)]
-    ///
     /// let v = &mut [0, 0, 0, 0, 0];
     /// let mut count = 1;
     ///
@@ -937,7 +925,7 @@ pub fn rchunks_exact(&self, chunk_size: usize) -> RChunksExact<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<T> {
         assert!(chunk_size != 0);
@@ -4022,25 +4010,25 @@ fn may_have_side_effect() -> bool { false }
 /// [`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<T> Clone for ChunksExact<'_, T> {
     fn clone(&self) -> Self {
         ChunksExact {
@@ -4051,7 +4039,7 @@ fn clone(&self) -> Self {
     }
 }
 
-#[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 @@ fn last(mut self) -> Option<Self::Item> {
     }
 }
 
-#[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 @@ fn next_back(&mut self) -> Option<&'a [T]> {
     }
 }
 
-#[unstable(feature = "chunks_exact", issue = "47115")]
+#[stable(feature = "chunks_exact", since = "1.31.0")]
 impl<T> ExactSizeIterator for ChunksExact<'_, T> {
     fn is_empty(&self) -> bool {
         self.v.is_empty()
@@ -4120,11 +4108,11 @@ fn is_empty(&self) -> bool {
 #[unstable(feature = "trusted_len", issue = "37572")]
 unsafe impl<T> TrustedLen for ChunksExact<'_, T> {}
 
-#[unstable(feature = "chunks_exact", issue = "47115")]
+#[stable(feature = "chunks_exact", since = "1.31.0")]
 impl<T> 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 @@ fn may_have_side_effect() -> bool { false }
 /// [`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 @@ fn last(mut self) -> Option<Self::Item> {
     }
 }
 
-#[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 @@ fn next_back(&mut self) -> Option<&'a mut [T]> {
     }
 }
 
-#[unstable(feature = "chunks_exact", issue = "47115")]
+#[stable(feature = "chunks_exact", since = "1.31.0")]
 impl<T> ExactSizeIterator for ChunksExactMut<'_, T> {
     fn is_empty(&self) -> bool {
         self.v.is_empty()
@@ -4236,11 +4224,11 @@ fn is_empty(&self) -> bool {
 #[unstable(feature = "trusted_len", issue = "37572")]
 unsafe impl<T> TrustedLen for ChunksExactMut<'_, T> {}
 
-#[unstable(feature = "chunks_exact", issue = "47115")]
+#[stable(feature = "chunks_exact", since = "1.31.0")]
 impl<T> 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 @@ fn may_have_side_effect() -> bool { false }
 /// [`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 @@ fn clone(&self) -> 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 @@ fn last(self) -> Option<Self::Item> {
     }
 }
 
-#[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 @@ fn next_back(&mut self) -> Option<&'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 @@ fn may_have_side_effect() -> bool { false }
 /// [`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 @@ fn last(self) -> Option<Self::Item> {
     }
 }
 
-#[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 @@ fn next_back(&mut self) -> Option<&'a mut [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 @@ fn may_have_side_effect() -> bool { false }
 /// [`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 @@ fn clone(&self) -> 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 @@ fn last(mut self) -> Option<Self::Item> {
     }
 }
 
-#[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 @@ fn next_back(&mut self) -> Option<&'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 @@ fn is_empty(&self) -> bool {
 #[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 @@ fn may_have_side_effect() -> bool { false }
 /// [`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 @@ fn last(mut self) -> Option<Self::Item> {
     }
 }
 
-#[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 @@ fn next_back(&mut self) -> Option<&'a mut [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 @@ fn is_empty(&self) -> bool {
 #[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;
index e889d484353a586a78f8c6bdf2411ad52095efd8..965bd545eed591665b90be854ec0fab7c0fe9c1b 100644 (file)
@@ -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)]
index fc34a71f39221c00f2bbbbe9c030002a0d275dc8..db775beae4f97f092fd7896bd27acad759eced2e 100644 (file)
@@ -378,6 +378,9 @@ fn on_unimplemented_note(
                 flags.push(("from_method".to_owned(), Some(method.to_string())));
             }
         }
+        if let Some(t) = self.get_parent_trait_ref(&obligation.cause.code) {
+            flags.push(("parent_trait".to_owned(), Some(t.to_string())));
+        }
 
         if let Some(k) = obligation.cause.span.compiler_desugaring_kind() {
             flags.push(("from_desugaring".to_owned(), None));
index c0861abb774deda27da77623d852da04f2d8f316..ab82f28c8bff4d1b1c0a7ceb29a5706993a29da9 100644 (file)
@@ -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<CastTy<'tcx>> {
         match t.sty {
             ty::Bool => Some(CastTy::Int(IntTy::Bool)),
index 34ee03b895f9f6615522f5a4cf5e54f558950dd6..d9b64527700fccf3b232d7df8c401131d9bbd69b 100644 (file)
@@ -609,12 +609,12 @@ pub fn report_error_if_loan_conflicts_with_restriction(&self,
                         new_loan.span, &nl, old_loan.span, previous_end_span, Origin::Ast),
                 (ty::UniqueImmBorrow, _) =>
                     self.bccx.cannot_uniquely_borrow_by_one_closure(
-                        new_loan.span, &nl, &new_loan_msg,
+                        new_loan.span, "closure", &nl, &new_loan_msg,
                         old_loan.span, &ol_pronoun, &old_loan_msg, previous_end_span, Origin::Ast),
                 (_, ty::UniqueImmBorrow) => {
                     let new_loan_str = &new_loan.kind.to_user_str();
                     self.bccx.cannot_reborrow_already_uniquely_borrowed(
-                        new_loan.span, &nl, &new_loan_msg, new_loan_str,
+                        new_loan.span, "closure", &nl, &new_loan_msg, new_loan_str,
                         old_loan.span, &old_loan_msg, previous_end_span, Origin::Ast)
                 }
                 (..) =>
index 76717548521b7343b7b59cb002f9e1f08438fc19..4cf2072e792ca3ee6a50420f4df9c27177f71f67 100644 (file)
@@ -276,10 +276,13 @@ fn check_unused_parens_expr(&self,
                                 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 @@ fn get_lints(&self) -> LintArray {
 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 @@ fn check_expr(&mut self, cx: &EarlyContext, e: &ast::Expr) {
                 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) {
index 759b842e9dfee24731e9fb0493a18d165db6ffba..baf9e032270a684e9af3cc3d9471d58b3e897a4f 100644 (file)
 use rustc::hir::def_id::DefId;
 use rustc::middle::region::ScopeTree;
 use rustc::mir::{
-    self, AggregateKind, BindingForm, BorrowKind, ClearCrossCrate, Field, Local,
+    self, AggregateKind, BindingForm, BorrowKind, ClearCrossCrate, Constant, Field, Local,
     LocalDecl, LocalKind, Location, Operand, Place, PlaceProjection, ProjectionElem,
     Rvalue, Statement, StatementKind, TerminatorKind, VarBindingForm,
 };
-use rustc::ty;
+use rustc::ty::{self, DefIdTree};
 use rustc::util::ppaux::with_highlight_region_for_bound_region;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::sync::Lrc;
@@ -103,7 +103,7 @@ pub(super) fn report_use_of_moved_or_uninitialized(
 
             use_spans.var_span_label(
                 &mut err,
-                format!("{} occurs due to use in closure", desired_action.as_noun()),
+                format!("{} occurs due to use{}", desired_action.as_noun(), use_spans.describe()),
             );
 
             err.buffer(&mut self.errors_buffer);
@@ -131,6 +131,12 @@ pub(super) fn report_use_of_moved_or_uninitialized(
                 Origin::Mir,
             );
 
+            self.add_closure_invoked_twice_with_moved_variable_suggestion(
+                context.loc,
+                used_place,
+                &mut err,
+            );
+
             let mut is_loop_move = false;
             for move_site in &move_site_vec {
                 let move_out = self.move_data.moves[(*move_site).moi];
@@ -161,13 +167,16 @@ pub(super) fn report_use_of_moved_or_uninitialized(
                     );
                 } else {
                     err.span_label(move_span, format!("value moved{} here", move_msg));
-                    move_spans.var_span_label(&mut err, "variable moved due to use in closure");
+                    move_spans.var_span_label(
+                        &mut err,
+                        format!("variable moved due to use{}", move_spans.describe()),
+                    );
                 };
             }
 
             use_spans.var_span_label(
                 &mut err,
-                format!("{} occurs due to use in closure", desired_action.as_noun()),
+                format!("{} occurs due to use{}", desired_action.as_noun(), use_spans.describe()),
             );
 
             if !is_loop_move {
@@ -226,9 +235,13 @@ pub(super) fn report_use_of_moved_or_uninitialized(
     pub(super) fn report_move_out_while_borrowed(
         &mut self,
         context: Context,
-        (place, _span): (&Place<'tcx>, Span),
+        (place, span): (&Place<'tcx>, Span),
         borrow: &BorrowData<'tcx>,
     ) {
+        debug!(
+            "report_move_out_while_borrowed: context={:?} place={:?} span={:?} borrow={:?}",
+            context, place, span, borrow
+        );
         let tcx = self.infcx.tcx;
         let value_msg = match self.describe_place(place) {
             Some(name) => format!("`{}`", name),
@@ -253,9 +266,15 @@ pub(super) fn report_move_out_while_borrowed(
         err.span_label(borrow_span, format!("borrow of {} occurs here", borrow_msg));
         err.span_label(span, format!("move out of {} occurs here", value_msg));
 
-        borrow_spans.var_span_label(&mut err, "borrow occurs due to use in closure");
+        borrow_spans.var_span_label(
+            &mut err,
+            format!("borrow occurs due to use{}", borrow_spans.describe())
+        );
 
-        move_spans.var_span_label(&mut err, "move occurs due to use in closure");
+        move_spans.var_span_label(
+            &mut err,
+            format!("move occurs due to use{}", move_spans.describe())
+        );
 
         self.explain_why_borrow_contains_point(context, borrow, None)
             .add_explanation_to_diagnostic(self.infcx.tcx, self.mir, &mut err, "");
@@ -291,7 +310,7 @@ pub(super) fn report_use_while_mutably_borrowed(
             let place = &borrow.borrowed_place;
             let desc_place = self.describe_place(place).unwrap_or("_".to_owned());
 
-            format!("borrow occurs due to use of `{}` in closure", desc_place)
+            format!("borrow occurs due to use of `{}`{}", desc_place, borrow_spans.describe())
         });
 
         self.explain_why_borrow_contains_point(context, borrow, None)
@@ -312,6 +331,12 @@ pub(super) fn report_conflicting_borrow(
         let borrow_spans = self.borrow_spans(span, context.loc);
         let span = borrow_spans.args_or_use();
 
+        let container_name = if issued_spans.for_generator() || borrow_spans.for_generator() {
+            "generator"
+        } else {
+            "closure"
+        };
+
         let desc_place = self.describe_place(place).unwrap_or("_".to_owned());
         let tcx = self.infcx.tcx;
 
@@ -392,7 +417,9 @@ pub(super) fn report_conflicting_borrow(
                 );
                 borrow_spans.var_span_label(
                     &mut err,
-                    format!("borrow occurs due to use of `{}` in closure", desc_place),
+                    format!(
+                        "borrow occurs due to use of `{}`{}", desc_place, borrow_spans.describe()
+                    ),
                 );
                 err.buffer(&mut self.errors_buffer);
 
@@ -403,6 +430,7 @@ pub(super) fn report_conflicting_borrow(
                 first_borrow_desc = "first ";
                 tcx.cannot_uniquely_borrow_by_one_closure(
                     span,
+                    container_name,
                     &desc_place,
                     "",
                     issued_span,
@@ -417,6 +445,7 @@ pub(super) fn report_conflicting_borrow(
                 first_borrow_desc = "first ";
                 tcx.cannot_reborrow_already_uniquely_borrowed(
                     span,
+                    container_name,
                     &desc_place,
                     "",
                     lft,
@@ -431,6 +460,7 @@ pub(super) fn report_conflicting_borrow(
                 first_borrow_desc = "first ";
                 tcx.cannot_reborrow_already_uniquely_borrowed(
                     span,
+                    container_name,
                     &desc_place,
                     "",
                     lft,
@@ -456,7 +486,7 @@ pub(super) fn report_conflicting_borrow(
         if issued_spans == borrow_spans {
             borrow_spans.var_span_label(
                 &mut err,
-                format!("borrows occur due to use of `{}` in closure", desc_place),
+                format!("borrows occur due to use of `{}`{}", desc_place, borrow_spans.describe()),
             );
         } else {
             let borrow_place = &issued_borrow.borrowed_place;
@@ -464,16 +494,18 @@ pub(super) fn report_conflicting_borrow(
             issued_spans.var_span_label(
                 &mut err,
                 format!(
-                    "first borrow occurs due to use of `{}` in closure",
-                    borrow_place_desc
+                    "first borrow occurs due to use of `{}`{}",
+                    borrow_place_desc,
+                    issued_spans.describe(),
                 ),
             );
 
             borrow_spans.var_span_label(
                 &mut err,
                 format!(
-                    "second borrow occurs due to use of `{}` in closure",
-                    desc_place
+                    "second borrow occurs due to use of `{}`{}",
+                    desc_place,
+                    borrow_spans.describe(),
                 ),
             );
         }
@@ -643,7 +675,16 @@ fn report_local_value_does_not_live_long_enough(
                 format!("`{}` dropped here while still borrowed", name),
             );
 
-            borrow_spans.args_span_label(&mut err, "value captured here");
+            let within = if borrow_spans.for_generator() {
+                " by generator"
+            } else {
+                ""
+            };
+
+            borrow_spans.args_span_label(
+                &mut err,
+                format!("value captured here{}", within),
+            );
 
             explanation.add_explanation_to_diagnostic(self.infcx.tcx, self.mir, &mut err, "");
         }
@@ -774,7 +815,16 @@ fn report_temporary_value_does_not_live_long_enough(
         }
         explanation.add_explanation_to_diagnostic(self.infcx.tcx, self.mir, &mut err, "");
 
-        borrow_spans.args_span_label(&mut err, "value captured here");
+        let within = if borrow_spans.for_generator() {
+            " by generator"
+        } else {
+            ""
+        };
+
+        borrow_spans.args_span_label(
+            &mut err,
+            format!("value captured here{}", within),
+        );
 
         err
     }
@@ -906,7 +956,10 @@ pub(super) fn report_illegal_mutation_of_borrowed(
             )
         };
 
-        loan_spans.var_span_label(&mut err, "borrow occurs due to use in closure");
+        loan_spans.var_span_label(
+            &mut err,
+            format!("borrow occurs due to use{}", loan_spans.describe()),
+        );
 
         self.explain_why_borrow_contains_point(context, loan, None)
             .add_explanation_to_diagnostic(self.infcx.tcx, self.mir, &mut err, "");
@@ -1009,16 +1062,111 @@ enum StorageDeadOrDrop<'tcx> {
 }
 
 impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
-    // End-user visible description of `place` if one can be found. If the
-    // place is a temporary for instance, None will be returned.
+
+    /// Adds a suggestion when a closure is invoked twice with a moved variable.
+    ///
+    /// ```text
+    /// note: closure cannot be invoked more than once because it moves the variable `dict` out of
+    ///       its environment
+    ///   --> $DIR/issue-42065.rs:16:29
+    ///    |
+    /// LL |         for (key, value) in dict {
+    ///    |                             ^^^^
+    /// ```
+    pub(super) fn add_closure_invoked_twice_with_moved_variable_suggestion(
+        &self,
+        location: Location,
+        place: &Place<'tcx>,
+        diag: &mut DiagnosticBuilder<'_>,
+    ) {
+        let mut target = place.local();
+        debug!(
+            "add_closure_invoked_twice_with_moved_variable_suggestion: location={:?} place={:?} \
+             target={:?}",
+             location, place, target,
+        );
+        for stmt in &self.mir[location.block].statements[location.statement_index..] {
+            debug!(
+                "add_closure_invoked_twice_with_moved_variable_suggestion: stmt={:?} \
+                 target={:?}",
+                 stmt, target,
+            );
+            if let StatementKind::Assign(into, box Rvalue::Use(from)) = &stmt.kind {
+                debug!(
+                    "add_closure_invoked_twice_with_moved_variable_suggestion: into={:?} \
+                     from={:?}",
+                     into, from,
+                );
+                match from {
+                    Operand::Copy(ref place) |
+                    Operand::Move(ref place) if target == place.local() =>
+                        target = into.local(),
+                    _ => {},
+                }
+            }
+        }
+
+
+        let terminator = self.mir[location.block].terminator();
+        debug!(
+            "add_closure_invoked_twice_with_moved_variable_suggestion: terminator={:?}",
+            terminator,
+        );
+        if let TerminatorKind::Call {
+            func: Operand::Constant(box Constant {
+                literal: ty::Const { ty: &ty::TyS { sty: ty::TyKind::FnDef(id, _), ..  }, ..  },
+                ..
+            }),
+            args,
+            ..
+        } = &terminator.kind {
+            debug!("add_closure_invoked_twice_with_moved_variable_suggestion: id={:?}", id);
+            if self.infcx.tcx.parent(id) == self.infcx.tcx.lang_items().fn_once_trait() {
+                let closure = match args.first() {
+                    Some(Operand::Copy(ref place)) |
+                    Some(Operand::Move(ref place)) if target == place.local() =>
+                        place.local().unwrap(),
+                    _ => return,
+                };
+                debug!(
+                    "add_closure_invoked_twice_with_moved_variable_suggestion: closure={:?}",
+                     closure,
+                );
+
+                if let ty::TyKind::Closure(did, _substs) = self.mir.local_decls[closure].ty.sty {
+                    let node_id = match self.infcx.tcx.hir.as_local_node_id(did) {
+                        Some(node_id) => node_id,
+                        _ => return,
+                    };
+                    let hir_id = self.infcx.tcx.hir.node_to_hir_id(node_id);
+
+                    if let Some((
+                        span, name
+                    )) = self.infcx.tcx.typeck_tables_of(did).closure_kind_origins().get(hir_id) {
+                        diag.span_note(
+                            *span,
+                            &format!(
+                                "closure cannot be invoked more than once because it \
+                                 moves the variable `{}` out of its environment",
+                                 name,
+                            ),
+                        );
+                    }
+                }
+            }
+        }
+    }
+
+    /// End-user visible description of `place` if one can be found. If the
+    /// place is a temporary for instance, None will be returned.
     pub(super) fn describe_place(&self, place: &Place<'tcx>) -> Option<String> {
         self.describe_place_with_options(place, IncludingDowncast(false))
     }
 
-    // End-user visible description of `place` if one can be found. If the
-    // place is a temporary for instance, None will be returned.
-    // `IncludingDowncast` parameter makes the function return `Err` if `ProjectionElem` is
-    // `Downcast` and `IncludingDowncast` is true
+    /// End-user visible description of `place` if one can be found. If the
+    /// place is a temporary for instance, None will be returned.
+    /// `IncludingDowncast` parameter makes the function return `Err` if `ProjectionElem` is
+    /// `Downcast` and `IncludingDowncast` is true
     pub(super) fn describe_place_with_options(
         &self,
         place: &Place<'tcx>,
@@ -1031,7 +1179,7 @@ pub(super) fn describe_place_with_options(
         }
     }
 
-    // Appends end-user visible description of `place` to `buf`.
+    /// Appends end-user visible description of `place` to `buf`.
     fn append_place_to_string(
         &self,
         place: &Place<'tcx>,
@@ -1166,8 +1314,8 @@ fn append_place_to_string(
         Ok(())
     }
 
-    // Appends end-user visible description of the `local` place to `buf`. If `local` doesn't have
-    // a name, then `Err` is returned
+    /// Appends end-user visible description of the `local` place to `buf`. If `local` doesn't have
+    /// a name, then `Err` is returned
     fn append_local_to_string(&self, local_index: Local, buf: &mut String) -> Result<(), ()> {
         let local = &self.mir.local_decls[local_index];
         match local.name {
@@ -1179,7 +1327,7 @@ fn append_local_to_string(&self, local_index: Local, buf: &mut String) -> Result
         }
     }
 
-    // End-user visible description of the `field`nth field of `base`
+    /// End-user visible description of the `field`nth field of `base`
     fn describe_field(&self, base: &Place, field: Field) -> String {
         match *base {
             Place::Local(local) => {
@@ -1204,7 +1352,7 @@ fn describe_field(&self, base: &Place, field: Field) -> String {
         }
     }
 
-    // End-user visible description of the `field_index`nth field of `ty`
+    /// End-user visible description of the `field_index`nth field of `ty`
     fn describe_field_from_ty(&self, ty: &ty::Ty, field: Field) -> String {
         if ty.is_box() {
             // If the type is a box, the field is described from the boxed type
@@ -1247,7 +1395,7 @@ fn describe_field_from_ty(&self, ty: &ty::Ty, field: Field) -> String {
         }
     }
 
-    // Retrieve type of a place for the current MIR representation
+    /// Retrieve type of a place for the current MIR representation
     fn retrieve_type_for_place(&self, place: &Place<'tcx>) -> Option<ty::Ty> {
         match place {
             Place::Local(local) => {
@@ -1805,6 +1953,8 @@ fn get_region_name_for_ty(&self, ty: ty::Ty<'tcx>, counter: usize) -> String {
 pub(super) enum UseSpans {
     // The access is caused by capturing a variable for a closure.
     ClosureUse {
+        // This is true if the captured variable was from a generator.
+        is_generator: bool,
         // The span of the args of the closure, including the `move` keyword if
         // it's present.
         args_span: Span,
@@ -1845,10 +1995,31 @@ pub(super) fn var_span_label(self, err: &mut DiagnosticBuilder, message: impl In
         }
     }
 
-    pub(super) fn for_closure(self) -> bool {
-        match self {
-            UseSpans::ClosureUse { .. } => true,
-            UseSpans::OtherUse(_) => false,
+    /// Return `false` if this place is not used in a closure.
+    fn for_closure(&self) -> bool {
+        match *self {
+            UseSpans::ClosureUse { is_generator, .. } => !is_generator,
+            _ => false,
+        }
+    }
+
+    /// Return `false` if this place is not used in a generator.
+    fn for_generator(&self) -> bool {
+        match *self {
+            UseSpans::ClosureUse { is_generator, .. } => is_generator,
+            _ => false,
+        }
+    }
+
+    /// Describe the span associated with a use of a place.
+    fn describe(&self) -> String {
+        match *self {
+            UseSpans::ClosureUse { is_generator, .. } => if is_generator {
+                " in generator".to_string()
+            } else {
+                " in closure".to_string()
+            },
+            _ => "".to_string(),
         }
     }
 
@@ -1871,53 +2042,37 @@ pub(super) fn move_spans(
         location: Location,
     ) -> UseSpans {
         use self::UseSpans::*;
-        use rustc::hir::ExprKind::Closure;
-        use rustc::mir::AggregateKind;
 
-        let stmt = match self.mir[location.block]
-            .statements
-            .get(location.statement_index)
-        {
+        let stmt = match self.mir[location.block].statements.get(location.statement_index) {
             Some(stmt) => stmt,
             None => return OtherUse(self.mir.source_info(location).span),
         };
 
-        if let StatementKind::Assign(_, box Rvalue::Aggregate(ref kind, ref places)) = stmt.kind {
-            if let AggregateKind::Closure(def_id, _) = **kind {
-                debug!("find_closure_move_span: found closure {:?}", places);
+        debug!("move_spans: moved_place={:?} location={:?} stmt={:?}", moved_place, location, stmt);
+        if let  StatementKind::Assign(
+            _,
+            box Rvalue::Aggregate(ref kind, ref places)
+        ) = stmt.kind {
+            let (def_id, is_generator) = match kind {
+                box AggregateKind::Closure(def_id, _) => (def_id, false),
+                box AggregateKind::Generator(def_id, _, _) => (def_id, true),
+                _ => return OtherUse(stmt.source_info.span),
+            };
 
-                if let Some(node_id) = self.infcx.tcx.hir.as_local_node_id(def_id) {
-                    if let Closure(_, _, _, args_span, _) =
-                        self.infcx.tcx.hir.expect_expr(node_id).node
-                    {
-                        if let Some(var_span) = self.infcx.tcx.with_freevars(node_id, |freevars| {
-                            for (v, place) in freevars.iter().zip(places) {
-                                match place {
-                                    Operand::Copy(place) | Operand::Move(place)
-                                        if moved_place == place =>
-                                    {
-                                        debug!(
-                                            "find_closure_move_span: found captured local {:?}",
-                                            place
-                                        );
-                                        return Some(v.span);
-                                    }
-                                    _ => {}
-                                }
-                            }
-                            None
-                        }) {
-                            return ClosureUse {
-                                args_span,
-                                var_span,
-                            };
-                        }
-                    }
-                }
+            debug!(
+                "move_spans: def_id={:?} is_generator={:?} places={:?}",
+                def_id, is_generator, places
+            );
+            if let Some((args_span, var_span)) = self.closure_span(*def_id, moved_place, places) {
+                return ClosureUse {
+                    is_generator,
+                    args_span,
+                    var_span,
+                };
             }
         }
 
-        return OtherUse(stmt.source_info.span);
+        OtherUse(stmt.source_info.span)
     }
 
     /// Finds the span of arguments of a closure (within `maybe_closure_span`)
@@ -1926,9 +2081,9 @@ pub(super) fn move_spans(
     /// and originating from `maybe_closure_span`.
     pub(super) fn borrow_spans(&self, use_span: Span, location: Location) -> UseSpans {
         use self::UseSpans::*;
-        use rustc::hir::ExprKind::Closure;
+        debug!("borrow_spans: use_span={:?} location={:?}", use_span, location);
 
-        let local = match self.mir[location.block]
+        let target = match self.mir[location.block]
             .statements
             .get(location.statement_index)
         {
@@ -1939,54 +2094,35 @@ pub(super) fn borrow_spans(&self, use_span: Span, location: Location) -> UseSpan
             _ => return OtherUse(use_span),
         };
 
-        if self.mir.local_kind(local) != LocalKind::Temp {
+        if self.mir.local_kind(target) != LocalKind::Temp {
             // operands are always temporaries.
             return OtherUse(use_span);
         }
 
         for stmt in &self.mir[location.block].statements[location.statement_index + 1..] {
-            if let StatementKind::Assign(_, box Rvalue::Aggregate(ref kind, ref places)) = stmt.kind
-            {
-                if let AggregateKind::Closure(def_id, _) = **kind {
-                    debug!("find_closure_borrow_span: found closure {:?}", places);
-
-                    return if let Some(node_id) = self.infcx.tcx.hir.as_local_node_id(def_id) {
-                        let args_span = if let Closure(_, _, _, span, _) =
-                            self.infcx.tcx.hir.expect_expr(node_id).node
-                        {
-                            span
-                        } else {
-                            return OtherUse(use_span);
-                        };
+            if let StatementKind::Assign(
+                _, box Rvalue::Aggregate(ref kind, ref places)
+            ) = stmt.kind {
+                let (def_id, is_generator) = match kind {
+                    box AggregateKind::Closure(def_id, _) => (def_id, false),
+                    box AggregateKind::Generator(def_id, _, _) => (def_id, true),
+                    _ => continue,
+                };
 
-                        self.infcx
-                            .tcx
-                            .with_freevars(node_id, |freevars| {
-                                for (v, place) in freevars.iter().zip(places) {
-                                    match *place {
-                                        Operand::Copy(Place::Local(l))
-                                        | Operand::Move(Place::Local(l)) if local == l =>
-                                        {
-                                            debug!(
-                                                "find_closure_borrow_span: found captured local \
-                                                 {:?}",
-                                                l
-                                            );
-                                            return Some(v.span);
-                                        }
-                                        _ => {}
-                                    }
-                                }
-                                None
-                            })
-                            .map(|var_span| ClosureUse {
-                                args_span,
-                                var_span,
-                            })
-                            .unwrap_or(OtherUse(use_span))
-                    } else {
-                        OtherUse(use_span)
+                debug!(
+                    "borrow_spans: def_id={:?} is_generator={:?} places={:?}",
+                    def_id, is_generator, places
+                );
+                if let Some((args_span, var_span)) = self.closure_span(
+                    *def_id, &Place::Local(target), places
+                ) {
+                    return ClosureUse {
+                        is_generator,
+                        args_span,
+                        var_span,
                     };
+                } else {
+                    return OtherUse(use_span);
                 }
             }
 
@@ -1998,6 +2134,47 @@ pub(super) fn borrow_spans(&self, use_span: Span, location: Location) -> UseSpan
         OtherUse(use_span)
     }
 
+    /// Finds the span of a captured variable within a closure or generator.
+    fn closure_span(
+        &self,
+        def_id: DefId,
+        target_place: &Place<'tcx>,
+        places: &Vec<Operand<'tcx>>,
+    ) -> Option<(Span, Span)> {
+        debug!(
+            "closure_span: def_id={:?} target_place={:?} places={:?}",
+            def_id, target_place, places
+        );
+        let node_id = self.infcx.tcx.hir.as_local_node_id(def_id)?;
+        let expr = &self.infcx.tcx.hir.expect_expr(node_id).node;
+        debug!("closure_span: node_id={:?} expr={:?}", node_id, expr);
+        if let hir::ExprKind::Closure(
+            .., args_span, _
+        ) = expr {
+            let var_span = self.infcx.tcx.with_freevars(
+                node_id,
+                |freevars| {
+                    for (v, place) in freevars.iter().zip(places) {
+                        match place {
+                            Operand::Copy(place) |
+                            Operand::Move(place) if target_place == place => {
+                                debug!("closure_span: found captured local {:?}", place);
+                                return Some(v.span);
+                            },
+                            _ => {}
+                        }
+                    }
+
+                    None
+                },
+            )?;
+
+            Some((*args_span, var_span))
+        } else {
+            None
+        }
+    }
+
     /// Helper to retrieve span(s) of given borrow from the current MIR
     /// representation
     pub(super) fn retrieve_borrow_spans(&self, borrow: &BorrowData) -> UseSpans {
index aa559c96ec6682b179c1c976f151aefb52e776ad..52c557b83d5916979301d743b5f8aa2b4a6091bf 100644 (file)
@@ -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() {
index 2616d0cd9640b746618f7e4a06e5d6730dd3f251..d5c655a3de472dd035f8851dd3ec439e6a6d8e3e 100644 (file)
@@ -221,6 +221,7 @@ fn cannot_uniquely_borrow_by_two_closures(
     fn cannot_uniquely_borrow_by_one_closure(
         self,
         new_loan_span: Span,
+        container_name: &str,
         desc_new: &str,
         opt_via: &str,
         old_loan_span: Span,
@@ -241,7 +242,7 @@ fn cannot_uniquely_borrow_by_one_closure(
         );
         err.span_label(
             new_loan_span,
-            format!("closure construction occurs here{}", opt_via),
+            format!("{} construction occurs here{}", container_name, opt_via),
         );
         err.span_label(old_loan_span, format!("borrow occurs here{}", old_opt_via));
         if let Some(previous_end_span) = previous_end_span {
@@ -253,6 +254,7 @@ fn cannot_uniquely_borrow_by_one_closure(
     fn cannot_reborrow_already_uniquely_borrowed(
         self,
         new_loan_span: Span,
+        container_name: &str,
         desc_new: &str,
         opt_via: &str,
         kind_new: &str,
@@ -275,7 +277,7 @@ fn cannot_reborrow_already_uniquely_borrowed(
         err.span_label(new_loan_span, format!("borrow occurs here{}", opt_via));
         err.span_label(
             old_loan_span,
-            format!("closure construction occurs here{}", old_opt_via),
+            format!("{} construction occurs here{}", container_name, old_opt_via),
         );
         if let Some(previous_end_span) = previous_end_span {
             err.span_label(previous_end_span, "borrow from closure ends here");
index 25a7ff9cd3f566ed9a0c50cc188216f99da9eadb..e2f5829d14ff7ae3cab5698fdd7d8ede62a745b3 100644 (file)
@@ -139,7 +139,7 @@ fn build_reduced_graph_for_use_tree(
 
         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 @@ fn visit_trait_item(&mut self, item: &'a TraitItem) {
 
     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);
                 }
-                _ => {}
             }
         }
     }
index de9481579e2f429a5c6625eb9b1ff3a87add293e..6f3135b37cf05746dd3e9d5b903d3972f1a10ae7 100644 (file)
@@ -109,7 +109,7 @@ fn visit_use_tree(&mut self, use_tree: &'a ast::UseTree, id: ast::NodeId, nested
                 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::<Vec<Span>>();
+        let mut spans = spans.values().cloned().collect::<Vec<Span>>();
         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()
index ac0616e50b0913938a088bbc4c3bcb8f2eb2a53c..bf3fbdc2c5ad5740fd26b52d371843f67f0edd05 100644 (file)
@@ -1633,19 +1633,17 @@ fn resolve_hir_path_cb<F>(&mut self, path: &mut hir::Path, is_value: bool, error
                 *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 @@ fn resolve_use_tree(
                     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 @@ fn check_consistent_bindings(&mut self, pats: &[P<Pat>]) {
 
                 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 @@ fn resolve_arm(&mut self, arm: &Arm) {
         // 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 @@ fn smart_resolve_path_fragment(&mut self,
             // 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 @@ fn smart_resolve_path_fragment(&mut self,
             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<Ident> = ["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 @@ fn type_ascription_suggestion(&self,
                             );
                         }
                         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 @@ fn adjust_local_def(&mut self,
             }
             _ => {}
         }
-        return def;
+        def
     }
 
     fn lookup_assoc_candidate<FilterFn>(&mut self,
@@ -4386,10 +4380,9 @@ fn lookup_import_candidates_from_module<FilterFn>(&mut self,
         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::<ast::PathSegment>::new(), not_local_module));
+        let mut worklist = vec![(start_module, Vec::<ast::PathSegment>::new(), not_local_module)];
 
         while let Some((in_module,
                         path_segments,
@@ -4476,33 +4469,24 @@ fn lookup_import_candidates<FilterFn>(&mut self,
                                           -> Vec<ImportSuggestion>
         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 @@ fn find_module(&mut self,
                    -> 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
index 6c57e6c88abebd014fae159b31b32e645b6c8291..28284a45bcdd5f03098cf665c25e79013840cb28 100644 (file)
@@ -203,9 +203,7 @@ fn visit_ast_fragment_with_placeholders(&mut self, mark: Mark, fragment: &AstFra
         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 @@ fn find_legacy_attr_invoc(&mut self, attrs: &mut Vec<ast::Attribute>, allow_deri
                     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());
index 48f312ce9f27d46763e307a3babc0d10bf4e5d5f..d5d772e13591475cb6293b496241755a697cb073 100644 (file)
@@ -672,7 +672,7 @@ struct UniformPathsCanaryResults<'a> {
                 };
 
                 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 @@ struct UniformPathsCanaryResults<'a> {
                 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 @@ struct UniformPathsCanaryResults<'a> {
     fn throw_unresolved_import_error(&self, error_vec: Vec<(Span, String, String)>,
                                      span: Option<MultiSpan>) {
         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<String> = 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<String> = 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 @@ fn finalize_import(&mut self, directive: &'b ImportDirective<'b>) -> Option<(Spa
         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 @@ fn finalize_resolutions_in(&mut self, module: Module<'b>) {
                 }
             }
 
-            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();
                 }
-                _ => {}
             }
         }
 
index 8e8340b3ed901b557e23e7111bb54e236060cbc7..c3f225d1eb0136e72070a1f1555082b7da6b941d 100644 (file)
@@ -198,6 +198,35 @@ pub fn signum(self) -> 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.
     ///
index 6880294afcaafd4f41c40f6d0ef448f3b5bd14fd..da062dda77a47a5496e76e671875545653f3d91a 100644 (file)
@@ -176,6 +176,35 @@ pub fn signum(self) -> 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/closure_context/issue-42065.nll.stderr b/src/test/ui/closure_context/issue-42065.nll.stderr
deleted file mode 100644 (file)
index bda8a3b..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-error[E0382]: use of moved value: `debug_dump_dict`
-  --> $DIR/issue-42065.rs:21:5
-   |
-LL |     debug_dump_dict();
-   |     --------------- value moved here
-LL |     debug_dump_dict();
-   |     ^^^^^^^^^^^^^^^ value used here after move
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0382`.
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 (file)
index 0000000..3e42cb8
--- /dev/null
@@ -0,0 +1,5 @@
+const fn foo(a: i32) -> Vec<i32> {
+    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 (file)
index 0000000..f6b7043
--- /dev/null
@@ -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 (file)
index 0000000..8648cd3
--- /dev/null
@@ -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 (file)
index 0000000..ba980b7
--- /dev/null
@@ -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
+
index ab9020222ea2b4f7b7e149a1618b5b3f25ca4786..d0c089fa0f37428c7a8cd79b9a5b81ac01cd50fb 100644 (file)
@@ -2,7 +2,7 @@ error[E0277]: the size for values of type `[u8]` cannot be known at compilation
   --> $DIR/E0277.rs:23:6
    |
 LL | fn f(p: Path) { }
-   |      ^ doesn't have a size known at compile-time
+   |      ^ borrow the `Path` instead
    |
    = help: within `std::path::Path`, the trait `std::marker::Sized` is not implemented for `[u8]`
    = note: to learn more, visit <https://doc.rust-lang.org/book/second-edition/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
index 9d1a52a8335433845b91259c589bdfd71f62c432..52b5c9d891bb3459ff4568993fd4493be187d864 100644 (file)
@@ -1,10 +1,11 @@
 error[E0597]: `a` does not live long enough
-  --> $DIR/borrowing.rs:18:18
+  --> $DIR/borrowing.rs:18:29
    |
 LL |         unsafe { (|| yield &a).resume() }
-   |                  ^^^^^^^^^^^^^
-   |                  |
-   |                  borrowed value does not live long enough
+   |                  -----------^-
+   |                  ||         |
+   |                  ||         borrowed value does not live long enough
+   |                  |value captured here by generator
    |                  a temporary with access to the borrow is created here ...
 LL |         //~^ ERROR: `a` does not live long enough
 LL |     };
@@ -15,18 +16,18 @@ LL |     };
    = note: The temporary is part of an expression at the end of a block. Consider forcing this temporary to be dropped sooner, before the block's local variables are dropped. For example, you could save the expression's value in a new local variable `x` and then make `x` be the expression at the end of the block.
 
 error[E0597]: `a` does not live long enough
-  --> $DIR/borrowing.rs:24:9
+  --> $DIR/borrowing.rs:25:20
    |
-LL |       let _b = {
-   |           -- borrow later stored here
-LL |           let a = 3;
-LL |         || {
-LL | |             yield &a
-LL | |             //~^ ERROR: `a` does not live long enough
-LL | |         }
-   | |_________^ borrowed value does not live long enough
-LL |       };
-   |       - `a` dropped here while still borrowed
+LL |     let _b = {
+   |         -- borrow later stored here
+LL |         let a = 3;
+LL |         || {
+   |         -- value captured here by generator
+LL |             yield &a
+   |                    ^ borrowed value does not live long enough
+...
+LL |     };
+   |     - `a` dropped here while still borrowed
 
 error: aborting due to 2 previous errors
 
index 2b95a5caf6da07b7667785355da936cd3eadb029..078aaf6176ab82c0756b9e13fd29fa58c45f5b07 100644 (file)
@@ -13,21 +13,19 @@ LL | }
    = note: values in a scope are dropped in the opposite order they are defined
 
 error[E0597]: `ref_` does not live long enough
-  --> $DIR/dropck.rs:22:11
+  --> $DIR/dropck.rs:24:18
    |
-LL |       gen = || {
-   |  ___________^
-LL | |         // but the generator can use it to drop a `Ref<'a, i32>`.
-LL | |         let _d = ref_.take(); //~ ERROR `ref_` does not live long enough
-LL | |         yield;
-LL | |     };
-   | |_____^ borrowed value does not live long enough
+LL |     gen = || {
+   |           -- value captured here by generator
+LL |         // but the generator can use it to drop a `Ref<'a, i32>`.
+LL |         let _d = ref_.take(); //~ ERROR `ref_` does not live long enough
+   |                  ^^^^ borrowed value does not live long enough
 ...
-LL |   }
-   |   -
-   |   |
-   |   `ref_` dropped here while still borrowed
-   |   borrow might be used here, when `gen` is dropped and runs the destructor for generator
+LL | }
+   | -
+   | |
+   | `ref_` dropped here while still borrowed
+   | borrow might be used here, when `gen` is dropped and runs the destructor for generator
    |
    = note: values in a scope are dropped in the opposite order they are defined
 
index d332df6e4ba4667bc7465d19853d3abe447596a8..2f0a05898444c836d7ac550cf3e7e56080a5b900 100644 (file)
@@ -9,17 +9,15 @@ LL |             yield();
 error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable
   --> $DIR/yield-while-iterating.rs:67:20
    |
-LL |       let mut b = || {
-   |  _________________-
-LL | |         for p in &mut x {
-LL | |             yield p;
-LL | |         }
-LL | |     };
-   | |_____- mutable borrow occurs here
-LL |       println!("{}", x[0]); //~ ERROR
-   |                      ^ immutable borrow occurs here
-LL |       b.resume();
-   |       - mutable borrow later used here
+LL |     let mut b = || {
+   |                 -- mutable borrow occurs here
+LL |         for p in &mut x {
+   |                       - first borrow occurs due to use of `x` in generator
+...
+LL |     println!("{}", x[0]); //~ ERROR
+   |                    ^ immutable borrow occurs here
+LL |     b.resume();
+   |     - mutable borrow later used here
 
 error: aborting due to 2 previous errors
 
index b5c392c51ece5cb77b2627f5d3ed020c4f64e954..8dabb3c2505b637d863f0c3a549ebc5b4bb38aca 100644 (file)
@@ -1,17 +1,15 @@
 error[E0501]: cannot borrow `x` as immutable because previous closure requires unique access
   --> $DIR/yield-while-ref-reborrowed.rs:45:20
    |
-LL |       let mut b = || {
-   |  _________________-
-LL | |         let a = &mut *x;
-LL | |         yield();
-LL | |         println!("{}", a);
-LL | |     };
-   | |_____- closure construction occurs here
-LL |       println!("{}", x); //~ ERROR
-   |                      ^ borrow occurs here
-LL |       b.resume();
-   |       - first borrow later used here
+LL |     let mut b = || {
+   |                 -- generator construction occurs here
+LL |         let a = &mut *x;
+   |                       - first borrow occurs due to use of `x` in generator
+...
+LL |     println!("{}", x); //~ ERROR
+   |                    ^ borrow occurs here
+LL |     b.resume();
+   |     - first borrow later used here
 
 error: aborting due to previous error
 
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 (file)
index 0000000..37dc519
--- /dev/null
@@ -0,0 +1,9 @@
+// run-pass
+
+#![deny(unused_parens)]
+#![allow(unreachable_code)]
+
+fn main() {
+    match (return) {} // ok
+    if (return) {} // ok
+}
diff --git a/src/test/ui/suggestions/path-by-value.rs b/src/test/ui/suggestions/path-by-value.rs
new file mode 100644 (file)
index 0000000..c875ca6
--- /dev/null
@@ -0,0 +1,6 @@
+use std::path::Path;
+
+fn f(p: Path) { }
+//~^ ERROR E0277
+
+fn main() {}
diff --git a/src/test/ui/suggestions/path-by-value.stderr b/src/test/ui/suggestions/path-by-value.stderr
new file mode 100644 (file)
index 0000000..338cfc9
--- /dev/null
@@ -0,0 +1,15 @@
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+  --> $DIR/path-by-value.rs:3:6
+   |
+LL | fn f(p: Path) { }
+   |      ^ borrow the `Path` instead
+   |
+   = help: within `std::path::Path`, the trait `std::marker::Sized` is not implemented for `[u8]`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/second-edition/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = note: required because it appears within the type `std::path::Path`
+   = note: all local variables must have a statically known size
+   = help: unsized locals are gated as an unstable feature
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/unboxed-closures/unboxed-closures-infer-fnonce-call-twice.nll.stderr b/src/test/ui/unboxed-closures/unboxed-closures-infer-fnonce-call-twice.nll.stderr
deleted file mode 100644 (file)
index f475669..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-error[E0382]: use of moved value: `tick`
-  --> $DIR/unboxed-closures-infer-fnonce-call-twice.rs:20:5
-   |
-LL |     tick();
-   |     ---- value moved here
-LL |     tick(); //~ ERROR use of moved value: `tick`
-   |     ^^^^ value used here after move
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/unboxed-closures/unboxed-closures-infer-fnonce-move-call-twice.nll.stderr b/src/test/ui/unboxed-closures/unboxed-closures-infer-fnonce-move-call-twice.nll.stderr
deleted file mode 100644 (file)
index 95ed673..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-error[E0382]: use of moved value: `tick`
-  --> $DIR/unboxed-closures-infer-fnonce-move-call-twice.rs:20:5
-   |
-LL |     tick();
-   |     ---- value moved here
-LL |     tick(); //~ ERROR use of moved value: `tick`
-   |     ^^^^ value used here after move
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0382`.