+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)
===========================
[54639]: https://github.com/rust-lang/rust/pull/54639
+
Version 1.29.1 (2018-09-25)
===========================
Thank you to Scott McMurray for responsibily disclosing this vulnerability to
us.
+
Version 1.29.0 (2018-09-13)
==========================
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/
#![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
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};
////////////////////////////////////////////////////////////////////////////////
#![feature(str_escape)]
#![feature(try_reserve)]
#![feature(unboxed_closures)]
-#![feature(chunks_exact)]
-#![feature(rchunks)]
#![feature(repeat_generic_slice)]
extern crate alloc_system;
#[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/\
/// # 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']);
///
/// [`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);
/// # Examples
///
/// ```
- /// #![feature(chunks_exact)]
- ///
/// let v = &mut [0, 0, 0, 0, 0];
/// let mut count = 1;
///
///
/// [`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);
/// # Examples
///
/// ```
- /// #![feature(rchunks)]
- ///
/// let slice = ['l', 'o', 'r', 'e', 'm'];
/// let mut iter = slice.rchunks(2);
/// assert_eq!(iter.next().unwrap(), &['e', 'm']);
///
/// [`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);
/// # Examples
///
/// ```
- /// #![feature(rchunks)]
- ///
/// let v = &mut [0, 0, 0, 0, 0];
/// let mut count = 1;
///
///
/// [`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);
/// # Examples
///
/// ```
- /// #![feature(rchunks)]
- ///
/// let slice = ['l', 'o', 'r', 'e', 'm'];
/// let mut iter = slice.rchunks_exact(2);
/// assert_eq!(iter.next().unwrap(), &['e', 'm']);
///
/// [`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);
/// # Examples
///
/// ```
- /// #![feature(rchunks)]
- ///
/// let v = &mut [0, 0, 0, 0, 0];
/// let mut count = 1;
///
///
/// [`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);
/// [`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 {
}
}
-#[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];
}
}
-#[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]> {
}
}
-#[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()
#[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;
/// [`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];
}
}
-#[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]> {
}
}
-#[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()
#[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;
/// [`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 {
}
}
-#[unstable(feature = "rchunks", issue = "55177")]
+#[stable(feature = "rchunks", since = "1.31.0")]
impl<'a, T> Iterator for RChunks<'a, T> {
type Item = &'a [T];
}
}
-#[unstable(feature = "rchunks", issue = "55177")]
+#[stable(feature = "rchunks", since = "1.31.0")]
impl<'a, T> DoubleEndedIterator for RChunks<'a, T> {
#[inline]
fn next_back(&mut self) -> Option<&'a [T]> {
}
}
-#[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;
/// [`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];
}
}
-#[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]> {
}
}
-#[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;
/// [`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 {
}
}
-#[unstable(feature = "rchunks", issue = "55177")]
+#[stable(feature = "rchunks", since = "1.31.0")]
impl<'a, T> Iterator for RChunksExact<'a, T> {
type Item = &'a [T];
}
}
-#[unstable(feature = "rchunks", issue = "55177")]
+#[stable(feature = "rchunks", since = "1.31.0")]
impl<'a, T> DoubleEndedIterator for RChunksExact<'a, T> {
#[inline]
fn next_back(&mut self) -> Option<&'a [T]> {
}
}
-#[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()
#[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;
/// [`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];
}
}
-#[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]> {
}
}
-#[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()
#[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;
#![feature(trusted_len)]
#![feature(try_from)]
#![feature(try_trait)]
-#![feature(chunks_exact)]
-#![feature(rchunks)]
#![feature(align_offset)]
#![feature(reverse_bits)]
#![feature(inner_deref)]
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));
}
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)),
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)
}
(..) =>
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);
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),
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) {
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;
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);
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];
);
} 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 {
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),
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, "");
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)
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;
);
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);
first_borrow_desc = "first ";
tcx.cannot_uniquely_borrow_by_one_closure(
span,
+ container_name,
&desc_place,
"",
issued_span,
first_borrow_desc = "first ";
tcx.cannot_reborrow_already_uniquely_borrowed(
span,
+ container_name,
&desc_place,
"",
lft,
first_borrow_desc = "first ";
tcx.cannot_reborrow_already_uniquely_borrowed(
span,
+ container_name,
&desc_place,
"",
lft,
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;
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(),
),
);
}
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, "");
}
}
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
}
)
};
- 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, "");
}
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>,
}
}
- // 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>,
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 {
}
}
- // 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) => {
}
}
- // 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
}
}
- // 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) => {
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,
}
}
- 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(),
}
}
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`)
/// 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)
{
_ => 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);
}
}
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 {
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");
_ => 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)?;
))
}
}
- // 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() {
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,
);
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 {
fn cannot_reborrow_already_uniquely_borrowed(
self,
new_loan_span: Span,
+ container_name: &str,
desc_new: &str,
opt_via: &str,
kind_new: &str,
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");
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()
});
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);
}
- _ => {}
}
}
}
self.item_span
};
- if items.len() == 0 {
+ if items.is_empty() {
self.unused_imports
.entry(self.base_id)
.or_default()
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()
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()
*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, _) => {
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,
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 {
// 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);
// 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() {
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,
);
}
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;
}
}
_ => {}
}
- return def;
+ def
}
fn lookup_assoc_candidate<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,
-> 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));
}
}
}
-> 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
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(),
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());
};
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| {
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;
}
}
}
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) {
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;
}
});
}
}
- 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();
}
- _ => {}
}
}
}
}
+ /// 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.
///
}
}
+ /// 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.
///
+++ /dev/null
-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`.
--- /dev/null
+const fn foo(a: i32) -> Vec<i32> {
+ vec![1, 2, 3] //~ ERROR heap allocations are not allowed in const fn
+}
+
+fn main() {}
--- /dev/null
+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
+
--- /dev/null
+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
--- /dev/null
+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
+
--> $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>
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 | };
= 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
= 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
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
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
--- /dev/null
+// run-pass
+
+#![deny(unused_parens)]
+#![allow(unreachable_code)]
+
+fn main() {
+ match (return) {} // ok
+ if (return) {} // ok
+}
--- /dev/null
+use std::path::Path;
+
+fn f(p: Path) { }
+//~^ ERROR E0277
+
+fn main() {}
--- /dev/null
+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`.
+++ /dev/null
-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`.
+++ /dev/null
-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`.