Warn that `#![feature(rust_2018_preview)]` is implied when the edition is set to Rust 2018.
cc @varkor @petrochenkov @joshtriplett
echo '{"ipv6":true,"fixed-cidr-v6":"fd9a:8454:6789:13f7::/64"}' | sudo tee /etc/docker/daemon.json;
sudo service docker restart;
fi
- - date
- - sudo atq || true
- - sudo grep -rE 'shutdown|poweroff|halt' /var/spool/cron || true
- - sudo grep -E 'google-clock-skew|ntpd|startup-script' /var/log/syslog || true
install:
- case "$TRAVIS_OS_NAME" in
du . | sort -nr | head -n100
after_failure:
- # Requested by travis to debug "shutting down NOW" errors
- - sudo tail -n 500 /var/log/syslog
- >
echo "#### Build failed; Disk usage after running script:";
df -h;
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "backtrace-sys 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)",
+ "backtrace-sys 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)",
"cfg-if 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-demangle 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
[[package]]
name = "backtrace-sys"
-version = "0.1.23"
+version = "0.1.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cc 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)",
[[package]]
name = "chalk-engine"
-version = "0.6.0"
+version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"chalk-macros 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
"bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "chalk-engine 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "chalk-engine 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"flate2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"fmt_macros 0.0.0",
"graphviz 0.0.0",
version = "0.0.0"
dependencies = [
"bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "chalk-engine 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "chalk-engine 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"graphviz 0.0.0",
"log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc 0.0.0",
"checksum assert_cli 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "98589b0e465a6c510d95fceebd365bb79bedece7f6e18a480897f2015f85ec51"
"checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652"
"checksum backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "89a47830402e9981c5c41223151efcced65a0510c13097c769cede7efb34782a"
-"checksum backtrace-sys 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)" = "bff67d0c06556c0b8e6b5f090f0eac52d950d9dfd1d35ba04e4ca3543eaf6a7e"
+"checksum backtrace-sys 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)" = "c66d56ac8dabd07f6aacdaf633f4b8262f5b3601a810a0dcddffd5c22c69daa0"
"checksum bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5"
"checksum bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d0c54bb8f454c567f21197eefcdbf5679d0bd99f2ddbe52e84c77061952e6789"
"checksum bufstream 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f2f382711e76b9de6c744cc00d0497baba02fb00a787f088c879f01d09468e32"
"checksum cargo_metadata 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2d6809b327f87369e6f3651efd2c5a96c49847a3ed2559477ecba79014751ee1"
"checksum cc 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)" = "2119ea4867bd2b8ed3aecab467709720b2d55b1bcfe09f772fd68066eaf15275"
"checksum cfg-if 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "efe5c877e17a9c717a0bf3613b2709f723202c4e4675cc8f12926ded29bcb17e"
-"checksum chalk-engine 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a146c19172c7eea48ea55a7123ac95da786639bc665097f1e14034ee5f1d8699"
+"checksum chalk-engine 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "25ce2f28f55ed544a2a3756b7acf41dd7d6f27acffb2086439950925506af7d0"
"checksum chalk-macros 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "295635afd6853aa9f20baeb7f0204862440c0fe994c5a253d5f479dac41d047e"
"checksum chrono 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6962c635d530328acc53ac6a955e83093fedc91c5809dfac1fa60fa470830a37"
"checksum clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b957d88f4b6a63b9d70d5f454ac8011819c6efa7727858f458ab71c756ce2d3e"
builder.ensure(compile::Rustc { compiler, target });
}
- if builder.no_std(target) != Some(true) {
+ if builder.no_std(target) == Some(true) {
+ // the `test` doesn't compile for no-std targets
+ builder.ensure(compile::Std { compiler, target });
+ } else {
builder.ensure(compile::Test { compiler, target });
}
+
+ if builder.no_std(target) == Some(true) {
+ // for no_std run-make (e.g. thumb*),
+ // we need a host compiler which is called by cargo.
+ builder.ensure(compile::Std { compiler, target: compiler.host });
+ }
+
builder.ensure(native::TestHelpers { target });
builder.ensure(RemoteCopyLibs { compiler, target });
# goes ahead and sets it for all builders.
args="$args --privileged"
-if [ "$CI" != "" ]; then
- args="$args --dns 8.8.8.8 --dns 8.8.4.4 --dns 1.1.1.1 --dns 1.0.0.1"
-fi
-
exec docker \
run \
--volume "$root_dir:/checkout:ro" \
The `crate_in_paths` feature allows to explicitly refer to the crate root in absolute paths
using keyword `crate`.
-`crate` can be used *only* in absolute paths, i.e. either in `::crate::a::b::c` form or in `use`
-items where the starting `::` is added implicitly.
-Paths like `crate::a::b::c` are not accepted currently.
-
This feature is required in `feature(extern_absolute_paths)` mode to refer to any absolute path
in the local crate (absolute paths refer to extern crates by default in that mode), but can be
used without `feature(extern_absolute_paths)` as well.
use crate as root;
pub fn check() {
assert_eq!(f(), 1);
- // `::` is required in non-import paths
- assert_eq!(::crate::m::g(), 2);
+ assert_eq!(crate::m::g(), 2);
assert_eq!(root::m::h(), 3);
}
}
fn main() {
assert_eq!(f(), 1);
- assert_eq!(::crate::m::g(), 2);
+ assert_eq!(crate::m::g(), 2);
assert_eq!(root::m::h(), 3);
n::check();
}
`::my_crate::a::b` will resolve to path `a::b` in crate `my_crate`.
`feature(crate_in_paths)` can be used in `feature(extern_absolute_paths)` mode for referring
-to absolute paths in the local crate (`::crate::a::b`).
+to absolute paths in the local crate (`crate::a::b`).
`feature(extern_in_paths)` provides the same effect by using keyword `extern` to refer to
paths from other crates (`extern::my_crate::a::b`).
+++ /dev/null
-# `future_atomic_orderings`
-
-This feature is internal to the Rust compiler and is not intended for general use.
-
-------------------------
+++ /dev/null
-# `io_error_internals`
-
-This feature is internal to the Rust compiler and is not intended for general use.
-
-------------------------
TYPE_KIND_OS_STRING = 18
TYPE_KIND_STD_VECDEQUE = 19
TYPE_KIND_STD_BTREESET = 20
+TYPE_KIND_STD_BTREEMAP = 21
ENCODED_ENUM_PREFIX = "RUST$ENCODED$ENUM$"
ENUM_DISR_FIELD_NAME = "RUST$ENUM$DISR"
# std::collections::BTreeSet<> related constants
STD_BTREESET_FIELD_NAMES = ["map"]
+# std::collections::BTreeMap<> related constants
+STD_BTREEMAP_FIELD_NAMES = ["root", "length"]
+
# std::String related constants
STD_STRING_FIELD_NAMES = ["vec"]
self.__conforms_to_field_layout(STD_BTREESET_FIELD_NAMES)):
return TYPE_KIND_STD_BTREESET
+ # STD COLLECTION BTREEMAP
+ if (unqualified_type_name.startswith("BTreeMap<") and
+ self.__conforms_to_field_layout(STD_BTREEMAP_FIELD_NAMES)):
+ return TYPE_KIND_STD_BTREEMAP
+
# STD STRING
if (unqualified_type_name.startswith("String") and
self.__conforms_to_field_layout(STD_STRING_FIELD_NAMES)):
return (length, data_ptr)
+def extract_length_and_ptr_from_std_btreemap(vec_val):
+ assert vec_val.type.get_type_kind() == TYPE_KIND_STD_BTREEMAP
+ root = vec_val.get_child_at_index(0)
+ length = vec_val.get_child_at_index(1).as_integer()
+ node = root.get_child_at_index(0)
+ ptr = node.get_child_at_index(0)
+ unique_ptr_val = ptr.get_child_at_index(0)
+ data_ptr = unique_ptr_val.get_child_at_index(0)
+ assert data_ptr.type.get_dwarf_type_kind() == DWARF_TYPE_CODE_PTR
+ return (length, data_ptr)
+
+
def extract_length_and_ptr_from_slice(slice_val):
assert (slice_val.type.get_type_kind() == TYPE_KIND_SLICE or
slice_val.type.get_type_kind() == TYPE_KIND_STR_SLICE)
if type_kind == rustpp.TYPE_KIND_STD_BTREESET:
return RustStdBTreeSetPrinter(val)
+ if type_kind == rustpp.TYPE_KIND_STD_BTREEMAP:
+ return RustStdBTreeMapPrinter(val)
+
if type_kind == rustpp.TYPE_KIND_STD_STRING:
return RustStdStringPrinter(val)
yield (str(index), gdb_ptr[index])
+class RustStdBTreeMapPrinter(object):
+ def __init__(self, val):
+ self.__val = val
+
+ @staticmethod
+ def display_hint():
+ return "map"
+
+ def to_string(self):
+ (length, data_ptr) = \
+ rustpp.extract_length_and_ptr_from_std_btreemap(self.__val)
+ return (self.__val.type.get_unqualified_type_name() +
+ ("(len: %i)" % length))
+
+ def children(self):
+ (length, data_ptr) = \
+ rustpp.extract_length_and_ptr_from_std_btreemap(self.__val)
+ keys = GdbValue(data_ptr.get_wrapped_value().dereference()).get_child_at_index(3)
+ keys_ptr = keys.get_wrapped_value()
+ vals = GdbValue(data_ptr.get_wrapped_value().dereference()).get_child_at_index(4)
+ vals_ptr = vals.get_wrapped_value()
+ for index in xrange(length):
+ yield (str(index), keys_ptr[index])
+ yield (str(index), vals_ptr[index])
+
+
class RustStdStringPrinter(object):
def __init__(self, val):
self.__val = val
def display_hint(self):
return "string"
+
class RustOsStringPrinter(object):
def __init__(self, val):
self.__val = val
#![feature(const_slice_len)]
#![feature(const_str_as_bytes)]
#![feature(const_str_len)]
+#![feature(non_exhaustive)]
#[prelude_import]
#[allow(unused)]
/// ```
#[macro_export]
#[stable(feature = "rust1", since = "1.0.0")]
+#[allow_internal_unstable]
macro_rules! writeln {
($dst:expr) => (
write!($dst, "\n")
($dst:expr,) => (
writeln!($dst)
);
- ($dst:expr, $fmt:expr) => (
- write!($dst, concat!($fmt, "\n"))
- );
- ($dst:expr, $fmt:expr, $($arg:tt)*) => (
- write!($dst, concat!($fmt, "\n"), $($arg)*)
+ ($dst:expr, $($arg:tt)*) => (
+ $dst.write_fmt(format_args_nl!($($arg)*))
);
}
/// ```
/// #![feature(int_to_from_bytes)]
///
- /// let bytes = 0x12345678i32.to_be_bytes();
+ /// let bytes = 0x12_34_56_78_i32.to_be_bytes();
/// assert_eq!(bytes, [0x12, 0x34, 0x56, 0x78]);
/// ```
#[unstable(feature = "int_to_from_bytes", issue = "52963")]
/// ```
/// #![feature(int_to_from_bytes)]
///
- /// let bytes = 0x12345678i32.to_le_bytes();
+ /// let bytes = 0x12_34_56_78_i32.to_le_bytes();
/// assert_eq!(bytes, [0x78, 0x56, 0x34, 0x12]);
/// ```
#[unstable(feature = "int_to_from_bytes", issue = "52963")]
}
}
- /// Return the memory representation of this integer as a byte array.
+ /// Return the memory representation of this integer as a byte array in
+ /// big-endian (network) byte order.
+ ///
+ /// # Examples
///
- /// The target platform’s native endianness is used.
- /// Portable code likely wants to use this after [`to_be`] or [`to_le`].
+ /// ```
+ /// #![feature(int_to_from_bytes)]
///
- /// [`to_be`]: #method.to_be
- /// [`to_le`]: #method.to_le
+ /// let bytes = 0x12_34_56_78_i32.to_be_bytes();
+ /// assert_eq!(bytes, [0x12, 0x34, 0x56, 0x78]);
+ /// ```
+ #[unstable(feature = "int_to_from_bytes", issue = "52963")]
+ #[inline]
+ pub fn to_be_bytes(self) -> [u8; mem::size_of::<Self>()] {
+ self.to_be().to_ne_bytes()
+ }
+
+ /// Return the memory representation of this integer as a byte array in
+ /// little-endian byte order.
///
/// # Examples
///
/// ```
/// #![feature(int_to_from_bytes)]
///
- /// let bytes = 0x1234_5678_u32.to_be().to_bytes();
- /// assert_eq!(bytes, [0x12, 0x34, 0x56, 0x78]);
+ /// let bytes = 0x12_34_56_78_i32.to_le_bytes();
+ /// assert_eq!(bytes, [0x78, 0x56, 0x34, 0x12]);
+ /// ```
+ #[unstable(feature = "int_to_from_bytes", issue = "52963")]
+ #[inline]
+ pub fn to_le_bytes(self) -> [u8; mem::size_of::<Self>()] {
+ self.to_le().to_ne_bytes()
+ }
+
+ /// Return the memory representation of this integer as a byte array in
+ /// native byte order.
+ ///
+ /// As the target platform's native endianness is used, portable code
+ /// should use [`to_be_bytes`] or [`to_le_bytes`], as appropriate,
+ /// instead.
+ ///
+ /// [`to_be_bytes`]: #method.to_be_bytes
+ /// [`to_le_bytes`]: #method.to_le_bytes
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(int_to_from_bytes)]
+ ///
+ /// let bytes = i32::min_value().to_be().to_ne_bytes();
+ /// assert_eq!(bytes, [0x80, 0, 0, 0]);
/// ```
#[unstable(feature = "int_to_from_bytes", issue = "52963")]
#[inline]
- pub fn to_bytes(self) -> [u8; mem::size_of::<Self>()] {
+ pub fn to_ne_bytes(self) -> [u8; mem::size_of::<Self>()] {
unsafe { mem::transmute(self) }
}
- /// Create an integer value from its memory representation as a byte array.
+ /// Create an integer value from its representation as a byte array in
+ /// big endian.
+ ///
+ /// # Examples
///
- /// The target platform’s native endianness is used.
- /// Portable code likely wants to use [`to_be`] or [`to_le`] after this.
+ /// ```
+ /// #![feature(int_to_from_bytes)]
///
- /// [`to_be`]: #method.to_be
- /// [`to_le`]: #method.to_le
+ /// let int = i32::from_be_bytes([0x12, 0x34, 0x56, 0x78]);
+ /// assert_eq!(int, 0x12_34_56_78);
+ /// ```
+ #[unstable(feature = "int_to_from_bytes", issue = "52963")]
+ #[inline]
+ pub fn from_be_bytes(bytes: [u8; mem::size_of::<Self>()]) -> Self {
+ Self::from_be(Self::from_ne_bytes(bytes))
+ }
+
+ /// Create an integer value from its representation as a byte array in
+ /// little endian.
///
/// # Examples
///
/// ```
/// #![feature(int_to_from_bytes)]
///
- /// let int = u32::from_be(u32::from_bytes([0x12, 0x34, 0x56, 0x78]));
- /// assert_eq!(int, 0x1234_5678_u32);
+ /// let int = i32::from_le_bytes([0x12, 0x34, 0x56, 0x78]);
+ /// assert_eq!(int, 0x78_56_34_12);
/// ```
#[unstable(feature = "int_to_from_bytes", issue = "52963")]
#[inline]
- pub fn from_bytes(bytes: [u8; mem::size_of::<Self>()]) -> Self {
+ pub fn from_le_bytes(bytes: [u8; mem::size_of::<Self>()]) -> Self {
+ Self::from_le(Self::from_ne_bytes(bytes))
+ }
+
+ /// Create an integer value from its memory representation as a byte
+ /// array in native endianness.
+ ///
+ /// As the target platform's native endianness is used, portable code
+ /// likely wants to use [`from_be_bytes`] or [`from_le_bytes`], as
+ /// appropriate instead.
+ ///
+ /// [`from_be_bytes`]: #method.from_be_bytes
+ /// [`from_le_bytes`]: #method.from_le_bytes
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(int_to_from_bytes)]
+ ///
+ /// let int = i32::from_be(i32::from_ne_bytes([0x80, 0, 0, 0]));
+ /// assert_eq!(int, i32::min_value());
+ /// ```
+ #[unstable(feature = "int_to_from_bytes", issue = "52963")]
+ #[inline]
+ pub fn from_ne_bytes(bytes: [u8; mem::size_of::<Self>()]) -> Self {
unsafe { mem::transmute(bytes) }
}
}
/// [nomicon]: ../../../nomicon/atomics.html
#[stable(feature = "rust1", since = "1.0.0")]
#[derive(Copy, Clone, Debug)]
+#[non_exhaustive]
pub enum Ordering {
/// No ordering constraints, only atomic operations.
///
/// [`AcqRel`]: https://llvm.org/docs/Atomics.html#acquirerelease
#[stable(feature = "rust1", since = "1.0.0")]
SeqCst,
- // Prevent exhaustive matching to allow for future extension
- #[doc(hidden)]
- #[unstable(feature = "future_atomic_orderings", issue = "0")]
- __Nonexhaustive,
}
/// An [`AtomicBool`] initialized to `false`.
SeqCst => SeqCst,
Acquire => Acquire,
AcqRel => Acquire,
- __Nonexhaustive => __Nonexhaustive,
}
}
SeqCst => intrinsics::atomic_store(dst, val),
Acquire => panic!("there is no such thing as an acquire store"),
AcqRel => panic!("there is no such thing as an acquire/release store"),
- __Nonexhaustive => panic!("invalid memory ordering"),
}
}
SeqCst => intrinsics::atomic_load(dst),
Release => panic!("there is no such thing as a release load"),
AcqRel => panic!("there is no such thing as an acquire/release load"),
- __Nonexhaustive => panic!("invalid memory ordering"),
}
}
AcqRel => intrinsics::atomic_xchg_acqrel(dst, val),
Relaxed => intrinsics::atomic_xchg_relaxed(dst, val),
SeqCst => intrinsics::atomic_xchg(dst, val),
- __Nonexhaustive => panic!("invalid memory ordering"),
}
}
AcqRel => intrinsics::atomic_xadd_acqrel(dst, val),
Relaxed => intrinsics::atomic_xadd_relaxed(dst, val),
SeqCst => intrinsics::atomic_xadd(dst, val),
- __Nonexhaustive => panic!("invalid memory ordering"),
}
}
AcqRel => intrinsics::atomic_xsub_acqrel(dst, val),
Relaxed => intrinsics::atomic_xsub_relaxed(dst, val),
SeqCst => intrinsics::atomic_xsub(dst, val),
- __Nonexhaustive => panic!("invalid memory ordering"),
}
}
(AcqRel, Relaxed) => intrinsics::atomic_cxchg_acqrel_failrelaxed(dst, old, new),
(SeqCst, Relaxed) => intrinsics::atomic_cxchg_failrelaxed(dst, old, new),
(SeqCst, Acquire) => intrinsics::atomic_cxchg_failacq(dst, old, new),
- (__Nonexhaustive, _) => panic!("invalid memory ordering"),
- (_, __Nonexhaustive) => panic!("invalid memory ordering"),
(_, AcqRel) => panic!("there is no such thing as an acquire/release failure ordering"),
(_, Release) => panic!("there is no such thing as a release failure ordering"),
_ => panic!("a failure ordering can't be stronger than a success ordering"),
(AcqRel, Relaxed) => intrinsics::atomic_cxchgweak_acqrel_failrelaxed(dst, old, new),
(SeqCst, Relaxed) => intrinsics::atomic_cxchgweak_failrelaxed(dst, old, new),
(SeqCst, Acquire) => intrinsics::atomic_cxchgweak_failacq(dst, old, new),
- (__Nonexhaustive, _) => panic!("invalid memory ordering"),
- (_, __Nonexhaustive) => panic!("invalid memory ordering"),
(_, AcqRel) => panic!("there is no such thing as an acquire/release failure ordering"),
(_, Release) => panic!("there is no such thing as a release failure ordering"),
_ => panic!("a failure ordering can't be stronger than a success ordering"),
AcqRel => intrinsics::atomic_and_acqrel(dst, val),
Relaxed => intrinsics::atomic_and_relaxed(dst, val),
SeqCst => intrinsics::atomic_and(dst, val),
- __Nonexhaustive => panic!("invalid memory ordering"),
}
}
AcqRel => intrinsics::atomic_nand_acqrel(dst, val),
Relaxed => intrinsics::atomic_nand_relaxed(dst, val),
SeqCst => intrinsics::atomic_nand(dst, val),
- __Nonexhaustive => panic!("invalid memory ordering"),
}
}
AcqRel => intrinsics::atomic_or_acqrel(dst, val),
Relaxed => intrinsics::atomic_or_relaxed(dst, val),
SeqCst => intrinsics::atomic_or(dst, val),
- __Nonexhaustive => panic!("invalid memory ordering"),
}
}
AcqRel => intrinsics::atomic_xor_acqrel(dst, val),
Relaxed => intrinsics::atomic_xor_relaxed(dst, val),
SeqCst => intrinsics::atomic_xor(dst, val),
- __Nonexhaustive => panic!("invalid memory ordering"),
}
}
AcqRel => intrinsics::atomic_max_acqrel(dst, val),
Relaxed => intrinsics::atomic_max_relaxed(dst, val),
SeqCst => intrinsics::atomic_max(dst, val),
- __Nonexhaustive => panic!("invalid memory ordering"),
}
}
AcqRel => intrinsics::atomic_min_acqrel(dst, val),
Relaxed => intrinsics::atomic_min_relaxed(dst, val),
SeqCst => intrinsics::atomic_min(dst, val),
- __Nonexhaustive => panic!("invalid memory ordering"),
}
}
AcqRel => intrinsics::atomic_umax_acqrel(dst, val),
Relaxed => intrinsics::atomic_umax_relaxed(dst, val),
SeqCst => intrinsics::atomic_umax(dst, val),
- __Nonexhaustive => panic!("invalid memory ordering"),
}
}
AcqRel => intrinsics::atomic_umin_acqrel(dst, val),
Relaxed => intrinsics::atomic_umin_relaxed(dst, val),
SeqCst => intrinsics::atomic_umin(dst, val),
- __Nonexhaustive => panic!("invalid memory ordering"),
}
}
AcqRel => intrinsics::atomic_fence_acqrel(),
SeqCst => intrinsics::atomic_fence(),
Relaxed => panic!("there is no such thing as a relaxed fence"),
- __Nonexhaustive => panic!("invalid memory ordering"),
}
}
}
AcqRel => intrinsics::atomic_singlethreadfence_acqrel(),
SeqCst => intrinsics::atomic_singlethreadfence(),
Relaxed => panic!("there is no such thing as a relaxed compiler fence"),
- __Nonexhaustive => panic!("invalid memory ordering"),
}
}
}
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Unwinding for wasm32
+//!
+//! Right now we don't support this, so this is just stubs
+
+use alloc::boxed::Box;
+use core::any::Any;
+use core::intrinsics;
+
+pub fn payload() -> *mut u8 {
+ 0 as *mut u8
+}
+
+pub unsafe fn cleanup(_ptr: *mut u8) -> Box<dyn Any + Send> {
+ intrinsics::abort()
+}
+
+pub unsafe fn panic(_data: Box<dyn Any + Send>) -> u32 {
+ intrinsics::abort()
+}
use core::raw;
use core::panic::BoxMeUp;
-// Rust runtime's startup objects depend on these symbols, so make them public.
-#[cfg(all(target_os="windows", target_arch = "x86", target_env="gnu"))]
-pub use imp::eh_frame_registry::*;
+#[macro_use]
+mod macros;
-// *-pc-windows-msvc
-#[cfg(target_env = "msvc")]
-#[path = "seh.rs"]
-mod imp;
-
-// x86_64-pc-windows-gnu
-#[cfg(all(windows, target_arch = "x86_64", target_env = "gnu"))]
-#[path = "seh64_gnu.rs"]
-mod imp;
-
-// i686-pc-windows-gnu and all others
-#[cfg(any(all(unix, not(target_os = "emscripten")),
- target_os = "cloudabi",
- target_os = "redox",
- all(windows, target_arch = "x86", target_env = "gnu")))]
-#[path = "gcc.rs"]
-mod imp;
-
-// emscripten
-#[cfg(target_os = "emscripten")]
-#[path = "emcc.rs"]
-mod imp;
-
-#[cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))]
-#[path = "wasm32.rs"]
-mod imp;
+cfg_if! {
+ if #[cfg(target_os = "emscripten")] {
+ #[path = "emcc.rs"]
+ mod imp;
+ } else if #[cfg(target_arch = "wasm32")] {
+ #[path = "dummy.rs"]
+ mod imp;
+ } else if #[cfg(all(target_env = "msvc", target_arch = "aarch64"))] {
+ #[path = "dummy.rs"]
+ mod imp;
+ } else if #[cfg(target_env = "msvc")] {
+ #[path = "seh.rs"]
+ mod imp;
+ } else if #[cfg(all(windows, target_arch = "x86_64", target_env = "gnu"))] {
+ #[path = "seh64_gnu.rs"]
+ mod imp;
+ } else {
+ // Rust runtime's startup objects depend on these symbols, so make them public.
+ #[cfg(all(target_os="windows", target_arch = "x86", target_env="gnu"))]
+ pub use imp::eh_frame_registry::*;
+ #[path = "gcc.rs"]
+ mod imp;
+ }
+}
mod dwarf;
mod windows;
--- /dev/null
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+/// A macro for defining `#[cfg]` if-else statements.
+///
+/// This is similar to the `if/elif` C preprocessor macro by allowing definition
+/// of a cascade of `#[cfg]` cases, emitting the implementation which matches
+/// first.
+///
+/// This allows you to conveniently provide a long list `#[cfg]`'d blocks of code
+/// without having to rewrite each clause multiple times.
+macro_rules! cfg_if {
+ ($(
+ if #[cfg($($meta:meta),*)] { $($it:item)* }
+ ) else * else {
+ $($it2:item)*
+ }) => {
+ __cfg_if_items! {
+ () ;
+ $( ( ($($meta),*) ($($it)*) ), )*
+ ( () ($($it2)*) ),
+ }
+ }
+}
+
+macro_rules! __cfg_if_items {
+ (($($not:meta,)*) ; ) => {};
+ (($($not:meta,)*) ; ( ($($m:meta),*) ($($it:item)*) ), $($rest:tt)*) => {
+ __cfg_if_apply! { cfg(all(not(any($($not),*)), $($m,)*)), $($it)* }
+ __cfg_if_items! { ($($not,)* $($m,)*) ; $($rest)* }
+ }
+}
+
+macro_rules! __cfg_if_apply {
+ ($m:meta, $($it:item)*) => {
+ $(#[$m] $it)*
+ }
+}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! Unwinding for wasm32
-//!
-//! Right now we don't support this, so this is just stubs
-
-use alloc::boxed::Box;
-use core::any::Any;
-use core::intrinsics;
-
-pub fn payload() -> *mut u8 {
- 0 as *mut u8
-}
-
-pub unsafe fn cleanup(_ptr: *mut u8) -> Box<dyn Any + Send> {
- intrinsics::abort()
-}
-
-pub unsafe fn panic(_data: Box<dyn Any + Send>) -> u32 {
- intrinsics::abort()
-}
/// An enum representing a diagnostic level.
#[unstable(feature = "proc_macro_diagnostic", issue = "38356")]
#[derive(Copy, Clone, Debug)]
+#[non_exhaustive]
pub enum Level {
/// An error.
Error,
Note,
/// A help message.
Help,
- #[doc(hidden)]
- __Nonexhaustive,
}
/// A structure representing a diagnostic message and associated children
#![feature(staged_api)]
#![feature(lang_items)]
#![feature(optin_builtin_traits)]
+#![feature(non_exhaustive)]
#![recursion_limit="256"]
}
}
+#[stable(feature = "token_stream_extend", since = "1.30.0")]
+impl Extend<TokenTree> for TokenStream {
+ fn extend<I: IntoIterator<Item = TokenTree>>(&mut self, trees: I) {
+ self.extend(trees.into_iter().map(TokenStream::from));
+ }
+}
+
+#[stable(feature = "token_stream_extend", since = "1.30.0")]
+impl Extend<TokenStream> for TokenStream {
+ fn extend<I: IntoIterator<Item = TokenStream>>(&mut self, streams: I) {
+ self.0.extend(streams.into_iter().map(|stream| stream.0));
+ }
+}
+
/// Public implementation details for the `TokenStream` type, such as iterators.
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
pub mod token_stream {
Level::Warning => errors::Level::Warning,
Level::Note => errors::Level::Note,
Level::Help => errors::Level::Help,
- Level::__Nonexhaustive => unreachable!("Level::__Nonexhaustive"),
}
}
}
backtrace = "0.3.3"
parking_lot = "0.5.5"
byteorder = { version = "1.1", features = ["i128"]}
-chalk-engine = { version = "0.6.0", default-features=false }
+chalk-engine = { version = "0.7.0", default-features=false }
rustc_fs_util = { path = "../librustc_fs_util" }
# Note that these dependencies are a lie, they're just here to get linkage to
use syntax::symbol::Symbol;
use syntax::ast::{Attribute, MetaItem, MetaItemKind};
use syntax_pos::{Span, DUMMY_SP};
-use hir;
-use hir::itemlikevisit::ItemLikeVisitor;
+use hir::intravisit::{self, NestedVisitorMap, Visitor};
use rustc_data_structures::fx::{FxHashSet, FxHashMap};
use errors::DiagnosticId;
}
}
- fn extract(&self, attrs: &[Attribute]) -> Vec<(Symbol, Option<Symbol>, Span)> {
+ fn extract(&self, attr: &Attribute) -> Option<(Symbol, Option<Symbol>, Span)> {
let stab_attrs = vec!["stable", "unstable", "rustc_const_unstable"];
- let mut features = vec![];
-
- for attr in attrs {
- // Find a stability attribute (i.e. `#[stable (..)]`, `#[unstable (..)]`,
- // `#[rustc_const_unstable (..)]`).
- if let Some(stab_attr) = stab_attrs.iter().find(|stab_attr| {
- attr.check_name(stab_attr)
- }) {
- let meta_item = attr.meta();
- if let Some(MetaItem { node: MetaItemKind::List(ref metas), .. }) = meta_item {
- let mut feature = None;
- let mut since = None;
- for meta in metas {
- if let Some(mi) = meta.meta_item() {
- // Find the `feature = ".."` meta-item.
- match (&*mi.name().as_str(), mi.value_str()) {
- ("feature", val) => feature = val,
- ("since", val) => since = val,
- _ => {}
- }
+
+ // Find a stability attribute (i.e. `#[stable (..)]`, `#[unstable (..)]`,
+ // `#[rustc_const_unstable (..)]`).
+ if let Some(stab_attr) = stab_attrs.iter().find(|stab_attr| {
+ attr.check_name(stab_attr)
+ }) {
+ let meta_item = attr.meta();
+ if let Some(MetaItem { node: MetaItemKind::List(ref metas), .. }) = meta_item {
+ let mut feature = None;
+ let mut since = None;
+ for meta in metas {
+ if let Some(mi) = meta.meta_item() {
+ // Find the `feature = ".."` meta-item.
+ match (&*mi.name().as_str(), mi.value_str()) {
+ ("feature", val) => feature = val,
+ ("since", val) => since = val,
+ _ => {}
}
}
- if let Some(feature) = feature {
- // This additional check for stability is to make sure we
- // don't emit additional, irrelevant errors for malformed
- // attributes.
- if *stab_attr != "stable" || since.is_some() {
- features.push((feature, since, attr.span));
- }
+ }
+ if let Some(feature) = feature {
+ // This additional check for stability is to make sure we
+ // don't emit additional, irrelevant errors for malformed
+ // attributes.
+ if *stab_attr != "stable" || since.is_some() {
+ return Some((feature, since, attr.span));
}
- // We need to iterate over the other attributes, because
- // `rustc_const_unstable` is not mutually exclusive with
- // the other stability attributes, so we can't just `break`
- // here.
}
+ // We need to iterate over the other attributes, because
+ // `rustc_const_unstable` is not mutually exclusive with
+ // the other stability attributes, so we can't just `break`
+ // here.
}
}
- features
+ None
}
fn collect_feature(&mut self, feature: Symbol, since: Option<Symbol>, span: Span) {
}
}
}
-
- fn collect_from_attrs(&mut self, attrs: &[Attribute]) {
- for (feature, stable, span) in self.extract(attrs) {
- self.collect_feature(feature, stable, span);
- }
- }
}
-impl<'a, 'v, 'tcx> ItemLikeVisitor<'v> for LibFeatureCollector<'a, 'tcx> {
- fn visit_item(&mut self, item: &hir::Item) {
- self.collect_from_attrs(&item.attrs);
- }
-
- fn visit_trait_item(&mut self, trait_item: &hir::TraitItem) {
- self.collect_from_attrs(&trait_item.attrs);
+impl<'a, 'tcx> Visitor<'tcx> for LibFeatureCollector<'a, 'tcx> {
+ fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
+ NestedVisitorMap::All(&self.tcx.hir)
}
- fn visit_impl_item(&mut self, impl_item: &hir::ImplItem) {
- self.collect_from_attrs(&impl_item.attrs);
+ fn visit_attribute(&mut self, attr: &'tcx Attribute) {
+ if let Some((feature, stable, span)) = self.extract(attr) {
+ self.collect_feature(feature, stable, span);
+ }
}
}
collector.collect_feature(feature, since, DUMMY_SP);
}
}
- collector.collect_from_attrs(&tcx.hir.krate().attrs);
- tcx.hir.krate().visit_all_item_likes(&mut collector);
- for exported_macro in &tcx.hir.krate().exported_macros {
- collector.collect_from_attrs(&exported_macro.attrs);
- }
+ intravisit::walk_crate(&mut collector, tcx.hir.krate());
collector.lib_features
}
/// Data must be immutable but not aliasable. This kind of borrow
/// cannot currently be expressed by the user and is used only in
- /// implicit closure bindings. It is needed when you the closure
- /// is borrowing or mutating a mutable referent, e.g.:
+ /// implicit closure bindings. It is needed when the closure is
+ /// borrowing or mutating a mutable referent, e.g.:
///
/// let x: &mut isize = ...;
/// let y = || *x += 5;
/// let y = (&mut Env { &x }, fn_ptr); // Closure is pair of env and fn
/// fn fn_ptr(env: &mut Env) { **env.x += 5; }
///
- /// This is then illegal because you cannot mutate a `&mut` found
+ /// This is then illegal because you cannot mutate an `&mut` found
/// in an aliasable location. To solve, you'd have to translate with
/// an `&mut` borrow:
///
/// (b) it gives a way to separate this case from the remaining cases
/// for diagnostics.
pub opt_match_place: Option<(Option<Place<'tcx>>, Span)>,
+ /// Span of the pattern in which this variable was bound.
+ pub pat_span: Span,
}
#[derive(Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
impl_stable_hash_for!(struct self::VarBindingForm<'tcx> {
binding_mode,
opt_ty_info,
- opt_match_place
+ opt_match_place,
+ pat_span
});
mod binding_form_impl {
/// ROOT SCOPE
/// │{ argument x: &str }
/// │
- /// │ │{ #[allow(unused_mut] } // this is actually split into 2 scopes
+ /// │ │{ #[allow(unused_mut)] } // this is actually split into 2 scopes
/// │ │ // in practice because I'm lazy.
/// │ │
/// │ │← x.source_info.scope
binding_mode: ty::BindingMode::BindByValue(_),
opt_ty_info: _,
opt_match_place: _,
+ pat_span: _,
}))) => true,
// FIXME: might be able to thread the distinction between
binding_mode: ty::BindingMode::BindByValue(_),
opt_ty_info: _,
opt_match_place: _,
+ pat_span: _,
}))) => true,
Some(ClearCrossCrate::Set(BindingForm::ImplicitSelf)) => true,
/// Drop the Place and assign the new value over it. This ensures
/// that the assignment to `P` occurs *even if* the destructor for
- /// place unwinds. Its semantics are best explained by by the
+ /// place unwinds. Its semantics are best explained by the
/// elaboration:
///
/// ```
parse_error(tcx, item.span,
"this attribute must have a valid value",
"expected value here",
- Some(r#"eg `#[rustc_on_unimplemented = "foo"]`"#));
+ Some(r#"eg `#[rustc_on_unimplemented(message="foo")]`"#));
}
if errored {
return Err(parse_error(tcx, attr.span,
"`#[rustc_on_unimplemented]` requires a value",
"value required here",
- Some(r#"eg `#[rustc_on_unimplemented = "foo"]`"#)));
+ Some(r#"eg `#[rustc_on_unimplemented(message="foo")]`"#)));
};
debug!("of_item({:?}/{:?}) = {:?}", trait_def_id, impl_def_id, result);
result
}
}
+ let options: FxHashMap<String, String> = options.into_iter()
+ .filter_map(|(k, v)| v.as_ref().map(|v| (k.to_owned(), v.to_owned())))
+ .collect();
OnUnimplementedNote {
- label: label.map(|l| l.format(tcx, trait_ref)),
- message: message.map(|m| m.format(tcx, trait_ref)),
- note: note.map(|n| n.format(tcx, trait_ref)),
+ label: label.map(|l| l.format(tcx, trait_ref, &options)),
+ message: message.map(|m| m.format(tcx, trait_ref, &options)),
+ note: note.map(|n| n.format(tcx, trait_ref, &options)),
}
}
}
Position::ArgumentNamed(s) if s == "Self" => (),
// `{ThisTraitsName}` is allowed
Position::ArgumentNamed(s) if s == name => (),
+ // `{from_method}` is allowed
+ Position::ArgumentNamed(s) if s == "from_method" => (),
+ // `{from_desugaring}` is allowed
+ Position::ArgumentNamed(s) if s == "from_desugaring" => (),
// So is `{A}` if A is a type parameter
Position::ArgumentNamed(s) => match generics.params.iter().find(|param| {
param.name == s
Some(_) => (),
None => {
span_err!(tcx.sess, span, E0230,
- "there is no parameter \
- {} on trait {}",
- s, name);
+ "there is no parameter `{}` on trait `{}`", s, name);
result = Err(ErrorReported);
}
},
// `{:1}` and `{}` are not to be used
Position::ArgumentIs(_) | Position::ArgumentImplicitlyIs(_) => {
span_err!(tcx.sess, span, E0231,
- "only named substitution \
- parameters are allowed");
+ "only named substitution parameters are allowed");
result = Err(ErrorReported);
}
}
pub fn format(&self,
tcx: TyCtxt<'a, 'gcx, 'tcx>,
- trait_ref: ty::TraitRef<'tcx>)
+ trait_ref: ty::TraitRef<'tcx>,
+ options: &FxHashMap<String, String>)
-> String
{
let name = tcx.item_name(trait_ref.def_id);
let name = param.name.to_string();
Some((name, value))
}).collect::<FxHashMap<String, String>>();
+ let empty_string = String::new();
let parser = Parser::new(&self.0, None);
parser.map(|p| {
&trait_str
}
None => {
- bug!("broken on_unimplemented {:?} for {:?}: \
- no argument matching {:?}",
- self.0, trait_ref, s)
+ if let Some(val) = options.get(s) {
+ val
+ } else if s == "from_desugaring" || s == "from_method" {
+ // don't break messages using these two arguments incorrectly
+ &empty_string
+ } else {
+ bug!("broken on_unimplemented {:?} for {:?}: \
+ no argument matching {:?}",
+ self.0, trait_ref, s)
+ }
}
},
_ => {
- bug!("broken on_unimplemented {:?} - bad \
- format arg", self.0)
+ bug!("broken on_unimplemented {:?} - bad format arg", self.0)
}
}
}
impl<'cx, 'gcx, 'tcx> Iterator for Elaborator<'cx, 'gcx, 'tcx> {
type Item = ty::Predicate<'tcx>;
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ (self.stack.len(), None)
+ }
+
fn next(&mut self) -> Option<ty::Predicate<'tcx>> {
// Extract next item from top-most stack frame, if any.
let next_predicate = match self.stack.pop() {
/// One, not zero, based LSB. That is, returns 0 for a zeroed significand.
pub(super) fn olsb(limbs: &[Limb]) -> usize {
- for (i, &limb) in limbs.iter().enumerate() {
- if limb != 0 {
- return i * LIMB_BITS + limb.trailing_zeros() as usize + 1;
- }
- }
-
- 0
+ limbs.iter().enumerate().find(|(_, &limb)| limb != 0).map_or(0,
+ |(i, limb)| i * LIMB_BITS + limb.trailing_zeros() as usize + 1)
}
/// One, not zero, based MSB. That is, returns 0 for a zeroed significand.
pub(super) fn omsb(limbs: &[Limb]) -> usize {
- for (i, &limb) in limbs.iter().enumerate().rev() {
- if limb != 0 {
- return (i + 1) * LIMB_BITS - limb.leading_zeros() as usize;
- }
- }
-
- 0
+ limbs.iter().enumerate().rfind(|(_, &limb)| limb != 0).map_or(0,
+ |(i, limb)| (i + 1) * LIMB_BITS - limb.leading_zeros() as usize)
}
/// Comparison (unsigned) of two significands.
ty::BindByReference(..) => {
let let_span = self.tcx.hir.span(node_id);
let suggestion = suggest_ref_mut(self.tcx, let_span);
- if let Some((let_span, replace_str)) = suggestion {
+ if let Some(replace_str) = suggestion {
db.span_suggestion(
let_span,
"use a mutable reference instead",
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use array_vec::ArrayVec;
use std::borrow::{Borrow, BorrowMut, ToOwned};
use std::fmt;
use std::iter;
///
/// In other words, `T` is the type used to index into the bitvector
/// this type uses to represent the set of object it holds.
+///
+/// The representation is dense, using one bit per possible element.
#[derive(Eq, PartialEq)]
pub struct IdxSetBuf<T: Idx> {
_pd: PhantomData<fn(&T)>,
}
}
+const BITS_PER_WORD: usize = mem::size_of::<Word>() * 8;
+
impl<T: Idx> fmt::Debug for IdxSetBuf<T> {
fn fmt(&self, w: &mut fmt::Formatter) -> fmt::Result {
w.debug_list()
impl<T: Idx> IdxSetBuf<T> {
fn new(init: Word, universe_size: usize) -> Self {
- let bits_per_word = mem::size_of::<Word>() * 8;
- let num_words = (universe_size + (bits_per_word - 1)) / bits_per_word;
+ let num_words = (universe_size + (BITS_PER_WORD - 1)) / BITS_PER_WORD;
IdxSetBuf {
_pd: Default::default(),
bits: vec![init; num_words],
}
}
+ /// Duplicates as a hybrid set.
+ pub fn to_hybrid(&self) -> HybridIdxSetBuf<T> {
+ // This universe_size may be slightly larger than the one specified
+ // upon creation, due to rounding up to a whole word. That's ok.
+ let universe_size = self.bits.len() * BITS_PER_WORD;
+
+ // Note: we currently don't bother trying to make a Sparse set.
+ HybridIdxSetBuf::Dense(self.to_owned(), universe_size)
+ }
+
/// Removes all elements
pub fn clear(&mut self) {
for b in &mut self.bits {
/// Clear all elements above `universe_size`.
fn trim_to(&mut self, universe_size: usize) {
- let word_bits = mem::size_of::<Word>() * 8;
-
// `trim_block` is the first block where some bits have
// to be cleared.
- let trim_block = universe_size / word_bits;
+ let trim_block = universe_size / BITS_PER_WORD;
// all the blocks above it have to be completely cleared.
if trim_block < self.bits.len() {
*b = 0;
}
- // at that block, the `universe_size % word_bits` lsbs
+ // at that block, the `universe_size % BITS_PER_WORD` lsbs
// should remain.
- let remaining_bits = universe_size % word_bits;
+ let remaining_bits = universe_size % BITS_PER_WORD;
let mask = (1<<remaining_bits)-1;
self.bits[trim_block] &= mask;
}
bitwise(self.words_mut(), other.words(), &Union)
}
+ /// Like `union()`, but takes a `SparseIdxSetBuf` argument.
+ fn union_sparse(&mut self, other: &SparseIdxSetBuf<T>) -> bool {
+ let mut changed = false;
+ for elem in other.iter() {
+ changed |= self.add(&elem);
+ }
+ changed
+ }
+
+ /// Like `union()`, but takes a `HybridIdxSetBuf` argument.
+ pub fn union_hybrid(&mut self, other: &HybridIdxSetBuf<T>) -> bool {
+ match other {
+ HybridIdxSetBuf::Sparse(sparse, _) => self.union_sparse(sparse),
+ HybridIdxSetBuf::Dense(dense, _) => self.union(dense),
+ }
+ }
+
/// Set `self = self - other` and return true if `self` changed.
/// (i.e., if any bits were removed).
pub fn subtract(&mut self, other: &IdxSet<T>) -> bool {
bitwise(self.words_mut(), other.words(), &Subtract)
}
+ /// Like `subtract()`, but takes a `SparseIdxSetBuf` argument.
+ fn subtract_sparse(&mut self, other: &SparseIdxSetBuf<T>) -> bool {
+ let mut changed = false;
+ for elem in other.iter() {
+ changed |= self.remove(&elem);
+ }
+ changed
+ }
+
+ /// Like `subtract()`, but takes a `HybridIdxSetBuf` argument.
+ pub fn subtract_hybrid(&mut self, other: &HybridIdxSetBuf<T>) -> bool {
+ match other {
+ HybridIdxSetBuf::Sparse(sparse, _) => self.subtract_sparse(sparse),
+ HybridIdxSetBuf::Dense(dense, _) => self.subtract(dense),
+ }
+ }
+
/// Set `self = self & other` and return true if `self` changed.
/// (i.e., if any bits were removed).
pub fn intersect(&mut self, other: &IdxSet<T>) -> bool {
type Item = T;
fn next(&mut self) -> Option<T> {
- let word_bits = mem::size_of::<Word>() * 8;
loop {
if let Some((ref mut word, offset)) = self.cur {
let bit_pos = word.trailing_zeros() as usize;
- if bit_pos != word_bits {
+ if bit_pos != BITS_PER_WORD {
let bit = 1 << bit_pos;
*word ^= bit;
return Some(T::new(bit_pos + offset))
}
let (i, word) = self.iter.next()?;
- self.cur = Some((*word, word_bits * i));
+ self.cur = Some((*word, BITS_PER_WORD * i));
+ }
+ }
+}
+
+const SPARSE_MAX: usize = 8;
+
+/// A sparse index set with a maximum of SPARSE_MAX elements. Used by
+/// HybridIdxSetBuf; do not use directly.
+///
+/// The elements are stored as an unsorted vector with no duplicates.
+#[derive(Clone, Debug)]
+pub struct SparseIdxSetBuf<T: Idx>(ArrayVec<[T; SPARSE_MAX]>);
+
+impl<T: Idx> SparseIdxSetBuf<T> {
+ fn new() -> Self {
+ SparseIdxSetBuf(ArrayVec::new())
+ }
+
+ fn len(&self) -> usize {
+ self.0.len()
+ }
+
+ fn contains(&self, elem: &T) -> bool {
+ self.0.contains(elem)
+ }
+
+ fn add(&mut self, elem: &T) -> bool {
+ // Ensure there are no duplicates.
+ if self.0.contains(elem) {
+ false
+ } else {
+ self.0.push(*elem);
+ true
+ }
+ }
+
+ fn remove(&mut self, elem: &T) -> bool {
+ if let Some(i) = self.0.iter().position(|e| e == elem) {
+ // Swap the found element to the end, then pop it.
+ let len = self.0.len();
+ self.0.swap(i, len - 1);
+ self.0.pop();
+ true
+ } else {
+ false
+ }
+ }
+
+ fn to_dense(&self, universe_size: usize) -> IdxSetBuf<T> {
+ let mut dense = IdxSetBuf::new_empty(universe_size);
+ for elem in self.0.iter() {
+ dense.add(elem);
+ }
+ dense
+ }
+
+ fn iter(&self) -> SparseIter<T> {
+ SparseIter {
+ iter: self.0.iter(),
+ }
+ }
+}
+
+pub struct SparseIter<'a, T: Idx> {
+ iter: slice::Iter<'a, T>,
+}
+
+impl<'a, T: Idx> Iterator for SparseIter<'a, T> {
+ type Item = T;
+
+ fn next(&mut self) -> Option<T> {
+ self.iter.next().map(|e| *e)
+ }
+}
+
+/// Like IdxSetBuf, but with a hybrid representation: sparse when there are few
+/// elements in the set, but dense when there are many. It's especially
+/// efficient for sets that typically have a small number of elements, but a
+/// large `universe_size`, and are cleared frequently.
+#[derive(Clone, Debug)]
+pub enum HybridIdxSetBuf<T: Idx> {
+ Sparse(SparseIdxSetBuf<T>, usize),
+ Dense(IdxSetBuf<T>, usize),
+}
+
+impl<T: Idx> HybridIdxSetBuf<T> {
+ pub fn new_empty(universe_size: usize) -> Self {
+ HybridIdxSetBuf::Sparse(SparseIdxSetBuf::new(), universe_size)
+ }
+
+ fn universe_size(&mut self) -> usize {
+ match *self {
+ HybridIdxSetBuf::Sparse(_, size) => size,
+ HybridIdxSetBuf::Dense(_, size) => size,
+ }
+ }
+
+ pub fn clear(&mut self) {
+ let universe_size = self.universe_size();
+ *self = HybridIdxSetBuf::new_empty(universe_size);
+ }
+
+ /// Returns true iff set `self` contains `elem`.
+ pub fn contains(&self, elem: &T) -> bool {
+ match self {
+ HybridIdxSetBuf::Sparse(sparse, _) => sparse.contains(elem),
+ HybridIdxSetBuf::Dense(dense, _) => dense.contains(elem),
+ }
+ }
+
+ /// Adds `elem` to the set `self`.
+ pub fn add(&mut self, elem: &T) -> bool {
+ match self {
+ HybridIdxSetBuf::Sparse(sparse, _) if sparse.len() < SPARSE_MAX => {
+ // The set is sparse and has space for `elem`.
+ sparse.add(elem)
+ }
+ HybridIdxSetBuf::Sparse(sparse, _) if sparse.contains(elem) => {
+ // The set is sparse and does not have space for `elem`, but
+ // that doesn't matter because `elem` is already present.
+ false
+ }
+ HybridIdxSetBuf::Sparse(_, _) => {
+ // The set is sparse and full. Convert to a dense set.
+ //
+ // FIXME: This code is awful, but I can't work out how else to
+ // appease the borrow checker.
+ let dummy = HybridIdxSetBuf::Sparse(SparseIdxSetBuf::new(), 0);
+ match mem::replace(self, dummy) {
+ HybridIdxSetBuf::Sparse(sparse, universe_size) => {
+ let mut dense = sparse.to_dense(universe_size);
+ let changed = dense.add(elem);
+ assert!(changed);
+ mem::replace(self, HybridIdxSetBuf::Dense(dense, universe_size));
+ changed
+ }
+ _ => panic!("impossible"),
+ }
+ }
+
+ HybridIdxSetBuf::Dense(dense, _) => dense.add(elem),
+ }
+ }
+
+ /// Removes `elem` from the set `self`.
+ pub fn remove(&mut self, elem: &T) -> bool {
+ // Note: we currently don't bother going from Dense back to Sparse.
+ match self {
+ HybridIdxSetBuf::Sparse(sparse, _) => sparse.remove(elem),
+ HybridIdxSetBuf::Dense(dense, _) => dense.remove(elem),
+ }
+ }
+
+ /// Converts to a dense set, consuming itself in the process.
+ pub fn to_dense(self) -> IdxSetBuf<T> {
+ match self {
+ HybridIdxSetBuf::Sparse(sparse, universe_size) => sparse.to_dense(universe_size),
+ HybridIdxSetBuf::Dense(dense, _) => dense,
+ }
+ }
+
+ /// Iteration order is unspecified.
+ pub fn iter(&self) -> HybridIter<T> {
+ match self {
+ HybridIdxSetBuf::Sparse(sparse, _) => HybridIter::Sparse(sparse.iter()),
+ HybridIdxSetBuf::Dense(dense, _) => HybridIter::Dense(dense.iter()),
+ }
+ }
+}
+
+pub enum HybridIter<'a, T: Idx> {
+ Sparse(SparseIter<'a, T>),
+ Dense(Iter<'a, T>),
+}
+
+impl<'a, T: Idx> Iterator for HybridIter<'a, T> {
+ type Item = T;
+
+ fn next(&mut self) -> Option<T> {
+ match self {
+ HybridIter::Sparse(sparse) => sparse.next(),
+ HybridIter::Dense(dense) => dense.next(),
}
}
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use rustc::hir;
+use core::unicode::property::Pattern_White_Space;
use rustc::mir::*;
use rustc::ty;
use rustc_errors::DiagnosticBuilder;
// let (&x, &y) = (&String::new(), &String::new());
#[derive(Debug)]
enum GroupedMoveError<'tcx> {
- // Match place can't be moved from
+ // Place expression can't be moved from,
// e.g. match x[0] { s => (), } where x: &[String]
- MovesFromMatchPlace {
+ MovesFromPlace {
original_path: Place<'tcx>,
span: Span,
move_from: Place<'tcx>,
kind: IllegalMoveOriginKind<'tcx>,
binds_to: Vec<Local>,
},
- // Part of a pattern can't be moved from,
+ // Part of a value expression can't be moved from,
// e.g. match &String::new() { &x => (), }
- MovesFromPattern {
+ MovesFromValue {
original_path: Place<'tcx>,
span: Span,
move_from: MovePathIndex,
opt_match_place: Some((ref opt_match_place, match_span)),
binding_mode: _,
opt_ty_info: _,
+ pat_span: _,
}))) = local_decl.is_user_variable
{
self.append_binding_error(
statement_span: Span,
) {
debug!(
- "append_to_grouped_errors(match_place={:?}, match_span={:?})",
+ "append_binding_error(match_place={:?}, match_span={:?})",
match_place, match_span
);
// Error with the match place
LookupResult::Parent(_) => {
for ge in &mut *grouped_errors {
- if let GroupedMoveError::MovesFromMatchPlace { span, binds_to, .. } = ge {
+ if let GroupedMoveError::MovesFromPlace { span, binds_to, .. } = ge {
if match_span == *span {
debug!("appending local({:?}) to list", bind_to);
if !binds_to.is_empty() {
} else {
(vec![bind_to], match_span)
};
- grouped_errors.push(GroupedMoveError::MovesFromMatchPlace {
+ grouped_errors.push(GroupedMoveError::MovesFromPlace {
span,
move_from: match_place.clone(),
original_path,
_ => unreachable!("Probably not unreachable..."),
};
for ge in &mut *grouped_errors {
- if let GroupedMoveError::MovesFromPattern {
+ if let GroupedMoveError::MovesFromValue {
span,
move_from: other_mpi,
binds_to,
}
}
debug!("found a new move error location");
- grouped_errors.push(GroupedMoveError::MovesFromPattern {
+ grouped_errors.push(GroupedMoveError::MovesFromValue {
span: match_span,
move_from: mpi,
original_path,
let (mut err, err_span) = {
let (span, original_path, kind): (Span, &Place<'tcx>, &IllegalMoveOriginKind) =
match error {
- GroupedMoveError::MovesFromMatchPlace {
+ GroupedMoveError::MovesFromPlace {
span,
ref original_path,
ref kind,
..
} |
- GroupedMoveError::MovesFromPattern { span, ref original_path, ref kind, .. } |
+ GroupedMoveError::MovesFromValue { span, ref original_path, ref kind, .. } |
GroupedMoveError::OtherIllegalMove { span, ref original_path, ref kind } => {
(span, original_path, kind)
},
err: &mut DiagnosticBuilder<'a>,
span: Span,
) {
+ let snippet = self.tcx.sess.codemap().span_to_snippet(span).unwrap();
match error {
- GroupedMoveError::MovesFromMatchPlace {
+ GroupedMoveError::MovesFromPlace {
mut binds_to,
move_from,
..
} => {
- // Ok to suggest a borrow, since the target can't be moved from
- // anyway.
- if let Ok(snippet) = self.tcx.sess.codemap().span_to_snippet(span) {
- match move_from {
- Place::Projection(ref proj)
- if self.suitable_to_remove_deref(proj, &snippet) =>
- {
- err.span_suggestion(
- span,
- "consider removing this dereference operator",
- (&snippet[1..]).to_owned(),
- );
- }
- _ => {
- err.span_suggestion(
- span,
- "consider using a reference instead",
- format!("&{}", snippet),
- );
- }
- }
-
- binds_to.sort();
- binds_to.dedup();
- for local in binds_to {
- let bind_to = &self.mir.local_decls[local];
- let binding_span = bind_to.source_info.span;
- err.span_label(
- binding_span,
- format!(
- "move occurs because {} has type `{}`, \
- which does not implement the `Copy` trait",
- bind_to.name.unwrap(),
- bind_to.ty
- ),
- );
- }
+ let try_remove_deref = match move_from {
+ Place::Projection(box PlaceProjection {
+ elem: ProjectionElem::Deref,
+ ..
+ }) => true,
+ _ => false,
+ };
+ if try_remove_deref && snippet.starts_with('*') {
+ // The snippet doesn't start with `*` in (e.g.) index
+ // expressions `a[b]`, which roughly desugar to
+ // `*Index::index(&a, b)` or
+ // `*IndexMut::index_mut(&mut a, b)`.
+ err.span_suggestion(
+ span,
+ "consider removing the `*`",
+ snippet[1..].to_owned(),
+ );
+ } else {
+ err.span_suggestion(
+ span,
+ "consider borrowing here",
+ format!("&{}", snippet),
+ );
}
+
+ binds_to.sort();
+ binds_to.dedup();
+ self.add_move_error_details(err, &binds_to);
}
- GroupedMoveError::MovesFromPattern { mut binds_to, .. } => {
- // Suggest ref, since there might be a move in
- // another match arm
+ GroupedMoveError::MovesFromValue { mut binds_to, .. } => {
binds_to.sort();
binds_to.dedup();
- let mut multipart_suggestion = Vec::with_capacity(binds_to.len());
- for (j, local) in binds_to.into_iter().enumerate() {
- let bind_to = &self.mir.local_decls[local];
- let binding_span = bind_to.source_info.span;
+ self.add_move_error_suggestions(err, &binds_to);
+ self.add_move_error_details(err, &binds_to);
+ }
+ // No binding. Nothing to suggest.
+ GroupedMoveError::OtherIllegalMove { .. } => (),
+ }
+ }
- // Suggest ref mut when the user has already written mut.
- let ref_kind = match bind_to.mutability {
- Mutability::Not => "ref",
- Mutability::Mut => "ref mut",
- };
- if j == 0 {
- err.span_label(binding_span, format!("data moved here"));
+ fn add_move_error_suggestions(
+ &self,
+ err: &mut DiagnosticBuilder<'a>,
+ binds_to: &[Local],
+ ) {
+ let mut suggestions: Vec<(Span, &str, String)> = Vec::new();
+ for local in binds_to {
+ let bind_to = &self.mir.local_decls[*local];
+ if let Some(
+ ClearCrossCrate::Set(BindingForm::Var(VarBindingForm {
+ pat_span,
+ ..
+ }))
+ ) = bind_to.is_user_variable {
+ let pat_snippet = self
+ .tcx.sess.codemap()
+ .span_to_snippet(pat_span)
+ .unwrap();
+ if pat_snippet.starts_with('&') {
+ let pat_snippet = pat_snippet[1..].trim_left();
+ let suggestion;
+ let to_remove;
+ if pat_snippet.starts_with("mut")
+ && pat_snippet["mut".len()..].starts_with(Pattern_White_Space)
+ {
+ suggestion = pat_snippet["mut".len()..].trim_left();
+ to_remove = "&mut";
} else {
- err.span_label(binding_span, format!("... and here"));
- }
- match bind_to.name {
- Some(name) => {
- multipart_suggestion.push((binding_span,
- format!("{} {}", ref_kind, name)));
- }
- None => {
- err.span_label(
- span,
- format!("Local {:?} is not suitable for ref", bind_to),
- );
- }
+ suggestion = pat_snippet;
+ to_remove = "&";
}
+ suggestions.push((
+ pat_span,
+ to_remove,
+ suggestion.to_owned(),
+ ));
}
- err.multipart_suggestion("to prevent move, use ref or ref mut",
- multipart_suggestion);
}
- // Nothing to suggest.
- GroupedMoveError::OtherIllegalMove { .. } => (),
+ }
+ suggestions.sort_unstable_by_key(|&(span, _, _)| span);
+ suggestions.dedup_by_key(|&mut (span, _, _)| span);
+ for (span, to_remove, suggestion) in suggestions {
+ err.span_suggestion(
+ span,
+ &format!("consider removing the `{}`", to_remove),
+ suggestion
+ );
}
}
- fn suitable_to_remove_deref(&self, proj: &PlaceProjection<'tcx>, snippet: &str) -> bool {
- let is_shared_ref = |ty: ty::Ty| match ty.sty {
- ty::TypeVariants::TyRef(.., hir::Mutability::MutImmutable) => true,
- _ => false,
- };
+ fn add_move_error_details(
+ &self,
+ err: &mut DiagnosticBuilder<'a>,
+ binds_to: &[Local],
+ ) {
+ let mut noncopy_var_spans = Vec::new();
+ for (j, local) in binds_to.into_iter().enumerate() {
+ let bind_to = &self.mir.local_decls[*local];
+ let binding_span = bind_to.source_info.span;
- proj.elem == ProjectionElem::Deref && snippet.starts_with('*') && match proj.base {
- Place::Local(local) => {
- let local_decl = &self.mir.local_decls[local];
- // If this is a temporary, then this could be from an
- // overloaded * operator.
- local_decl.is_user_variable.is_some() && is_shared_ref(local_decl.ty)
+ if j == 0 {
+ err.span_label(binding_span, format!("data moved here"));
+ } else {
+ err.span_label(binding_span, format!("...and here"));
}
- Place::Promoted(_) => true,
- Place::Static(ref st) => is_shared_ref(st.ty),
- Place::Projection(ref proj) => match proj.elem {
- ProjectionElem::Field(_, ty) => is_shared_ref(ty),
- _ => false,
- },
+
+ if binds_to.len() == 1 {
+ err.span_note(
+ binding_span,
+ &format!(
+ "move occurs because `{}` has type `{}`, \
+ which does not implement the `Copy` trait",
+ bind_to.name.unwrap(),
+ bind_to.ty
+ ),
+ );
+ } else {
+ noncopy_var_spans.push(binding_span);
+ }
+ }
+
+ if binds_to.len() > 1 {
+ err.span_note(
+ noncopy_var_spans,
+ "move occurs because these variables have types that \
+ don't implement the `Copy` trait",
+ );
}
}
}
ClearCrossCrate::Set(mir::BindingForm::Var(mir::VarBindingForm {
binding_mode: ty::BindingMode::BindByReference(_),
..
- })) => suggest_ref_mut(self.tcx, local_decl.source_info.span),
+ })) => {
+ let pattern_span = local_decl.source_info.span;
+ suggest_ref_mut(self.tcx, pattern_span)
+ .map(|replacement| (pattern_span, replacement))
+ }
//
ClearCrossCrate::Set(mir::BindingForm::RefForGuard) => unreachable!(),
block.unit()
}
- /// Declares the bindings of the given pattern and returns the visibility scope
- /// for the bindings in this patterns, if such a scope had to be created.
- /// NOTE: Declaring the bindings should always be done in their drop scope.
+ /// Declares the bindings of the given patterns and returns the visibility
+ /// scope for the bindings in these patterns, if such a scope had to be
+ /// created. NOTE: Declaring the bindings should always be done in their
+ /// drop scope.
pub fn declare_bindings(&mut self,
mut visibility_scope: Option<SourceScope>,
scope_span: Span,
let visibility_scope = visibility_scope.unwrap();
this.declare_binding(source_info, visibility_scope, mutability, name, mode,
num_patterns, var, ty, has_guard,
- opt_match_place.map(|(x, y)| (x.cloned(), y)));
+ opt_match_place.map(|(x, y)| (x.cloned(), y)),
+ patterns[0].span);
});
visibility_scope
}
var_id: NodeId,
var_ty: Ty<'tcx>,
has_guard: ArmHasGuard,
- opt_match_place: Option<(Option<Place<'tcx>>, Span)>)
+ opt_match_place: Option<(Option<Place<'tcx>>, Span)>,
+ pat_span: Span)
{
debug!("declare_binding(var_id={:?}, name={:?}, mode={:?}, var_ty={:?}, \
visibility_scope={:?}, source_info={:?})",
// Instead, just abandon providing diagnostic info.
opt_ty_info: None,
opt_match_place,
+ pat_span,
}))),
};
let for_arm_body = self.local_decls.push(local.clone());
binding_mode,
opt_ty_info,
opt_match_place: Some((Some(place.clone()), span)),
+ pat_span: span,
})))
};
self.var_indices.insert(var, LocalsForNode::One(local));
//! locations.
use rustc::mir::{BasicBlock, Location};
-use rustc_data_structures::indexed_set::{IdxSetBuf, Iter};
+use rustc_data_structures::indexed_set::{HybridIdxSetBuf, IdxSetBuf, Iter};
use rustc_data_structures::indexed_vec::Idx;
use dataflow::{BitDenotation, BlockSets, DataflowResults};
{
base_results: DataflowResults<BD>,
curr_state: IdxSetBuf<BD::Idx>,
- stmt_gen: IdxSetBuf<BD::Idx>,
- stmt_kill: IdxSetBuf<BD::Idx>,
+ stmt_gen: HybridIdxSetBuf<BD::Idx>,
+ stmt_kill: HybridIdxSetBuf<BD::Idx>,
}
impl<BD> FlowAtLocation<BD>
pub fn new(results: DataflowResults<BD>) -> Self {
let bits_per_block = results.sets().bits_per_block();
let curr_state = IdxSetBuf::new_empty(bits_per_block);
- let stmt_gen = IdxSetBuf::new_empty(bits_per_block);
- let stmt_kill = IdxSetBuf::new_empty(bits_per_block);
+ let stmt_gen = HybridIdxSetBuf::new_empty(bits_per_block);
+ let stmt_kill = HybridIdxSetBuf::new_empty(bits_per_block);
FlowAtLocation {
base_results: results,
curr_state: curr_state,
F: FnOnce(Iter<BD::Idx>),
{
let mut curr_state = self.curr_state.clone();
- curr_state.union(&self.stmt_gen);
- curr_state.subtract(&self.stmt_kill);
+ curr_state.union_hybrid(&self.stmt_gen);
+ curr_state.subtract_hybrid(&self.stmt_kill);
f(curr_state.iter());
}
}
}
fn apply_local_effect(&mut self, _loc: Location) {
- self.curr_state.union(&self.stmt_gen);
- self.curr_state.subtract(&self.stmt_kill);
+ self.curr_state.union_hybrid(&self.stmt_gen);
+ self.curr_state.subtract_hybrid(&self.stmt_kill);
}
}
let i = n.index();
macro_rules! dump_set_for {
- ($set:ident) => {
+ ($set:ident, $interpret:ident) => {
write!(w, "<td>")?;
let flow = self.mbcx.flow_state();
- let entry_interp = flow.interpret_set(&flow.operator,
- flow.sets.$set(i),
- &self.render_idx);
+ let entry_interp = flow.$interpret(&flow.operator,
+ flow.sets.$set(i),
+ &self.render_idx);
for e in &entry_interp {
write!(w, "{:?}<br/>", e)?;
}
write!(w, "<tr>")?;
// Entry
- dump_set_for!(on_entry_set_for);
+ dump_set_for!(on_entry_set_for, interpret_set);
// MIR statements
write!(w, "<td>")?;
write!(w, "</td>")?;
// Gen
- dump_set_for!(gen_set_for);
+ dump_set_for!(gen_set_for, interpret_hybrid_set);
// Kill
- dump_set_for!(kill_set_for);
+ dump_set_for!(kill_set_for, interpret_hybrid_set);
write!(w, "</tr>")?;
-> io::Result<()> {
let i = n.index();
- macro_rules! dump_set_for {
- ($set:ident) => {
- let flow = self.mbcx.flow_state();
- let bits_per_block = flow.sets.bits_per_block();
- let set = flow.sets.$set(i);
- write!(w, "<td>{:?}</td>",
- dot::escape_html(&bits_to_string(set.words(), bits_per_block)))?;
- }
- }
+ let flow = self.mbcx.flow_state();
+ let bits_per_block = flow.sets.bits_per_block();
write!(w, "<tr>")?;
+
// Entry
- dump_set_for!(on_entry_set_for);
+ let set = flow.sets.on_entry_set_for(i);
+ write!(w, "<td>{:?}</td>", dot::escape_html(&bits_to_string(set.words(), bits_per_block)))?;
// Terminator
write!(w, "<td>")?;
write!(w, "</td>")?;
// Gen
- dump_set_for!(gen_set_for);
+ let set = flow.sets.gen_set_for(i);
+ write!(w, "<td>{:?}</td>", dot::escape_html(&format!("{:?}", set)))?;
// Kill
- dump_set_for!(kill_set_for);
+ let set = flow.sets.kill_set_for(i);
+ write!(w, "<td>{:?}</td>", dot::escape_html(&format!("{:?}", set)))?;
write!(w, "</tr>")?;
use syntax::ast::{self, MetaItem};
-use rustc_data_structures::indexed_set::{IdxSet, IdxSetBuf};
-use rustc_data_structures::indexed_vec::Idx;
use rustc_data_structures::bitslice::{bitwise, BitwiseOperator, Word};
+use rustc_data_structures::indexed_set::{HybridIdxSetBuf, IdxSet, IdxSetBuf};
+use rustc_data_structures::indexed_vec::Idx;
use rustc_data_structures::work_queue::WorkQueue;
use rustc::ty::{self, TyCtxt};
builder: self,
};
propcx.walk_cfg(&mut temp);
-
}
fn build_sets(&mut self) {
let sets = self.builder.flow_state.sets.for_block(bb.index());
debug_assert!(in_out.words().len() == sets.on_entry.words().len());
in_out.overwrite(sets.on_entry);
- in_out.union(sets.gen_set);
- in_out.subtract(sets.kill_set);
+ in_out.union_hybrid(sets.gen_set);
+ in_out.subtract_hybrid(sets.kill_set);
}
self.builder.propagate_bits_into_graph_successors_of(
in_out, (bb, bb_data), &mut dirty_queue);
}
/// Maps each block to a set of bits
-#[derive(Debug)]
+#[derive(Clone, Debug)]
pub(crate) struct Bits<E:Idx> {
bits: IdxSetBuf<E>,
}
-impl<E:Idx> Clone for Bits<E> {
- fn clone(&self) -> Self { Bits { bits: self.bits.clone() } }
-}
-
impl<E:Idx> Bits<E> {
fn new(bits: IdxSetBuf<E>) -> Self {
Bits { bits: bits }
result: &DataflowResults<T>,
mir: &Mir<'tcx>)
-> IdxSetBuf<T::Idx> {
- let mut entry = result.sets().on_entry_set_for(loc.block.index()).to_owned();
+ let mut on_entry = result.sets().on_entry_set_for(loc.block.index()).to_owned();
+ let mut kill_set = on_entry.to_hybrid();
+ let mut gen_set = kill_set.clone();
{
let mut sets = BlockSets {
- on_entry: &mut entry.clone(),
- kill_set: &mut entry.clone(),
- gen_set: &mut entry,
+ on_entry: &mut on_entry,
+ kill_set: &mut kill_set,
+ gen_set: &mut gen_set,
};
for stmt in 0..loc.statement_index {
}
}
- entry
+ gen_set.to_dense()
}
pub struct DataflowAnalysis<'a, 'tcx: 'a, O> where O: BitDenotation
impl<O: BitDenotation> DataflowState<O> {
pub(crate) fn interpret_set<'c, P>(&self,
o: &'c O,
- words: &IdxSet<O::Idx>,
+ set: &IdxSet<O::Idx>,
render_idx: &P)
-> Vec<DebugFormatted>
where P: Fn(&O, O::Idx) -> DebugFormatted
{
- words.iter().map(|i| render_idx(o, i)).collect()
+ set.iter().map(|i| render_idx(o, i)).collect()
+ }
+
+ pub(crate) fn interpret_hybrid_set<'c, P>(&self,
+ o: &'c O,
+ set: &HybridIdxSetBuf<O::Idx>,
+ render_idx: &P)
+ -> Vec<DebugFormatted>
+ where P: Fn(&O, O::Idx) -> DebugFormatted
+ {
+ set.iter().map(|i| render_idx(o, i)).collect()
}
}
/// equal to bits_per_block / (mem::size_of::<Word> * 8), rounded up.
words_per_block: usize,
+ /// For each block, bits valid on entry to the block.
+ on_entry_sets: Bits<E>,
+
/// For each block, bits generated by executing the statements in
/// the block. (For comparison, the Terminator for each block is
/// handled in a flow-specific manner during propagation.)
- gen_sets: Bits<E>,
+ gen_sets: Vec<HybridIdxSetBuf<E>>,
/// For each block, bits killed by executing the statements in the
/// block. (For comparison, the Terminator for each block is
/// handled in a flow-specific manner during propagation.)
- kill_sets: Bits<E>,
-
- /// For each block, bits valid on entry to the block.
- on_entry_sets: Bits<E>,
+ kill_sets: Vec<HybridIdxSetBuf<E>>,
}
/// Triple of sets associated with a given block.
/// Dataflow state immediately before control flow enters the given block.
pub(crate) on_entry: &'a mut IdxSet<E>,
- /// Bits that are set to 1 by the time we exit the given block.
- pub(crate) gen_set: &'a mut IdxSet<E>,
+ /// Bits that are set to 1 by the time we exit the given block. Hybrid
+ /// because it usually contains only 0 or 1 elements.
+ pub(crate) gen_set: &'a mut HybridIdxSetBuf<E>,
- /// Bits that are set to 0 by the time we exit the given block.
- pub(crate) kill_set: &'a mut IdxSet<E>,
+ /// Bits that are set to 0 by the time we exit the given block. Hybrid
+ /// because it usually contains only 0 or 1 elements.
+ pub(crate) kill_set: &'a mut HybridIdxSetBuf<E>,
}
impl<'a, E:Idx> BlockSets<'a, E> {
}
fn apply_local_effect(&mut self) {
- self.on_entry.union(&self.gen_set);
- self.on_entry.subtract(&self.kill_set);
+ self.on_entry.union_hybrid(&self.gen_set);
+ self.on_entry.subtract_hybrid(&self.kill_set);
}
}
let range = E::new(offset)..E::new(offset + self.words_per_block);
BlockSets {
on_entry: self.on_entry_sets.bits.range_mut(&range),
- gen_set: self.gen_sets.bits.range_mut(&range),
- kill_set: self.kill_sets.bits.range_mut(&range),
+ gen_set: &mut self.gen_sets[block_idx],
+ kill_set: &mut self.kill_sets[block_idx],
}
}
- fn lookup_set_for<'a>(&self, sets: &'a Bits<E>, block_idx: usize) -> &'a IdxSet<E> {
+ pub fn on_entry_set_for(&self, block_idx: usize) -> &IdxSet<E> {
let offset = self.words_per_block * block_idx;
let range = E::new(offset)..E::new(offset + self.words_per_block);
- sets.bits.range(&range)
+ self.on_entry_sets.bits.range(&range)
}
- pub fn gen_set_for(&self, block_idx: usize) -> &IdxSet<E> {
- self.lookup_set_for(&self.gen_sets, block_idx)
+ pub fn gen_set_for(&self, block_idx: usize) -> &HybridIdxSetBuf<E> {
+ &self.gen_sets[block_idx]
}
- pub fn kill_set_for(&self, block_idx: usize) -> &IdxSet<E> {
- self.lookup_set_for(&self.kill_sets, block_idx)
- }
- pub fn on_entry_set_for(&self, block_idx: usize) -> &IdxSet<E> {
- self.lookup_set_for(&self.on_entry_sets, block_idx)
+ pub fn kill_set_for(&self, block_idx: usize) -> &HybridIdxSetBuf<E> {
+ &self.kill_sets[block_idx]
}
}
let num_blocks = mir.basic_blocks().len();
let num_overall = num_blocks * bits_per_block_rounded_up;
- let zeroes = Bits::new(IdxSetBuf::new_empty(num_overall));
let on_entry = Bits::new(if D::bottom_value() {
IdxSetBuf::new_filled(num_overall)
} else {
IdxSetBuf::new_empty(num_overall)
});
+ let empties = vec![HybridIdxSetBuf::new_empty(bits_per_block); num_blocks];
DataflowAnalysis {
mir,
sets: AllSets {
bits_per_block,
words_per_block,
- gen_sets: zeroes.clone(),
- kill_sets: zeroes,
on_entry_sets: on_entry,
+ gen_sets: empties.clone(),
+ kill_sets: empties,
},
operator: denotation,
}
#![feature(try_trait)]
#![feature(unicode_internals)]
#![feature(step_trait)]
+#![feature(slice_concat_ext)]
#![recursion_limit="256"]
}
};
- let mut entry = results.0.sets.on_entry_set_for(bb.index()).to_owned();
- let mut gen = results.0.sets.gen_set_for(bb.index()).to_owned();
- let mut kill = results.0.sets.kill_set_for(bb.index()).to_owned();
+ let mut on_entry = results.0.sets.on_entry_set_for(bb.index()).to_owned();
+ let mut gen_set = results.0.sets.gen_set_for(bb.index()).clone();
+ let mut kill_set = results.0.sets.kill_set_for(bb.index()).clone();
// Emulate effect of all statements in the block up to (but not
// including) the borrow within `peek_arg_place`. Do *not* include
// of the argument at time immediate preceding Call to
// `rustc_peek`).
- let mut sets = dataflow::BlockSets { on_entry: &mut entry,
- gen_set: &mut gen,
- kill_set: &mut kill };
+ let mut sets = dataflow::BlockSets { on_entry: &mut on_entry,
+ gen_set: &mut gen_set,
+ kill_set: &mut kill_set };
for (j, stmt) in statements.iter().enumerate() {
debug!("rustc_peek: ({:?},{}) {:?}", bb, j, stmt);
debug!("rustc_peek: computing effect on place: {:?} ({:?}) in stmt: {:?}",
place, lhs_mpi, stmt);
// reset GEN and KILL sets before emulating their effect.
- for e in sets.gen_set.words_mut() { *e = 0; }
- for e in sets.kill_set.words_mut() { *e = 0; }
+ sets.gen_set.clear();
+ sets.kill_set.clear();
results.0.operator.before_statement_effect(
&mut sets, Location { block: bb, statement_index: j });
results.0.operator.statement_effect(
&mut sets, Location { block: bb, statement_index: j });
- sets.on_entry.union(sets.gen_set);
- sets.on_entry.subtract(sets.kill_set);
+ sets.on_entry.union_hybrid(sets.gen_set);
+ sets.on_entry.subtract_hybrid(sets.kill_set);
}
results.0.operator.before_terminator_effect(
/// If possible, suggest replacing `ref` with `ref mut`.
pub fn suggest_ref_mut<'cx, 'gcx, 'tcx>(
tcx: ty::TyCtxt<'cx, 'gcx, 'tcx>,
- pattern_span: Span,
-) -> Option<(Span, String)> {
- let hi_src = tcx.sess.codemap().span_to_snippet(pattern_span).unwrap();
+ binding_span: Span,
+) -> Option<(String)> {
+ let hi_src = tcx.sess.codemap().span_to_snippet(binding_span).unwrap();
if hi_src.starts_with("ref")
&& hi_src["ref".len()..].starts_with(Pattern_White_Space)
{
let replacement = format!("ref mut{}", &hi_src["ref".len()..]);
- Some((pattern_span, replacement))
+ Some(replacement)
} else {
None
}
let ns = if is_last { opt_ns.unwrap_or(TypeNS) } else { TypeNS };
let name = ident.name;
- if i == 0 && ns == TypeNS && name == keywords::SelfValue.name() {
- let mut ctxt = ident.span.ctxt().modern();
- module = Some(ModuleOrUniformRoot::Module(
- self.resolve_self(&mut ctxt, self.current_module)));
- continue
- } else if allow_super && ns == TypeNS && name == keywords::Super.name() {
- let mut ctxt = ident.span.ctxt().modern();
- let self_module_parent = match i {
- 0 => self.resolve_self(&mut ctxt, self.current_module).parent,
- _ => match module {
- Some(ModuleOrUniformRoot::Module(module)) => module.parent,
- _ => None,
- },
- };
- if let Some(parent) = self_module_parent {
- module = Some(ModuleOrUniformRoot::Module(
- self.resolve_self(&mut ctxt, parent)));
- continue
- } else {
+ allow_super &= ns == TypeNS &&
+ (name == keywords::SelfValue.name() ||
+ name == keywords::Super.name());
+
+ if ns == TypeNS {
+ if allow_super && name == keywords::Super.name() {
+ let mut ctxt = ident.span.ctxt().modern();
+ let self_module = match i {
+ 0 => Some(self.resolve_self(&mut ctxt, self.current_module)),
+ _ => match module {
+ Some(ModuleOrUniformRoot::Module(module)) => Some(module),
+ _ => None,
+ },
+ };
+ if let Some(self_module) = self_module {
+ if let Some(parent) = self_module.parent {
+ module = Some(ModuleOrUniformRoot::Module(
+ self.resolve_self(&mut ctxt, parent)));
+ continue;
+ }
+ }
let msg = "There are too many initial `super`s.".to_string();
return PathResult::Failed(ident.span, msg, false);
}
- }
- allow_super = false;
-
- if ns == TypeNS {
if i == 0 {
+ if name == keywords::SelfValue.name() {
+ let mut ctxt = ident.span.ctxt().modern();
+ module = Some(ModuleOrUniformRoot::Module(
+ self.resolve_self(&mut ctxt, self.current_module)));
+ continue;
+ }
if name == keywords::Extern.name() ||
name == keywords::CrateRoot.name() &&
self.session.features_untracked().extern_absolute_paths &&
module = Some(ModuleOrUniformRoot::UniformRoot(name));
continue;
}
- }
- if (i == 0 && name == keywords::CrateRoot.name()) ||
- (i == 0 && name == keywords::Crate.name()) ||
- (i == 0 && name == keywords::DollarCrate.name()) ||
- (i == 1 && name == keywords::Crate.name() &&
- path[0].name == keywords::CrateRoot.name()) {
- // `::a::b`, `crate::a::b`, `::crate::a::b` or `$crate::a::b`
- module = Some(ModuleOrUniformRoot::Module(
- self.resolve_crate_root(ident)));
- continue
+ if name == keywords::CrateRoot.name() ||
+ name == keywords::Crate.name() ||
+ name == keywords::DollarCrate.name() {
+ // `::a::b`, `crate::a::b` or `$crate::a::b`
+ module = Some(ModuleOrUniformRoot::Module(
+ self.resolve_crate_root(ident)));
+ continue;
+ }
}
}
// Report special messages for path segment keywords in wrong positions.
- if name == keywords::CrateRoot.name() && i != 0 ||
- name == keywords::DollarCrate.name() && i != 0 ||
- name == keywords::SelfValue.name() && i != 0 ||
- name == keywords::SelfType.name() && i != 0 ||
- name == keywords::Super.name() && i != 0 ||
- name == keywords::Extern.name() && i != 0 ||
- // we allow crate::foo and ::crate::foo but nothing else
- name == keywords::Crate.name() && i > 1 &&
- path[0].name != keywords::CrateRoot.name() ||
- name == keywords::Crate.name() && path.len() == 1 {
+ if ident.is_path_segment_keyword() && i != 0 {
let name_str = if name == keywords::CrateRoot.name() {
"crate root".to_string()
} else {
use self::ImportDirectiveSubclass::*;
use {AmbiguityError, CrateLint, Module, ModuleOrUniformRoot, PerNS};
-use Namespace::{self, TypeNS, MacroNS, ValueNS};
+use Namespace::{self, TypeNS, MacroNS};
use {NameBinding, NameBindingKind, ToNameBinding, PathResult, PrivacyError};
use Resolver;
use {names_to_string, module_to_string};
use syntax_pos::Span;
use std::cell::{Cell, RefCell};
+use std::collections::BTreeMap;
+use std::fmt::Write;
use std::{mem, ptr};
/// Contains data for specific types of import directives.
self.finalize_resolutions_in(module);
}
+ #[derive(Default)]
+ struct UniformPathsCanaryResult {
+ module_scope: Option<Span>,
+ block_scopes: Vec<Span>,
+ }
+ // Collect all tripped `uniform_paths` canaries separately.
+ let mut uniform_paths_canaries: BTreeMap<
+ (Span, NodeId),
+ (Name, PerNS<UniformPathsCanaryResult>),
+ > = BTreeMap::new();
+
let mut errors = false;
let mut seen_spans = FxHashSet();
for i in 0 .. self.determined_imports.len() {
// For a `#![feature(uniform_paths)]` `use self::x as _` canary,
// failure is ignored, while success may cause an ambiguity error.
if import.is_uniform_paths_canary {
- let (name, result) = match import.subclass {
- SingleImport { source, ref result, .. } => {
- let type_ns = result[TypeNS].get().ok();
- let value_ns = result[ValueNS].get().ok();
- (source.name, type_ns.or(value_ns))
- }
- _ => bug!(),
- };
-
if error.is_some() {
continue;
}
- let is_explicit_self =
+ let (name, result) = match import.subclass {
+ SingleImport { source, ref result, .. } => (source.name, result),
+ _ => bug!(),
+ };
+
+ let has_explicit_self =
import.module_path.len() > 0 &&
import.module_path[0].name == keywords::SelfValue.name();
- let extern_crate_exists = self.extern_prelude.contains(&name);
- // A successful `self::x` is ambiguous with an `x` external crate.
- if is_explicit_self && !extern_crate_exists {
- continue;
- }
+ let (prev_name, canary_results) =
+ uniform_paths_canaries.entry((import.span, import.id))
+ .or_insert((name, PerNS::default()));
- errors = true;
+ // All the canaries with the same `id` should have the same `name`.
+ assert_eq!(*prev_name, name);
- let msg = format!("import from `{}` is ambiguous", name);
- let mut err = self.session.struct_span_err(import.span, &msg);
- if extern_crate_exists {
- err.span_label(import.span,
- format!("could refer to external crate `::{}`", name));
- }
- if let Some(result) = result {
- if is_explicit_self {
- err.span_label(result.span,
- format!("could also refer to `self::{}`", name));
- } else {
- err.span_label(result.span,
- format!("shadowed by block-scoped `{}`", name));
+ self.per_ns(|_, ns| {
+ if let Some(result) = result[ns].get().ok() {
+ if has_explicit_self {
+ // There should only be one `self::x` (module-scoped) canary.
+ assert_eq!(canary_results[ns].module_scope, None);
+ canary_results[ns].module_scope = Some(result.span);
+ } else {
+ canary_results[ns].block_scopes.push(result.span);
+ }
}
- }
- err.help(&format!("write `::{0}` or `self::{0}` explicitly instead", name));
- err.note("relative `use` paths enabled by `#![feature(uniform_paths)]`");
- err.emit();
+ });
} else if let Some((span, err)) = error {
errors = true;
}
}
+ for ((span, _), (name, results)) in uniform_paths_canaries {
+ self.per_ns(|this, ns| {
+ let results = &results[ns];
+
+ let has_external_crate =
+ ns == TypeNS && this.extern_prelude.contains(&name);
+
+ // An ambiguity requires more than one possible resolution.
+ let possible_resultions =
+ (has_external_crate as usize) +
+ (results.module_scope.is_some() as usize) +
+ (!results.block_scopes.is_empty() as usize);
+ if possible_resultions <= 1 {
+ return;
+ }
+
+ errors = true;
+
+ // Special-case the error when `self::x` finds its own `use x;`.
+ if has_external_crate &&
+ results.module_scope == Some(span) &&
+ results.block_scopes.is_empty() {
+ let msg = format!("`{}` import is redundant", name);
+ this.session.struct_span_err(span, &msg)
+ .span_label(span,
+ format!("refers to external crate `::{}`", name))
+ .span_label(span,
+ format!("defines `self::{}`, shadowing itself", name))
+ .help(&format!("remove or write `::{}` explicitly instead", name))
+ .note("relative `use` paths enabled by `#![feature(uniform_paths)]`")
+ .emit();
+ return;
+ }
+
+ let msg = format!("`{}` import is ambiguous", name);
+ let mut err = this.session.struct_span_err(span, &msg);
+ let mut suggestion_choices = String::new();
+ if has_external_crate {
+ write!(suggestion_choices, "`::{}`", name);
+ err.span_label(span,
+ format!("can refer to external crate `::{}`", name));
+ }
+ if let Some(span) = results.module_scope {
+ if !suggestion_choices.is_empty() {
+ suggestion_choices.push_str(" or ");
+ }
+ write!(suggestion_choices, "`self::{}`", name);
+ err.span_label(span,
+ format!("can refer to `self::{}`", name));
+ }
+ for &span in &results.block_scopes {
+ err.span_label(span,
+ format!("shadowed by block-scoped `{}`", name));
+ }
+ err.help(&format!("write {} explicitly instead", suggestion_choices));
+ err.note("relative `use` paths enabled by `#![feature(uniform_paths)]`");
+ err.emit();
+ });
+ }
+
// Report unresolved imports only if no hard error was already reported
// to avoid generating multiple errors on the same import.
if !errors {
--- /dev/null
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use spec::{LinkerFlavor, Target, TargetResult, PanicStrategy, LldFlavor};
+
+pub fn target() -> TargetResult {
+ let mut base = super::windows_msvc_base::opts();
+ base.max_atomic_width = Some(64);
+ base.has_elf_tls = true;
+
+ // FIXME: this shouldn't be panic=abort, it should be panic=unwind
+ base.panic_strategy = PanicStrategy::Abort;
+ base.linker = Some("rust-lld".to_owned());
+
+ Ok(Target {
+ llvm_target: "aarch64-pc-windows-msvc".to_string(),
+ target_endian: "little".to_string(),
+ target_pointer_width: "64".to_string(),
+ target_c_int_width: "32".to_string(),
+ data_layout: "e-m:w-p:64:64-i32:32-i64:64-i128:128-n32:64-S128".to_string(),
+ arch: "aarch64".to_string(),
+ target_os: "windows".to_string(),
+ target_env: "msvc".to_string(),
+ target_vendor: "pc".to_string(),
+ linker_flavor: LinkerFlavor::Lld(LldFlavor::Link),
+ options: base,
+ })
+}
("x86_64-pc-windows-gnu", x86_64_pc_windows_gnu),
("i686-pc-windows-gnu", i686_pc_windows_gnu),
+ ("aarch64-pc-windows-msvc", aarch64_pc_windows_msvc),
("x86_64-pc-windows-msvc", x86_64_pc_windows_msvc),
("i686-pc-windows-msvc", i686_pc_windows_msvc),
("i586-pc-windows-msvc", i586_pc_windows_msvc),
rustc_data_structures = { path = "../librustc_data_structures" }
syntax = { path = "../libsyntax" }
syntax_pos = { path = "../libsyntax_pos" }
-chalk-engine = { version = "0.6.0", default-features=false }
+chalk-engine = { version = "0.7.0", default-features=false }
let methods = self.get_conversion_methods(expr.span, expected, found);
if let Ok(expr_text) = self.sess().codemap().span_to_snippet(expr.span) {
let suggestions = iter::repeat(expr_text).zip(methods.iter())
- .map(|(receiver, method)| format!("{}.{}()", receiver, method.ident))
- .collect::<Vec<_>>();
+ .filter_map(|(receiver, method)| {
+ let method_call = format!(".{}()", method.ident);
+ if receiver.ends_with(&method_call) {
+ None // do not suggest code that is already there (#53348)
+ } else {
+ Some(format!("{}{}", receiver, method_call))
+ }
+ }) .collect::<Vec<_>>();
if !suggestions.is_empty() {
err.span_suggestions(expr.span, "try using a conversion method", suggestions);
}
Some("mmx_target_feature") => rust_features.mmx_target_feature,
Some("sse4a_target_feature") => rust_features.sse4a_target_feature,
Some("tbm_target_feature") => rust_features.tbm_target_feature,
+ Some("wasm_target_feature") => rust_features.wasm_target_feature,
Some(name) => bug!("unknown target feature gate {}", name),
None => true,
};
}
impl From<fmt::Error> for EncoderError {
+ /// Converts a [`fmt::Error`] into `EncoderError`
+ ///
+ /// This conversion does not allocate memory.
fn from(err: fmt::Error) -> EncoderError { EncoderError::FmtError(err) }
}
// Used by Parser to test whether the top-most element is an index.
fn last_is_index(&self) -> bool {
- if let Some(InternalIndex(_)) = self.stack.last() {
- true
- } else {
- false
+ match self.stack.last() {
+ Some(InternalIndex(_)) => true,
+ _ => false,
}
}
} else {
build.file("../libbacktrace/elf.c");
- if target.contains("64") {
+ let pointer_width = env::var("CARGO_CFG_TARGET_POINTER_WIDTH").unwrap();
+ if pointer_width == "64" {
build.define("BACKTRACE_ELF_SIZE", "64");
} else {
build.define("BACKTRACE_ELF_SIZE", "32");
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[stable(feature = "rust1", since = "1.0.0")]
#[allow(deprecated)]
+#[non_exhaustive]
pub enum ErrorKind {
/// An entity was not found, often a file.
#[stable(feature = "rust1", since = "1.0.0")]
/// read.
#[stable(feature = "read_exact", since = "1.6.0")]
UnexpectedEof,
-
- /// A marker variant that tells the compiler that users of this enum cannot
- /// match it exhaustively.
- #[unstable(feature = "io_error_internals",
- reason = "better expressed through extensible enums that this \
- enum cannot be exhaustively matched against",
- issue = "0")]
- #[doc(hidden)]
- __Nonexhaustive,
}
impl ErrorKind {
ErrorKind::Interrupted => "operation interrupted",
ErrorKind::Other => "other os error",
ErrorKind::UnexpectedEof => "unexpected end of file",
- ErrorKind::__Nonexhaustive => unreachable!()
}
}
}
#![feature(doc_keyword)]
#![feature(panic_info_message)]
#![feature(panic_implementation)]
+#![feature(non_exhaustive)]
#![default_lib_allocator]
/// File or memory access pattern advisory information.
#[repr(u8)]
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
+#[non_exhaustive]
pub enum advice {
/// The application expects that it will not access the
/// specified data in the near future.
/// The application expects to access the specified data
/// in the near future.
WILLNEED = 6,
- #[doc(hidden)] _NonExhaustive = -1 as isize as u8,
}
/// Enumeration describing the kind of value stored in [`auxv`](struct.auxv.html).
#[repr(u32)]
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
+#[non_exhaustive]
pub enum auxtype {
/// Base address of the binary argument data provided to
/// [`proc_exec()`](fn.proc_exec.html).
SYSINFO_EHDR = 262,
/// Thread ID of the initial thread of the process.
TID = 261,
- #[doc(hidden)] _NonExhaustive = -1 as isize as u32,
}
/// Identifiers for clocks.
#[repr(u32)]
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
+#[non_exhaustive]
pub enum clockid {
/// The system-wide monotonic clock, which is defined as a
/// clock measuring real time, whose value cannot be
REALTIME = 3,
/// The CPU-time clock associated with the current thread.
THREAD_CPUTIME_ID = 4,
- #[doc(hidden)] _NonExhaustive = -1 as isize as u32,
}
/// A userspace condition variable.
/// exclusively or merely provided for alignment with POSIX.
#[repr(u16)]
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
+#[non_exhaustive]
pub enum errno {
/// No error occurred. System call completed successfully.
SUCCESS = 0,
XDEV = 75,
/// Extension: Capabilities insufficient.
NOTCAPABLE = 76,
- #[doc(hidden)] _NonExhaustive = -1 as isize as u16,
}
bitflags! {
/// Type of a subscription to an event or its occurrence.
#[repr(u8)]
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
+#[non_exhaustive]
pub enum eventtype {
/// The time value of clock [`subscription.union.clock.clock_id`](struct.subscription_clock.html#structfield.clock_id)
/// has reached timestamp [`subscription.union.clock.timeout`](struct.subscription_clock.html#structfield.timeout).
/// The process associated with process descriptor
/// [`subscription.union.proc_terminate.fd`](struct.subscription_proc_terminate.html#structfield.fd) has terminated.
PROC_TERMINATE = 7,
- #[doc(hidden)] _NonExhaustive = -1 as isize as u8,
}
/// Exit code generated by a process when exiting.
/// The type of a file descriptor or file.
#[repr(u8)]
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
+#[non_exhaustive]
pub enum filetype {
/// The type of the file descriptor or file is unknown or
/// is different from any of the other types specified.
SOCKET_STREAM = 130,
/// The file refers to a symbolic link inode.
SYMBOLIC_LINK = 144,
- #[doc(hidden)] _NonExhaustive = -1 as isize as u8,
}
bitflags! {
/// memory.
#[repr(u8)]
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
+#[non_exhaustive]
pub enum scope {
/// The object is stored in private memory.
PRIVATE = 4,
/// The object is stored in shared memory.
SHARED = 8,
- #[doc(hidden)] _NonExhaustive = -1 as isize as u8,
}
bitflags! {
/// Signal condition.
#[repr(u8)]
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
+#[non_exhaustive]
pub enum signal {
/// Process abort signal.
///
///
/// Action: Terminates the process.
XFSZ = 26,
- #[doc(hidden)] _NonExhaustive = -1 as isize as u8,
}
bitflags! {
/// should be set.
#[repr(u8)]
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
+#[non_exhaustive]
pub enum whence {
/// Seek relative to current position.
CUR = 1,
END = 2,
/// Seek relative to start-of-file.
SET = 3,
- #[doc(hidden)] _NonExhaustive = -1 as isize as u8,
}
/// Auxiliary vector entry.
self.AddrFrame.Mode = c::ADDRESS_MODE::AddrModeFlat;
c::IMAGE_FILE_MACHINE_I386
}
+
#[cfg(target_arch = "x86_64")]
fn init(&mut self, ctx: &c::CONTEXT) -> c::DWORD {
self.AddrPC.Offset = ctx.Rip as u64;
c::IMAGE_FILE_MACHINE_AMD64
}
+ #[cfg(target_arch = "aarch64")]
+ fn init(&mut self, ctx: &c::CONTEXT) -> c::DWORD {
+ self.AddrPC.Offset = ctx.Pc as u64;
+ self.AddrPC.Mode = c::ADDRESS_MODE::AddrModeFlat;
+ self.AddrStack.Offset = ctx.Sp as u64;
+ self.AddrStack.Mode = c::ADDRESS_MODE::AddrModeFlat;
+ self.AddrFrame.Offset = ctx.Fp as u64;
+ self.AddrFrame.Mode = c::ADDRESS_MODE::AddrModeFlat;
+ c::IMAGE_FILE_MACHINE_ARM64
+ }
+
fn get_addr(&self) -> *const u8 {
(self.AddrPC.Offset - 1) as *const u8
}
self.AddrFrame.Mode = c::ADDRESS_MODE::AddrModeFlat;
c::IMAGE_FILE_MACHINE_I386
}
+
#[cfg(target_arch = "x86_64")]
fn init(&mut self, ctx: &c::CONTEXT) -> c::DWORD {
self.AddrPC.Offset = ctx.Rip as u64;
c::IMAGE_FILE_MACHINE_AMD64
}
+ #[cfg(target_arch = "aarch64")]
+ fn init(&mut self, ctx: &c::CONTEXT) -> c::DWORD {
+ self.AddrPC.Offset = ctx.Pc as u64;
+ self.AddrPC.Mode = c::ADDRESS_MODE::AddrModeFlat;
+ self.AddrStack.Offset = ctx.Sp as u64;
+ self.AddrStack.Mode = c::ADDRESS_MODE::AddrModeFlat;
+ self.AddrFrame.Offset = ctx.Fp as u64;
+ self.AddrFrame.Mode = c::ADDRESS_MODE::AddrModeFlat;
+ c::IMAGE_FILE_MACHINE_ARM64
+ }
+
fn get_addr(&self) -> *const u8 {
(self.AddrPC.Offset - 1) as *const u8
}
#[cfg(target_arch = "x86_64")]
#[cfg(feature = "backtrace")]
pub const IMAGE_FILE_MACHINE_AMD64: DWORD = 0x8664;
+#[cfg(target_arch = "aarch64")]
+#[cfg(feature = "backtrace")]
+pub const IMAGE_FILE_MACHINE_ARM64: DWORD = 0xAA64;
pub const EXCEPTION_CONTINUE_SEARCH: LONG = 0;
pub const EXCEPTION_STACK_OVERFLOW: DWORD = 0xc00000fd;
// will not appear in the final documentation. This should be also defined for
// other architectures supported by Windows such as ARM, and for historical
// interest, maybe MIPS and PowerPC as well.
-#[cfg(all(dox, not(any(target_arch = "x86_64", target_arch = "x86"))))]
+#[cfg(all(dox, not(any(target_arch = "x86_64", target_arch = "x86", target_arch = "aarch64"))))]
pub enum CONTEXT {}
+#[cfg(target_arch = "aarch64")]
+pub const ARM64_MAX_BREAKPOINTS: usize = 8;
+
+#[cfg(target_arch = "aarch64")]
+pub const ARM64_MAX_WATCHPOINTS: usize = 2;
+
+#[cfg(target_arch = "aarch64")]
+#[repr(C)]
+pub struct ARM64_NT_NEON128 {
+ pub D: [f64; 2],
+}
+
+#[cfg(target_arch = "aarch64")]
+#[repr(C, align(16))]
+pub struct CONTEXT {
+ pub ContextFlags: DWORD,
+ pub Cpsr: DWORD,
+ pub X0: u64,
+ pub X1: u64,
+ pub X2: u64,
+ pub X3: u64,
+ pub X4: u64,
+ pub X5: u64,
+ pub X6: u64,
+ pub X7: u64,
+ pub X8: u64,
+ pub X9: u64,
+ pub X10: u64,
+ pub X11: u64,
+ pub X12: u64,
+ pub X13: u64,
+ pub X14: u64,
+ pub X15: u64,
+ pub X16: u64,
+ pub X17: u64,
+ pub X18: u64,
+ pub X19: u64,
+ pub X20: u64,
+ pub X21: u64,
+ pub X22: u64,
+ pub X23: u64,
+ pub X24: u64,
+ pub X25: u64,
+ pub X26: u64,
+ pub X27: u64,
+ pub X28: u64,
+ pub Fp: u64,
+ pub Lr: u64,
+ pub Sp: u64,
+ pub Pc: u64,
+ pub V: [ARM64_NT_NEON128; 32],
+ pub Fpcr: DWORD,
+ pub Fpsr: DWORD,
+ pub Bcr: [DWORD; ARM64_MAX_BREAKPOINTS],
+ pub Bvr: [DWORD; ARM64_MAX_BREAKPOINTS],
+ pub Wcr: [DWORD; ARM64_MAX_WATCHPOINTS],
+ pub Wvr: [DWORD; ARM64_MAX_WATCHPOINTS],
+}
+
#[repr(C)]
pub struct SOCKADDR_STORAGE_LH {
pub ss_family: ADDRESS_FAMILY,
// handlers.
//
// https://msdn.microsoft.com/en-us/library/dn774154.aspx
-#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
+#[allow(unreachable_code)]
pub unsafe fn abort_internal() -> ! {
- asm!("int $$0x29" :: "{ecx}"(7) ::: volatile); // 7 is FAST_FAIL_FATAL_APP_EXIT
- ::intrinsics::unreachable();
+ #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
+ {
+ asm!("int $$0x29" :: "{ecx}"(7) ::: volatile); // 7 is FAST_FAIL_FATAL_APP_EXIT
+ ::intrinsics::unreachable();
+ }
+ ::intrinsics::abort();
}
}
impl Lit {
- fn tokens(&self) -> TokenStream {
+ crate fn tokens(&self) -> TokenStream {
TokenTree::Token(self.span, self.node.token()).into()
}
}
);
let start_span = parser.span;
- let (path, tokens) = panictry!(parser.parse_path_and_tokens());
+ let (path, tokens) = panictry!(parser.parse_meta_item_unrestricted());
let end_span = parser.span;
if parser.token != token::Eof {
parse_sess.span_diagnostic
let cfg = parser.parse_meta_item()?;
parser.expect(&token::Comma)?;
let lo = parser.span.lo();
- let (path, tokens) = parser.parse_path_and_tokens()?;
+ let (path, tokens) = parser.parse_meta_item_unrestricted()?;
parser.expect(&token::CloseDelim(token::Paren))?;
Ok((cfg, path, tokens, parser.prev_span.with_lo(lo)))
}) {
}
}
- match attr.parse_meta(self.context.parse_sess) {
- Ok(meta) => {
- // allow attr_literals in #[repr(align(x))] and #[repr(packed(n))]
- let mut allow_attr_literal = false;
- if attr.path == "repr" {
- if let Some(content) = meta.meta_item_list() {
- allow_attr_literal = content.iter().any(
- |c| c.check_name("align") || c.check_name("packed"));
+ if !self.context.features.unrestricted_attribute_tokens {
+ // Unfortunately, `parse_meta` cannot be called speculatively because it can report
+ // errors by itself, so we have to call it only if the feature is disabled.
+ match attr.parse_meta(self.context.parse_sess) {
+ Ok(meta) => {
+ // allow attr_literals in #[repr(align(x))] and #[repr(packed(n))]
+ let mut allow_attr_literal = false;
+ if attr.path == "repr" {
+ if let Some(content) = meta.meta_item_list() {
+ allow_attr_literal = content.iter().any(
+ |c| c.check_name("align") || c.check_name("packed"));
+ }
}
- }
- if !allow_attr_literal && contains_novel_literal(&meta) {
- gate_feature_post!(&self, attr_literals, attr.span,
- "non-string literals in attributes, or string \
- literals in top-level positions, are experimental");
+ if !allow_attr_literal && contains_novel_literal(&meta) {
+ gate_feature_post!(&self, attr_literals, attr.span,
+ "non-string literals in attributes, or string \
+ literals in top-level positions, are experimental");
+ }
+ }
+ Err(mut err) => {
+ err.help("try enabling `#![feature(unrestricted_attribute_tokens)]`").emit()
}
- }
- Err(mut err) => {
- err.cancel();
- gate_feature_post!(&self, unrestricted_attribute_tokens, attr.span,
- "arbitrary tokens in non-macro attributes are unstable");
}
}
}
err.emit();
}
+ // Some features are known to be incomplete and using them is likely to have
+ // unanticipated results, such as compiler crashes. We warn the user about these
+ // to alert them.
+ let incomplete_features = ["generic_associated_types"];
+
let mut features = Features::new();
let mut edition_enabled_features = FxHashMap();
continue
};
+ if incomplete_features.iter().any(|f| *f == name.as_str()) {
+ span_handler.struct_span_warn(
+ mi.span,
+ &format!(
+ "the feature `{}` is incomplete and may cause the compiler to crash",
+ name
+ )
+ ).emit();
+ }
+
if let Some(edition) = ALL_EDITIONS.iter().find(|e| name == e.feature_name()) {
if *edition <= crate_edition {
continue;
mod rc_slice;
pub use self::rc_slice::RcSlice;
+
+ mod rc_vec;
+ pub use self::rc_vec::RcVec;
}
pub mod json;
use ast;
use codemap::respan;
use parse::{SeqSep, PResult};
-use parse::token::{self, Nonterminal};
+use parse::token::{self, Nonterminal, DelimToken};
use parse::parser::{Parser, TokenType, PathStyle};
-use tokenstream::TokenStream;
+use tokenstream::{TokenStream, TokenTree};
#[derive(Debug)]
enum InnerAttributeParsePolicy<'a> {
};
self.expect(&token::OpenDelim(token::Bracket))?;
- let (path, tokens) = self.parse_path_and_tokens()?;
+ let (path, tokens) = self.parse_meta_item_unrestricted()?;
self.expect(&token::CloseDelim(token::Bracket))?;
let hi = self.prev_span;
})
}
- crate fn parse_path_and_tokens(&mut self) -> PResult<'a, (ast::Path, TokenStream)> {
+ /// Parse an inner part of attribute - path and following tokens.
+ /// The tokens must be either a delimited token stream, or empty token stream,
+ /// or the "legacy" key-value form.
+ /// PATH `(` TOKEN_STREAM `)`
+ /// PATH `[` TOKEN_STREAM `]`
+ /// PATH `{` TOKEN_STREAM `}`
+ /// PATH
+ /// PATH `=` TOKEN_TREE
+ /// The delimiters or `=` are still put into the resulting token stream.
+ crate fn parse_meta_item_unrestricted(&mut self) -> PResult<'a, (ast::Path, TokenStream)> {
let meta = match self.token {
token::Interpolated(ref nt) => match nt.0 {
Nonterminal::NtMeta(ref meta) => Some(meta.clone()),
self.bump();
(meta.ident, meta.node.tokens(meta.span))
} else {
- (self.parse_path(PathStyle::Mod)?, self.parse_tokens())
+ let path = self.parse_path(PathStyle::Mod)?;
+ let tokens = if self.check(&token::OpenDelim(DelimToken::Paren)) ||
+ self.check(&token::OpenDelim(DelimToken::Bracket)) ||
+ self.check(&token::OpenDelim(DelimToken::Brace)) {
+ self.parse_token_tree().into()
+ } else if self.eat(&token::Eq) {
+ let eq = TokenTree::Token(self.prev_span, token::Eq);
+ let tree = match self.token {
+ token::CloseDelim(_) | token::Eof => self.unexpected()?,
+ _ => self.parse_token_tree(),
+ };
+ TokenStream::concat(vec![eq.into(), tree.into()])
+ } else {
+ TokenStream::empty()
+ };
+ (path, tokens)
})
}
if !lines.is_empty() && lines[0].chars().all(|c| c == '*') {
i += 1;
}
+
while i < j && lines[i].trim().is_empty() {
i += 1;
}
.all(|c| c == '*') {
j -= 1;
}
+
while j > i && lines[j - 1].trim().is_empty() {
j -= 1;
}
+
lines[i..j].to_vec()
}
let mut i = usize::MAX;
let mut can_trim = true;
let mut first = true;
+
for line in &lines {
for (j, c) in line.chars().enumerate() {
if j > i || !"* \t".contains(c) {
}
// one-line comments lose their prefix
- const ONELINERS: &'static [&'static str] = &["///!", "///", "//!", "//"];
+ const ONELINERS: &[&str] = &["///!", "///", "//!", "//"];
+
for prefix in ONELINERS {
if comment.starts_with(*prefix) {
return (&comment[prefix.len()..]).to_string();
let len = s.len();
let mut col = col.to_usize();
let mut cursor: usize = 0;
+
while col > 0 && cursor < len {
let ch = char_at(s, cursor);
if !ch.is_whitespace() {
cursor += ch.len_utf8();
col -= 1;
}
- return Some(cursor);
+
+ Some(cursor)
}
fn trim_whitespace_prefix_and_push_line(lines: &mut Vec<String>, s: String, col: CharPos) {
"src_index={}, end_src_index={}, line_begin_pos={}",
src_index, end_src_index, rdr.filemap.line_begin_pos(rdr.pos).to_u32());
let mut n = 0;
+
while src_index < end_src_index {
let c = char_at(&rdr.src, src_index);
src_index += c.len_utf8();
n += 1;
}
+
let col = CharPos(n);
rdr.bump();
// it appears this function is called only from pprust... that's
// probably not a good thing.
pub fn gather_comments_and_literals(sess: &ParseSess, path: FileName, srdr: &mut dyn Read)
- -> (Vec<Comment>, Vec<Literal>) {
- let mut src = Vec::new();
- srdr.read_to_end(&mut src).unwrap();
- let src = String::from_utf8(src).unwrap();
+ -> (Vec<Comment>, Vec<Literal>)
+{
+ let mut src = String::new();
+ srdr.read_to_string(&mut src).unwrap();
let cm = CodeMap::new(sess.codemap().path_mapping().clone());
let filemap = cm.new_filemap(path, src);
let mut rdr = lexer::StringReader::new_raw(sess, filemap, None);
let mut literals: Vec<Literal> = Vec::new();
let mut code_to_the_left = false; // Only code
let mut anything_to_the_left = false; // Code or comments
+
while !rdr.is_eof() {
loop {
// Eat all the whitespace and count blank lines.
span_src_raw: Span,
open_braces: Vec<(token::DelimToken, Span)>,
crate override_span: Option<Span>,
+ last_unclosed_found_span: Option<Span>,
}
impl<'a> StringReader<'a> {
fn mk_sp(&self, lo: BytePos, hi: BytePos) -> Span {
self.mk_sp_and_raw(lo, hi).0
}
+
fn mk_sp_and_raw(&self, lo: BytePos, hi: BytePos) -> (Span, Span) {
let raw = Span::new(lo, hi, NO_EXPANSION);
- let real = unwrap_or!(self.override_span, raw);
+ let real = self.override_span.unwrap_or(raw);
+
(real, raw)
}
+
fn mk_ident(&self, string: &str) -> Ident {
let mut ident = Ident::from_str(string);
if let Some(span) = self.override_span {
ident.span = span;
}
+
ident
}
- fn next_token(&mut self) -> TokenAndSpan where Self: Sized {
- let res = self.try_next_token();
- self.unwrap_or_abort(res)
- }
fn unwrap_or_abort(&mut self, res: Result<TokenAndSpan, ()>) -> TokenAndSpan {
match res {
Ok(tok) => tok,
}
}
}
+
+ fn next_token(&mut self) -> TokenAndSpan where Self: Sized {
+ let res = self.try_next_token();
+ self.unwrap_or_abort(res)
+ }
+
+ /// Return the next token. EFFECT: advances the string_reader.
+ pub fn try_next_token(&mut self) -> Result<TokenAndSpan, ()> {
+ assert!(self.fatal_errs.is_empty());
+ let ret_val = TokenAndSpan {
+ tok: replace(&mut self.peek_tok, token::Whitespace),
+ sp: self.peek_span,
+ };
+ self.advance_token()?;
+ self.span_src_raw = self.peek_span_src_raw;
+
+ Ok(ret_val)
+ }
+
fn try_real_token(&mut self) -> Result<TokenAndSpan, ()> {
let mut t = self.try_next_token()?;
loop {
_ => break,
}
}
+
self.token = t.tok.clone();
self.span = t.sp;
+
Ok(t)
}
+
pub fn real_token(&mut self) -> TokenAndSpan {
let res = self.try_real_token();
self.unwrap_or_abort(res)
}
+
+ #[inline]
fn is_eof(&self) -> bool {
self.ch.is_none()
}
- /// Return the next token. EFFECT: advances the string_reader.
- pub fn try_next_token(&mut self) -> Result<TokenAndSpan, ()> {
- assert!(self.fatal_errs.is_empty());
- let ret_val = TokenAndSpan {
- tok: replace(&mut self.peek_tok, token::Whitespace),
- sp: self.peek_span,
- };
- self.advance_token()?;
- self.span_src_raw = self.peek_span_src_raw;
- Ok(ret_val)
- }
fn fail_unterminated_raw_string(&self, pos: BytePos, hash_count: u16) {
let mut err = self.struct_span_fatal(pos, pos, "unterminated raw string");
err.span_label(self.mk_sp(pos, pos), "unterminated raw string");
+
if hash_count > 0 {
err.note(&format!("this raw string should be terminated with `\"{}`",
"#".repeat(hash_count as usize)));
}
+
err.emit();
FatalError.raise();
}
fn fatal(&self, m: &str) -> FatalError {
self.fatal_span(self.peek_span, m)
}
+
pub fn emit_fatal_errors(&mut self) {
for err in &mut self.fatal_errs {
err.emit();
}
+
self.fatal_errs.clear();
}
+
pub fn peek(&self) -> TokenAndSpan {
// FIXME(pcwalton): Bad copy!
TokenAndSpan {
}
/// For comments.rs, which hackily pokes into next_pos and ch
- fn new_raw(sess: &'a ParseSess, filemap: Lrc<syntax_pos::FileMap>,
- override_span: Option<Span>) -> Self {
+ fn new_raw(sess: &'a ParseSess, filemap: Lrc<syntax_pos::FileMap>, override_span: Option<Span>)
+ -> Self
+ {
let mut sr = StringReader::new_raw_internal(sess, filemap, override_span);
sr.bump();
+
sr
}
fn new_raw_internal(sess: &'a ParseSess, filemap: Lrc<syntax_pos::FileMap>,
- override_span: Option<Span>) -> Self {
+ override_span: Option<Span>) -> Self
+ {
if filemap.src.is_none() {
sess.span_diagnostic.bug(&format!("Cannot lex filemap without source: {}",
filemap.name));
span_src_raw: syntax_pos::DUMMY_SP,
open_braces: Vec::new(),
override_span,
+ last_unclosed_found_span: None,
}
}
pub fn new(sess: &'a ParseSess, filemap: Lrc<syntax_pos::FileMap>, override_span: Option<Span>)
- -> Self {
+ -> Self
+ {
let mut sr = StringReader::new_raw(sess, filemap, override_span);
if sr.advance_token().is_err() {
sr.emit_fatal_errors();
FatalError.raise();
}
+
sr
}
sr.emit_fatal_errors();
FatalError.raise();
}
+
sr
}
+ #[inline]
fn ch_is(&self, c: char) -> bool {
self.ch == Some(c)
}
let mut m = m.to_string();
m.push_str(": ");
Self::push_escaped_char_for_msg(&mut m, c);
+
self.fatal_span_(from_pos, to_pos, &m[..])
}
- fn struct_span_fatal(&self,
- from_pos: BytePos,
- to_pos: BytePos,
- m: &str)
- -> DiagnosticBuilder<'a> {
+ fn struct_span_fatal(&self, from_pos: BytePos, to_pos: BytePos, m: &str)
+ -> DiagnosticBuilder<'a>
+ {
self.sess.span_diagnostic.struct_span_fatal(self.mk_sp(from_pos, to_pos), m)
}
- fn struct_fatal_span_char(&self,
- from_pos: BytePos,
- to_pos: BytePos,
- m: &str,
- c: char)
- -> DiagnosticBuilder<'a> {
+ fn struct_fatal_span_char(&self, from_pos: BytePos, to_pos: BytePos, m: &str, c: char)
+ -> DiagnosticBuilder<'a>
+ {
let mut m = m.to_string();
m.push_str(": ");
Self::push_escaped_char_for_msg(&mut m, c);
+
self.sess.span_diagnostic.struct_span_fatal(self.mk_sp(from_pos, to_pos), &m[..])
}
Self::push_escaped_char_for_msg(&mut m, c);
self.err_span_(from_pos, to_pos, &m[..]);
}
- fn struct_err_span_char(&self,
- from_pos: BytePos,
- to_pos: BytePos,
- m: &str,
- c: char)
- -> DiagnosticBuilder<'a> {
+
+ fn struct_err_span_char(&self, from_pos: BytePos, to_pos: BytePos, m: &str, c: char)
+ -> DiagnosticBuilder<'a>
+ {
let mut m = m.to_string();
m.push_str(": ");
Self::push_escaped_char_for_msg(&mut m, c);
+
self.sess.span_diagnostic.struct_span_err(self.mk_sp(from_pos, to_pos), &m[..])
}
fn fatal_span_verbose(&self, from_pos: BytePos, to_pos: BytePos, mut m: String) -> FatalError {
m.push_str(": ");
m.push_str(&self.src[self.src_index(from_pos)..self.src_index(to_pos)]);
+
self.fatal_span_(from_pos, to_pos, &m[..])
}
};
}
}
+
Ok(())
}
}
}
+ #[inline]
fn nextch_is(&self, c: char) -> bool {
self.nextch() == Some(c)
}
None
}
+ #[inline]
fn nextnextch_is(&self, c: char) -> bool {
self.nextnextch() == Some(c)
}
if !ident_start(self.ch) {
return None;
}
+
let start = self.pos;
self.bump();
+
while ident_continue(self.ch) {
self.bump();
}
fn scan_digits(&mut self, real_radix: u32, scan_radix: u32) -> usize {
assert!(real_radix <= scan_radix);
let mut len = 0;
+
loop {
let c = self.ch;
if c == Some('_') {
/// Lex a LIT_INTEGER or a LIT_FLOAT
fn scan_number(&mut self, c: char) -> token::Lit {
- let num_digits;
let mut base = 10;
let start_bpos = self.pos;
-
self.bump();
- if c == '0' {
+ let num_digits = if c == '0' {
match self.ch.unwrap_or('\0') {
'b' => {
self.bump();
base = 2;
- num_digits = self.scan_digits(2, 10);
+ self.scan_digits(2, 10)
}
'o' => {
self.bump();
base = 8;
- num_digits = self.scan_digits(8, 10);
+ self.scan_digits(8, 10)
}
'x' => {
self.bump();
base = 16;
- num_digits = self.scan_digits(16, 16);
+ self.scan_digits(16, 16)
}
'0'..='9' | '_' | '.' | 'e' | 'E' => {
- num_digits = self.scan_digits(10, 10) + 1;
+ self.scan_digits(10, 10) + 1
}
_ => {
// just a 0
}
}
} else if c.is_digit(10) {
- num_digits = self.scan_digits(10, 10) + 1;
+ self.scan_digits(10, 10) + 1
} else {
- num_digits = 0;
- }
+ 0
+ };
if num_digits == 0 {
- self.err_span_(start_bpos,
- self.pos,
- "no valid digits found for number");
+ self.err_span_(start_bpos, self.pos, "no valid digits found for number");
+
return token::Integer(Symbol::intern("0"));
}
}
let pos = self.pos;
self.check_float_base(start_bpos, pos, base);
+
token::Float(self.name_from(start_bpos))
} else {
// it might be a float if it has an exponent
first_source_char: char,
ascii_only: bool,
delim: char)
- -> bool {
+ -> bool
+ {
match first_source_char {
'\\' => {
// '\X' for some X must be a character constant:
"overlong unicode escape (must have at most 6 hex digits)");
valid = false;
}
+
loop {
match self.ch {
Some('}') => {
}
self.bump();
}
+
valid
}
fn scan_float_exponent(&mut self) {
if self.ch_is('e') || self.ch_is('E') {
self.bump();
+
if self.ch_is('-') || self.ch_is('+') {
self.bump();
}
+
if self.scan_digits(10, 10) == 0 {
let mut err = self.struct_span_fatal(
self.pos, self.next_pos,
('b', Some('r'), Some('#')) => (false, false),
_ => (true, false),
};
+
if is_ident_start {
let raw_start = self.pos;
if is_raw_ident {
let start = self.pos;
self.bump();
+
while ident_continue(self.ch) {
self.bump();
}
return Ok(self.with_str_from(start, |string| {
// FIXME: perform NFKC normalization here. (Issue #2253)
let ident = self.mk_ident(string);
+
if is_raw_ident && (ident.is_path_segment_keyword() ||
ident.name == keywords::Underscore.name()) {
self.fatal_span_(raw_start, self.pos,
&format!("`r#{}` is not currently supported.", ident.name)
).raise();
}
+
if is_raw_ident {
let span = self.mk_sp(raw_start, self.pos);
self.sess.raw_identifier_spans.borrow_mut().push(span);
}
+
token::Ident(ident, is_raw_ident)
}));
}
return Ok(token::Lifetime(ident));
}
- let valid = self.scan_char_or_byte(start,
- c2,
- // ascii_only =
- false,
- '\'');
+ let valid = self.scan_char_or_byte(start, c2, /* ascii_only */ false, '\'');
if !self.ch_is('\'') {
let pos = self.pos;
+
loop {
self.bump();
if self.ch_is('\'') {
break;
}
}
+
self.fatal_span_verbose(start_with_quote, pos,
String::from("character literal may only contain one codepoint")).raise();
}
} else {
Symbol::intern("0")
};
+
self.bump(); // advance ch past token
let suffix = self.scan_optional_raw_name();
+
Ok(token::Literal(token::Char(id), suffix))
}
'b' => {
_ => unreachable!(), // Should have been a token::Ident above.
};
let suffix = self.scan_optional_raw_name();
+
Ok(token::Literal(lit, suffix))
}
'"' => {
let start_bpos = self.pos;
let mut valid = true;
self.bump();
+
while !self.ch_is('"') {
if self.is_eof() {
let last_bpos = self.pos;
let ch_start = self.pos;
let ch = self.ch.unwrap();
self.bump();
- valid &= self.scan_char_or_byte(ch_start,
- ch,
- // ascii_only =
- false,
- '"');
+ valid &= self.scan_char_or_byte(ch_start, ch, /* ascii_only */ false, '"');
}
// adjust for the ASCII " at the start of the literal
let id = if valid {
};
self.bump();
let suffix = self.scan_optional_raw_name();
+
Ok(token::Literal(token::Str_(id), suffix))
}
'r' => {
}
self.bump();
}
+
self.bump();
let id = if valid {
self.name_from_to(content_start_bpos, content_end_bpos)
Symbol::intern("??")
};
let suffix = self.scan_optional_raw_name();
+
Ok(token::Literal(token::StrRaw(id, hash_count), suffix))
}
'-' => {
c);
unicode_chars::check_for_substitution(self, c, &mut err);
self.fatal_errs.push(err);
+
Err(())
}
}
val.push(self.ch.unwrap());
self.bump();
}
+
if self.ch_is('\n') {
self.bump();
}
+
val
}
Symbol::intern("?")
};
self.bump(); // advance ch past token
+
token::Byte(id)
}
+ #[inline]
fn scan_byte_escape(&mut self, delim: char, below_0x7f_only: bool) -> bool {
self.scan_hex_digits(2, delim, below_0x7f_only)
}
true,
'"');
}
+
let id = if valid {
self.name_from(start)
} else {
Symbol::intern("??")
};
self.bump();
+
token::ByteStr(id)
}
}
self.bump();
}
+
self.bump();
- token::ByteStrRaw(self.name_from_to(content_start_bpos, content_end_bpos),
- hash_count)
+
+ token::ByteStrRaw(self.name_from_to(content_start_bpos, content_end_bpos), hash_count)
}
}
// This tests the character for the unicode property 'PATTERN_WHITE_SPACE' which
// is guaranteed to be forward compatible. http://unicode.org/reports/tr31/#R3
+#[inline]
crate fn is_pattern_whitespace(c: Option<char>) -> bool {
c.map_or(false, Pattern_White_Space)
}
+#[inline]
fn in_range(c: Option<char>, lo: char, hi: char) -> bool {
- match c {
- Some(c) => lo <= c && c <= hi,
- _ => false,
- }
+ c.map_or(false, |c| lo <= c && c <= hi)
}
+#[inline]
fn is_dec_digit(c: Option<char>) -> bool {
in_range(c, '0', '9')
}
// Parse a stream of tokens into a list of `TokenTree`s, up to an `Eof`.
crate fn parse_all_token_trees(&mut self) -> PResult<'a, TokenStream> {
let mut tts = Vec::new();
+
while self.token != token::Eof {
tts.push(self.parse_token_tree()?);
}
+
Ok(TokenStream::concat(tts))
}
if let token::CloseDelim(..) = self.token {
return TokenStream::concat(tts);
}
+
match self.parse_token_tree() {
Ok(tree) => tts.push(tree),
Err(mut e) => {
for &(_, sp) in &self.open_braces {
err.span_help(sp, "did you mean to close this delimiter?");
}
+
Err(err)
},
token::OpenDelim(delim) => {
// Incorrect delimiter.
token::CloseDelim(other) => {
let token_str = token_to_string(&self.token);
- let msg = format!("incorrect close delimiter: `{}`", token_str);
- let mut err = self.sess.span_diagnostic.struct_span_err(self.span, &msg);
- // This is a conservative error: only report the last unclosed delimiter.
- // The previous unclosed delimiters could actually be closed! The parser
- // just hasn't gotten to them yet.
- if let Some(&(_, sp)) = self.open_braces.last() {
- err.span_note(sp, "unclosed delimiter");
- };
- err.emit();
-
+ if self.last_unclosed_found_span != Some(self.span) {
+ // do not complain about the same unclosed delimiter multiple times
+ self.last_unclosed_found_span = Some(self.span);
+ let msg = format!("incorrect close delimiter: `{}`", token_str);
+ let mut err = self.sess.span_diagnostic.struct_span_err(
+ self.span,
+ &msg,
+ );
+ err.span_label(self.span, "incorrect close delimiter");
+ // This is a conservative error: only report the last unclosed
+ // delimiter. The previous unclosed delimiters could actually be
+ // closed! The parser just hasn't gotten to them yet.
+ if let Some(&(_, sp)) = self.open_braces.last() {
+ err.span_label(sp, "unclosed delimiter");
+ };
+ err.emit();
+ }
self.open_braces.pop().unwrap();
// If the incorrect delimiter matches an earlier opening
// matching opening delimiter).
let token_str = token_to_string(&self.token);
let msg = format!("unexpected close delimiter: `{}`", token_str);
- let err = self.sess.span_diagnostic.struct_span_err(self.span, &msg);
+ let mut err = self.sess.span_diagnostic.struct_span_err(self.span, &msg);
+ err.span_label(self.span, "unexpected close delimiter");
Err(err)
},
_ => {
let raw = self.span_src_raw;
self.real_token();
let is_joint = raw.hi() == self.span_src_raw.lo() && token::is_op(&self.token);
+
Ok(if is_joint { tt.joint() } else { tt.into() })
}
}
use errors::DiagnosticBuilder;
use super::StringReader;
-const UNICODE_ARRAY: &'static [(char, &'static str, char)] = &[
+const UNICODE_ARRAY: &[(char, &str, char)] = &[
('
', "Line Separator", ' '),
('
', "Paragraph Separator", ' '),
(' ', "Ogham Space mark", ' '),
///
/// This method will automatically add `tok` to `expected_tokens` if `tok` is not
/// encountered.
- fn check(&mut self, tok: &token::Token) -> bool {
+ crate fn check(&mut self, tok: &token::Token) -> bool {
let is_present = self.token == *tok;
if !is_present { self.expected_tokens.push(TokenType::Token(tok.clone())); }
is_present
if !self.eat(&token::OpenDelim(token::Brace)) {
let sp = self.span;
let tok = self.this_token_to_string();
+ let mut do_not_suggest_help = false;
let mut e = self.span_fatal(sp, &format!("expected `{{`, found `{}`", tok));
+ if self.token.is_keyword(keywords::In) || self.token == token::Colon {
+ do_not_suggest_help = true;
+ e.span_label(sp, "expected `{`");
+ }
// Check to see if the user has written something like
//
// Which is valid in other languages, but not Rust.
match self.parse_stmt_without_recovery(false) {
Ok(Some(stmt)) => {
- if self.look_ahead(1, |t| t == &token::OpenDelim(token::Brace)) {
+ if self.look_ahead(1, |t| t == &token::OpenDelim(token::Brace))
+ || do_not_suggest_help {
// if the next token is an open brace (e.g., `if a b {`), the place-
// inside-a-block suggestion would be more likely wrong than right
return Err(e);
use parse::token::{self, Token};
use print::pprust;
use serialize::{Decoder, Decodable, Encoder, Encodable};
-use util::RcSlice;
+use util::RcVec;
use std::borrow::Cow;
use std::{fmt, iter, mem};
new_slice.extend_from_slice(parts.0);
new_slice.push(comma);
new_slice.extend_from_slice(parts.1);
- let slice = RcSlice::new(new_slice);
+ let slice = RcVec::new(new_slice);
return Some((TokenStream { kind: TokenStreamKind::Stream(slice) }, sp));
}
}
Empty,
Tree(TokenTree),
JointTree(TokenTree),
- Stream(RcSlice<TokenStream>),
+ Stream(RcVec<TokenStream>),
}
impl From<TokenTree> for TokenStream {
}
}
+impl Extend<TokenStream> for TokenStream {
+ fn extend<I: IntoIterator<Item = TokenStream>>(&mut self, iter: I) {
+ let iter = iter.into_iter();
+ let kind = mem::replace(&mut self.kind, TokenStreamKind::Empty);
+
+ // Vector of token streams originally in self.
+ let tts: Vec<TokenStream> = match kind {
+ TokenStreamKind::Empty => {
+ let mut vec = Vec::new();
+ vec.reserve(iter.size_hint().0);
+ vec
+ }
+ TokenStreamKind::Tree(_) | TokenStreamKind::JointTree(_) => {
+ let mut vec = Vec::new();
+ vec.reserve(1 + iter.size_hint().0);
+ vec.push(TokenStream { kind });
+ vec
+ }
+ TokenStreamKind::Stream(rc_vec) => match RcVec::try_unwrap(rc_vec) {
+ Ok(mut vec) => {
+ // Extend in place using the existing capacity if possible.
+ // This is the fast path for libraries like `quote` that
+ // build a token stream.
+ vec.reserve(iter.size_hint().0);
+ vec
+ }
+ Err(rc_vec) => {
+ // Self is shared so we need to copy and extend that.
+ let mut vec = Vec::new();
+ vec.reserve(rc_vec.len() + iter.size_hint().0);
+ vec.extend_from_slice(&rc_vec);
+ vec
+ }
+ }
+ };
+
+ // Perform the extend, joining tokens as needed along the way.
+ let mut builder = TokenStreamBuilder(tts);
+ for stream in iter {
+ builder.push(stream);
+ }
+
+ // Build the resulting token stream. If it contains more than one token,
+ // preserve capacity in the vector in anticipation of the caller
+ // performing additional calls to extend.
+ let mut tts = builder.0;
+ *self = match tts.len() {
+ 0 => TokenStream::empty(),
+ 1 => tts.pop().unwrap(),
+ _ => TokenStream::concat_rc_vec(RcVec::new_preserving_capacity(tts)),
+ };
+ }
+}
+
impl Eq for TokenStream {}
impl PartialEq<TokenStream> for TokenStream {
match streams.len() {
0 => TokenStream::empty(),
1 => streams.pop().unwrap(),
- _ => TokenStream::concat_rc_slice(RcSlice::new(streams)),
+ _ => TokenStream::concat_rc_vec(RcVec::new(streams)),
}
}
- fn concat_rc_slice(streams: RcSlice<TokenStream>) -> TokenStream {
+ fn concat_rc_vec(streams: RcVec<TokenStream>) -> TokenStream {
TokenStream { kind: TokenStreamKind::Stream(streams) }
}
match len {
1 => {}
2 => self.0.push(streams[0].clone().into()),
- _ => self.0.push(TokenStream::concat_rc_slice(streams.sub_slice(0 .. len - 1))),
+ _ => self.0.push(TokenStream::concat_rc_vec(streams.sub_slice(0 .. len - 1))),
}
self.push_all_but_last_tree(&streams[len - 1])
}
match len {
1 => {}
2 => self.0.push(streams[1].clone().into()),
- _ => self.0.push(TokenStream::concat_rc_slice(streams.sub_slice(1 .. len))),
+ _ => self.0.push(TokenStream::concat_rc_vec(streams.sub_slice(1 .. len))),
}
self.push_all_but_first_tree(&streams[0])
}
#[derive(Clone)]
struct StreamCursor {
- stream: RcSlice<TokenStream>,
+ stream: RcVec<TokenStream>,
index: usize,
- stack: Vec<(RcSlice<TokenStream>, usize)>,
+ stack: Vec<(RcVec<TokenStream>, usize)>,
}
impl StreamCursor {
- fn new(stream: RcSlice<TokenStream>) -> Self {
+ fn new(stream: RcVec<TokenStream>) -> Self {
StreamCursor { stream: stream, index: 0, stack: Vec::new() }
}
}
}
- fn insert(&mut self, stream: RcSlice<TokenStream>) {
+ fn insert(&mut self, stream: RcVec<TokenStream>) {
self.stack.push((mem::replace(&mut self.stream, stream),
mem::replace(&mut self.index, 0)));
}
CursorKind::Empty => TokenStream::empty(),
CursorKind::Tree(ref tree, _) => tree.clone().into(),
CursorKind::JointTree(ref tree, _) => tree.clone().joint(),
- CursorKind::Stream(ref cursor) => TokenStream::concat_rc_slice({
+ CursorKind::Stream(ref cursor) => TokenStream::concat_rc_vec({
cursor.stack.get(0).cloned().map(|(stream, _)| stream)
.unwrap_or(cursor.stream.clone())
}),
/// `ThinTokenStream` is smaller, but needs to allocate to represent a single `TokenTree`.
/// We must use `ThinTokenStream` in `TokenTree::Delimited` to avoid infinite size due to recursion.
#[derive(Debug, Clone)]
-pub struct ThinTokenStream(Option<RcSlice<TokenStream>>);
+pub struct ThinTokenStream(Option<RcVec<TokenStream>>);
impl From<TokenStream> for ThinTokenStream {
fn from(stream: TokenStream) -> ThinTokenStream {
ThinTokenStream(match stream.kind {
TokenStreamKind::Empty => None,
- TokenStreamKind::Tree(tree) => Some(RcSlice::new(vec![tree.into()])),
- TokenStreamKind::JointTree(tree) => Some(RcSlice::new(vec![tree.joint()])),
+ TokenStreamKind::Tree(tree) => Some(RcVec::new(vec![tree.into()])),
+ TokenStreamKind::JointTree(tree) => Some(RcVec::new(vec![tree.joint()])),
TokenStreamKind::Stream(stream) => Some(stream),
})
}
impl From<ThinTokenStream> for TokenStream {
fn from(stream: ThinTokenStream) -> TokenStream {
- stream.0.map(TokenStream::concat_rc_slice).unwrap_or_else(TokenStream::empty)
+ stream.0.map(TokenStream::concat_rc_vec).unwrap_or_else(TokenStream::empty)
}
}
assert_eq!(stream.trees().count(), 1);
}
+ #[test]
+ fn test_extend_empty() {
+ with_globals(|| {
+ // Append a token onto an empty token stream.
+ let mut stream = TokenStream::empty();
+ stream.extend(vec![string_to_ts("t")]);
+
+ let expected = string_to_ts("t");
+ assert!(stream.eq_unspanned(&expected));
+ });
+ }
+
+ #[test]
+ fn test_extend_nothing() {
+ with_globals(|| {
+ // Append nothing onto a token stream containing one token.
+ let mut stream = string_to_ts("t");
+ stream.extend(vec![]);
+
+ let expected = string_to_ts("t");
+ assert!(stream.eq_unspanned(&expected));
+ });
+ }
+
+ #[test]
+ fn test_extend_single() {
+ with_globals(|| {
+ // Append a token onto token stream containing a single token.
+ let mut stream = string_to_ts("t1");
+ stream.extend(vec![string_to_ts("t2")]);
+
+ let expected = string_to_ts("t1 t2");
+ assert!(stream.eq_unspanned(&expected));
+ });
+ }
+
+ #[test]
+ fn test_extend_in_place() {
+ with_globals(|| {
+ // Append a token onto token stream containing a reference counted
+ // vec of tokens. The token stream has a reference count of 1 so
+ // this can happen in place.
+ let mut stream = string_to_ts("t1 t2");
+ stream.extend(vec![string_to_ts("t3")]);
+
+ let expected = string_to_ts("t1 t2 t3");
+ assert!(stream.eq_unspanned(&expected));
+ });
+ }
+
+ #[test]
+ fn test_extend_copy() {
+ with_globals(|| {
+ // Append a token onto token stream containing a reference counted
+ // vec of tokens. The token stream is shared so the extend takes
+ // place on a copy.
+ let mut stream = string_to_ts("t1 t2");
+ let _incref = stream.clone();
+ stream.extend(vec![string_to_ts("t3")]);
+
+ let expected = string_to_ts("t1 t2 t3");
+ assert!(stream.eq_unspanned(&expected));
+ });
+ }
+
+ #[test]
+ fn test_extend_no_join() {
+ with_globals(|| {
+ let first = TokenTree::Token(DUMMY_SP, Token::Dot);
+ let second = TokenTree::Token(DUMMY_SP, Token::Dot);
+
+ // Append a dot onto a token stream containing a dot, but do not
+ // join them.
+ let mut stream = TokenStream::from(first);
+ stream.extend(vec![TokenStream::from(second)]);
+
+ let expected = string_to_ts(". .");
+ assert!(stream.eq_unspanned(&expected));
+
+ let unexpected = string_to_ts("..");
+ assert!(!stream.eq_unspanned(&unexpected));
+ });
+ }
+
+ #[test]
+ fn test_extend_join() {
+ with_globals(|| {
+ let first = TokenTree::Token(DUMMY_SP, Token::Dot).joint();
+ let second = TokenTree::Token(DUMMY_SP, Token::Dot);
+
+ // Append a dot onto a token stream containing a dot, forming a
+ // dotdot.
+ let mut stream = first;
+ stream.extend(vec![TokenStream::from(second)]);
+
+ let expected = string_to_ts("..");
+ assert!(stream.eq_unspanned(&expected));
+
+ let unexpected = string_to_ts(". .");
+ assert!(!stream.eq_unspanned(&unexpected));
+ });
+ }
}
--- /dev/null
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::fmt;
+use std::ops::{Deref, Range};
+
+use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableHasherResult};
+use rustc_data_structures::sync::Lrc;
+
+#[derive(Clone)]
+pub struct RcVec<T> {
+ data: Lrc<Vec<T>>,
+ offset: u32,
+ len: u32,
+}
+
+impl<T> RcVec<T> {
+ pub fn new(mut vec: Vec<T>) -> Self {
+ // By default, constructing RcVec from Vec gives it just enough capacity
+ // to hold the initial elements. Callers that anticipate needing to
+ // extend the vector may prefer RcVec::new_preserving_capacity.
+ vec.shrink_to_fit();
+ Self::new_preserving_capacity(vec)
+ }
+
+ pub fn new_preserving_capacity(vec: Vec<T>) -> Self {
+ RcVec {
+ offset: 0,
+ len: vec.len() as u32,
+ data: Lrc::new(vec),
+ }
+ }
+
+ pub fn sub_slice(&self, range: Range<usize>) -> Self {
+ RcVec {
+ data: self.data.clone(),
+ offset: self.offset + range.start as u32,
+ len: (range.end - range.start) as u32,
+ }
+ }
+
+ /// If this RcVec has exactly one strong reference, returns ownership of the
+ /// underlying vector. Otherwise returns self unmodified.
+ pub fn try_unwrap(self) -> Result<Vec<T>, Self> {
+ match Lrc::try_unwrap(self.data) {
+ // If no other RcVec shares ownership of this data.
+ Ok(mut vec) => {
+ // Drop any elements after our view of the data.
+ vec.truncate(self.offset as usize + self.len as usize);
+ // Drop any elements before our view of the data. Do this after
+ // the `truncate` so that elements past the end of our view do
+ // not need to be copied around.
+ vec.drain(..self.offset as usize);
+ Ok(vec)
+ }
+
+ // If the data is shared.
+ Err(data) => Err(RcVec { data, ..self }),
+ }
+ }
+}
+
+impl<T> Deref for RcVec<T> {
+ type Target = [T];
+ fn deref(&self) -> &[T] {
+ &self.data[self.offset as usize..(self.offset + self.len) as usize]
+ }
+}
+
+impl<T: fmt::Debug> fmt::Debug for RcVec<T> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ fmt::Debug::fmt(self.deref(), f)
+ }
+}
+
+impl<CTX, T> HashStable<CTX> for RcVec<T>
+where
+ T: HashStable<CTX>,
+{
+ fn hash_stable<W: StableHasherResult>(&self, hcx: &mut CTX, hasher: &mut StableHasher<W>) {
+ (**self).hash_stable(hcx, hasher);
+ }
+}
}
}
StaticEnum(..) => {
- span_err_if_not_stage0!(cx, trait_span, E0665,
- "`Default` cannot be derived for enums, only structs");
+ span_err!(cx, trait_span, E0665,
+ "`Default` cannot be derived for enums, only structs");
// let compilation continue
cx.expr_usize(trait_span, 0)
}
use syntax::symbol::Symbol;
use syntax_pos::Span;
-macro_rules! span_err_if_not_stage0 {
- ($cx:expr, $sp:expr, $code:ident, $text:tt) => {
- #[cfg(not(stage0))] {
- span_err!($cx, $sp, $code, $text)
- }
- #[cfg(stage0)] {
- $cx.span_err($sp, $text)
- }
- }
-}
-
macro path_local($x:ident) {
generic::ty::Path::new_local(stringify!($x))
}
#![feature(plugin)]
#![plugin(macro_crate_test)]
-#[noop_attribute"x"] //~ ERROR expected one of
-fn night() { }
-
-#[noop_attribute("hi"), rank = 2] //~ ERROR unexpected token
+#[noop_attribute("hi", rank = a)] //~ ERROR expected unsuffixed literal or identifier, found a
fn knight() { }
#[noop_attribute("/user", data= = "<user")] //~ ERROR literal or identifier
#[C] //~ ERROR: The attribute `C` is currently unknown to the compiler
#[B(D)]
#[B(E = "foo")]
-#[B arbitrary tokens] //~ ERROR arbitrary tokens in non-macro attributes are unstable
+#[B(arbitrary tokens)] //~ ERROR expected one of `(`, `)`, `,`, `::`, or `=`, found `tokens`
struct B;
fn main() {}
#[a = y] //~ ERROR: must only be followed by a delimiter token
fn _test3() {}
-#[a = ] //~ ERROR: must only be followed by a delimiter token
-fn _test4() {}
-
-#[a () = ] //~ ERROR: must only be followed by a delimiter token
-fn _test5() {}
-
fn attrs() {
// Statement, item
#[a] // OK
// gdb-command: print btree_set
// gdb-check:$1 = BTreeSet<i32>(len: 3) = {3, 5, 7}
+// gdb-command: print btree_map
+// gdb-check:$2 = BTreeMap<i32, i32>(len: 3) = {[3] = 3, [5] = 7, [7] = 4}
+
// gdb-command: print vec_deque
-// gdb-check:$2 = VecDeque<i32>(len: 3, cap: 8) = {5, 3, 7}
+// gdb-check:$3 = VecDeque<i32>(len: 3, cap: 8) = {5, 3, 7}
#![allow(unused_variables)]
use std::collections::BTreeSet;
+use std::collections::BTreeMap;
use std::collections::VecDeque;
btree_set.insert(3);
btree_set.insert(7);
+ // BTreeMap
+ let mut btree_map = BTreeMap::new();
+ btree_map.insert(5, 7);
+ btree_map.insert(3, 3);
+ btree_map.insert(7, 4);
+
// VecDeque
let mut vec_deque = VecDeque::new();
vec_deque.push_back(5);
--- /dev/null
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#[path =] //~ ERROR unexpected token: `]`
+mod m {}
--- /dev/null
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#[path() token] //~ ERROR expected `]`, found `token`
+mod m {}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// asterisk is bogus
-#[path*] //~ ERROR arbitrary tokens in non-macro attributes are unstable
+#![feature(unrestricted_attribute_tokens)]
+
+#[path*] //~ ERROR expected one of `(`, `::`, `=`, `[`, `]`, or `{`, found `*`
mod m {}
+++ /dev/null
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// compile-flags: -Z parse-only
-
-struct Obj { //~ NOTE: unclosed delimiter
- member: usize
-) //~ ERROR: incorrect close delimiter
--- /dev/null
+#!/bin/bash -x
+
+# Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+# file at the top-level directory of this distribution and at
+# http://rust-lang.org/COPYRIGHT.
+#
+# Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+# http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+# <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+# option. This file may not be copied, modified, or distributed
+# except according to those terms.
+
+# Usage: $0 project_name url sha1
+# Get the crate with the specified sha1.
+#
+# all arguments are required.
+#
+# See below link for git usage:
+# https://stackoverflow.com/questions/3489173#14091182
+
+# Mandatory arguments:
+PROJECT_NAME=$1
+URL=$2
+SHA1=$3
+
+function err_exit() {
+ echo "ERROR:" $*
+ exit 1
+}
+
+git clone $URL $PROJECT_NAME || err_exit
+cd $PROJECT_NAME || err_exit
+git reset --hard $SHA1 || err_exit
--- /dev/null
+-include ../../run-make-fulldeps/tools.mk
+
+# How to run this
+# $ ./x.py clean
+# $ ./x.py test --target thumbv6m-none-eabi,thumbv7m-none-eabi src/test/run-make
+
+# Supported targets:
+# - thumbv6m-none-eabi (Bare Cortex-M0, M0+, M1)
+# - thumbv7em-none-eabi (Bare Cortex-M4, M7)
+# - thumbv7em-none-eabihf (Bare Cortex-M4F, M7F, FPU, hardfloat)
+# - thumbv7m-none-eabi (Bare Cortex-M3)
+
+# See https://stackoverflow.com/questions/7656425/makefile-ifeq-logical-or
+ifneq (,$(filter $(TARGET),thumbv6m-none-eabi thumbv7em-none-eabi thumbv7em-none-eabihf thumbv7m-none-eabi))
+
+# For cargo setting
+RUSTC := $(RUSTC_ORIGINAL)
+LD_LIBRARY_PATH := $(HOST_RPATH_DIR)
+# We need to be outside of 'src' dir in order to run cargo
+WORK_DIR := $(TMPDIR)
+
+HERE := $(shell pwd)
+
+CRATE := cortex-m
+CRATE_URL := https://github.com/rust-embedded/cortex-m
+CRATE_SHA1 := a448e9156e2cb1e556e5441fd65426952ef4b927 # 0.5.0
+
+all:
+ env
+ mkdir -p $(WORK_DIR)
+ -cd $(WORK_DIR) && rm -rf $(CRATE)
+ cd $(WORK_DIR) && bash -x $(HERE)/../git_clone_sha1.sh $(CRATE) $(CRATE_URL) $(CRATE_SHA1)
+ cd $(WORK_DIR) && cd $(CRATE) && $(CARGO) build --target $(TARGET) -v
+else
+
+all:
+
+endif
#[proc_macro_derive(B, attributes(B, C))]
pub fn derive(input: TokenStream) -> TokenStream {
let input = input.to_string();
- assert!(input.contains("#[B arbitrary tokens]"));
+ assert!(input.contains("#[B [ arbitrary tokens ]]"));
assert!(input.contains("struct B {"));
assert!(input.contains("#[C]"));
"".parse().unwrap()
extern crate derive_b;
#[derive(Debug, PartialEq, derive_b::B, Eq, Copy, Clone)]
-#[cfg_attr(all(), B arbitrary tokens)]
+#[cfg_attr(all(), B[arbitrary tokens])]
struct B {
#[C]
a: u64
use crate as root;
pub fn check() {
assert_eq!(f(), 1);
- assert_eq!(::crate::m::g(), 2);
+ assert_eq!(crate::m::g(), 2);
assert_eq!(root::m::h(), 3);
}
}
fn main() {
assert_eq!(f(), 1);
- assert_eq!(::crate::m::g(), 2);
+ assert_eq!(crate::m::g(), 2);
assert_eq!(root::m::h(), 3);
n::check();
}
mod m {
pub struct Z;
pub struct S1(crate (::m::Z)); // OK
- pub struct S2(::crate ::m::Z); // OK
+ pub struct S2((crate ::m::Z)); // OK
pub struct S3(crate ::m::Z); // OK
+ pub struct S4(crate crate::m::Z); // OK
}
fn main() {
// edition:2018
-#![feature(uniform_paths)]
+#![feature(decl_macro, uniform_paths)]
// This test is similar to `basic.rs`, but nested in modules.
// item, e.g. the automatically injected `extern crate std;`, which in
// the Rust 2018 should no longer be visible through `crate::std`.
pub use std::io;
+
+ // Also test that items named `std` in other namespaces don't
+ // cause ambiguity errors for the import from `std` above.
+ pub fn std() {}
+ pub macro std() {}
}
foo::local_io(());
io::stdout();
bar::io::stdout();
+ bar::std();
+ bar::std!();
}
--> $DIR/invalid-punct-ident-4.rs:16:1
|
LL | lexer_failure!(); //~ ERROR proc macro panicked
- | ^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^^ unexpected close delimiter
error: proc macro panicked
--> $DIR/invalid-punct-ident-4.rs:16:1
use foo::foo;
#[ foo ( let y: u32 = "z"; ) ] //~ ERROR: mismatched types
-#[ bar let x: u32 = "y"; ] //~ ERROR: mismatched types
+#[ bar { let x: u32 = "y"; } ] //~ ERROR: mismatched types
fn main() {
}
found type `&'static str`
error[E0308]: mismatched types
- --> $DIR/attribute-spans-preserved.rs:20:21
+ --> $DIR/attribute-spans-preserved.rs:20:23
|
-LL | #[ bar let x: u32 = "y"; ] //~ ERROR: mismatched types
- | ^^^ expected u32, found reference
+LL | #[ bar { let x: u32 = "y"; } ] //~ ERROR: mismatched types
+ | ^^^ expected u32, found reference
|
= note: expected type `u32`
found type `&'static str`
-fn main ( ) { let y : u32 = "z" ; let x : u32 = "y" ; }
+fn main ( ) { let y : u32 = "z" ; { let x : u32 = "y" ; } }
--- /dev/null
+error[E0508]: cannot move out of type `[NonCopy; 1]`, a non-copy array
+ --> $DIR/E0508-fail.rs:18:18
+ |
+LL | let _value = array[0]; //[ast]~ ERROR [E0508]
+ | ^^^^^^^^
+ | |
+ | cannot move out of here
+ | help: consider borrowing here: `&array[0]`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0508`.
| ^^^^^^^^
| |
| cannot move out of here
- | help: consider using a reference instead: `&array[0]`
+ | help: consider borrowing here: `&array[0]`
error: aborting due to previous error
--- /dev/null
+error[E0508]: cannot move out of type `[NonCopy; 1]`, a non-copy array
+ --> $DIR/E0508.rs:15:18
+ |
+LL | let _value = array[0]; //~ ERROR [E0508]
+ | ^^^^^^^^
+ | |
+ | cannot move out of here
+ | help: consider borrowing here: `&array[0]`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0508`.
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// ignore-stage1
-
#![feature(asm)]
fn main() {
error[E0660]: malformed inline assembly
- --> $DIR/E0660.rs:17:5
+ --> $DIR/E0660.rs:15:5
|
LL | asm!("nop" "nop");
| ^^^^^^^^^^^^^^^^^^
error[E0660]: malformed inline assembly
- --> $DIR/E0660.rs:19:5
+ --> $DIR/E0660.rs:17:5
|
LL | asm!("nop" "nop" : "=r"(a));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// ignore-stage1
-
#![feature(asm)]
fn main() {
error[E0661]: output operand constraint lacks '=' or '+'
- --> $DIR/E0661.rs:17:18
+ --> $DIR/E0661.rs:15:18
|
LL | asm!("nop" : "r"(a));
| ^^^
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// ignore-stage1
-
#![feature(asm)]
fn main() {
error[E0662]: input operand constraint contains '='
- --> $DIR/E0662.rs:18:12
+ --> $DIR/E0662.rs:16:12
|
LL | : "=test"("a") //~ ERROR E0662
| ^^^^^^^
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// ignore-stage1
-
#![feature(asm)]
fn main() {
error[E0663]: input operand constraint contains '+'
- --> $DIR/E0663.rs:18:12
+ --> $DIR/E0663.rs:16:12
|
LL | : "+test"("a") //~ ERROR E0663
| ^^^^^^^
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// ignore-stage1
-
#![feature(asm)]
fn main() {
error[E0664]: clobber should not be surrounded by braces
- --> $DIR/E0664.rs:19:12
+ --> $DIR/E0664.rs:17:12
|
LL | : "{eax}" //~ ERROR E0664
| ^^^^^^^
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// ignore-stage1
-
#[derive(Default)] //~ ERROR E0665
enum Food {
Sweet,
error[E0665]: `Default` cannot be derived for enums, only structs
- --> $DIR/E0665.rs:13:10
+ --> $DIR/E0665.rs:11:10
|
LL | #[derive(Default)] //~ ERROR E0665
| ^^^^^^^
--> $DIR/access-mode-in-closures.rs:19:15
|
LL | match *s { sty(v) => v } //~ ERROR cannot move out
- | ^^ - move occurs because v has type `std::vec::Vec<isize>`, which does not implement the `Copy` trait
+ | ^^ - data moved here
| |
| cannot move out of borrowed content
- | help: consider removing this dereference operator: `s`
+ | help: consider removing the `*`: `s`
+ |
+note: move occurs because `v` has type `std::vec::Vec<isize>`, which does not implement the `Copy` trait
+ --> $DIR/access-mode-in-closures.rs:19:24
+ |
+LL | match *s { sty(v) => v } //~ ERROR cannot move out
+ | ^
error: aborting due to previous error
--- /dev/null
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-pass
+
+#![feature(custom_attribute, unrestricted_attribute_tokens)]
+
+#[my_attr = !] // OK under feature gate
+fn main() {}
--- /dev/null
+error[E0499]: cannot borrow `x` as mutable more than once at a time
+ --> $DIR/borrowck-closures-two-mut-fail.rs:26:24
+ |
+LL | let c1 = to_fn_mut(|| x = 4);
+ | -- - first borrow occurs due to use of `x` in closure
+ | |
+ | first mutable borrow occurs here
+LL | let c2 = to_fn_mut(|| x = 5); //~ ERROR cannot borrow `x` as mutable more than once
+ | ^^ - second borrow occurs due to use of `x` in closure
+ | |
+ | second mutable borrow occurs here
+LL | c1;
+ | -- borrow later used here
+
+error[E0499]: cannot borrow `x` as mutable more than once at a time
+ --> $DIR/borrowck-closures-two-mut-fail.rs:37:24
+ |
+LL | let c1 = to_fn_mut(|| set(&mut x));
+ | -- - first borrow occurs due to use of `x` in closure
+ | |
+ | first mutable borrow occurs here
+LL | let c2 = to_fn_mut(|| set(&mut x)); //~ ERROR cannot borrow `x` as mutable more than once
+ | ^^ - second borrow occurs due to use of `x` in closure
+ | |
+ | second mutable borrow occurs here
+LL | c1;
+ | -- borrow later used here
+
+error[E0499]: cannot borrow `x` as mutable more than once at a time
+ --> $DIR/borrowck-closures-two-mut-fail.rs:44:24
+ |
+LL | let c1 = to_fn_mut(|| x = 5);
+ | -- - first borrow occurs due to use of `x` in closure
+ | |
+ | first mutable borrow occurs here
+LL | let c2 = to_fn_mut(|| set(&mut x)); //~ ERROR cannot borrow `x` as mutable more than once
+ | ^^ - second borrow occurs due to use of `x` in closure
+ | |
+ | second mutable borrow occurs here
+LL | c1;
+ | -- borrow later used here
+
+error[E0499]: cannot borrow `x` as mutable more than once at a time
+ --> $DIR/borrowck-closures-two-mut-fail.rs:51:24
+ |
+LL | let c1 = to_fn_mut(|| x = 5);
+ | -- - first borrow occurs due to use of `x` in closure
+ | |
+ | first mutable borrow occurs here
+LL | let c2 = to_fn_mut(|| { let _y = to_fn_mut(|| set(&mut x)); }); // (nested closure)
+ | ^^ - second borrow occurs due to use of `x` in closure
+ | |
+ | second mutable borrow occurs here
+LL | //~^ ERROR cannot borrow `x` as mutable more than once
+LL | c1;
+ | -- borrow later used here
+
+error[E0499]: cannot borrow `x` as mutable more than once at a time
+ --> $DIR/borrowck-closures-two-mut-fail.rs:63:24
+ |
+LL | let c1 = to_fn_mut(|| set(&mut *x.f));
+ | -- - first borrow occurs due to use of `x` in closure
+ | |
+ | first mutable borrow occurs here
+LL | let c2 = to_fn_mut(|| set(&mut *x.f));
+ | ^^ - second borrow occurs due to use of `x` in closure
+ | |
+ | second mutable borrow occurs here
+LL | //~^ ERROR cannot borrow `x` as mutable more than once
+LL | c1;
+ | -- borrow later used here
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0499`.
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// ignore-compare-mode-nll
-
// Tests that two closures cannot simultaneously have mutable
// access to the variable, whether that mutable access be used
// for direct assignment or for taking mutable ref. Issue #6801.
-// ignore-compare-mode-nll
-
#![feature(box_syntax)]
+
+
+
+
fn to_fn_mut<F: FnMut()>(f: F) -> F { f }
fn a() {
let mut x = 3;
let c1 = to_fn_mut(|| x = 4);
let c2 = to_fn_mut(|| x = 5); //~ ERROR cannot borrow `x` as mutable more than once
+ c1;
}
fn set(x: &mut isize) {
let mut x = 3;
let c1 = to_fn_mut(|| set(&mut x));
let c2 = to_fn_mut(|| set(&mut x)); //~ ERROR cannot borrow `x` as mutable more than once
+ c1;
}
fn c() {
let mut x = 3;
let c1 = to_fn_mut(|| x = 5);
let c2 = to_fn_mut(|| set(&mut x)); //~ ERROR cannot borrow `x` as mutable more than once
+ c1;
}
fn d() {
let c1 = to_fn_mut(|| x = 5);
let c2 = to_fn_mut(|| { let _y = to_fn_mut(|| set(&mut x)); }); // (nested closure)
//~^ ERROR cannot borrow `x` as mutable more than once
+ c1;
}
fn g() {
let c1 = to_fn_mut(|| set(&mut *x.f));
let c2 = to_fn_mut(|| set(&mut *x.f));
//~^ ERROR cannot borrow `x` as mutable more than once
+ c1;
}
fn main() {
| ^^ - borrow occurs due to use of `x` in closure
| |
| second mutable borrow occurs here
+LL | c1;
LL | }
| - first borrow ends here
error[E0499]: cannot borrow `x` as mutable more than once at a time
- --> $DIR/borrowck-closures-two-mut-fail.rs:36:24
+ --> $DIR/borrowck-closures-two-mut-fail.rs:37:24
|
LL | let c1 = to_fn_mut(|| set(&mut x));
| -- - previous borrow occurs due to use of `x` in closure
| ^^ - borrow occurs due to use of `x` in closure
| |
| second mutable borrow occurs here
+LL | c1;
LL | }
| - first borrow ends here
error[E0499]: cannot borrow `x` as mutable more than once at a time
- --> $DIR/borrowck-closures-two-mut-fail.rs:42:24
+ --> $DIR/borrowck-closures-two-mut-fail.rs:44:24
|
LL | let c1 = to_fn_mut(|| x = 5);
| -- - previous borrow occurs due to use of `x` in closure
| ^^ - borrow occurs due to use of `x` in closure
| |
| second mutable borrow occurs here
+LL | c1;
LL | }
| - first borrow ends here
error[E0499]: cannot borrow `x` as mutable more than once at a time
- --> $DIR/borrowck-closures-two-mut-fail.rs:48:24
+ --> $DIR/borrowck-closures-two-mut-fail.rs:51:24
|
LL | let c1 = to_fn_mut(|| x = 5);
| -- - previous borrow occurs due to use of `x` in closure
| ^^ - borrow occurs due to use of `x` in closure
| |
| second mutable borrow occurs here
-LL | //~^ ERROR cannot borrow `x` as mutable more than once
+...
LL | }
| - first borrow ends here
error[E0499]: cannot borrow `x` as mutable more than once at a time
- --> $DIR/borrowck-closures-two-mut-fail.rs:59:24
+ --> $DIR/borrowck-closures-two-mut-fail.rs:63:24
|
LL | let c1 = to_fn_mut(|| set(&mut *x.f));
| -- - previous borrow occurs due to use of `x` in closure
| ^^ - borrow occurs due to use of `x` in closure
| |
| second mutable borrow occurs here
-LL | //~^ ERROR cannot borrow `x` as mutable more than once
+...
LL | }
| - first borrow ends here
--- /dev/null
+error[E0500]: closure requires unique access to `x` but it is already borrowed
+ --> $DIR/borrowck-closures-unique.rs:36:14
+ |
+LL | let c1 = || get(x);
+ | -- - first borrow occurs due to use of `x` in closure
+ | |
+ | borrow occurs here
+LL | let c2 = || set(x); //~ ERROR closure requires unique access to `x`
+ | ^^ - second borrow occurs due to use of `x` in closure
+ | |
+ | closure construction occurs here
+LL | c1;
+ | -- borrow later used here
+
+error[E0500]: closure requires unique access to `x` but it is already borrowed
+ --> $DIR/borrowck-closures-unique.rs:42:14
+ |
+LL | let c1 = || get(x);
+ | -- - first borrow occurs due to use of `x` in closure
+ | |
+ | borrow occurs here
+LL | let c2 = || { get(x); set(x); }; //~ ERROR closure requires unique access to `x`
+ | ^^ - second borrow occurs due to use of `x` in closure
+ | |
+ | closure construction occurs here
+LL | c1;
+ | -- borrow later used here
+
+error[E0524]: two closures require unique access to `x` at the same time
+ --> $DIR/borrowck-closures-unique.rs:48:14
+ |
+LL | let c1 = || set(x);
+ | -- - first borrow occurs due to use of `x` in closure
+ | |
+ | first closure is constructed here
+LL | let c2 = || set(x); //~ ERROR two closures require unique access to `x` at the same time
+ | ^^ - second borrow occurs due to use of `x` in closure
+ | |
+ | second closure is constructed here
+LL | c1;
+ | -- borrow later used here
+
+error[E0594]: cannot assign to `x`, as it is not declared as mutable
+ --> $DIR/borrowck-closures-unique.rs:57:38
+ |
+LL | fn e(x: &'static mut isize) {
+ | - help: consider changing this to be mutable: `mut x`
+LL | let c1 = |y: &'static mut isize| x = y; //~ ERROR closure cannot assign to immutable argument
+ | ^^^^^ cannot assign
+
+error: aborting due to 4 previous errors
+
+Some errors occurred: E0500, E0524, E0594.
+For more information about an error, try `rustc --explain E0500`.
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// ignore-compare-mode-nll
-
// Tests that a closure which requires mutable access to the referent
// of an `&mut` requires a "unique" borrow -- that is, the variable to
// be borrowed (here, `x`) will not be borrowed *mutably*, but
// may be *immutable*, but we cannot allow
// multiple borrows.
+
+
fn get(x: &isize) -> isize {
*x
}
fn a(x: &mut isize) {
let c1 = || get(x);
let c2 = || get(x);
+ c1();
+ c2();
}
fn b(x: &mut isize) {
let c1 = || get(x);
let c2 = || set(x); //~ ERROR closure requires unique access to `x`
+ c1;
}
fn c(x: &mut isize) {
let c1 = || get(x);
let c2 = || { get(x); set(x); }; //~ ERROR closure requires unique access to `x`
+ c1;
}
fn d(x: &mut isize) {
let c1 = || set(x);
let c2 = || set(x); //~ ERROR two closures require unique access to `x` at the same time
+ c1;
+}
+
+// This test was originally encoded in the form shown as `fn f` below.
+// However, since MIR-borrowck and thus NLL takes more control-flow information
+// into account, it was necessary to change the test in order to witness the
+// same (expected) error under both AST-borrowck and NLL.
+fn e(x: &'static mut isize) {
+ let c1 = |y: &'static mut isize| x = y; //~ ERROR closure cannot assign to immutable argument
+ c1;
}
-fn e(x: &mut isize) {
+fn f(x: &'static mut isize) {
let c1 = || x = panic!(); //~ ERROR closure cannot assign to immutable argument
+ c1;
}
fn main() {
error[E0500]: closure requires unique access to `x` but it is already borrowed
- --> $DIR/borrowck-closures-unique.rs:34:14
+ --> $DIR/borrowck-closures-unique.rs:36:14
|
LL | let c1 = || get(x);
| -- - previous borrow occurs due to use of `x` in closure
| ^^ - borrow occurs due to use of `x` in closure
| |
| closure construction occurs here
+LL | c1;
LL | }
| - borrow ends here
error[E0500]: closure requires unique access to `x` but it is already borrowed
- --> $DIR/borrowck-closures-unique.rs:39:14
+ --> $DIR/borrowck-closures-unique.rs:42:14
|
LL | let c1 = || get(x);
| -- - previous borrow occurs due to use of `x` in closure
| ^^ - borrow occurs due to use of `x` in closure
| |
| closure construction occurs here
+LL | c1;
LL | }
| - borrow ends here
error[E0524]: two closures require unique access to `x` at the same time
- --> $DIR/borrowck-closures-unique.rs:44:14
+ --> $DIR/borrowck-closures-unique.rs:48:14
|
LL | let c1 = || set(x);
| -- - previous borrow occurs due to use of `x` in closure
| ^^ - borrow occurs due to use of `x` in closure
| |
| second closure is constructed here
+LL | c1;
LL | }
| - borrow from first closure ends here
error[E0595]: closure cannot assign to immutable argument `x`
- --> $DIR/borrowck-closures-unique.rs:48:14
+ --> $DIR/borrowck-closures-unique.rs:57:14
+ |
+LL | let c1 = |y: &'static mut isize| x = y; //~ ERROR closure cannot assign to immutable argument
+ | ^^^^^^^^^^^^^^^^^^^^^^^ cannot borrow mutably
+help: consider removing the `&mut`, as it is an immutable binding to a mutable reference
+ |
+LL | x //~ ERROR closure cannot assign to immutable argument
+ | ^
+
+error[E0595]: closure cannot assign to immutable argument `x`
+ --> $DIR/borrowck-closures-unique.rs:62:14
|
LL | let c1 = || x = panic!(); //~ ERROR closure cannot assign to immutable argument
| ^^ cannot borrow mutably
LL | x //~ ERROR closure cannot assign to immutable argument
| ^
-error: aborting due to 4 previous errors
+error: aborting due to 5 previous errors
Some errors occurred: E0500, E0524, E0595.
For more information about an error, try `rustc --explain E0500`.
--> $DIR/borrowck-for-loop-correct-cmt-for-pattern.rs:22:15
|
LL | for &a in x.iter() { //~ ERROR cannot move out
- | - ^^^^^^^^ cannot move out of borrowed content
- | |
- | data moved here
- | help: to prevent move, use ref or ref mut: `ref a`
+ | -- ^^^^^^^^ cannot move out of borrowed content
+ | ||
+ | |data moved here
+ | help: consider removing the `&`: `a`
+ |
+note: move occurs because `a` has type `&mut i32`, which does not implement the `Copy` trait
+ --> $DIR/borrowck-for-loop-correct-cmt-for-pattern.rs:22:10
+ |
+LL | for &a in x.iter() { //~ ERROR cannot move out
+ | ^
error[E0507]: cannot move out of borrowed content
--> $DIR/borrowck-for-loop-correct-cmt-for-pattern.rs:28:15
|
LL | for &a in &f.a { //~ ERROR cannot move out
- | - ^^^^ cannot move out of borrowed content
- | |
- | data moved here
- | help: to prevent move, use ref or ref mut: `ref a`
+ | -- ^^^^ cannot move out of borrowed content
+ | ||
+ | |data moved here
+ | help: consider removing the `&`: `a`
+ |
+note: move occurs because `a` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
+ --> $DIR/borrowck-for-loop-correct-cmt-for-pattern.rs:28:10
+ |
+LL | for &a in &f.a { //~ ERROR cannot move out
+ | ^
error[E0507]: cannot move out of borrowed content
--> $DIR/borrowck-for-loop-correct-cmt-for-pattern.rs:32:15
|
LL | for &a in x.iter() { //~ ERROR cannot move out
- | - ^^^^^^^^ cannot move out of borrowed content
- | |
- | data moved here
- | help: to prevent move, use ref or ref mut: `ref a`
+ | -- ^^^^^^^^ cannot move out of borrowed content
+ | ||
+ | |data moved here
+ | help: consider removing the `&`: `a`
+ |
+note: move occurs because `a` has type `std::boxed::Box<i32>`, which does not implement the `Copy` trait
+ --> $DIR/borrowck-for-loop-correct-cmt-for-pattern.rs:32:10
+ |
+LL | for &a in x.iter() { //~ ERROR cannot move out
+ | ^
error: aborting due to 3 previous errors
| ^^
| |
| cannot move out of borrowed content
- | help: consider removing this dereference operator: `y`
+ | help: consider removing the `*`: `y`
error: aborting due to previous error
| ^^
| |
| cannot move out of borrowed content
- | help: consider removing this dereference operator: `f`
+ | help: consider removing the `*`: `f`
LL | //~| cannot move out
LL | Foo::Foo1(num1,
- | ---- move occurs because num1 has type `std::boxed::Box<u32>`, which does not implement the `Copy` trait
+ | ---- data moved here
LL | num2) => (),
- | ---- move occurs because num2 has type `std::boxed::Box<u32>`, which does not implement the `Copy` trait
+ | ---- ...and here
LL | Foo::Foo2(num) => (),
- | --- move occurs because num has type `std::boxed::Box<u32>`, which does not implement the `Copy` trait
+ | --- ...and here
+ |
+note: move occurs because these variables have types that don't implement the `Copy` trait
+ --> $DIR/borrowck-move-error-with-note.rs:23:19
+ |
+LL | Foo::Foo1(num1,
+ | ^^^^
+LL | num2) => (),
+ | ^^^^
+LL | Foo::Foo2(num) => (),
+ | ^^^
error[E0509]: cannot move out of type `S`, which implements the `Drop` trait
--> $DIR/borrowck-move-error-with-note.rs:39:11
LL | f: _s,
| -- data moved here
LL | g: _t
- | -- ... and here
-help: to prevent move, use ref or ref mut
+ | -- ...and here
|
-LL | f: ref _s,
-LL | g: ref _t
+note: move occurs because these variables have types that don't implement the `Copy` trait
+ --> $DIR/borrowck-move-error-with-note.rs:42:16
|
+LL | f: _s,
+ | ^^
+LL | g: _t
+ | ^^
error[E0507]: cannot move out of borrowed content
--> $DIR/borrowck-move-error-with-note.rs:57:11
| ^^^
| |
| cannot move out of borrowed content
- | help: consider using a reference instead: `&a.a`
+ | help: consider borrowing here: `&a.a`
LL | //~| cannot move out
LL | n => {
- | - move occurs because n has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
+ | - data moved here
+ |
+note: move occurs because `n` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
+ --> $DIR/borrowck-move-error-with-note.rs:59:9
+ |
+LL | n => {
+ | ^
error: aborting due to 3 previous errors
| ^^
| |
| cannot move out of borrowed content
- | help: consider using a reference instead: `&*x`
+ | help: consider removing the `*`: `x`
error: aborting due to previous error
| ^--
| ||
| |data moved here
- | |help: to prevent move, use ref or ref mut: `ref _x`
| cannot move out of borrowed content
+ | help: consider removing the `&`: `_x`
+ |
+note: move occurs because `_x` has type `std::string::String`, which does not implement the `Copy` trait
+ --> $DIR/borrowck-move-in-irrefut-pat.rs:16:14
+ |
+LL | fn arg_item(&_x: &String) {}
+ | ^^
error[E0507]: cannot move out of borrowed content
--> $DIR/borrowck-move-in-irrefut-pat.rs:21:11
| ^--
| ||
| |data moved here
- | |help: to prevent move, use ref or ref mut: `ref _x`
| cannot move out of borrowed content
+ | help: consider removing the `&`: `_x`
+ |
+note: move occurs because `_x` has type `std::string::String`, which does not implement the `Copy` trait
+ --> $DIR/borrowck-move-in-irrefut-pat.rs:21:12
+ |
+LL | with(|&_x| ())
+ | ^^
error[E0507]: cannot move out of borrowed content
--> $DIR/borrowck-move-in-irrefut-pat.rs:27:15
|
LL | let &_x = &"hi".to_string();
- | -- ^^^^^^^^^^^^^^^^^ cannot move out of borrowed content
- | |
- | data moved here
- | help: to prevent move, use ref or ref mut: `ref _x`
+ | --- ^^^^^^^^^^^^^^^^^ cannot move out of borrowed content
+ | ||
+ | |data moved here
+ | help: consider removing the `&`: `_x`
+ |
+note: move occurs because `_x` has type `std::string::String`, which does not implement the `Copy` trait
+ --> $DIR/borrowck-move-in-irrefut-pat.rs:27:10
+ |
+LL | let &_x = &"hi".to_string();
+ | ^^
error: aborting due to 3 previous errors
| ^--
| ||
| |data moved here
- | |help: to prevent move, use ref or ref mut: `ref _x`
| cannot move out of borrowed content
+ | help: consider removing the `&`: `_x`
+ |
+note: move occurs because `_x` has type `std::string::String`, which does not implement the `Copy` trait
+ --> $DIR/borrowck-move-in-irrefut-pat.rs:16:14
+ |
+LL | fn arg_item(&_x: &String) {}
+ | ^^
error[E0507]: cannot move out of borrowed content
--> $DIR/borrowck-move-in-irrefut-pat.rs:21:11
| ^--
| ||
| |data moved here
- | |help: to prevent move, use ref or ref mut: `ref _x`
| cannot move out of borrowed content
+ | help: consider removing the `&`: `_x`
+ |
+note: move occurs because `_x` has type `std::string::String`, which does not implement the `Copy` trait
+ --> $DIR/borrowck-move-in-irrefut-pat.rs:21:12
+ |
+LL | with(|&_x| ())
+ | ^^
error[E0507]: cannot move out of borrowed content
--> $DIR/borrowck-move-in-irrefut-pat.rs:27:15
|
LL | let &_x = &"hi".to_string();
- | -- ^^^^^^^^^^^^^^^^^ cannot move out of borrowed content
- | |
- | data moved here
- | help: to prevent move, use ref or ref mut: `ref _x`
+ | --- ^^^^^^^^^^^^^^^^^ cannot move out of borrowed content
+ | ||
+ | |data moved here
+ | help: consider removing the `&`: `_x`
+ |
+note: move occurs because `_x` has type `std::string::String`, which does not implement the `Copy` trait
+ --> $DIR/borrowck-move-in-irrefut-pat.rs:27:10
+ |
+LL | let &_x = &"hi".to_string();
+ | ^^
error: aborting due to 3 previous errors
--- /dev/null
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/borrowck-move-out-of-overloaded-deref.rs:14:14
+ |
+LL | let _x = *Rc::new("hi".to_string());
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | |
+ | cannot move out of borrowed content
+ | help: consider removing the `*`: `Rc::new("hi".to_string())`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0507`.
| ^^^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of here
LL | //[mir]~^ ERROR [E0509]
LL | S {f:_s} => {}
- | --
- | |
- | data moved here
- | help: to prevent move, use ref or ref mut: `ref _s`
+ | -- data moved here
+ |
+note: move occurs because `_s` has type `std::string::String`, which does not implement the `Copy` trait
+ --> $DIR/borrowck-move-out-of-struct-with-dtor.rs:22:14
+ |
+LL | S {f:_s} => {}
+ | ^^
error[E0509]: cannot move out of type `S`, which implements the `Drop` trait
--> $DIR/borrowck-move-out-of-struct-with-dtor.rs:28:20
| -- ^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of here
| |
| data moved here
- | help: to prevent move, use ref or ref mut: `ref _s`
+ |
+note: move occurs because `_s` has type `std::string::String`, which does not implement the `Copy` trait
+ --> $DIR/borrowck-move-out-of-struct-with-dtor.rs:28:14
+ |
+LL | let S {f:_s} = S {f:"foo".to_string()};
+ | ^^
error[E0509]: cannot move out of type `S`, which implements the `Drop` trait
--> $DIR/borrowck-move-out-of-struct-with-dtor.rs:33:19
| ^^^^^--^
| | |
| | data moved here
- | | help: to prevent move, use ref or ref mut: `ref _s`
| cannot move out of here
+ |
+note: move occurs because `_s` has type `std::string::String`, which does not implement the `Copy` trait
+ --> $DIR/borrowck-move-out-of-struct-with-dtor.rs:33:24
+ |
+LL | fn move_in_fn_arg(S {f:_s}: S) {
+ | ^^
error: aborting due to 3 previous errors
| ^^^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of here
LL | //[mir]~^ ERROR [E0509]
LL | S {f:_s} => {}
- | --
- | |
- | data moved here
- | help: to prevent move, use ref or ref mut: `ref _s`
+ | -- data moved here
+ |
+note: move occurs because `_s` has type `std::string::String`, which does not implement the `Copy` trait
+ --> $DIR/borrowck-move-out-of-struct-with-dtor.rs:22:14
+ |
+LL | S {f:_s} => {}
+ | ^^
error[E0509]: cannot move out of type `S`, which implements the `Drop` trait
--> $DIR/borrowck-move-out-of-struct-with-dtor.rs:28:20
| -- ^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of here
| |
| data moved here
- | help: to prevent move, use ref or ref mut: `ref _s`
+ |
+note: move occurs because `_s` has type `std::string::String`, which does not implement the `Copy` trait
+ --> $DIR/borrowck-move-out-of-struct-with-dtor.rs:28:14
+ |
+LL | let S {f:_s} = S {f:"foo".to_string()};
+ | ^^
error[E0509]: cannot move out of type `S`, which implements the `Drop` trait
--> $DIR/borrowck-move-out-of-struct-with-dtor.rs:33:19
| ^^^^^--^
| | |
| | data moved here
- | | help: to prevent move, use ref or ref mut: `ref _s`
| cannot move out of here
+ |
+note: move occurs because `_s` has type `std::string::String`, which does not implement the `Copy` trait
+ --> $DIR/borrowck-move-out-of-struct-with-dtor.rs:33:24
+ |
+LL | fn move_in_fn_arg(S {f:_s}: S) {
+ | ^^
error: aborting due to 3 previous errors
LL | match S("foo".to_string()) {
| ^^^^^^^^^^^^^^^^^^^^ cannot move out of here
LL | S(_s) => {}
- | --
- | |
- | data moved here
- | help: to prevent move, use ref or ref mut: `ref _s`
+ | -- data moved here
+ |
+note: move occurs because `_s` has type `std::string::String`, which does not implement the `Copy` trait
+ --> $DIR/borrowck-move-out-of-tuple-struct-with-dtor.rs:18:11
+ |
+LL | S(_s) => {}
+ | ^^
error[E0509]: cannot move out of type `S`, which implements the `Drop` trait
--> $DIR/borrowck-move-out-of-tuple-struct-with-dtor.rs:24:17
| -- ^^^^^^^^^^^^^^^^^^^^ cannot move out of here
| |
| data moved here
- | help: to prevent move, use ref or ref mut: `ref _s`
+ |
+note: move occurs because `_s` has type `std::string::String`, which does not implement the `Copy` trait
+ --> $DIR/borrowck-move-out-of-tuple-struct-with-dtor.rs:24:11
+ |
+LL | let S(_s) = S("foo".to_string());
+ | ^^
error[E0509]: cannot move out of type `S`, which implements the `Drop` trait
--> $DIR/borrowck-move-out-of-tuple-struct-with-dtor.rs:28:19
| ^^--^
| | |
| | data moved here
- | | help: to prevent move, use ref or ref mut: `ref _s`
| cannot move out of here
+ |
+note: move occurs because `_s` has type `std::string::String`, which does not implement the `Copy` trait
+ --> $DIR/borrowck-move-out-of-tuple-struct-with-dtor.rs:28:21
+ |
+LL | fn move_in_fn_arg(S(_s): S) {
+ | ^^
error: aborting due to 3 previous errors
| - data moved here
...
LL | Foo { string: b }] => {
- | - ... and here
-help: to prevent move, use ref or ref mut
+ | - ...and here
|
-LL | &[Foo { string: ref a },
+note: move occurs because these variables have types that don't implement the `Copy` trait
+ --> $DIR/borrowck-move-out-of-vec-tail.rs:30:33
+ |
+LL | &[Foo { string: a },
+ | ^
+...
+LL | Foo { string: b }] => {
+ | ^
+help: consider removing the `&`
+ |
+LL | [Foo { string: a },
LL | //~^ ERROR cannot move out of type `[Foo]`
LL | //~| cannot move out
LL | //~| to prevent move
-LL | Foo { string: ref b }] => {
+LL | Foo { string: b }] => {
|
error: aborting due to previous error
| ^^^^
| |
| cannot move out of borrowed content
- | help: consider using a reference instead: `&v[0]`
+ | help: consider borrowing here: `&v[0]`
error: aborting due to previous error
LL | match vec {
| ^^^ cannot move out of here
LL | &mut [_a, //~ ERROR cannot move out
- | --
- | |
- | data moved here
- | help: to prevent move, use ref or ref mut: `ref _a`
+ | -- data moved here
+ |
+note: move occurs because `_a` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
+ --> $DIR/borrowck-vec-pattern-nesting.rs:44:15
+ |
+LL | &mut [_a, //~ ERROR cannot move out
+ | ^^
+help: consider removing the `&mut`
+ |
+LL | [_a, //~ ERROR cannot move out
+LL | //~| cannot move out
+LL | //~| to prevent move
+LL | ..
+LL | ] => {
+ |
error[E0508]: cannot move out of type `[std::boxed::Box<isize>]`, a non-copy slice
--> $DIR/borrowck-vec-pattern-nesting.rs:57:13
| ^^^^^^
| |
| cannot move out of here
- | help: consider using a reference instead: `&vec[0]`
+ | help: consider borrowing here: `&vec[0]`
error[E0508]: cannot move out of type `[std::boxed::Box<isize>]`, a non-copy slice
--> $DIR/borrowck-vec-pattern-nesting.rs:64:11
| ^^^ cannot move out of here
...
LL | _b] => {}
- | --
- | |
- | data moved here
- | help: to prevent move, use ref or ref mut: `ref _b`
+ | -- data moved here
+ |
+note: move occurs because `_b` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
+ --> $DIR/borrowck-vec-pattern-nesting.rs:67:10
+ |
+LL | _b] => {}
+ | ^^
+help: consider removing the `&mut`
+ |
+LL | [ //~ ERROR cannot move out
+LL | //~^ cannot move out
+LL | _b] => {}
+ |
error[E0508]: cannot move out of type `[std::boxed::Box<isize>]`, a non-copy slice
--> $DIR/borrowck-vec-pattern-nesting.rs:70:13
| ^^^^^^
| |
| cannot move out of here
- | help: consider using a reference instead: `&vec[0]`
+ | help: consider borrowing here: `&vec[0]`
error[E0508]: cannot move out of type `[std::boxed::Box<isize>]`, a non-copy slice
--> $DIR/borrowck-vec-pattern-nesting.rs:77:11
LL | match vec {
| ^^^ cannot move out of here
LL | &mut [_a, _b, _c] => {} //~ ERROR cannot move out
- | -- -- -- ... and here
- | | |
- | | ... and here
- | data moved here
-help: to prevent move, use ref or ref mut
- |
-LL | &mut [ref _a, ref _b, ref _c] => {} //~ ERROR cannot move out
- | ^^^^^^ ^^^^^^ ^^^^^^
+ | -----------------
+ | | | | |
+ | | | | ...and here
+ | | | ...and here
+ | | data moved here
+ | help: consider removing the `&mut`: `[_a, _b, _c]`
+ |
+note: move occurs because these variables have types that don't implement the `Copy` trait
+ --> $DIR/borrowck-vec-pattern-nesting.rs:78:15
+ |
+LL | &mut [_a, _b, _c] => {} //~ ERROR cannot move out
+ | ^^ ^^ ^^
error[E0508]: cannot move out of type `[std::boxed::Box<isize>]`, a non-copy slice
--> $DIR/borrowck-vec-pattern-nesting.rs:82:13
| ^^^^^^
| |
| cannot move out of here
- | help: consider using a reference instead: `&vec[0]`
+ | help: consider borrowing here: `&vec[0]`
error: aborting due to 8 previous errors
| ^^^^^-^
| | |
| | data moved here
- | | help: to prevent move, use ref or ref mut: `ref s`
| cannot move out of borrowed content
+ |
+note: move occurs because `s` has type `std::string::String`, which does not implement the `Copy` trait
+ --> $DIR/issue-51415.rs:16:47
+ |
+LL | let opt = a.iter().enumerate().find(|(_, &s)| {
+ | ^
error: aborting due to previous error
| ^^^^ cannot move out of borrowed content
LL | &E::Foo => {}
LL | &E::Bar(identifier) => f(identifier.clone()) //~ ERROR cannot move
- | ----------
- | |
- | data moved here
- | help: to prevent move, use ref or ref mut: `ref identifier`
+ | -------------------
+ | | |
+ | | data moved here
+ | help: consider removing the `&`: `E::Bar(identifier)`
+ |
+note: move occurs because `identifier` has type `std::string::String`, which does not implement the `Copy` trait
+ --> $DIR/by-move-pattern-binding.rs:26:17
+ |
+LL | &E::Bar(identifier) => f(identifier.clone()) //~ ERROR cannot move
+ | ^^^^^^^^^^
error: aborting due to previous error
| ^
| |
| cannot move out of static item
- | help: consider using a reference instead: `&x`
+ | help: consider borrowing here: `&x`
error[E0010]: allocations are not allowed in statics
--> $DIR/check-static-values-constraints.rs:120:38
LL | match (S {f:"foo".to_string()}) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of here
LL | S {f:_s} => {} //~ ERROR cannot move out
- | --
- | |
- | data moved here
- | help: to prevent move, use ref or ref mut: `ref _s`
+ | -- data moved here
+ |
+note: move occurs because `_s` has type `std::string::String`, which does not implement the `Copy` trait
+ --> $DIR/overlapping_spans.rs:21:14
+ |
+LL | S {f:_s} => {} //~ ERROR cannot move out
+ | ^^
error: aborting due to previous error
| - ^ cannot move out of here
| |
| data moved here
- | help: to prevent move, use ref or ref mut: `ref y`
+ |
+note: move occurs because `y` has type `std::string::String`, which does not implement the `Copy` trait
+ --> $DIR/disallowed-deconstructing-destructing-struct-let.rs:22:16
+ |
+LL | let X { x: y } = x; //~ ERROR cannot move out of type
+ | ^
error: aborting due to previous error
LL | match x {
| ^ cannot move out of here
LL | X { x: y } => println!("contents: {}", y)
- | -
- | |
- | data moved here
- | help: to prevent move, use ref or ref mut: `ref y`
+ | - data moved here
+ |
+note: move occurs because `y` has type `std::string::String`, which does not implement the `Copy` trait
+ --> $DIR/disallowed-deconstructing-destructing-struct-match.rs:25:16
+ |
+LL | X { x: y } => println!("contents: {}", y)
+ | ^
error: aborting due to previous error
LL | #[rustc_on_unimplemented]
| ^^^^^^^^^^^^^^^^^^^^^^^^^ value required here
|
- = note: eg `#[rustc_on_unimplemented = "foo"]`
+ = note: eg `#[rustc_on_unimplemented(message="foo")]`
error: aborting due to previous error
--- /dev/null
+error[E0509]: cannot move out of type `DropStruct`, which implements the `Drop` trait
+ --> $DIR/E0509.rs:26:23
+ |
+LL | let fancy_field = drop_struct.fancy; //~ ERROR E0509
+ | ^^^^^^^^^^^^^^^^^
+ | |
+ | cannot move out of here
+ | help: consider borrowing here: `&drop_struct.fancy`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0509`.
struct S;
fn main() {
- let _ = ::crate::S; //~ ERROR `crate` in paths is experimental
+ let _ = crate::S; //~ ERROR `crate` in paths is experimental
}
error[E0658]: `crate` in paths is experimental (see issue #45477)
- --> $DIR/feature-gate-crate_in_paths.rs:14:15
+ --> $DIR/feature-gate-crate_in_paths.rs:14:13
|
-LL | let _ = ::crate::S; //~ ERROR `crate` in paths is experimental
- | ^^^^^
+LL | let _ = crate::S; //~ ERROR `crate` in paths is experimental
+ | ^^^^^
|
= help: add #![feature(crate_in_paths)] to the crate attributes to enable
--- /dev/null
+error[E0502]: cannot borrow `my_stuff` as mutable because it is also borrowed as immutable
+ --> $DIR/hashmap-lifetimes.rs:18:5
+ |
+LL | let mut it = my_stuff.iter();
+ | -------- immutable borrow occurs here
+LL | my_stuff.insert(1, 43); //~ ERROR cannot borrow
+ | ^^^^^^^^^^^^^^^^^^^^^^ mutable borrow occurs here
+LL | it;
+ | -- borrow later used here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0502`.
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// ignore-compare-mode-nll
+
fn main() {
let mut my_stuff = std::collections::HashMap::new();
let mut it = my_stuff.iter();
my_stuff.insert(1, 43); //~ ERROR cannot borrow
+ it;
}
| -------- immutable borrow occurs here
LL | my_stuff.insert(1, 43); //~ ERROR cannot borrow
| ^^^^^^^^ mutable borrow occurs here
+LL | it;
LL | }
| - immutable borrow ends here
--- /dev/null
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-flags: -Z parse-only
+
+struct Obj { //~ NOTE: unclosed delimiter
+ member: usize
+)
+//~^ ERROR incorrect close delimiter
+//~| NOTE incorrect close delimiter
+
+fn main() {}
--- /dev/null
+error: incorrect close delimiter: `)`
+ --> $DIR/issue-10636-1.rs:15:1
+ |
+LL | struct Obj { //~ NOTE: unclosed delimiter
+ | - unclosed delimiter
+LL | member: usize
+LL | )
+ | ^ incorrect close delimiter
+
+error: aborting due to previous error
+
--- /dev/null
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main(){
+ if i in 1..10 {
+ break;
+ }
+}
--- /dev/null
+error: expected `{`, found `in`
+ --> $DIR/issue-51602.rs:12:10
+ |
+LL | if i in 1..10 {
+ | -- ^^ expected `{`
+ | |
+ | this `if` statement has a condition, but no block
+
+error: aborting due to previous error
+
| -- data moved here
...
LL | (&[hd1, ..], &[hd2, ..])
- | --- ... and here
-help: to prevent move, use ref or ref mut
+ | --- ...and here
|
-LL | (&[], &[ref hd, ..]) | (&[hd, ..], &[])
-LL | => println!("one empty"),
-LL | //~^^ ERROR: cannot move out of type `[T]`, a non-copy slice
-LL | //~^^^ ERROR: cannot move out of type `[T]`, a non-copy slice
-LL | (&[hd1, ..], &[ref hd2, ..])
+note: move occurs because these variables have types that don't implement the `Copy` trait
+ --> $DIR/issue-12567.rs:16:17
|
+LL | (&[], &[hd, ..]) | (&[hd, ..], &[])
+ | ^^
+...
+LL | (&[hd1, ..], &[hd2, ..])
+ | ^^^
error[E0508]: cannot move out of type `[T]`, a non-copy slice
--> $DIR/issue-12567.rs:14:11
| -- data moved here
...
LL | (&[hd1, ..], &[hd2, ..])
- | --- ... and here
-help: to prevent move, use ref or ref mut
+ | --- ...and here
|
-LL | (&[], &[ref hd, ..]) | (&[hd, ..], &[])
-LL | => println!("one empty"),
-LL | //~^^ ERROR: cannot move out of type `[T]`, a non-copy slice
-LL | //~^^^ ERROR: cannot move out of type `[T]`, a non-copy slice
-LL | (&[ref hd1, ..], &[hd2, ..])
+note: move occurs because these variables have types that don't implement the `Copy` trait
+ --> $DIR/issue-12567.rs:16:17
|
+LL | (&[], &[hd, ..]) | (&[hd, ..], &[])
+ | ^^
+...
+LL | (&[hd1, ..], &[hd2, ..])
+ | ^^^
error: aborting due to 2 previous errors
--- /dev/null
+error[E0507]: cannot move out of static item
+ --> $DIR/issue-17718-static-move.rs:16:14
+ |
+LL | let _a = FOO; //~ ERROR: cannot move out of static item
+ | ^^^
+ | |
+ | cannot move out of static item
+ | help: consider borrowing here: `&FOO`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0507`.
| ^^^^^^^^^^
| |
| cannot move out of borrowed content
- | help: consider using a reference instead: `&*mut_ref()`
+ | help: consider removing the `*`: `mut_ref()`
error[E0507]: cannot move out of borrowed content
--> $DIR/issue-20801.rs:39:22
| ^^^^^^^^^^
| |
| cannot move out of borrowed content
- | help: consider using a reference instead: `&*imm_ref()`
+ | help: consider removing the `*`: `imm_ref()`
error[E0507]: cannot move out of borrowed content
--> $DIR/issue-20801.rs:42:22
| ^^^^^^^^^^
| |
| cannot move out of borrowed content
- | help: consider using a reference instead: `&*mut_ptr()`
+ | help: consider removing the `*`: `mut_ptr()`
error[E0507]: cannot move out of borrowed content
--> $DIR/issue-20801.rs:45:22
| ^^^^^^^^^^^^
| |
| cannot move out of borrowed content
- | help: consider using a reference instead: `&*const_ptr()`
+ | help: consider removing the `*`: `const_ptr()`
error: aborting due to 4 previous errors
| ^^^^^^
| |
| cannot move out of borrowed content
- | help: consider using a reference instead: `&f.v[0]`
+ | help: consider borrowing here: `&f.v[0]`
error: aborting due to previous error
| - - ^^^^
| | | |
| | | cannot move out of borrowed content
- | | | help: consider using a reference instead: `&x[0]`
- | | move occurs because b has type `std::string::String`, which does not implement the `Copy` trait
- | move occurs because a has type `std::string::String`, which does not implement the `Copy` trait
+ | | | help: consider borrowing here: `&x[0]`
+ | | ...and here
+ | data moved here
+ |
+note: move occurs because these variables have types that don't implement the `Copy` trait
+ --> $DIR/issue-40402-2.rs:15:10
+ |
+LL | let (a, b) = x[0]; //~ ERROR cannot move out of indexed content
+ | ^ ^
error: aborting due to previous error
--- /dev/null
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+ let mut v = vec!["hello", "this", "is", "a", "test"];
+
+ let v2 = Vec::new();
+
+ v.into_iter().map(|s|s.to_owned()).collect::<Vec<_>>();
+
+ let mut a = String::new();
+ for i in v {
+ a = *i.to_string();
+ //~^ ERROR mismatched types
+ //~| NOTE expected struct `std::string::String`, found str
+ //~| NOTE expected type
+ v2.push(a);
+ }
+}
--- /dev/null
+error[E0308]: mismatched types
+ --> $DIR/issue-53348.rs:20:13
+ |
+LL | a = *i.to_string();
+ | ^^^^^^^^^^^^^^ expected struct `std::string::String`, found str
+ |
+ = note: expected type `std::string::String`
+ found type `str`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
--- /dev/null
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::fmt::Write;
+
+fn main() {
+ println!(0);
+ //~^ ERROR format argument must be a string literal
+ eprintln!('a');
+ //~^ ERROR format argument must be a string literal
+ let mut s = String::new();
+ writeln!(s, true).unwrap();
+ //~^ ERROR format argument must be a string literal
+}
--- /dev/null
+error: format argument must be a string literal
+ --> $DIR/issue-30143.rs:14:14
+ |
+LL | println!(0);
+ | ^
+help: you might be missing a string literal to format with
+ |
+LL | println!("{}", 0);
+ | ^^^^^
+
+error: format argument must be a string literal
+ --> $DIR/issue-30143.rs:16:15
+ |
+LL | eprintln!('a');
+ | ^^^
+help: you might be missing a string literal to format with
+ |
+LL | eprintln!("{}", 'a');
+ | ^^^^^
+
+error: format argument must be a string literal
+ --> $DIR/issue-30143.rs:19:17
+ |
+LL | writeln!(s, true).unwrap();
+ | ^^^^
+help: you might be missing a string literal to format with
+ |
+LL | writeln!(s, "{}", true).unwrap();
+ | ^^^^^
+
+error: aborting due to 3 previous errors
+
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#[doc = $not_there] //~ ERROR arbitrary tokens in non-macro attributes are unstable
+#![feature(unrestricted_attribute_tokens)]
+
+#[doc = $not_there] //~ ERROR expected `]`, found `not_there`
fn main() { }
-error[E0658]: arbitrary tokens in non-macro attributes are unstable (see issue #44690)
- --> $DIR/macro-attribute.rs:11:1
+error: expected `]`, found `not_there`
+ --> $DIR/macro-attribute.rs:13:10
|
-LL | #[doc = $not_there] //~ ERROR arbitrary tokens in non-macro attributes are unstable
- | ^^^^^^^^^^^^^^^^^^^
- |
- = help: add #![feature(unrestricted_attribute_tokens)] to the crate attributes to enable
+LL | #[doc = $not_there] //~ ERROR expected `]`, found `not_there`
+ | ^^^^^^^^^ expected `]`
error: aborting due to previous error
-For more information about this error, try `rustc --explain E0658`.
// normalize-stderr-test: "The system cannot find the file specified\." -> "No such file or directory"
// ignore-tidy-linelength
-// ignore-stage1
// test that errors in a (selection) of macros don't kill compilation
// immediately, so that we get more errors listed at a time.
error[E0665]: `Default` cannot be derived for enums, only structs
- --> $DIR/macros-nonfatal-errors.rs:21:10
+ --> $DIR/macros-nonfatal-errors.rs:20:10
|
LL | #[derive(Default)] //~ ERROR
| ^^^^^^^
error: inline assembly must be a string literal
- --> $DIR/macros-nonfatal-errors.rs:25:10
+ --> $DIR/macros-nonfatal-errors.rs:24:10
|
LL | asm!(invalid); //~ ERROR
| ^^^^^^^
error: concat_idents! requires ident args.
- --> $DIR/macros-nonfatal-errors.rs:27:5
+ --> $DIR/macros-nonfatal-errors.rs:26:5
|
LL | concat_idents!("not", "idents"); //~ ERROR
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: argument must be a string literal
- --> $DIR/macros-nonfatal-errors.rs:29:17
+ --> $DIR/macros-nonfatal-errors.rs:28:17
|
LL | option_env!(invalid); //~ ERROR
| ^^^^^^^
error: expected string literal
- --> $DIR/macros-nonfatal-errors.rs:30:10
+ --> $DIR/macros-nonfatal-errors.rs:29:10
|
LL | env!(invalid); //~ ERROR
| ^^^^^^^
error: expected string literal
- --> $DIR/macros-nonfatal-errors.rs:31:10
+ --> $DIR/macros-nonfatal-errors.rs:30:10
|
LL | env!(foo, abr, baz); //~ ERROR
| ^^^
error: environment variable `RUST_HOPEFULLY_THIS_DOESNT_EXIST` not defined
- --> $DIR/macros-nonfatal-errors.rs:32:5
+ --> $DIR/macros-nonfatal-errors.rs:31:5
|
LL | env!("RUST_HOPEFULLY_THIS_DOESNT_EXIST"); //~ ERROR
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0658]: non-ident macro paths are experimental (see issue #35896)
- --> $DIR/macros-nonfatal-errors.rs:34:5
+ --> $DIR/macros-nonfatal-errors.rs:33:5
|
LL | foo::blah!(); //~ ERROR
| ^^^^^^^^^
= help: add #![feature(use_extern_macros)] to the crate attributes to enable
error: format argument must be a string literal
- --> $DIR/macros-nonfatal-errors.rs:36:13
+ --> $DIR/macros-nonfatal-errors.rs:35:13
|
LL | format!(invalid); //~ ERROR
| ^^^^^^^
| ^^^^^
error: argument must be a string literal
- --> $DIR/macros-nonfatal-errors.rs:38:14
+ --> $DIR/macros-nonfatal-errors.rs:37:14
|
LL | include!(invalid); //~ ERROR
| ^^^^^^^
error: argument must be a string literal
- --> $DIR/macros-nonfatal-errors.rs:40:18
+ --> $DIR/macros-nonfatal-errors.rs:39:18
|
LL | include_str!(invalid); //~ ERROR
| ^^^^^^^
error: couldn't read $DIR/i'd be quite surprised if a file with this name existed: No such file or directory (os error 2)
- --> $DIR/macros-nonfatal-errors.rs:41:5
+ --> $DIR/macros-nonfatal-errors.rs:40:5
|
LL | include_str!("i'd be quite surprised if a file with this name existed"); //~ ERROR
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: argument must be a string literal
- --> $DIR/macros-nonfatal-errors.rs:42:20
+ --> $DIR/macros-nonfatal-errors.rs:41:20
|
LL | include_bytes!(invalid); //~ ERROR
| ^^^^^^^
error: couldn't read $DIR/i'd be quite surprised if a file with this name existed: No such file or directory (os error 2)
- --> $DIR/macros-nonfatal-errors.rs:43:5
+ --> $DIR/macros-nonfatal-errors.rs:42:5
|
LL | include_bytes!("i'd be quite surprised if a file with this name existed"); //~ ERROR
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: trace_macros! accepts only `true` or `false`
- --> $DIR/macros-nonfatal-errors.rs:45:5
+ --> $DIR/macros-nonfatal-errors.rs:44:5
|
LL | trace_macros!(invalid); //~ ERROR
| ^^^^^^^^^^^^^^^^^^^^^^^
LL | match a {
| ^ cannot move out of here
LL | box [a] => {}, //~ ERROR cannot move out of type `[A]`, a non-copy slice
- | -
- | |
- | data moved here
- | help: to prevent move, use ref or ref mut: `ref a`
+ | - data moved here
+ |
+note: move occurs because `a` has type `A`, which does not implement the `Copy` trait
+ --> $DIR/move-out-of-slice-1.rs:18:14
+ |
+LL | box [a] => {}, //~ ERROR cannot move out of type `[A]`, a non-copy slice
+ | ^
error: aborting due to previous error
| ^^^^^^^^^^^^
| |
| cannot move out of borrowed content
- | help: consider using a reference instead: `&hellothere.x`
+ | help: consider borrowing here: `&hellothere.x`
...
LL | box E::Bar(x) => println!("{}", x.to_string()),
- | - move occurs because x has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
+ | - data moved here
+ |
+note: move occurs because `x` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
+ --> $DIR/moves-based-on-type-block-bad.rs:37:28
+ |
+LL | box E::Bar(x) => println!("{}", x.to_string()),
+ | ^
error: aborting due to previous error
| ^^
| |
| cannot move out of borrowed content
- | help: consider removing this dereference operator: `r`
+ | help: consider removing the `*`: `r`
error[E0507]: cannot move out of borrowed content
--> $DIR/cannot-move-block-spans.rs:16:22
| ^^
| |
| cannot move out of borrowed content
- | help: consider removing this dereference operator: `r`
+ | help: consider removing the `*`: `r`
error[E0507]: cannot move out of borrowed content
--> $DIR/cannot-move-block-spans.rs:17:26
| ^^
| |
| cannot move out of borrowed content
- | help: consider removing this dereference operator: `r`
+ | help: consider removing the `*`: `r`
error[E0508]: cannot move out of type `[std::string::String; 2]`, a non-copy array
--> $DIR/cannot-move-block-spans.rs:21:15
| ^^^^^^
| |
| cannot move out of here
- | help: consider using a reference instead: `&arr[0]`
+ | help: consider borrowing here: `&arr[0]`
error[E0508]: cannot move out of type `[std::string::String; 2]`, a non-copy array
--> $DIR/cannot-move-block-spans.rs:22:22
| ^^^^^^
| |
| cannot move out of here
- | help: consider using a reference instead: `&arr[0]`
+ | help: consider borrowing here: `&arr[0]`
error[E0508]: cannot move out of type `[std::string::String; 2]`, a non-copy array
--> $DIR/cannot-move-block-spans.rs:23:26
| ^^^^^^
| |
| cannot move out of here
- | help: consider using a reference instead: `&arr[0]`
+ | help: consider borrowing here: `&arr[0]`
error[E0507]: cannot move out of borrowed content
--> $DIR/cannot-move-block-spans.rs:27:38
| ^^
| |
| cannot move out of borrowed content
- | help: consider removing this dereference operator: `r`
+ | help: consider removing the `*`: `r`
error[E0507]: cannot move out of borrowed content
--> $DIR/cannot-move-block-spans.rs:28:45
| ^^
| |
| cannot move out of borrowed content
- | help: consider removing this dereference operator: `r`
+ | help: consider removing the `*`: `r`
error[E0507]: cannot move out of borrowed content
--> $DIR/cannot-move-block-spans.rs:29:49
| ^^
| |
| cannot move out of borrowed content
- | help: consider removing this dereference operator: `r`
+ | help: consider removing the `*`: `r`
error: aborting due to 9 previous errors
--- /dev/null
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Regression test for issue #27868
+
+#![feature(nll)]
+
+use std::ops::AddAssign;
+
+struct MyVec<T>(Vec<T>);
+
+impl <T> Drop for MyVec<T> {
+ fn drop(&mut self) {
+ println!("Being dropped.");
+ }
+}
+
+impl<T> AddAssign<T> for MyVec<T> {
+ fn add_assign(&mut self, _elem: T) {
+ println!("In add_assign.");
+ }
+}
+
+fn main() {
+ let mut vec = MyVec(vec![0]);
+ let mut vecvec = vec![vec];
+
+ vecvec[0] += {
+ vecvec = vec![];
+ //~^ ERROR cannot assign to `vecvec` because it is borrowed [E0506]
+ 0
+ };
+}
--- /dev/null
+error[E0506]: cannot assign to `vecvec` because it is borrowed
+ --> $DIR/issue-27868.rs:36:9
+ |
+LL | vecvec[0] += {
+ | ------
+ | |
+ | _____borrow of `vecvec` occurs here
+ | |
+LL | | vecvec = vec![];
+ | | ^^^^^^ assignment to borrowed `vecvec` occurs here
+LL | | //~^ ERROR cannot assign to `vecvec` because it is borrowed [E0506]
+LL | | 0
+LL | | };
+ | |_____- borrow later used here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0506`.
--- /dev/null
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Regression test for #30104
+
+// compile-pass
+
+#![feature(nll)]
+
+use std::ops::{Deref, DerefMut};
+
+fn box_two_field(v: &mut Box<(i32, i32)>) {
+ let _a = &mut v.0;
+ let _b = &mut v.1;
+}
+
+fn box_destructure(v: &mut Box<(i32, i32)>) {
+ let (ref mut _head, ref mut _tail) = **v;
+}
+
+struct Wrap<T>(T);
+
+impl<T> Deref for Wrap<T> {
+ type Target = T;
+ fn deref(&self) -> &T {
+ &self.0
+ }
+}
+
+impl<T> DerefMut for Wrap<T> {
+ fn deref_mut(&mut self) -> &mut T {
+ &mut self.0
+ }
+}
+
+fn smart_two_field(v: &mut Wrap<(i32, i32)>) {
+ let _a = &mut v.0;
+ let _b = &mut v.1;
+}
+
+fn smart_destructure(v: &mut Wrap<(i32, i32)>) {
+ let (ref mut _head, ref mut _tail) = **v;
+}
+
+fn main() {}
--- /dev/null
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Regression test for #48697
+
+// compile-pass
+
+#![feature(nll)]
+
+fn foo(x: &i32) -> &i32 {
+ let z = 4;
+ let f = &|y| y;
+ let k = f(&z);
+ f(x)
+}
+
+fn main() {}
| ^^
| |
| cannot move out of borrowed content
- | help: consider removing this dereference operator: `a`
+ | help: consider removing the `*`: `a`
error[E0508]: cannot move out of type `[A; 1]`, a non-copy array
--> $DIR/move-errors.rs:25:13
| ^^^^
| |
| cannot move out of here
- | help: consider using a reference instead: `&a[0]`
+ | help: consider borrowing here: `&a[0]`
error[E0507]: cannot move out of borrowed content
--> $DIR/move-errors.rs:32:13
| ^^^
| |
| cannot move out of borrowed content
- | help: consider using a reference instead: `&**r`
+ | help: consider removing the `*`: `*r`
error[E0507]: cannot move out of borrowed content
--> $DIR/move-errors.rs:40:13
| ^^
| |
| cannot move out of borrowed content
- | help: consider using a reference instead: `&*r`
+ | help: consider removing the `*`: `r`
error[E0508]: cannot move out of type `[A; 1]`, a non-copy array
--> $DIR/move-errors.rs:45:13
| ^^^^^^^^^^^^^^^^^^^^^^
| |
| cannot move out of here
- | help: consider using a reference instead: `&[A("".to_string())][0]`
+ | help: consider borrowing here: `&[A("".to_string())][0]`
error[E0507]: cannot move out of borrowed content
--> $DIR/move-errors.rs:51:16
| - ^^
| | |
| | cannot move out of borrowed content
- | | help: consider removing this dereference operator: `a`
- | move occurs because s has type `std::string::String`, which does not implement the `Copy` trait
+ | | help: consider removing the `*`: `a`
+ | data moved here
+ |
+note: move occurs because `s` has type `std::string::String`, which does not implement the `Copy` trait
+ --> $DIR/move-errors.rs:51:11
+ |
+LL | let A(s) = *a;
+ | ^
error[E0509]: cannot move out of type `D`, which implements the `Drop` trait
--> $DIR/move-errors.rs:57:19
| - ^ cannot move out of here
| |
| data moved here
- | help: to prevent move, use ref or ref mut: `ref s`
+ |
+note: move occurs because `s` has type `std::string::String`, which does not implement the `Copy` trait
+ --> $DIR/move-errors.rs:57:13
+ |
+LL | let C(D(s)) = c;
+ | ^
error[E0507]: cannot move out of borrowed content
--> $DIR/move-errors.rs:64:9
| ^^^^
| |
| cannot move out of here
- | help: consider using a reference instead: `&x[0]`
+ | help: consider borrowing here: `&x[0]`
LL | //~^ ERROR
LL | B::U(d) => (),
- | - move occurs because d has type `D`, which does not implement the `Copy` trait
+ | - data moved here
LL | B::V(s) => (),
- | - move occurs because s has type `std::string::String`, which does not implement the `Copy` trait
+ | - ...and here
+ |
+note: move occurs because these variables have types that don't implement the `Copy` trait
+ --> $DIR/move-errors.rs:89:14
+ |
+LL | B::U(d) => (),
+ | ^
+LL | B::V(s) => (),
+ | ^
error[E0509]: cannot move out of type `D`, which implements the `Drop` trait
--> $DIR/move-errors.rs:96:11
| ^ cannot move out of here
...
LL | B::U(D(s)) => (),
- | -
- | |
- | data moved here
- | help: to prevent move, use ref or ref mut: `ref s`
+ | - data moved here
+ |
+note: move occurs because `s` has type `std::string::String`, which does not implement the `Copy` trait
+ --> $DIR/move-errors.rs:99:16
+ |
+LL | B::U(D(s)) => (),
+ | ^
error[E0509]: cannot move out of type `D`, which implements the `Drop` trait
--> $DIR/move-errors.rs:105:11
| ^ cannot move out of here
...
LL | (D(s), &t) => (),
- | -
- | |
- | data moved here
- | help: to prevent move, use ref or ref mut: `ref s`
+ | - data moved here
+ |
+note: move occurs because `s` has type `std::string::String`, which does not implement the `Copy` trait
+ --> $DIR/move-errors.rs:108:12
+ |
+LL | (D(s), &t) => (),
+ | ^
error[E0507]: cannot move out of borrowed content
--> $DIR/move-errors.rs:105:11
| ^ cannot move out of borrowed content
...
LL | (D(s), &t) => (),
- | -
- | |
- | data moved here
- | help: to prevent move, use ref or ref mut: `ref t`
+ | - data moved here
+ |
+note: move occurs because `t` has type `std::string::String`, which does not implement the `Copy` trait
+ --> $DIR/move-errors.rs:108:17
+ |
+LL | (D(s), &t) => (),
+ | ^
error[E0509]: cannot move out of type `F`, which implements the `Drop` trait
--> $DIR/move-errors.rs:115:11
| ^ cannot move out of here
LL | //~^ ERROR
LL | F(s, mut t) => (),
- | - ----- ... and here
+ | - ----- ...and here
| |
| data moved here
-help: to prevent move, use ref or ref mut
|
-LL | F(ref s, ref mut t) => (),
- | ^^^^^ ^^^^^^^^^
+note: move occurs because these variables have types that don't implement the `Copy` trait
+ --> $DIR/move-errors.rs:117:11
+ |
+LL | F(s, mut t) => (),
+ | ^ ^^^^^
error[E0507]: cannot move out of borrowed content
--> $DIR/move-errors.rs:123:11
| ^^
| |
| cannot move out of borrowed content
- | help: consider removing this dereference operator: `x`
+ | help: consider removing the `*`: `x`
LL | //~^ ERROR
LL | Ok(s) | Err(s) => (),
- | - move occurs because s has type `std::string::String`, which does not implement the `Copy` trait
+ | - data moved here
+ |
+note: move occurs because `s` has type `std::string::String`, which does not implement the `Copy` trait
+ --> $DIR/move-errors.rs:125:12
+ |
+LL | Ok(s) | Err(s) => (),
+ | ^
error: aborting due to 14 previous errors
{}
#[rustc_on_unimplemented = "Unimplemented trait error on `{Self}` with params `<{A},{B},{C}>`"]
-//~^ ERROR there is no parameter C on trait BadAnnotation2
+//~^ ERROR there is no parameter `C` on trait `BadAnnotation2`
trait BadAnnotation2<A,B>
{}
LL | #[rustc_on_unimplemented] //~ ERROR `#[rustc_on_unimplemented]` requires a value
| ^^^^^^^^^^^^^^^^^^^^^^^^^ value required here
|
- = note: eg `#[rustc_on_unimplemented = "foo"]`
+ = note: eg `#[rustc_on_unimplemented(message="foo")]`
-error[E0230]: there is no parameter C on trait BadAnnotation2
+error[E0230]: there is no parameter `C` on trait `BadAnnotation2`
--> $DIR/bad-annotation.rs:30:1
|
LL | #[rustc_on_unimplemented = "Unimplemented trait error on `{Self}` with params `<{A},{B},{C}>`"]
LL | #[rustc_on_unimplemented(lorem="")]
| ^^^^^^^^ expected value here
|
- = note: eg `#[rustc_on_unimplemented = "foo"]`
+ = note: eg `#[rustc_on_unimplemented(message="foo")]`
error[E0232]: this attribute must have a valid value
--> $DIR/bad-annotation.rs:44:26
LL | #[rustc_on_unimplemented(lorem(ipsum(dolor)))]
| ^^^^^^^^^^^^^^^^^^^ expected value here
|
- = note: eg `#[rustc_on_unimplemented = "foo"]`
+ = note: eg `#[rustc_on_unimplemented(message="foo")]`
error[E0232]: this attribute must have a valid value
--> $DIR/bad-annotation.rs:48:39
LL | #[rustc_on_unimplemented(message="x", message="y")]
| ^^^^^^^^^^^ expected value here
|
- = note: eg `#[rustc_on_unimplemented = "foo"]`
+ = note: eg `#[rustc_on_unimplemented(message="foo")]`
error[E0232]: this attribute must have a valid value
--> $DIR/bad-annotation.rs:52:39
LL | #[rustc_on_unimplemented(message="x", on(desugared, message="y"))]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ expected value here
|
- = note: eg `#[rustc_on_unimplemented = "foo"]`
+ = note: eg `#[rustc_on_unimplemented(message="foo")]`
error[E0232]: empty `on`-clause in `#[rustc_on_unimplemented]`
--> $DIR/bad-annotation.rs:56:26
LL | #[rustc_on_unimplemented(on="x", message="y")]
| ^^^^^^ expected value here
|
- = note: eg `#[rustc_on_unimplemented = "foo"]`
+ = note: eg `#[rustc_on_unimplemented(message="foo")]`
error[E0232]: this attribute must have a valid value
--> $DIR/bad-annotation.rs:67:40
LL | #[rustc_on_unimplemented(on(desugared, on(desugared, message="x")), message="y")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ expected value here
|
- = note: eg `#[rustc_on_unimplemented = "foo"]`
+ = note: eg `#[rustc_on_unimplemented(message="foo")]`
error: aborting due to 10 previous errors
error: incorrect close delimiter: `)`
--> $DIR/parser-recovery-2.rs:18:5
|
-LL | ) //~ ERROR incorrect close delimiter: `)`
- | ^
- |
-note: unclosed delimiter
- --> $DIR/parser-recovery-2.rs:16:14
- |
LL | fn bar() {
- | ^
+ | - unclosed delimiter
+LL | let x = foo(); //~ ERROR cannot find function `foo` in this scope
+LL | ) //~ ERROR incorrect close delimiter: `)`
+ | ^ incorrect close delimiter
error: unexpected token: `;`
--> $DIR/parser-recovery-2.rs:22:15
error: incorrect close delimiter: `)`
--> $DIR/token-error-correct-2.rs:16:5
|
-LL | ) //~ ERROR: incorrect close delimiter: `)`
- | ^
- |
-note: unclosed delimiter
- --> $DIR/token-error-correct-2.rs:14:12
- |
LL | if foo {
- | ^
+ | - unclosed delimiter
+LL | //~^ ERROR: cannot find value `foo`
+LL | ) //~ ERROR: incorrect close delimiter: `)`
+ | ^ incorrect close delimiter
error[E0425]: cannot find value `foo` in this scope
--> $DIR/token-error-correct-2.rs:14:8
error: incorrect close delimiter: `}`
--> $DIR/token-error-correct-3.rs:30:9
|
-LL | } else { //~ ERROR: incorrect close delimiter: `}`
- | ^
- |
-note: unclosed delimiter
- --> $DIR/token-error-correct-3.rs:24:21
- |
LL | callback(path.as_ref(); //~ ERROR expected one of
- | ^
+ | - unclosed delimiter
+...
+LL | } else { //~ ERROR: incorrect close delimiter: `}`
+ | ^ incorrect close delimiter
error: expected one of `)`, `,`, `.`, `?`, or an operator, found `;`
--> $DIR/token-error-correct-3.rs:24:35
//~^ ERROR: expected expression, found `;`
}
//~^ ERROR: incorrect close delimiter: `}`
-//~| ERROR: incorrect close delimiter: `}`
error: incorrect close delimiter: `}`
--> $DIR/token-error-correct.rs:16:1
|
-LL | }
- | ^
- |
-note: unclosed delimiter
- --> $DIR/token-error-correct.rs:14:12
- |
LL | foo(bar(;
- | ^
-
-error: incorrect close delimiter: `}`
- --> $DIR/token-error-correct.rs:16:1
- |
+ | - unclosed delimiter
+LL | //~^ ERROR: expected expression, found `;`
LL | }
- | ^
- |
-note: unclosed delimiter
- --> $DIR/token-error-correct.rs:14:8
- |
-LL | foo(bar(;
- | ^
+ | ^ incorrect close delimiter
error: expected expression, found `;`
--> $DIR/token-error-correct.rs:14:13
LL | foo(bar(;
| ^ expected expression
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
pub mod m {
fn f() {
let s = ::m::crate::S; //~ ERROR failed to resolve
+ let s1 = ::crate::S; //~ ERROR failed to resolve
let s2 = crate::S; // no error
}
}
-error[E0433]: failed to resolve. Could not find `crate` in `m`
+error[E0433]: failed to resolve. `crate` in paths can only be used in start position
--> $DIR/crate-path-non-absolute.rs:17:22
|
LL | let s = ::m::crate::S; //~ ERROR failed to resolve
- | ^^^^^ Could not find `crate` in `m`
+ | ^^^^^ `crate` in paths can only be used in start position
-error: aborting due to previous error
+error[E0433]: failed to resolve. global paths cannot start with `crate`
+ --> $DIR/crate-path-non-absolute.rs:18:20
+ |
+LL | let s1 = ::crate::S; //~ ERROR failed to resolve
+ | ^^^^^ global paths cannot start with `crate`
+
+error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0433`.
#![feature(crate_in_paths)]
fn main() {
- let crate = 0; //~ ERROR failed to resolve. `crate` in paths can only be used in start position
+ let crate = 0;
+ //~^ ERROR expected unit struct/variant or constant, found module `crate`
}
-error[E0433]: failed to resolve. `crate` in paths can only be used in start position
+error[E0532]: expected unit struct/variant or constant, found module `crate`
--> $DIR/keyword-crate-as-identifier.rs:14:9
|
-LL | let crate = 0; //~ ERROR failed to resolve. `crate` in paths can only be used in start position
- | ^^^^^ `crate` in paths can only be used in start position
+LL | let crate = 0;
+ | ^^^^^ not a unit struct/variant or constant
error: aborting due to previous error
-For more information about this error, try `rustc --explain E0433`.
+For more information about this error, try `rustc --explain E0532`.
// except according to those terms.
#![feature(generic_associated_types)]
+//~^ WARNING the feature `generic_associated_types` is incomplete
#![feature(associated_type_defaults)]
-//FIXME(#44265): "lifetime parameters are not allowed on this type" errors will be addressed in a
-//follow-up PR
+// FIXME(#44265): "lifetime parameters are not allowed on this type" errors will be addressed in a
+// follow-up PR.
// A Collection trait and collection families. Based on
// http://smallcultfollowing.com/babysteps/blog/2016/11/03/
+warning: the feature `generic_associated_types` is incomplete and may cause the compiler to crash
+ --> $DIR/collections.rs:11:12
+ |
+LL | #![feature(generic_associated_types)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
+
error[E0109]: type parameters are not allowed on this type
- --> $DIR/collections.rs:65:90
+ --> $DIR/collections.rs:66:90
|
LL | fn floatify<C>(ints: &C) -> <<C as Collection<i32>>::Family as CollectionFamily>::Member<f32>
| ^^^ type parameter not allowed
error[E0109]: type parameters are not allowed on this type
- --> $DIR/collections.rs:77:69
+ --> $DIR/collections.rs:78:69
|
LL | fn floatify_sibling<C>(ints: &C) -> <C as Collection<i32>>::Sibling<f32>
| ^^^ type parameter not allowed
error[E0109]: type parameters are not allowed on this type
- --> $DIR/collections.rs:26:71
+ --> $DIR/collections.rs:27:71
|
LL | <<Self as Collection<T>>::Family as CollectionFamily>::Member<U>;
| ^ type parameter not allowed
error[E0110]: lifetime parameters are not allowed on this type
- --> $DIR/collections.rs:33:50
+ --> $DIR/collections.rs:34:50
|
LL | fn iterate<'iter>(&'iter self) -> Self::Iter<'iter>;
| ^^^^^ lifetime parameter not allowed
error[E0110]: lifetime parameters are not allowed on this type
- --> $DIR/collections.rs:59:50
+ --> $DIR/collections.rs:60:50
|
LL | fn iterate<'iter>(&'iter self) -> Self::Iter<'iter> {
| ^^^^^ lifetime parameter not allowed
// except according to those terms.
#![feature(generic_associated_types)]
+//~^ WARNING the feature `generic_associated_types` is incomplete
use std::ops::Deref;
-//FIXME(#44265): "lifetime parameters are not allowed on this type" errors will be addressed in a
-//follow-up PR
+// FIXME(#44265): "lifetime parameters are not allowed on this type" errors will be addressed in a
+// follow-up PR.
trait Foo {
type Bar<'a, 'b>;
+warning: the feature `generic_associated_types` is incomplete and may cause the compiler to crash
+ --> $DIR/construct_with_other_type.rs:11:12
+ |
+LL | #![feature(generic_associated_types)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
+
error[E0110]: lifetime parameters are not allowed on this type
- --> $DIR/construct_with_other_type.rs:26:46
+ --> $DIR/construct_with_other_type.rs:27:46
|
LL | type Baa<'a>: Deref<Target = <Self::Quux<'a> as Foo>::Bar<'a, 'static>>;
| ^^ lifetime parameter not allowed
error[E0110]: lifetime parameters are not allowed on this type
- --> $DIR/construct_with_other_type.rs:26:63
+ --> $DIR/construct_with_other_type.rs:27:63
|
LL | type Baa<'a>: Deref<Target = <Self::Quux<'a> as Foo>::Bar<'a, 'static>>;
| ^^ lifetime parameter not allowed
error[E0110]: lifetime parameters are not allowed on this type
- --> $DIR/construct_with_other_type.rs:34:40
+ --> $DIR/construct_with_other_type.rs:35:40
|
LL | type Baa<'a> = &'a <T as Foo>::Bar<'a, 'static>;
| ^^ lifetime parameter not allowed
// except according to those terms.
#![feature(generic_associated_types)]
+//~^ WARNING the feature `generic_associated_types` is incomplete
trait Foo {
type Bar<,>;
error: expected one of `>`, identifier, or lifetime, found `,`
- --> $DIR/empty_generics.rs:14:14
+ --> $DIR/empty_generics.rs:15:14
|
LL | type Bar<,>;
| ^ expected one of `>`, identifier, or lifetime here
+warning: the feature `generic_associated_types` is incomplete and may cause the compiler to crash
+ --> $DIR/empty_generics.rs:11:12
+ |
+LL | #![feature(generic_associated_types)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
+
error: aborting due to previous error
--- /dev/null
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// run-pass
+
+#![feature(generic_associated_types)]
+//~^ WARNING the feature `generic_associated_types` is incomplete
+
+fn main() {}
--- /dev/null
+warning: the feature `generic_associated_types` is incomplete and may cause the compiler to crash
+ --> $DIR/gat-incomplete-warning.rs:13:12
+ |
+LL | #![feature(generic_associated_types)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
+
--- /dev/null
+warning: the feature `generic_associated_types` is incomplete and may cause the compiler to crash
+ --> $DIR/generic-associated-types-where.rs:11:12
+ |
+LL | #![feature(generic_associated_types)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
+
// except according to those terms.
#![feature(generic_associated_types)]
+//~^ WARNING the feature `generic_associated_types` is incomplete
use std::ops::Deref;
-//FIXME(#44265): "lifetime parameters are not allowed on this type" errors will be addressed in a
-//follow-up PR
+// FIXME(#44265): "lifetime parameters are not allowed on this type" errors will be addressed in a
+// follow-up PR.
trait Iterable {
type Item<'a>;
+warning: the feature `generic_associated_types` is incomplete and may cause the compiler to crash
+ --> $DIR/generic_associated_type_undeclared_lifetimes.rs:11:12
+ |
+LL | #![feature(generic_associated_types)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
+
error[E0261]: use of undeclared lifetime name `'b`
- --> $DIR/generic_associated_type_undeclared_lifetimes.rs:22:37
+ --> $DIR/generic_associated_type_undeclared_lifetimes.rs:23:37
|
LL | + Deref<Target = Self::Item<'b>>;
| ^^ undeclared lifetime
error[E0261]: use of undeclared lifetime name `'undeclared`
- --> $DIR/generic_associated_type_undeclared_lifetimes.rs:26:41
+ --> $DIR/generic_associated_type_undeclared_lifetimes.rs:27:41
|
LL | fn iter<'a>(&'a self) -> Self::Iter<'undeclared>;
| ^^^^^^^^^^^ undeclared lifetime
error[E0110]: lifetime parameters are not allowed on this type
- --> $DIR/generic_associated_type_undeclared_lifetimes.rs:20:47
+ --> $DIR/generic_associated_type_undeclared_lifetimes.rs:21:47
|
LL | type Iter<'a>: Iterator<Item = Self::Item<'a>>
| ^^ lifetime parameter not allowed
error[E0110]: lifetime parameters are not allowed on this type
- --> $DIR/generic_associated_type_undeclared_lifetimes.rs:22:37
+ --> $DIR/generic_associated_type_undeclared_lifetimes.rs:23:37
|
LL | + Deref<Target = Self::Item<'b>>;
| ^^ lifetime parameter not allowed
error[E0110]: lifetime parameters are not allowed on this type
- --> $DIR/generic_associated_type_undeclared_lifetimes.rs:26:41
+ --> $DIR/generic_associated_type_undeclared_lifetimes.rs:27:41
|
LL | fn iter<'a>(&'a self) -> Self::Iter<'undeclared>;
| ^^^^^^^^^^^ lifetime parameter not allowed
// except according to those terms.
#![feature(generic_associated_types)]
+//~^ WARNING the feature `generic_associated_types` is incomplete
use std::ops::Deref;
-//FIXME(#44265): "lifetime parameters are not allowed on this type" errors will be addressed in a
-//follow-up PR
+// FIXME(#44265): "lifetime parameters are not allowed on this type" errors will be addressed in a
+// follow-up PR.
trait Iterable {
type Item<'a>;
+warning: the feature `generic_associated_types` is incomplete and may cause the compiler to crash
+ --> $DIR/iterable.rs:11:12
+ |
+LL | #![feature(generic_associated_types)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
+
error[E0110]: lifetime parameters are not allowed on this type
- --> $DIR/iterable.rs:20:47
+ --> $DIR/iterable.rs:21:47
|
LL | type Iter<'a>: Iterator<Item = Self::Item<'a>>;
| ^^ lifetime parameter not allowed
error[E0110]: lifetime parameters are not allowed on this type
- --> $DIR/iterable.rs:49:53
+ --> $DIR/iterable.rs:50:53
|
LL | fn make_iter<'a, I: Iterable>(it: &'a I) -> I::Iter<'a> {
| ^^ lifetime parameter not allowed
error[E0110]: lifetime parameters are not allowed on this type
- --> $DIR/iterable.rs:54:60
+ --> $DIR/iterable.rs:55:60
|
LL | fn get_first<'a, I: Iterable>(it: &'a I) -> Option<I::Item<'a>> {
| ^^ lifetime parameter not allowed
error[E0110]: lifetime parameters are not allowed on this type
- --> $DIR/iterable.rs:23:41
+ --> $DIR/iterable.rs:24:41
|
LL | fn iter<'a>(&'a self) -> Self::Iter<'a>;
| ^^ lifetime parameter not allowed
error[E0110]: lifetime parameters are not allowed on this type
- --> $DIR/iterable.rs:32:41
+ --> $DIR/iterable.rs:33:41
|
LL | fn iter<'a>(&'a self) -> Self::Iter<'a> {
| ^^ lifetime parameter not allowed
error[E0110]: lifetime parameters are not allowed on this type
- --> $DIR/iterable.rs:43:41
+ --> $DIR/iterable.rs:44:41
|
LL | fn iter<'a>(&'a self) -> Self::Iter<'a> {
| ^^ lifetime parameter not allowed
// except according to those terms.
#![feature(generic_associated_types)]
+//~^ WARNING the feature `generic_associated_types` is incomplete
#![feature(associated_type_defaults)]
-//FIXME(#44265): "lifetime parameters are not allowed on this type" errors will be addressed in a
-//follow-up PR
+// FIXME(#44265): "lifetime parameters are not allowed on this type" errors will be addressed in a
+// follow-up PR.
-//FIXME(#44265): Update expected errors once E110 is resolved, now does not get past `trait Foo`
+// FIXME(#44265): Update expected errors once E110 is resolved, now does not get past `trait Foo`.
trait Foo {
type A<'a>;
+warning: the feature `generic_associated_types` is incomplete and may cause the compiler to crash
+ --> $DIR/parameter_number_and_kind.rs:11:12
+ |
+LL | #![feature(generic_associated_types)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
+
error[E0110]: lifetime parameters are not allowed on this type
- --> $DIR/parameter_number_and_kind.rs:26:27
+ --> $DIR/parameter_number_and_kind.rs:27:27
|
LL | type FOk<T> = Self::E<'static, T>;
| ^^^^^^^ lifetime parameter not allowed
error[E0109]: type parameters are not allowed on this type
- --> $DIR/parameter_number_and_kind.rs:26:36
+ --> $DIR/parameter_number_and_kind.rs:27:36
|
LL | type FOk<T> = Self::E<'static, T>;
| ^ type parameter not allowed
error[E0110]: lifetime parameters are not allowed on this type
- --> $DIR/parameter_number_and_kind.rs:29:26
+ --> $DIR/parameter_number_and_kind.rs:30:26
|
LL | type FErr1 = Self::E<'static, 'static>; // Error
| ^^^^^^^ lifetime parameter not allowed
error[E0110]: lifetime parameters are not allowed on this type
- --> $DIR/parameter_number_and_kind.rs:31:29
+ --> $DIR/parameter_number_and_kind.rs:32:29
|
LL | type FErr2<T> = Self::E<'static, T, u32>; // Error
| ^^^^^^^ lifetime parameter not allowed
error[E0109]: type parameters are not allowed on this type
- --> $DIR/parameter_number_and_kind.rs:31:38
+ --> $DIR/parameter_number_and_kind.rs:32:38
|
LL | type FErr2<T> = Self::E<'static, T, u32>; // Error
| ^ type parameter not allowed
// except according to those terms.
#![feature(generic_associated_types)]
+//~^ WARNING the feature `generic_associated_types` is incomplete
-//FIXME(#44265): "type parameter not allowed" errors will be addressed in a follow-up PR
+// FIXME(#44265): "type parameter not allowed" errors will be addressed in a follow-up PR.
use std::rc::Rc;
use std::sync::Arc;
+warning: the feature `generic_associated_types` is incomplete and may cause the compiler to crash
+ --> $DIR/pointer_family.rs:11:12
+ |
+LL | #![feature(generic_associated_types)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
+
error[E0109]: type parameters are not allowed on this type
- --> $DIR/pointer_family.rs:46:21
+ --> $DIR/pointer_family.rs:47:21
|
LL | bar: P::Pointer<String>,
| ^^^^^^ type parameter not allowed
error[E0109]: type parameters are not allowed on this type
- --> $DIR/pointer_family.rs:21:42
+ --> $DIR/pointer_family.rs:22:42
|
LL | fn new<T>(value: T) -> Self::Pointer<T>;
| ^ type parameter not allowed
error[E0109]: type parameters are not allowed on this type
- --> $DIR/pointer_family.rs:29:42
+ --> $DIR/pointer_family.rs:30:42
|
LL | fn new<T>(value: T) -> Self::Pointer<T> {
| ^ type parameter not allowed
error[E0109]: type parameters are not allowed on this type
- --> $DIR/pointer_family.rs:39:42
+ --> $DIR/pointer_family.rs:40:42
|
LL | fn new<T>(value: T) -> Self::Pointer<T> {
| ^ type parameter not allowed
--- /dev/null
+warning: the feature `generic_associated_types` is incomplete and may cause the compiler to crash
+ --> $DIR/shadowing.rs:11:12
+ |
+LL | #![feature(generic_associated_types)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
+
// except according to those terms.
#![feature(generic_associated_types)]
+//~^ WARNING the feature `generic_associated_types` is incomplete
-//FIXME(#44265): "lifetime parameter not allowed on this type" errors will be addressed in a
+// FIXME(#44265): "lifetime parameter not allowed on this type" errors will be addressed in a
// follow-up PR
use std::fmt::Display;
+warning: the feature `generic_associated_types` is incomplete and may cause the compiler to crash
+ --> $DIR/streaming_iterator.rs:11:12
+ |
+LL | #![feature(generic_associated_types)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
+
error[E0110]: lifetime parameters are not allowed on this type
- --> $DIR/streaming_iterator.rs:27:41
+ --> $DIR/streaming_iterator.rs:28:41
|
LL | bar: <T as StreamingIterator>::Item<'static>,
| ^^^^^^^ lifetime parameter not allowed
error[E0110]: lifetime parameters are not allowed on this type
- --> $DIR/streaming_iterator.rs:35:64
+ --> $DIR/streaming_iterator.rs:36:64
|
LL | fn foo<T>(iter: T) where T: StreamingIterator, for<'a> T::Item<'a>: Display { /* ... */ }
| ^^ lifetime parameter not allowed
error[E0110]: lifetime parameters are not allowed on this type
- --> $DIR/streaming_iterator.rs:21:48
+ --> $DIR/streaming_iterator.rs:22:48
|
LL | fn next<'a>(&'a self) -> Option<Self::Item<'a>>;
| ^^ lifetime parameter not allowed
error[E0110]: lifetime parameters are not allowed on this type
- --> $DIR/streaming_iterator.rs:47:37
+ --> $DIR/streaming_iterator.rs:48:37
|
LL | type Item<'a> = (usize, I::Item<'a>);
| ^^ lifetime parameter not allowed
error[E0110]: lifetime parameters are not allowed on this type
- --> $DIR/streaming_iterator.rs:49:48
+ --> $DIR/streaming_iterator.rs:50:48
|
LL | fn next<'a>(&'a self) -> Option<Self::Item<'a>> {
| ^^ lifetime parameter not allowed
//~^ ERROR absolute
//~| WARN this was previously accepted
let x = bar::Bar;
- let x = ::crate::bar::Bar;
+ let x = crate::bar::Bar;
let x = self::bar::Bar;
foo::test();
//~^ ERROR absolute
//~| WARN this was previously accepted
let x = bar::Bar;
- let x = ::crate::bar::Bar;
+ let x = crate::bar::Bar;
let x = self::bar::Bar;
foo::test();
mod foo {
pub use std::io;
- //~^ ERROR import from `std` is ambiguous
+ //~^ ERROR `std` import is ambiguous
macro_rules! m {
() => {
-error: import from `std` is ambiguous
+error: `std` import is ambiguous
--> $DIR/ambiguity-macros-nested.rs:18:13
|
LL | pub use std::io;
- | ^^^ could refer to external crate `::std`
+ | ^^^ can refer to external crate `::std`
...
LL | / mod std {
LL | | pub struct io;
LL | | }
- | |_____________- could also refer to `self::std`
+ | |_____________- can refer to `self::std`
|
= help: write `::std` or `self::std` explicitly instead
= note: relative `use` paths enabled by `#![feature(uniform_paths)]`
// This test is similar to `ambiguity.rs`, but with macros defining local items.
use std::io;
-//~^ ERROR import from `std` is ambiguous
+//~^ ERROR `std` import is ambiguous
macro_rules! m {
() => {
-error: import from `std` is ambiguous
+error: `std` import is ambiguous
--> $DIR/ambiguity-macros.rs:17:5
|
LL | use std::io;
- | ^^^ could refer to external crate `::std`
+ | ^^^ can refer to external crate `::std`
...
LL | / mod std {
LL | | pub struct io;
LL | | }
- | |_________- could also refer to `self::std`
+ | |_________- can refer to `self::std`
|
= help: write `::std` or `self::std` explicitly instead
= note: relative `use` paths enabled by `#![feature(uniform_paths)]`
mod foo {
pub use std::io;
- //~^ ERROR import from `std` is ambiguous
+ //~^ ERROR `std` import is ambiguous
mod std {
pub struct io;
-error: import from `std` is ambiguous
+error: `std` import is ambiguous
--> $DIR/ambiguity-nested.rs:18:13
|
LL | pub use std::io;
- | ^^^ could refer to external crate `::std`
+ | ^^^ can refer to external crate `::std`
...
LL | / mod std {
LL | | pub struct io;
LL | | }
- | |_____- could also refer to `self::std`
+ | |_____- can refer to `self::std`
|
= help: write `::std` or `self::std` explicitly instead
= note: relative `use` paths enabled by `#![feature(uniform_paths)]`
#![feature(uniform_paths)]
use std::io;
-//~^ ERROR import from `std` is ambiguous
+//~^ ERROR `std` import is ambiguous
mod std {
pub struct io;
-error: import from `std` is ambiguous
+error: `std` import is ambiguous
--> $DIR/ambiguity.rs:15:5
|
LL | use std::io;
- | ^^^ could refer to external crate `::std`
+ | ^^^ can refer to external crate `::std`
...
LL | / mod std {
LL | | pub struct io;
LL | | }
- | |_- could also refer to `self::std`
+ | |_- can refer to `self::std`
|
= help: write `::std` or `self::std` explicitly instead
= note: relative `use` paths enabled by `#![feature(uniform_paths)]`
enum Foo { A, B }
+struct std;
+
fn main() {
enum Foo {}
use Foo::*;
- //~^ ERROR import from `Foo` is ambiguous
+ //~^ ERROR `Foo` import is ambiguous
let _ = (A, B);
+
+ fn std() {}
+ enum std {}
+ use std as foo;
+ //~^ ERROR `std` import is ambiguous
+ //~| ERROR `std` import is ambiguous
}
-error: import from `Foo` is ambiguous
- --> $DIR/block-scoped-shadow.rs:19:9
+error: `Foo` import is ambiguous
+ --> $DIR/block-scoped-shadow.rs:21:9
|
+LL | enum Foo { A, B }
+ | ----------------- can refer to `self::Foo`
+...
LL | enum Foo {}
| ----------- shadowed by block-scoped `Foo`
LL | use Foo::*;
| ^^^
|
- = help: write `::Foo` or `self::Foo` explicitly instead
+ = help: write `self::Foo` explicitly instead
= note: relative `use` paths enabled by `#![feature(uniform_paths)]`
-error: aborting due to previous error
+error: `std` import is ambiguous
+ --> $DIR/block-scoped-shadow.rs:28:9
+ |
+LL | struct std;
+ | ----------- can refer to `self::std`
+...
+LL | enum std {}
+ | ----------- shadowed by block-scoped `std`
+LL | use std as foo;
+ | ^^^ can refer to external crate `::std`
+ |
+ = help: write `::std` or `self::std` explicitly instead
+ = note: relative `use` paths enabled by `#![feature(uniform_paths)]`
+
+error: `std` import is ambiguous
+ --> $DIR/block-scoped-shadow.rs:28:9
+ |
+LL | struct std;
+ | ----------- can refer to `self::std`
+...
+LL | fn std() {}
+ | ----------- shadowed by block-scoped `std`
+LL | enum std {}
+LL | use std as foo;
+ | ^^^
+ |
+ = help: write `self::std` explicitly instead
+ = note: relative `use` paths enabled by `#![feature(uniform_paths)]`
+
+error: aborting due to 3 previous errors
--- /dev/null
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// edition:2018
+
+#![feature(uniform_paths)]
+
+use std;
+
+fn main() {}
--- /dev/null
+error: `std` import is redundant
+ --> $DIR/redundant.rs:15:5
+ |
+LL | use std;
+ | ^^^
+ | |
+ | refers to external crate `::std`
+ | defines `self::std`, shadowing itself
+ |
+ = help: remove or write `::std` explicitly instead
+ = note: relative `use` paths enabled by `#![feature(uniform_paths)]`
+
+error: aborting due to previous error
+
--- /dev/null
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/std-uncopyable-atomics.rs:19:13
+ |
+LL | let x = *&x; //~ ERROR: cannot move out of borrowed content
+ | ^^^
+ | |
+ | cannot move out of borrowed content
+ | help: consider removing the `*`: `&x`
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/std-uncopyable-atomics.rs:21:13
+ |
+LL | let x = *&x; //~ ERROR: cannot move out of borrowed content
+ | ^^^
+ | |
+ | cannot move out of borrowed content
+ | help: consider removing the `*`: `&x`
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/std-uncopyable-atomics.rs:23:13
+ |
+LL | let x = *&x; //~ ERROR: cannot move out of borrowed content
+ | ^^^
+ | |
+ | cannot move out of borrowed content
+ | help: consider removing the `*`: `&x`
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/std-uncopyable-atomics.rs:25:13
+ |
+LL | let x = *&x; //~ ERROR: cannot move out of borrowed content
+ | ^^^
+ | |
+ | cannot move out of borrowed content
+ | help: consider removing the `*`: `&x`
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0507`.
--- /dev/null
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(nll)]
+
+#[derive(Clone)]
+enum Either {
+ One(X),
+ Two(X),
+}
+
+#[derive(Clone)]
+struct X(Y);
+
+#[derive(Clone)]
+struct Y;
+
+
+pub fn main() {
+ let e = Either::One(X(Y));
+ let mut em = Either::One(X(Y));
+
+ let r = &e;
+ let rm = &mut Either::One(X(Y));
+
+ let x = X(Y);
+ let mut xm = X(Y);
+
+ let s = &x;
+ let sm = &mut X(Y);
+
+ let ve = vec![Either::One(X(Y))];
+
+ let vr = &ve;
+ let vrm = &mut vec![Either::One(X(Y))];
+
+ let vx = vec![X(Y)];
+
+ let vs = &vx;
+ let vsm = &mut vec![X(Y)];
+
+ // -------- test for duplicate suggestions --------
+
+ let &(X(_t), X(_u)) = &(x.clone(), x.clone());
+ //~^ ERROR cannot move
+ //~| HELP consider removing the `&`
+ //~| SUGGESTION (X(_t), X(_u))
+ if let &(Either::One(_t), Either::Two(_u)) = &(e.clone(), e.clone()) { }
+ //~^ ERROR cannot move
+ //~| HELP consider removing the `&`
+ //~| SUGGESTION (Either::One(_t), Either::Two(_u))
+ while let &(Either::One(_t), Either::Two(_u)) = &(e.clone(), e.clone()) { }
+ //~^ ERROR cannot move
+ //~| HELP consider removing the `&`
+ //~| SUGGESTION (Either::One(_t), Either::Two(_u))
+ match &(e.clone(), e.clone()) {
+ //~^ ERROR cannot move
+ &(Either::One(_t), Either::Two(_u)) => (),
+ //~^ HELP consider removing the `&`
+ //~| SUGGESTION (Either::One(_t), Either::Two(_u))
+ &(Either::Two(_t), Either::One(_u)) => (),
+ //~^ HELP consider removing the `&`
+ //~| SUGGESTION (Either::Two(_t), Either::One(_u))
+ _ => (),
+ }
+ match &(e.clone(), e.clone()) {
+ //~^ ERROR cannot move
+ &(Either::One(_t), Either::Two(_u))
+ //~^ HELP consider removing the `&`
+ //~| SUGGESTION (Either::One(_t), Either::Two(_u))
+ | &(Either::Two(_t), Either::One(_u)) => (),
+ // FIXME: would really like a suggestion here too
+ _ => (),
+ }
+ match &(e.clone(), e.clone()) {
+ //~^ ERROR cannot move
+ &(Either::One(_t), Either::Two(_u)) => (),
+ //~^ HELP consider removing the `&`
+ //~| SUGGESTION (Either::One(_t), Either::Two(_u))
+ &(Either::Two(ref _t), Either::One(ref _u)) => (),
+ _ => (),
+ }
+ match &(e.clone(), e.clone()) {
+ //~^ ERROR cannot move
+ &(Either::One(_t), Either::Two(_u)) => (),
+ //~^ HELP consider removing the `&`
+ //~| SUGGESTION (Either::One(_t), Either::Two(_u))
+ (Either::Two(_t), Either::One(_u)) => (),
+ _ => (),
+ }
+ fn f5(&(X(_t), X(_u)): &(X, X)) { }
+ //~^ ERROR cannot move
+ //~| HELP consider removing the `&`
+ //~| SUGGESTION (X(_t), X(_u))
+
+ let &mut (X(_t), X(_u)) = &mut (xm.clone(), xm.clone());
+ //~^ ERROR cannot move
+ //~| HELP consider removing the `&mut`
+ //~| SUGGESTION (X(_t), X(_u))
+ if let &mut (Either::One(_t), Either::Two(_u)) = &mut (em.clone(), em.clone()) { }
+ //~^ ERROR cannot move
+ //~| HELP consider removing the `&mut`
+ //~| SUGGESTION (Either::One(_t), Either::Two(_u))
+ while let &mut (Either::One(_t), Either::Two(_u)) = &mut (em.clone(), em.clone()) { }
+ //~^ ERROR cannot move
+ //~| HELP consider removing the `&mut`
+ //~| SUGGESTION (Either::One(_t), Either::Two(_u))
+ match &mut (em.clone(), em.clone()) {
+ //~^ ERROR cannot move
+ &mut (Either::One(_t), Either::Two(_u)) => (),
+ //~^ HELP consider removing the `&mut`
+ //~| SUGGESTION (Either::One(_t), Either::Two(_u))
+ &mut (Either::Two(_t), Either::One(_u)) => (),
+ //~^ HELP consider removing the `&mut`
+ //~| SUGGESTION (Either::Two(_t), Either::One(_u))
+ _ => (),
+ }
+ match &mut (em.clone(), em.clone()) {
+ //~^ ERROR cannot move
+ &mut (Either::One(_t), Either::Two(_u))
+ //~^ HELP consider removing the `&mut`
+ //~| SUGGESTION (Either::One(_t), Either::Two(_u))
+ | &mut (Either::Two(_t), Either::One(_u)) => (),
+ // FIXME: would really like a suggestion here too
+ _ => (),
+ }
+ match &mut (em.clone(), em.clone()) {
+ //~^ ERROR cannot move
+ &mut (Either::One(_t), Either::Two(_u)) => (),
+ //~^ HELP consider removing the `&mut`
+ //~| SUGGESTION (Either::One(_t), Either::Two(_u))
+ &mut (Either::Two(ref _t), Either::One(ref _u)) => (),
+ _ => (),
+ }
+ match &mut (em.clone(), em.clone()) {
+ //~^ ERROR cannot move
+ &mut (Either::One(_t), Either::Two(_u)) => (),
+ //~^ HELP consider removing the `&mut`
+ //~| SUGGESTION (Either::One(_t), Either::Two(_u))
+ &mut (Either::Two(ref mut _t), Either::One(ref mut _u)) => (),
+ _ => (),
+ }
+ match &mut (em.clone(), em.clone()) {
+ //~^ ERROR cannot move
+ &mut (Either::One(_t), Either::Two(_u)) => (),
+ //~^ HELP consider removing the `&mut`
+ //~| SUGGESTION (Either::One(_t), Either::Two(_u))
+ (Either::Two(_t), Either::One(_u)) => (),
+ _ => (),
+ }
+ fn f6(&mut (X(_t), X(_u)): &mut (X, X)) { }
+ //~^ ERROR cannot move
+ //~| HELP consider removing the `&mut`
+ //~| SUGGESTION (X(_t), X(_u))
+}
--- /dev/null
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/duplicate-suggestions.rs:51:27
+ |
+LL | let &(X(_t), X(_u)) = &(x.clone(), x.clone());
+ | --------------- ^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of borrowed content
+ | | | |
+ | | | ...and here
+ | | data moved here
+ | help: consider removing the `&`: `(X(_t), X(_u))`
+ |
+note: move occurs because these variables have types that don't implement the `Copy` trait
+ --> $DIR/duplicate-suggestions.rs:51:13
+ |
+LL | let &(X(_t), X(_u)) = &(x.clone(), x.clone());
+ | ^^ ^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/duplicate-suggestions.rs:55:50
+ |
+LL | if let &(Either::One(_t), Either::Two(_u)) = &(e.clone(), e.clone()) { }
+ | ----------------------------------- ^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of borrowed content
+ | | | |
+ | | | ...and here
+ | | data moved here
+ | help: consider removing the `&`: `(Either::One(_t), Either::Two(_u))`
+ |
+note: move occurs because these variables have types that don't implement the `Copy` trait
+ --> $DIR/duplicate-suggestions.rs:55:26
+ |
+LL | if let &(Either::One(_t), Either::Two(_u)) = &(e.clone(), e.clone()) { }
+ | ^^ ^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/duplicate-suggestions.rs:59:53
+ |
+LL | while let &(Either::One(_t), Either::Two(_u)) = &(e.clone(), e.clone()) { }
+ | ----------------------------------- ^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of borrowed content
+ | | | |
+ | | | ...and here
+ | | data moved here
+ | help: consider removing the `&`: `(Either::One(_t), Either::Two(_u))`
+ |
+note: move occurs because these variables have types that don't implement the `Copy` trait
+ --> $DIR/duplicate-suggestions.rs:59:29
+ |
+LL | while let &(Either::One(_t), Either::Two(_u)) = &(e.clone(), e.clone()) { }
+ | ^^ ^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/duplicate-suggestions.rs:63:11
+ |
+LL | match &(e.clone(), e.clone()) {
+ | ^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of borrowed content
+LL | //~^ ERROR cannot move
+LL | &(Either::One(_t), Either::Two(_u)) => (),
+ | -- -- ...and here
+ | |
+ | data moved here
+...
+LL | &(Either::Two(_t), Either::One(_u)) => (),
+ | -- ...and here -- ...and here
+ |
+note: move occurs because these variables have types that don't implement the `Copy` trait
+ --> $DIR/duplicate-suggestions.rs:65:23
+ |
+LL | &(Either::One(_t), Either::Two(_u)) => (),
+ | ^^ ^^
+...
+LL | &(Either::Two(_t), Either::One(_u)) => (),
+ | ^^ ^^
+help: consider removing the `&`
+ |
+LL | (Either::One(_t), Either::Two(_u)) => (),
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: consider removing the `&`
+ |
+LL | (Either::Two(_t), Either::One(_u)) => (),
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/duplicate-suggestions.rs:73:11
+ |
+LL | match &(e.clone(), e.clone()) {
+ | ^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of borrowed content
+LL | //~^ ERROR cannot move
+LL | &(Either::One(_t), Either::Two(_u))
+ | -----------------------------------
+ | | | |
+ | | | ...and here
+ | | data moved here
+ | help: consider removing the `&`: `(Either::One(_t), Either::Two(_u))`
+ |
+note: move occurs because these variables have types that don't implement the `Copy` trait
+ --> $DIR/duplicate-suggestions.rs:75:23
+ |
+LL | &(Either::One(_t), Either::Two(_u))
+ | ^^ ^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/duplicate-suggestions.rs:82:11
+ |
+LL | match &(e.clone(), e.clone()) {
+ | ^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of borrowed content
+LL | //~^ ERROR cannot move
+LL | &(Either::One(_t), Either::Two(_u)) => (),
+ | -----------------------------------
+ | | | |
+ | | | ...and here
+ | | data moved here
+ | help: consider removing the `&`: `(Either::One(_t), Either::Two(_u))`
+ |
+note: move occurs because these variables have types that don't implement the `Copy` trait
+ --> $DIR/duplicate-suggestions.rs:84:23
+ |
+LL | &(Either::One(_t), Either::Two(_u)) => (),
+ | ^^ ^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/duplicate-suggestions.rs:90:11
+ |
+LL | match &(e.clone(), e.clone()) {
+ | ^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of borrowed content
+LL | //~^ ERROR cannot move
+LL | &(Either::One(_t), Either::Two(_u)) => (),
+ | -----------------------------------
+ | | | |
+ | | | ...and here
+ | | data moved here
+ | help: consider removing the `&`: `(Either::One(_t), Either::Two(_u))`
+ |
+note: move occurs because these variables have types that don't implement the `Copy` trait
+ --> $DIR/duplicate-suggestions.rs:92:23
+ |
+LL | &(Either::One(_t), Either::Two(_u)) => (),
+ | ^^ ^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/duplicate-suggestions.rs:103:31
+ |
+LL | let &mut (X(_t), X(_u)) = &mut (xm.clone(), xm.clone());
+ | ------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of borrowed content
+ | | | |
+ | | | ...and here
+ | | data moved here
+ | help: consider removing the `&mut`: `(X(_t), X(_u))`
+ |
+note: move occurs because these variables have types that don't implement the `Copy` trait
+ --> $DIR/duplicate-suggestions.rs:103:17
+ |
+LL | let &mut (X(_t), X(_u)) = &mut (xm.clone(), xm.clone());
+ | ^^ ^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/duplicate-suggestions.rs:107:54
+ |
+LL | if let &mut (Either::One(_t), Either::Two(_u)) = &mut (em.clone(), em.clone()) { }
+ | --------------------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of borrowed content
+ | | | |
+ | | | ...and here
+ | | data moved here
+ | help: consider removing the `&mut`: `(Either::One(_t), Either::Two(_u))`
+ |
+note: move occurs because these variables have types that don't implement the `Copy` trait
+ --> $DIR/duplicate-suggestions.rs:107:30
+ |
+LL | if let &mut (Either::One(_t), Either::Two(_u)) = &mut (em.clone(), em.clone()) { }
+ | ^^ ^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/duplicate-suggestions.rs:111:57
+ |
+LL | while let &mut (Either::One(_t), Either::Two(_u)) = &mut (em.clone(), em.clone()) { }
+ | --------------------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of borrowed content
+ | | | |
+ | | | ...and here
+ | | data moved here
+ | help: consider removing the `&mut`: `(Either::One(_t), Either::Two(_u))`
+ |
+note: move occurs because these variables have types that don't implement the `Copy` trait
+ --> $DIR/duplicate-suggestions.rs:111:33
+ |
+LL | while let &mut (Either::One(_t), Either::Two(_u)) = &mut (em.clone(), em.clone()) { }
+ | ^^ ^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/duplicate-suggestions.rs:115:11
+ |
+LL | match &mut (em.clone(), em.clone()) {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of borrowed content
+LL | //~^ ERROR cannot move
+LL | &mut (Either::One(_t), Either::Two(_u)) => (),
+ | -- -- ...and here
+ | |
+ | data moved here
+...
+LL | &mut (Either::Two(_t), Either::One(_u)) => (),
+ | -- ...and here -- ...and here
+ |
+note: move occurs because these variables have types that don't implement the `Copy` trait
+ --> $DIR/duplicate-suggestions.rs:117:27
+ |
+LL | &mut (Either::One(_t), Either::Two(_u)) => (),
+ | ^^ ^^
+...
+LL | &mut (Either::Two(_t), Either::One(_u)) => (),
+ | ^^ ^^
+help: consider removing the `&mut`
+ |
+LL | (Either::One(_t), Either::Two(_u)) => (),
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: consider removing the `&mut`
+ |
+LL | (Either::Two(_t), Either::One(_u)) => (),
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/duplicate-suggestions.rs:125:11
+ |
+LL | match &mut (em.clone(), em.clone()) {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of borrowed content
+LL | //~^ ERROR cannot move
+LL | &mut (Either::One(_t), Either::Two(_u))
+ | ---------------------------------------
+ | | | |
+ | | | ...and here
+ | | data moved here
+ | help: consider removing the `&mut`: `(Either::One(_t), Either::Two(_u))`
+ |
+note: move occurs because these variables have types that don't implement the `Copy` trait
+ --> $DIR/duplicate-suggestions.rs:127:27
+ |
+LL | &mut (Either::One(_t), Either::Two(_u))
+ | ^^ ^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/duplicate-suggestions.rs:134:11
+ |
+LL | match &mut (em.clone(), em.clone()) {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of borrowed content
+LL | //~^ ERROR cannot move
+LL | &mut (Either::One(_t), Either::Two(_u)) => (),
+ | ---------------------------------------
+ | | | |
+ | | | ...and here
+ | | data moved here
+ | help: consider removing the `&mut`: `(Either::One(_t), Either::Two(_u))`
+ |
+note: move occurs because these variables have types that don't implement the `Copy` trait
+ --> $DIR/duplicate-suggestions.rs:136:27
+ |
+LL | &mut (Either::One(_t), Either::Two(_u)) => (),
+ | ^^ ^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/duplicate-suggestions.rs:142:11
+ |
+LL | match &mut (em.clone(), em.clone()) {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of borrowed content
+LL | //~^ ERROR cannot move
+LL | &mut (Either::One(_t), Either::Two(_u)) => (),
+ | ---------------------------------------
+ | | | |
+ | | | ...and here
+ | | data moved here
+ | help: consider removing the `&mut`: `(Either::One(_t), Either::Two(_u))`
+ |
+note: move occurs because these variables have types that don't implement the `Copy` trait
+ --> $DIR/duplicate-suggestions.rs:144:27
+ |
+LL | &mut (Either::One(_t), Either::Two(_u)) => (),
+ | ^^ ^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/duplicate-suggestions.rs:150:11
+ |
+LL | match &mut (em.clone(), em.clone()) {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of borrowed content
+LL | //~^ ERROR cannot move
+LL | &mut (Either::One(_t), Either::Two(_u)) => (),
+ | ---------------------------------------
+ | | | |
+ | | | ...and here
+ | | data moved here
+ | help: consider removing the `&mut`: `(Either::One(_t), Either::Two(_u))`
+ |
+note: move occurs because these variables have types that don't implement the `Copy` trait
+ --> $DIR/duplicate-suggestions.rs:152:27
+ |
+LL | &mut (Either::One(_t), Either::Two(_u)) => (),
+ | ^^ ^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/duplicate-suggestions.rs:98:11
+ |
+LL | fn f5(&(X(_t), X(_u)): &(X, X)) { }
+ | ^^^^--^^^^^--^^
+ | | | |
+ | | | ...and here
+ | | data moved here
+ | cannot move out of borrowed content
+ | help: consider removing the `&`: `(X(_t), X(_u))`
+ |
+note: move occurs because these variables have types that don't implement the `Copy` trait
+ --> $DIR/duplicate-suggestions.rs:98:15
+ |
+LL | fn f5(&(X(_t), X(_u)): &(X, X)) { }
+ | ^^ ^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/duplicate-suggestions.rs:158:11
+ |
+LL | fn f6(&mut (X(_t), X(_u)): &mut (X, X)) { }
+ | ^^^^^^^^--^^^^^--^^
+ | | | |
+ | | | ...and here
+ | | data moved here
+ | cannot move out of borrowed content
+ | help: consider removing the `&mut`: `(X(_t), X(_u))`
+ |
+note: move occurs because these variables have types that don't implement the `Copy` trait
+ --> $DIR/duplicate-suggestions.rs:158:19
+ |
+LL | fn f6(&mut (X(_t), X(_u)): &mut (X, X)) { }
+ | ^^ ^^
+
+error: aborting due to 17 previous errors
+
+For more information about this error, try `rustc --explain E0507`.
--- /dev/null
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(nll)]
+
+#[derive(Clone)]
+enum Either {
+ One(X),
+ Two(X),
+}
+
+#[derive(Clone)]
+struct X(Y);
+
+#[derive(Clone)]
+struct Y;
+
+fn consume_fn<F: Fn()>(_f: F) { }
+
+fn consume_fnmut<F: FnMut()>(_f: F) { }
+
+pub fn main() { }
+
+fn move_into_fn() {
+ let e = Either::One(X(Y));
+ let mut em = Either::One(X(Y));
+
+ let x = X(Y);
+
+ // -------- move into Fn --------
+
+ consume_fn(|| {
+ let X(_t) = x;
+ //~^ ERROR cannot move
+ //~| HELP consider borrowing here
+ //~| SUGGESTION &x
+ if let Either::One(_t) = e { }
+ //~^ ERROR cannot move
+ //~| HELP consider borrowing here
+ //~| SUGGESTION &e
+ while let Either::One(_t) = e { }
+ //~^ ERROR cannot move
+ //~| HELP consider borrowing here
+ //~| SUGGESTION &e
+ match e {
+ //~^ ERROR cannot move
+ //~| HELP consider borrowing here
+ //~| SUGGESTION &e
+ Either::One(_t)
+ | Either::Two(_t) => (),
+ }
+ match e {
+ //~^ ERROR cannot move
+ //~| HELP consider borrowing here
+ //~| SUGGESTION &e
+ Either::One(_t) => (),
+ Either::Two(ref _t) => (),
+ // FIXME: should suggest removing `ref` too
+ }
+
+ let X(mut _t) = x;
+ //~^ ERROR cannot move
+ //~| HELP consider borrowing here
+ //~| SUGGESTION &x
+ if let Either::One(mut _t) = em { }
+ //~^ ERROR cannot move
+ //~| HELP consider borrowing here
+ //~| SUGGESTION &em
+ while let Either::One(mut _t) = em { }
+ //~^ ERROR cannot move
+ //~| HELP consider borrowing here
+ //~| SUGGESTION &em
+ match em {
+ //~^ ERROR cannot move
+ //~| HELP consider borrowing here
+ //~| SUGGESTION &em
+ Either::One(mut _t)
+ | Either::Two(mut _t) => (),
+ }
+ match em {
+ //~^ ERROR cannot move
+ //~| HELP consider borrowing here
+ //~| SUGGESTION &em
+ Either::One(mut _t) => (),
+ Either::Two(ref _t) => (),
+ // FIXME: should suggest removing `ref` too
+ }
+ });
+}
+
+fn move_into_fnmut() {
+ let e = Either::One(X(Y));
+ let mut em = Either::One(X(Y));
+
+ let x = X(Y);
+
+ // -------- move into FnMut --------
+
+ consume_fnmut(|| {
+ let X(_t) = x;
+ //~^ ERROR cannot move
+ //~| HELP consider borrowing here
+ //~| SUGGESTION &x
+ if let Either::One(_t) = e { }
+ //~^ ERROR cannot move
+ //~| HELP consider borrowing here
+ //~| SUGGESTION &e
+ while let Either::One(_t) = e { }
+ //~^ ERROR cannot move
+ //~| HELP consider borrowing here
+ //~| SUGGESTION &e
+ match e {
+ //~^ ERROR cannot move
+ //~| HELP consider borrowing here
+ //~| SUGGESTION &e
+ Either::One(_t)
+ | Either::Two(_t) => (),
+ }
+ match e {
+ //~^ ERROR cannot move
+ //~| HELP consider borrowing here
+ //~| SUGGESTION &e
+ Either::One(_t) => (),
+ Either::Two(ref _t) => (),
+ // FIXME: should suggest removing `ref` too
+ }
+
+ let X(mut _t) = x;
+ //~^ ERROR cannot move
+ //~| HELP consider borrowing here
+ //~| SUGGESTION &x
+ if let Either::One(mut _t) = em { }
+ //~^ ERROR cannot move
+ //~| HELP consider borrowing here
+ //~| SUGGESTION &em
+ while let Either::One(mut _t) = em { }
+ //~^ ERROR cannot move
+ //~| HELP consider borrowing here
+ //~| SUGGESTION &em
+ match em {
+ //~^ ERROR cannot move
+ //~| HELP consider borrowing here
+ //~| SUGGESTION &em
+ Either::One(mut _t)
+ | Either::Two(mut _t) => (),
+ }
+ match em {
+ //~^ ERROR cannot move
+ //~| HELP consider borrowing here
+ //~| SUGGESTION &em
+ Either::One(mut _t) => (),
+ Either::Two(ref _t) => (),
+ // FIXME: should suggest removing `ref` too
+ }
+ match em {
+ //~^ ERROR cannot move
+ //~| HELP consider borrowing here
+ //~| SUGGESTION &em
+ Either::One(mut _t) => (),
+ Either::Two(ref mut _t) => (),
+ // FIXME: should suggest removing `ref` too
+ }
+ });
+}
--- /dev/null
+error[E0507]: cannot move out of captured variable in an `Fn` closure
+ --> $DIR/move-into-closure.rs:40:21
+ |
+LL | let x = X(Y);
+ | - captured outer variable
+...
+LL | let X(_t) = x;
+ | -- ^
+ | | |
+ | | cannot move out of captured variable in an `Fn` closure
+ | | help: consider borrowing here: `&x`
+ | data moved here
+ |
+note: move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+ --> $DIR/move-into-closure.rs:40:15
+ |
+LL | let X(_t) = x;
+ | ^^
+
+error[E0507]: cannot move out of captured variable in an `Fn` closure
+ --> $DIR/move-into-closure.rs:44:34
+ |
+LL | let e = Either::One(X(Y));
+ | - captured outer variable
+...
+LL | if let Either::One(_t) = e { }
+ | -- ^
+ | | |
+ | | cannot move out of captured variable in an `Fn` closure
+ | | help: consider borrowing here: `&e`
+ | data moved here
+ |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ --> $DIR/move-into-closure.rs:44:28
+ |
+LL | if let Either::One(_t) = e { }
+ | ^^
+
+error[E0507]: cannot move out of captured variable in an `Fn` closure
+ --> $DIR/move-into-closure.rs:48:37
+ |
+LL | let e = Either::One(X(Y));
+ | - captured outer variable
+...
+LL | while let Either::One(_t) = e { }
+ | -- ^
+ | | |
+ | | cannot move out of captured variable in an `Fn` closure
+ | | help: consider borrowing here: `&e`
+ | data moved here
+ |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ --> $DIR/move-into-closure.rs:48:31
+ |
+LL | while let Either::One(_t) = e { }
+ | ^^
+
+error[E0507]: cannot move out of captured variable in an `Fn` closure
+ --> $DIR/move-into-closure.rs:52:15
+ |
+LL | let e = Either::One(X(Y));
+ | - captured outer variable
+...
+LL | match e {
+ | ^
+ | |
+ | cannot move out of captured variable in an `Fn` closure
+ | help: consider borrowing here: `&e`
+...
+LL | Either::One(_t)
+ | -- data moved here
+ |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ --> $DIR/move-into-closure.rs:56:25
+ |
+LL | Either::One(_t)
+ | ^^
+
+error[E0507]: cannot move out of captured variable in an `Fn` closure
+ --> $DIR/move-into-closure.rs:59:15
+ |
+LL | let e = Either::One(X(Y));
+ | - captured outer variable
+...
+LL | match e {
+ | ^
+ | |
+ | cannot move out of captured variable in an `Fn` closure
+ | help: consider borrowing here: `&e`
+...
+LL | Either::One(_t) => (),
+ | -- data moved here
+ |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ --> $DIR/move-into-closure.rs:63:25
+ |
+LL | Either::One(_t) => (),
+ | ^^
+
+error[E0507]: cannot move out of captured variable in an `Fn` closure
+ --> $DIR/move-into-closure.rs:68:25
+ |
+LL | let x = X(Y);
+ | - captured outer variable
+...
+LL | let X(mut _t) = x;
+ | ------ ^
+ | | |
+ | | cannot move out of captured variable in an `Fn` closure
+ | | help: consider borrowing here: `&x`
+ | data moved here
+ |
+note: move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+ --> $DIR/move-into-closure.rs:68:15
+ |
+LL | let X(mut _t) = x;
+ | ^^^^^^
+
+error[E0507]: cannot move out of captured variable in an `Fn` closure
+ --> $DIR/move-into-closure.rs:72:38
+ |
+LL | let mut em = Either::One(X(Y));
+ | ------ captured outer variable
+...
+LL | if let Either::One(mut _t) = em { }
+ | ------ ^^
+ | | |
+ | | cannot move out of captured variable in an `Fn` closure
+ | | help: consider borrowing here: `&em`
+ | data moved here
+ |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ --> $DIR/move-into-closure.rs:72:28
+ |
+LL | if let Either::One(mut _t) = em { }
+ | ^^^^^^
+
+error[E0507]: cannot move out of captured variable in an `Fn` closure
+ --> $DIR/move-into-closure.rs:76:41
+ |
+LL | let mut em = Either::One(X(Y));
+ | ------ captured outer variable
+...
+LL | while let Either::One(mut _t) = em { }
+ | ------ ^^
+ | | |
+ | | cannot move out of captured variable in an `Fn` closure
+ | | help: consider borrowing here: `&em`
+ | data moved here
+ |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ --> $DIR/move-into-closure.rs:76:31
+ |
+LL | while let Either::One(mut _t) = em { }
+ | ^^^^^^
+
+error[E0507]: cannot move out of captured variable in an `Fn` closure
+ --> $DIR/move-into-closure.rs:80:15
+ |
+LL | let mut em = Either::One(X(Y));
+ | ------ captured outer variable
+...
+LL | match em {
+ | ^^
+ | |
+ | cannot move out of captured variable in an `Fn` closure
+ | help: consider borrowing here: `&em`
+...
+LL | Either::One(mut _t)
+ | ------ data moved here
+ |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ --> $DIR/move-into-closure.rs:84:25
+ |
+LL | Either::One(mut _t)
+ | ^^^^^^
+
+error[E0507]: cannot move out of captured variable in an `Fn` closure
+ --> $DIR/move-into-closure.rs:87:15
+ |
+LL | let mut em = Either::One(X(Y));
+ | ------ captured outer variable
+...
+LL | match em {
+ | ^^
+ | |
+ | cannot move out of captured variable in an `Fn` closure
+ | help: consider borrowing here: `&em`
+...
+LL | Either::One(mut _t) => (),
+ | ------ data moved here
+ |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ --> $DIR/move-into-closure.rs:91:25
+ |
+LL | Either::One(mut _t) => (),
+ | ^^^^^^
+
+error[E0507]: cannot move out of captured variable in an `FnMut` closure
+ --> $DIR/move-into-closure.rs:107:21
+ |
+LL | let x = X(Y);
+ | - captured outer variable
+...
+LL | let X(_t) = x;
+ | -- ^
+ | | |
+ | | cannot move out of captured variable in an `FnMut` closure
+ | | help: consider borrowing here: `&x`
+ | data moved here
+ |
+note: move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+ --> $DIR/move-into-closure.rs:107:15
+ |
+LL | let X(_t) = x;
+ | ^^
+
+error[E0507]: cannot move out of captured variable in an `FnMut` closure
+ --> $DIR/move-into-closure.rs:111:34
+ |
+LL | let e = Either::One(X(Y));
+ | - captured outer variable
+...
+LL | if let Either::One(_t) = e { }
+ | -- ^
+ | | |
+ | | cannot move out of captured variable in an `FnMut` closure
+ | | help: consider borrowing here: `&e`
+ | data moved here
+ |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ --> $DIR/move-into-closure.rs:111:28
+ |
+LL | if let Either::One(_t) = e { }
+ | ^^
+
+error[E0507]: cannot move out of captured variable in an `FnMut` closure
+ --> $DIR/move-into-closure.rs:115:37
+ |
+LL | let e = Either::One(X(Y));
+ | - captured outer variable
+...
+LL | while let Either::One(_t) = e { }
+ | -- ^
+ | | |
+ | | cannot move out of captured variable in an `FnMut` closure
+ | | help: consider borrowing here: `&e`
+ | data moved here
+ |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ --> $DIR/move-into-closure.rs:115:31
+ |
+LL | while let Either::One(_t) = e { }
+ | ^^
+
+error[E0507]: cannot move out of captured variable in an `FnMut` closure
+ --> $DIR/move-into-closure.rs:119:15
+ |
+LL | let e = Either::One(X(Y));
+ | - captured outer variable
+...
+LL | match e {
+ | ^
+ | |
+ | cannot move out of captured variable in an `FnMut` closure
+ | help: consider borrowing here: `&e`
+...
+LL | Either::One(_t)
+ | -- data moved here
+ |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ --> $DIR/move-into-closure.rs:123:25
+ |
+LL | Either::One(_t)
+ | ^^
+
+error[E0507]: cannot move out of captured variable in an `FnMut` closure
+ --> $DIR/move-into-closure.rs:126:15
+ |
+LL | let e = Either::One(X(Y));
+ | - captured outer variable
+...
+LL | match e {
+ | ^
+ | |
+ | cannot move out of captured variable in an `FnMut` closure
+ | help: consider borrowing here: `&e`
+...
+LL | Either::One(_t) => (),
+ | -- data moved here
+ |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ --> $DIR/move-into-closure.rs:130:25
+ |
+LL | Either::One(_t) => (),
+ | ^^
+
+error[E0507]: cannot move out of captured variable in an `FnMut` closure
+ --> $DIR/move-into-closure.rs:135:25
+ |
+LL | let x = X(Y);
+ | - captured outer variable
+...
+LL | let X(mut _t) = x;
+ | ------ ^
+ | | |
+ | | cannot move out of captured variable in an `FnMut` closure
+ | | help: consider borrowing here: `&x`
+ | data moved here
+ |
+note: move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+ --> $DIR/move-into-closure.rs:135:15
+ |
+LL | let X(mut _t) = x;
+ | ^^^^^^
+
+error[E0507]: cannot move out of captured variable in an `FnMut` closure
+ --> $DIR/move-into-closure.rs:139:38
+ |
+LL | let mut em = Either::One(X(Y));
+ | ------ captured outer variable
+...
+LL | if let Either::One(mut _t) = em { }
+ | ------ ^^
+ | | |
+ | | cannot move out of captured variable in an `FnMut` closure
+ | | help: consider borrowing here: `&em`
+ | data moved here
+ |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ --> $DIR/move-into-closure.rs:139:28
+ |
+LL | if let Either::One(mut _t) = em { }
+ | ^^^^^^
+
+error[E0507]: cannot move out of captured variable in an `FnMut` closure
+ --> $DIR/move-into-closure.rs:143:41
+ |
+LL | let mut em = Either::One(X(Y));
+ | ------ captured outer variable
+...
+LL | while let Either::One(mut _t) = em { }
+ | ------ ^^
+ | | |
+ | | cannot move out of captured variable in an `FnMut` closure
+ | | help: consider borrowing here: `&em`
+ | data moved here
+ |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ --> $DIR/move-into-closure.rs:143:31
+ |
+LL | while let Either::One(mut _t) = em { }
+ | ^^^^^^
+
+error[E0507]: cannot move out of captured variable in an `FnMut` closure
+ --> $DIR/move-into-closure.rs:147:15
+ |
+LL | let mut em = Either::One(X(Y));
+ | ------ captured outer variable
+...
+LL | match em {
+ | ^^
+ | |
+ | cannot move out of captured variable in an `FnMut` closure
+ | help: consider borrowing here: `&em`
+...
+LL | Either::One(mut _t)
+ | ------ data moved here
+ |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ --> $DIR/move-into-closure.rs:151:25
+ |
+LL | Either::One(mut _t)
+ | ^^^^^^
+
+error[E0507]: cannot move out of captured variable in an `FnMut` closure
+ --> $DIR/move-into-closure.rs:154:15
+ |
+LL | let mut em = Either::One(X(Y));
+ | ------ captured outer variable
+...
+LL | match em {
+ | ^^
+ | |
+ | cannot move out of captured variable in an `FnMut` closure
+ | help: consider borrowing here: `&em`
+...
+LL | Either::One(mut _t) => (),
+ | ------ data moved here
+ |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ --> $DIR/move-into-closure.rs:158:25
+ |
+LL | Either::One(mut _t) => (),
+ | ^^^^^^
+
+error[E0507]: cannot move out of captured variable in an `FnMut` closure
+ --> $DIR/move-into-closure.rs:162:15
+ |
+LL | let mut em = Either::One(X(Y));
+ | ------ captured outer variable
+...
+LL | match em {
+ | ^^
+ | |
+ | cannot move out of captured variable in an `FnMut` closure
+ | help: consider borrowing here: `&em`
+...
+LL | Either::One(mut _t) => (),
+ | ------ data moved here
+ |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ --> $DIR/move-into-closure.rs:166:25
+ |
+LL | Either::One(mut _t) => (),
+ | ^^^^^^
+
+error: aborting due to 21 previous errors
+
+For more information about this error, try `rustc --explain E0507`.
--- /dev/null
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(nll)]
+
+#[derive(Clone)]
+enum Either {
+ One(X),
+ Two(X),
+}
+
+#[derive(Clone)]
+struct X(Y);
+
+#[derive(Clone)]
+struct Y;
+
+pub fn main() {
+ let e = Either::One(X(Y));
+ let mut em = Either::One(X(Y));
+
+ let r = &e;
+ let rm = &mut Either::One(X(Y));
+
+ let x = X(Y);
+ let mut xm = X(Y);
+
+ let s = &x;
+ let sm = &mut X(Y);
+
+ let ve = vec![Either::One(X(Y))];
+
+ let vr = &ve;
+ let vrm = &mut vec![Either::One(X(Y))];
+
+ let vx = vec![X(Y)];
+
+ let vs = &vx;
+ let vsm = &mut vec![X(Y)];
+
+ // -------- move from Either/X place --------
+
+ let X(_t) = *s;
+ //~^ ERROR cannot move
+ //~| HELP consider removing the `*`
+ //~| SUGGESTION s
+ if let Either::One(_t) = *r { }
+ //~^ ERROR cannot move
+ //~| HELP consider removing the `*`
+ //~| SUGGESTION r
+ while let Either::One(_t) = *r { }
+ //~^ ERROR cannot move
+ //~| HELP consider removing the `*`
+ //~| SUGGESTION r
+ match *r {
+ //~^ ERROR cannot move
+ //~| HELP consider removing the `*`
+ //~| SUGGESTION r
+ Either::One(_t)
+ | Either::Two(_t) => (),
+ }
+ match *r {
+ //~^ ERROR cannot move
+ //~| HELP consider removing the `*`
+ //~| SUGGESTION r
+ Either::One(_t) => (),
+ Either::Two(ref _t) => (),
+ // FIXME: should suggest removing `ref` too
+ }
+
+ let X(_t) = *sm;
+ //~^ ERROR cannot move
+ //~| HELP consider removing the `*`
+ //~| SUGGESTION sm
+ if let Either::One(_t) = *rm { }
+ //~^ ERROR cannot move
+ //~| HELP consider removing the `*`
+ //~| SUGGESTION rm
+ while let Either::One(_t) = *rm { }
+ //~^ ERROR cannot move
+ //~| HELP consider removing the `*`
+ //~| SUGGESTION rm
+ match *rm {
+ //~^ ERROR cannot move
+ //~| HELP consider removing the `*`
+ //~| SUGGESTION rm
+ Either::One(_t)
+ | Either::Two(_t) => (),
+ }
+ match *rm {
+ //~^ ERROR cannot move
+ //~| HELP consider removing the `*`
+ //~| SUGGESTION rm
+ Either::One(_t) => (),
+ Either::Two(ref _t) => (),
+ // FIXME: should suggest removing `ref` too
+ }
+ match *rm {
+ //~^ ERROR cannot move
+ //~| HELP consider removing the `*`
+ //~| SUGGESTION rm
+ Either::One(_t) => (),
+ Either::Two(ref mut _t) => (),
+ // FIXME: should suggest removing `ref` too
+ }
+
+ let X(_t) = vs[0];
+ //~^ ERROR cannot move
+ //~| HELP consider borrowing here
+ //~| SUGGESTION &vs[0]
+ if let Either::One(_t) = vr[0] { }
+ //~^ ERROR cannot move
+ //~| HELP consider borrowing here
+ //~| SUGGESTION &vr[0]
+ while let Either::One(_t) = vr[0] { }
+ //~^ ERROR cannot move
+ //~| HELP consider borrowing here
+ //~| SUGGESTION &vr[0]
+ match vr[0] {
+ //~^ ERROR cannot move
+ //~| HELP consider borrowing here
+ //~| SUGGESTION &vr[0]
+ Either::One(_t)
+ | Either::Two(_t) => (),
+ }
+ match vr[0] {
+ //~^ ERROR cannot move
+ //~| HELP consider borrowing here
+ //~| SUGGESTION &vr[0]
+ Either::One(_t) => (),
+ Either::Two(ref _t) => (),
+ // FIXME: should suggest removing `ref` too
+ }
+
+ let X(_t) = vsm[0];
+ //~^ ERROR cannot move
+ //~| HELP consider borrowing here
+ //~| SUGGESTION &vsm[0]
+ if let Either::One(_t) = vrm[0] { }
+ //~^ ERROR cannot move
+ //~| HELP consider borrowing here
+ //~| SUGGESTION &vrm[0]
+ while let Either::One(_t) = vrm[0] { }
+ //~^ ERROR cannot move
+ //~| HELP consider borrowing here
+ //~| SUGGESTION &vrm[0]
+ match vrm[0] {
+ //~^ ERROR cannot move
+ //~| HELP consider borrowing here
+ //~| SUGGESTION &vrm[0]
+ Either::One(_t)
+ | Either::Two(_t) => (),
+ }
+ match vrm[0] {
+ //~^ ERROR cannot move
+ //~| HELP consider borrowing here
+ //~| SUGGESTION &vrm[0]
+ Either::One(_t) => (),
+ Either::Two(ref _t) => (),
+ // FIXME: should suggest removing `ref` too
+ }
+ match vrm[0] {
+ //~^ ERROR cannot move
+ //~| HELP consider borrowing here
+ //~| SUGGESTION &vrm[0]
+ Either::One(_t) => (),
+ Either::Two(ref mut _t) => (),
+ // FIXME: should suggest removing `ref` too
+ }
+
+ // -------- move from &Either/&X place --------
+
+ let &X(_t) = s;
+ //~^ ERROR cannot move
+ //~| HELP consider removing the `&`
+ //~| SUGGESTION X(_t)
+ if let &Either::One(_t) = r { }
+ //~^ ERROR cannot move
+ //~| HELP consider removing the `&`
+ //~| SUGGESTION Either::One(_t)
+ while let &Either::One(_t) = r { }
+ //~^ ERROR cannot move
+ //~| HELP consider removing the `&`
+ //~| SUGGESTION Either::One(_t)
+ match r {
+ //~^ ERROR cannot move
+ &Either::One(_t)
+ //~^ HELP consider removing the `&`
+ //~| SUGGESTION Either::One(_t)
+ | &Either::Two(_t) => (),
+ // FIXME: would really like a suggestion here too
+ }
+ match r {
+ //~^ ERROR cannot move
+ &Either::One(_t) => (),
+ //~^ HELP consider removing the `&`
+ //~| SUGGESTION Either::One(_t)
+ &Either::Two(ref _t) => (),
+ }
+ match r {
+ //~^ ERROR cannot move
+ &Either::One(_t) => (),
+ //~^ HELP consider removing the `&`
+ //~| SUGGESTION Either::One(_t)
+ Either::Two(_t) => (),
+ }
+ fn f1(&X(_t): &X) { }
+ //~^ ERROR cannot move
+ //~| HELP consider removing the `&`
+ //~| SUGGESTION X(_t)
+
+ let &mut X(_t) = sm;
+ //~^ ERROR cannot move
+ //~| HELP consider removing the `&mut`
+ //~| SUGGESTION X(_t)
+ if let &mut Either::One(_t) = rm { }
+ //~^ ERROR cannot move
+ //~| HELP consider removing the `&mut`
+ //~| SUGGESTION Either::One(_t)
+ while let &mut Either::One(_t) = rm { }
+ //~^ ERROR cannot move
+ //~| HELP consider removing the `&mut`
+ //~| SUGGESTION Either::One(_t)
+ match rm {
+ //~^ ERROR cannot move
+ &mut Either::One(_t) => (),
+ //~^ HELP consider removing the `&mut`
+ //~| SUGGESTION Either::One(_t)
+ &mut Either::Two(_t) => (),
+ //~^ HELP consider removing the `&mut`
+ //~| SUGGESTION Either::Two(_t)
+ }
+ match rm {
+ //~^ ERROR cannot move
+ &mut Either::One(_t) => (),
+ //~^ HELP consider removing the `&mut`
+ //~| SUGGESTION Either::One(_t)
+ &mut Either::Two(ref _t) => (),
+ }
+ match rm {
+ //~^ ERROR cannot move
+ &mut Either::One(_t) => (),
+ //~^ HELP consider removing the `&mut`
+ //~| SUGGESTION Either::One(_t)
+ &mut Either::Two(ref mut _t) => (),
+ }
+ match rm {
+ //~^ ERROR cannot move
+ &mut Either::One(_t) => (),
+ //~^ HELP consider removing the `&mut`
+ //~| SUGGESTION Either::One(_t)
+ Either::Two(_t) => (),
+ }
+ fn f2(&mut X(_t): &mut X) { }
+ //~^ ERROR cannot move
+ //~| HELP consider removing the `&mut`
+ //~| SUGGESTION X(_t)
+
+ // -------- move from tuple of &Either/&X --------
+
+ // FIXME: These should have suggestions.
+
+ let (&X(_t),) = (&x.clone(),);
+ //~^ ERROR cannot move
+ if let (&Either::One(_t),) = (&e.clone(),) { }
+ //~^ ERROR cannot move
+ while let (&Either::One(_t),) = (&e.clone(),) { }
+ //~^ ERROR cannot move
+ match (&e.clone(),) {
+ //~^ ERROR cannot move
+ (&Either::One(_t),)
+ | (&Either::Two(_t),) => (),
+ }
+ fn f3((&X(_t),): (&X,)) { }
+ //~^ ERROR cannot move
+
+ let (&mut X(_t),) = (&mut xm.clone(),);
+ //~^ ERROR cannot move
+ if let (&mut Either::One(_t),) = (&mut em.clone(),) { }
+ //~^ ERROR cannot move
+ while let (&mut Either::One(_t),) = (&mut em.clone(),) { }
+ //~^ ERROR cannot move
+ match (&mut em.clone(),) {
+ //~^ ERROR cannot move
+ (&mut Either::One(_t),) => (),
+ (&mut Either::Two(_t),) => (),
+ }
+ fn f4((&mut X(_t),): (&mut X,)) { }
+ //~^ ERROR cannot move
+
+ // -------- move from &Either/&X value --------
+
+ let &X(_t) = &x;
+ //~^ ERROR cannot move
+ //~| HELP consider removing the `&`
+ //~| SUGGESTION X(_t)
+ if let &Either::One(_t) = &e { }
+ //~^ ERROR cannot move
+ //~| HELP consider removing the `&`
+ //~| SUGGESTION Either::One(_t)
+ while let &Either::One(_t) = &e { }
+ //~^ ERROR cannot move
+ //~| HELP consider removing the `&`
+ //~| SUGGESTION Either::One(_t)
+ match &e {
+ //~^ ERROR cannot move
+ &Either::One(_t)
+ //~^ HELP consider removing the `&`
+ //~| SUGGESTION Either::One(_t)
+ | &Either::Two(_t) => (),
+ // FIXME: would really like a suggestion here too
+ }
+ match &e {
+ //~^ ERROR cannot move
+ &Either::One(_t) => (),
+ //~^ HELP consider removing the `&`
+ //~| SUGGESTION Either::One(_t)
+ &Either::Two(ref _t) => (),
+ }
+ match &e {
+ //~^ ERROR cannot move
+ &Either::One(_t) => (),
+ //~^ HELP consider removing the `&`
+ //~| SUGGESTION Either::One(_t)
+ Either::Two(_t) => (),
+ }
+
+ let &mut X(_t) = &mut xm;
+ //~^ ERROR cannot move
+ //~| HELP consider removing the `&mut`
+ //~| SUGGESTION X(_t)
+ if let &mut Either::One(_t) = &mut em { }
+ //~^ ERROR cannot move
+ //~| HELP consider removing the `&mut`
+ //~| SUGGESTION Either::One(_t)
+ while let &mut Either::One(_t) = &mut em { }
+ //~^ ERROR cannot move
+ //~| HELP consider removing the `&mut`
+ //~| SUGGESTION Either::One(_t)
+ match &mut em {
+ //~^ ERROR cannot move
+ &mut Either::One(_t)
+ //~^ HELP consider removing the `&mut`
+ //~| SUGGESTION Either::One(_t)
+ | &mut Either::Two(_t) => (),
+ // FIXME: would really like a suggestion here too
+ }
+ match &mut em {
+ //~^ ERROR cannot move
+ &mut Either::One(_t) => (),
+ //~^ HELP consider removing the `&mut`
+ //~| SUGGESTION Either::One(_t)
+ &mut Either::Two(ref _t) => (),
+ }
+ match &mut em {
+ //~^ ERROR cannot move
+ &mut Either::One(_t) => (),
+ //~^ HELP consider removing the `&mut`
+ //~| SUGGESTION Either::One(_t)
+ &mut Either::Two(ref mut _t) => (),
+ }
+ match &mut em {
+ //~^ ERROR cannot move
+ &mut Either::One(_t) => (),
+ //~^ HELP consider removing the `&mut`
+ //~| SUGGESTION Either::One(_t)
+ Either::Two(_t) => (),
+ }
+}
--- /dev/null
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/simple.rs:50:17
+ |
+LL | let X(_t) = *s;
+ | -- ^^
+ | | |
+ | | cannot move out of borrowed content
+ | | help: consider removing the `*`: `s`
+ | data moved here
+ |
+note: move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+ --> $DIR/simple.rs:50:11
+ |
+LL | let X(_t) = *s;
+ | ^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/simple.rs:54:30
+ |
+LL | if let Either::One(_t) = *r { }
+ | -- ^^
+ | | |
+ | | cannot move out of borrowed content
+ | | help: consider removing the `*`: `r`
+ | data moved here
+ |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ --> $DIR/simple.rs:54:24
+ |
+LL | if let Either::One(_t) = *r { }
+ | ^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/simple.rs:58:33
+ |
+LL | while let Either::One(_t) = *r { }
+ | -- ^^
+ | | |
+ | | cannot move out of borrowed content
+ | | help: consider removing the `*`: `r`
+ | data moved here
+ |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ --> $DIR/simple.rs:58:27
+ |
+LL | while let Either::One(_t) = *r { }
+ | ^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/simple.rs:62:11
+ |
+LL | match *r {
+ | ^^
+ | |
+ | cannot move out of borrowed content
+ | help: consider removing the `*`: `r`
+...
+LL | Either::One(_t)
+ | -- data moved here
+ |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ --> $DIR/simple.rs:66:21
+ |
+LL | Either::One(_t)
+ | ^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/simple.rs:69:11
+ |
+LL | match *r {
+ | ^^
+ | |
+ | cannot move out of borrowed content
+ | help: consider removing the `*`: `r`
+...
+LL | Either::One(_t) => (),
+ | -- data moved here
+ |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ --> $DIR/simple.rs:73:21
+ |
+LL | Either::One(_t) => (),
+ | ^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/simple.rs:78:17
+ |
+LL | let X(_t) = *sm;
+ | -- ^^^
+ | | |
+ | | cannot move out of borrowed content
+ | | help: consider removing the `*`: `sm`
+ | data moved here
+ |
+note: move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+ --> $DIR/simple.rs:78:11
+ |
+LL | let X(_t) = *sm;
+ | ^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/simple.rs:82:30
+ |
+LL | if let Either::One(_t) = *rm { }
+ | -- ^^^
+ | | |
+ | | cannot move out of borrowed content
+ | | help: consider removing the `*`: `rm`
+ | data moved here
+ |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ --> $DIR/simple.rs:82:24
+ |
+LL | if let Either::One(_t) = *rm { }
+ | ^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/simple.rs:86:33
+ |
+LL | while let Either::One(_t) = *rm { }
+ | -- ^^^
+ | | |
+ | | cannot move out of borrowed content
+ | | help: consider removing the `*`: `rm`
+ | data moved here
+ |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ --> $DIR/simple.rs:86:27
+ |
+LL | while let Either::One(_t) = *rm { }
+ | ^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/simple.rs:90:11
+ |
+LL | match *rm {
+ | ^^^
+ | |
+ | cannot move out of borrowed content
+ | help: consider removing the `*`: `rm`
+...
+LL | Either::One(_t)
+ | -- data moved here
+ |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ --> $DIR/simple.rs:94:21
+ |
+LL | Either::One(_t)
+ | ^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/simple.rs:97:11
+ |
+LL | match *rm {
+ | ^^^
+ | |
+ | cannot move out of borrowed content
+ | help: consider removing the `*`: `rm`
+...
+LL | Either::One(_t) => (),
+ | -- data moved here
+ |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ --> $DIR/simple.rs:101:21
+ |
+LL | Either::One(_t) => (),
+ | ^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/simple.rs:105:11
+ |
+LL | match *rm {
+ | ^^^
+ | |
+ | cannot move out of borrowed content
+ | help: consider removing the `*`: `rm`
+...
+LL | Either::One(_t) => (),
+ | -- data moved here
+ |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ --> $DIR/simple.rs:109:21
+ |
+LL | Either::One(_t) => (),
+ | ^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/simple.rs:114:17
+ |
+LL | let X(_t) = vs[0];
+ | -- ^^^^^
+ | | |
+ | | cannot move out of borrowed content
+ | | help: consider borrowing here: `&vs[0]`
+ | data moved here
+ |
+note: move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+ --> $DIR/simple.rs:114:11
+ |
+LL | let X(_t) = vs[0];
+ | ^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/simple.rs:118:30
+ |
+LL | if let Either::One(_t) = vr[0] { }
+ | -- ^^^^^
+ | | |
+ | | cannot move out of borrowed content
+ | | help: consider borrowing here: `&vr[0]`
+ | data moved here
+ |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ --> $DIR/simple.rs:118:24
+ |
+LL | if let Either::One(_t) = vr[0] { }
+ | ^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/simple.rs:122:33
+ |
+LL | while let Either::One(_t) = vr[0] { }
+ | -- ^^^^^
+ | | |
+ | | cannot move out of borrowed content
+ | | help: consider borrowing here: `&vr[0]`
+ | data moved here
+ |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ --> $DIR/simple.rs:122:27
+ |
+LL | while let Either::One(_t) = vr[0] { }
+ | ^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/simple.rs:126:11
+ |
+LL | match vr[0] {
+ | ^^^^^
+ | |
+ | cannot move out of borrowed content
+ | help: consider borrowing here: `&vr[0]`
+...
+LL | Either::One(_t)
+ | -- data moved here
+ |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ --> $DIR/simple.rs:130:21
+ |
+LL | Either::One(_t)
+ | ^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/simple.rs:133:11
+ |
+LL | match vr[0] {
+ | ^^^^^
+ | |
+ | cannot move out of borrowed content
+ | help: consider borrowing here: `&vr[0]`
+...
+LL | Either::One(_t) => (),
+ | -- data moved here
+ |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ --> $DIR/simple.rs:137:21
+ |
+LL | Either::One(_t) => (),
+ | ^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/simple.rs:142:17
+ |
+LL | let X(_t) = vsm[0];
+ | -- ^^^^^^
+ | | |
+ | | cannot move out of borrowed content
+ | | help: consider borrowing here: `&vsm[0]`
+ | data moved here
+ |
+note: move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+ --> $DIR/simple.rs:142:11
+ |
+LL | let X(_t) = vsm[0];
+ | ^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/simple.rs:146:30
+ |
+LL | if let Either::One(_t) = vrm[0] { }
+ | -- ^^^^^^
+ | | |
+ | | cannot move out of borrowed content
+ | | help: consider borrowing here: `&vrm[0]`
+ | data moved here
+ |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ --> $DIR/simple.rs:146:24
+ |
+LL | if let Either::One(_t) = vrm[0] { }
+ | ^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/simple.rs:150:33
+ |
+LL | while let Either::One(_t) = vrm[0] { }
+ | -- ^^^^^^
+ | | |
+ | | cannot move out of borrowed content
+ | | help: consider borrowing here: `&vrm[0]`
+ | data moved here
+ |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ --> $DIR/simple.rs:150:27
+ |
+LL | while let Either::One(_t) = vrm[0] { }
+ | ^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/simple.rs:154:11
+ |
+LL | match vrm[0] {
+ | ^^^^^^
+ | |
+ | cannot move out of borrowed content
+ | help: consider borrowing here: `&vrm[0]`
+...
+LL | Either::One(_t)
+ | -- data moved here
+ |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ --> $DIR/simple.rs:158:21
+ |
+LL | Either::One(_t)
+ | ^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/simple.rs:161:11
+ |
+LL | match vrm[0] {
+ | ^^^^^^
+ | |
+ | cannot move out of borrowed content
+ | help: consider borrowing here: `&vrm[0]`
+...
+LL | Either::One(_t) => (),
+ | -- data moved here
+ |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ --> $DIR/simple.rs:165:21
+ |
+LL | Either::One(_t) => (),
+ | ^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/simple.rs:169:11
+ |
+LL | match vrm[0] {
+ | ^^^^^^
+ | |
+ | cannot move out of borrowed content
+ | help: consider borrowing here: `&vrm[0]`
+...
+LL | Either::One(_t) => (),
+ | -- data moved here
+ |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ --> $DIR/simple.rs:173:21
+ |
+LL | Either::One(_t) => (),
+ | ^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/simple.rs:180:18
+ |
+LL | let &X(_t) = s;
+ | ------ ^ cannot move out of borrowed content
+ | | |
+ | | data moved here
+ | help: consider removing the `&`: `X(_t)`
+ |
+note: move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+ --> $DIR/simple.rs:180:12
+ |
+LL | let &X(_t) = s;
+ | ^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/simple.rs:184:31
+ |
+LL | if let &Either::One(_t) = r { }
+ | ---------------- ^ cannot move out of borrowed content
+ | | |
+ | | data moved here
+ | help: consider removing the `&`: `Either::One(_t)`
+ |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ --> $DIR/simple.rs:184:25
+ |
+LL | if let &Either::One(_t) = r { }
+ | ^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/simple.rs:188:34
+ |
+LL | while let &Either::One(_t) = r { }
+ | ---------------- ^ cannot move out of borrowed content
+ | | |
+ | | data moved here
+ | help: consider removing the `&`: `Either::One(_t)`
+ |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ --> $DIR/simple.rs:188:28
+ |
+LL | while let &Either::One(_t) = r { }
+ | ^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/simple.rs:192:11
+ |
+LL | match r {
+ | ^ cannot move out of borrowed content
+LL | //~^ ERROR cannot move
+LL | &Either::One(_t)
+ | ----------------
+ | | |
+ | | data moved here
+ | help: consider removing the `&`: `Either::One(_t)`
+ |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ --> $DIR/simple.rs:194:22
+ |
+LL | &Either::One(_t)
+ | ^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/simple.rs:200:11
+ |
+LL | match r {
+ | ^ cannot move out of borrowed content
+LL | //~^ ERROR cannot move
+LL | &Either::One(_t) => (),
+ | ----------------
+ | | |
+ | | data moved here
+ | help: consider removing the `&`: `Either::One(_t)`
+ |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ --> $DIR/simple.rs:202:22
+ |
+LL | &Either::One(_t) => (),
+ | ^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/simple.rs:207:11
+ |
+LL | match r {
+ | ^ cannot move out of borrowed content
+LL | //~^ ERROR cannot move
+LL | &Either::One(_t) => (),
+ | ----------------
+ | | |
+ | | data moved here
+ | help: consider removing the `&`: `Either::One(_t)`
+ |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ --> $DIR/simple.rs:209:22
+ |
+LL | &Either::One(_t) => (),
+ | ^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/simple.rs:219:22
+ |
+LL | let &mut X(_t) = sm;
+ | ---------- ^^ cannot move out of borrowed content
+ | | |
+ | | data moved here
+ | help: consider removing the `&mut`: `X(_t)`
+ |
+note: move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+ --> $DIR/simple.rs:219:16
+ |
+LL | let &mut X(_t) = sm;
+ | ^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/simple.rs:223:35
+ |
+LL | if let &mut Either::One(_t) = rm { }
+ | -------------------- ^^ cannot move out of borrowed content
+ | | |
+ | | data moved here
+ | help: consider removing the `&mut`: `Either::One(_t)`
+ |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ --> $DIR/simple.rs:223:29
+ |
+LL | if let &mut Either::One(_t) = rm { }
+ | ^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/simple.rs:227:38
+ |
+LL | while let &mut Either::One(_t) = rm { }
+ | -------------------- ^^ cannot move out of borrowed content
+ | | |
+ | | data moved here
+ | help: consider removing the `&mut`: `Either::One(_t)`
+ |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ --> $DIR/simple.rs:227:32
+ |
+LL | while let &mut Either::One(_t) = rm { }
+ | ^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/simple.rs:231:11
+ |
+LL | match rm {
+ | ^^ cannot move out of borrowed content
+LL | //~^ ERROR cannot move
+LL | &mut Either::One(_t) => (),
+ | -- data moved here
+...
+LL | &mut Either::Two(_t) => (),
+ | -- ...and here
+ |
+note: move occurs because these variables have types that don't implement the `Copy` trait
+ --> $DIR/simple.rs:233:26
+ |
+LL | &mut Either::One(_t) => (),
+ | ^^
+...
+LL | &mut Either::Two(_t) => (),
+ | ^^
+help: consider removing the `&mut`
+ |
+LL | Either::One(_t) => (),
+ | ^^^^^^^^^^^^^^^
+help: consider removing the `&mut`
+ |
+LL | Either::Two(_t) => (),
+ | ^^^^^^^^^^^^^^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/simple.rs:240:11
+ |
+LL | match rm {
+ | ^^ cannot move out of borrowed content
+LL | //~^ ERROR cannot move
+LL | &mut Either::One(_t) => (),
+ | --------------------
+ | | |
+ | | data moved here
+ | help: consider removing the `&mut`: `Either::One(_t)`
+ |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ --> $DIR/simple.rs:242:26
+ |
+LL | &mut Either::One(_t) => (),
+ | ^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/simple.rs:247:11
+ |
+LL | match rm {
+ | ^^ cannot move out of borrowed content
+LL | //~^ ERROR cannot move
+LL | &mut Either::One(_t) => (),
+ | --------------------
+ | | |
+ | | data moved here
+ | help: consider removing the `&mut`: `Either::One(_t)`
+ |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ --> $DIR/simple.rs:249:26
+ |
+LL | &mut Either::One(_t) => (),
+ | ^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/simple.rs:254:11
+ |
+LL | match rm {
+ | ^^ cannot move out of borrowed content
+LL | //~^ ERROR cannot move
+LL | &mut Either::One(_t) => (),
+ | --------------------
+ | | |
+ | | data moved here
+ | help: consider removing the `&mut`: `Either::One(_t)`
+ |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ --> $DIR/simple.rs:256:26
+ |
+LL | &mut Either::One(_t) => (),
+ | ^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/simple.rs:270:21
+ |
+LL | let (&X(_t),) = (&x.clone(),);
+ | -- ^^^^^^^^^^^^^ cannot move out of borrowed content
+ | |
+ | data moved here
+ |
+note: move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+ --> $DIR/simple.rs:270:13
+ |
+LL | let (&X(_t),) = (&x.clone(),);
+ | ^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/simple.rs:272:34
+ |
+LL | if let (&Either::One(_t),) = (&e.clone(),) { }
+ | -- ^^^^^^^^^^^^^ cannot move out of borrowed content
+ | |
+ | data moved here
+ |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ --> $DIR/simple.rs:272:26
+ |
+LL | if let (&Either::One(_t),) = (&e.clone(),) { }
+ | ^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/simple.rs:274:37
+ |
+LL | while let (&Either::One(_t),) = (&e.clone(),) { }
+ | -- ^^^^^^^^^^^^^ cannot move out of borrowed content
+ | |
+ | data moved here
+ |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ --> $DIR/simple.rs:274:29
+ |
+LL | while let (&Either::One(_t),) = (&e.clone(),) { }
+ | ^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/simple.rs:276:11
+ |
+LL | match (&e.clone(),) {
+ | ^^^^^^^^^^^^^ cannot move out of borrowed content
+LL | //~^ ERROR cannot move
+LL | (&Either::One(_t),)
+ | -- data moved here
+ |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ --> $DIR/simple.rs:278:23
+ |
+LL | (&Either::One(_t),)
+ | ^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/simple.rs:284:25
+ |
+LL | let (&mut X(_t),) = (&mut xm.clone(),);
+ | -- ^^^^^^^^^^^^^^^^^^ cannot move out of borrowed content
+ | |
+ | data moved here
+ |
+note: move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+ --> $DIR/simple.rs:284:17
+ |
+LL | let (&mut X(_t),) = (&mut xm.clone(),);
+ | ^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/simple.rs:286:38
+ |
+LL | if let (&mut Either::One(_t),) = (&mut em.clone(),) { }
+ | -- ^^^^^^^^^^^^^^^^^^ cannot move out of borrowed content
+ | |
+ | data moved here
+ |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ --> $DIR/simple.rs:286:30
+ |
+LL | if let (&mut Either::One(_t),) = (&mut em.clone(),) { }
+ | ^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/simple.rs:288:41
+ |
+LL | while let (&mut Either::One(_t),) = (&mut em.clone(),) { }
+ | -- ^^^^^^^^^^^^^^^^^^ cannot move out of borrowed content
+ | |
+ | data moved here
+ |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ --> $DIR/simple.rs:288:33
+ |
+LL | while let (&mut Either::One(_t),) = (&mut em.clone(),) { }
+ | ^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/simple.rs:290:11
+ |
+LL | match (&mut em.clone(),) {
+ | ^^^^^^^^^^^^^^^^^^ cannot move out of borrowed content
+LL | //~^ ERROR cannot move
+LL | (&mut Either::One(_t),) => (),
+ | -- data moved here
+LL | (&mut Either::Two(_t),) => (),
+ | -- ...and here
+ |
+note: move occurs because these variables have types that don't implement the `Copy` trait
+ --> $DIR/simple.rs:292:27
+ |
+LL | (&mut Either::One(_t),) => (),
+ | ^^
+LL | (&mut Either::Two(_t),) => (),
+ | ^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/simple.rs:300:18
+ |
+LL | let &X(_t) = &x;
+ | ------ ^^ cannot move out of borrowed content
+ | | |
+ | | data moved here
+ | help: consider removing the `&`: `X(_t)`
+ |
+note: move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+ --> $DIR/simple.rs:300:12
+ |
+LL | let &X(_t) = &x;
+ | ^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/simple.rs:304:31
+ |
+LL | if let &Either::One(_t) = &e { }
+ | ---------------- ^^ cannot move out of borrowed content
+ | | |
+ | | data moved here
+ | help: consider removing the `&`: `Either::One(_t)`
+ |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ --> $DIR/simple.rs:304:25
+ |
+LL | if let &Either::One(_t) = &e { }
+ | ^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/simple.rs:308:34
+ |
+LL | while let &Either::One(_t) = &e { }
+ | ---------------- ^^ cannot move out of borrowed content
+ | | |
+ | | data moved here
+ | help: consider removing the `&`: `Either::One(_t)`
+ |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ --> $DIR/simple.rs:308:28
+ |
+LL | while let &Either::One(_t) = &e { }
+ | ^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/simple.rs:312:11
+ |
+LL | match &e {
+ | ^^ cannot move out of borrowed content
+LL | //~^ ERROR cannot move
+LL | &Either::One(_t)
+ | ----------------
+ | | |
+ | | data moved here
+ | help: consider removing the `&`: `Either::One(_t)`
+ |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ --> $DIR/simple.rs:314:22
+ |
+LL | &Either::One(_t)
+ | ^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/simple.rs:320:11
+ |
+LL | match &e {
+ | ^^ cannot move out of borrowed content
+LL | //~^ ERROR cannot move
+LL | &Either::One(_t) => (),
+ | ----------------
+ | | |
+ | | data moved here
+ | help: consider removing the `&`: `Either::One(_t)`
+ |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ --> $DIR/simple.rs:322:22
+ |
+LL | &Either::One(_t) => (),
+ | ^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/simple.rs:327:11
+ |
+LL | match &e {
+ | ^^ cannot move out of borrowed content
+LL | //~^ ERROR cannot move
+LL | &Either::One(_t) => (),
+ | ----------------
+ | | |
+ | | data moved here
+ | help: consider removing the `&`: `Either::One(_t)`
+ |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ --> $DIR/simple.rs:329:22
+ |
+LL | &Either::One(_t) => (),
+ | ^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/simple.rs:335:22
+ |
+LL | let &mut X(_t) = &mut xm;
+ | ---------- ^^^^^^^ cannot move out of borrowed content
+ | | |
+ | | data moved here
+ | help: consider removing the `&mut`: `X(_t)`
+ |
+note: move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+ --> $DIR/simple.rs:335:16
+ |
+LL | let &mut X(_t) = &mut xm;
+ | ^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/simple.rs:339:35
+ |
+LL | if let &mut Either::One(_t) = &mut em { }
+ | -------------------- ^^^^^^^ cannot move out of borrowed content
+ | | |
+ | | data moved here
+ | help: consider removing the `&mut`: `Either::One(_t)`
+ |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ --> $DIR/simple.rs:339:29
+ |
+LL | if let &mut Either::One(_t) = &mut em { }
+ | ^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/simple.rs:343:38
+ |
+LL | while let &mut Either::One(_t) = &mut em { }
+ | -------------------- ^^^^^^^ cannot move out of borrowed content
+ | | |
+ | | data moved here
+ | help: consider removing the `&mut`: `Either::One(_t)`
+ |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ --> $DIR/simple.rs:343:32
+ |
+LL | while let &mut Either::One(_t) = &mut em { }
+ | ^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/simple.rs:347:11
+ |
+LL | match &mut em {
+ | ^^^^^^^ cannot move out of borrowed content
+LL | //~^ ERROR cannot move
+LL | &mut Either::One(_t)
+ | --------------------
+ | | |
+ | | data moved here
+ | help: consider removing the `&mut`: `Either::One(_t)`
+ |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ --> $DIR/simple.rs:349:26
+ |
+LL | &mut Either::One(_t)
+ | ^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/simple.rs:355:11
+ |
+LL | match &mut em {
+ | ^^^^^^^ cannot move out of borrowed content
+LL | //~^ ERROR cannot move
+LL | &mut Either::One(_t) => (),
+ | --------------------
+ | | |
+ | | data moved here
+ | help: consider removing the `&mut`: `Either::One(_t)`
+ |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ --> $DIR/simple.rs:357:26
+ |
+LL | &mut Either::One(_t) => (),
+ | ^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/simple.rs:362:11
+ |
+LL | match &mut em {
+ | ^^^^^^^ cannot move out of borrowed content
+LL | //~^ ERROR cannot move
+LL | &mut Either::One(_t) => (),
+ | --------------------
+ | | |
+ | | data moved here
+ | help: consider removing the `&mut`: `Either::One(_t)`
+ |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ --> $DIR/simple.rs:364:26
+ |
+LL | &mut Either::One(_t) => (),
+ | ^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/simple.rs:369:11
+ |
+LL | match &mut em {
+ | ^^^^^^^ cannot move out of borrowed content
+LL | //~^ ERROR cannot move
+LL | &mut Either::One(_t) => (),
+ | --------------------
+ | | |
+ | | data moved here
+ | help: consider removing the `&mut`: `Either::One(_t)`
+ |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ --> $DIR/simple.rs:371:26
+ |
+LL | &mut Either::One(_t) => (),
+ | ^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/simple.rs:214:11
+ |
+LL | fn f1(&X(_t): &X) { }
+ | ^^^--^
+ | | |
+ | | data moved here
+ | cannot move out of borrowed content
+ | help: consider removing the `&`: `X(_t)`
+ |
+note: move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+ --> $DIR/simple.rs:214:14
+ |
+LL | fn f1(&X(_t): &X) { }
+ | ^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/simple.rs:261:11
+ |
+LL | fn f2(&mut X(_t): &mut X) { }
+ | ^^^^^^^--^
+ | | |
+ | | data moved here
+ | cannot move out of borrowed content
+ | help: consider removing the `&mut`: `X(_t)`
+ |
+note: move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+ --> $DIR/simple.rs:261:18
+ |
+LL | fn f2(&mut X(_t): &mut X) { }
+ | ^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/simple.rs:281:11
+ |
+LL | fn f3((&X(_t),): (&X,)) { }
+ | ^^^^--^^^
+ | | |
+ | | data moved here
+ | cannot move out of borrowed content
+ |
+note: move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+ --> $DIR/simple.rs:281:15
+ |
+LL | fn f3((&X(_t),): (&X,)) { }
+ | ^^
+
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/simple.rs:295:11
+ |
+LL | fn f4((&mut X(_t),): (&mut X,)) { }
+ | ^^^^^^^^--^^^
+ | | |
+ | | data moved here
+ | cannot move out of borrowed content
+ |
+note: move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+ --> $DIR/simple.rs:295:19
+ |
+LL | fn f4((&mut X(_t),): (&mut X,)) { }
+ | ^^
+
+error: aborting due to 60 previous errors
+
+For more information about this error, try `rustc --explain E0507`.
error: incorrect close delimiter: `}`
--> $DIR/issue-10636-2.rs:18:1
|
-LL | } //~ ERROR: incorrect close delimiter
- | ^
- |
-note: unclosed delimiter
- --> $DIR/issue-10636-2.rs:15:15
- |
LL | option.map(|some| 42;
- | ^
+ | - unclosed delimiter
+...
+LL | } //~ ERROR: incorrect close delimiter
+ | ^ incorrect close delimiter
error: expected one of `)`, `,`, `.`, `?`, or an operator, found `;`
--> $DIR/issue-10636-2.rs:15:25
--- /dev/null
+error[E0597]: `x` does not live long enough
+ --> $DIR/unboxed-closure-region.rs:18:12
+ |
+LL | || x //~ ERROR `x` does not live long enough
+ | -- ^ borrowed value does not live long enough
+ | |
+ | value captured here
+LL | };
+ | - `x` dropped here while still borrowed
+LL | _f;
+ | -- borrow later used here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// ignore-compare-mode-nll
-
// Test that an unboxed closure that captures a free variable by
// reference cannot escape the region of that variable.
+
+
fn main() {
let _f = {
let x = 0;
|| x //~ ERROR `x` does not live long enough
};
+ _f;
}
| capture occurs here
LL | };
| - borrowed value only lives until here
+LL | _f;
LL | }
| - borrowed value needs to live until here
--- /dev/null
+error[E0503]: cannot use `x` because it was mutably borrowed
+ --> $DIR/unboxed-closures-borrow-conflict.rs:19:14
+ |
+LL | let f = || x += 1;
+ | -- - borrow occurs due to use of `x` in closure
+ | |
+ | borrow of `x` occurs here
+LL | let _y = x; //~ ERROR cannot use `x` because it was mutably borrowed
+ | ^ use of borrowed `x`
+LL | f;
+ | - borrow later used here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0503`.
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// ignore-compare-mode-nll
-
// Test that an unboxed closure that mutates a free variable will
// cause borrow conflicts.
+
+
fn main() {
let mut x = 0;
let f = || x += 1;
let _y = x; //~ ERROR cannot use `x` because it was mutably borrowed
+ f;
}
--- /dev/null
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-pass
+
+#![feature(custom_attribute, unrestricted_attribute_tokens)]
+
+#[my_attr(a b c d)]
+fn main() {}
Err(error) => {
proc_res.fatal(Some(&format!(
"failed to decode compiler output as json: \
- `{}`\noutput: {}\nline: {}",
+ `{}`\nline: {}\noutput: {}",
error, line, output
)));
}
Err(error) => {
proc_res.fatal(Some(&format!(
"failed to decode compiler output as json: \
- `{}`\noutput: {}\nline: {}",
+ `{}`\nline: {}\noutput: {}",
error, line, output
)));
}
.map(|entry| entry.expect("could not read directory entry"))
.filter(dir_entry_is_file)
.map(|entry| entry.file_name().into_string().unwrap())
+ .filter(|n| n.ends_with(".md"))
.map(|n| n.trim_right_matches(".md").to_owned())
.collect()
}