Auto merge of #67104 - Centril:rollup-07vahh9, r=Centril
Rollup of 10 pull requests
Successful merges:
- #66606 (Add feature gate for mut refs in const fn)
- #66841 (Add `{f32,f64}::approx_unchecked_to<Int>` unsafe methods)
- #67009 (Emit coercion suggestions in more places)
- #67052 (Ditch `parse_in_attr`)
- #67071 (Do not ICE on closure typeck)
- #67078 (accept union inside enum if not followed by identifier)
- #67090 (Change "either" to "any" in Layout::from_size_align's docs)
- #67092 (Fix comment typos in src/libcore/alloc.rs)
- #67094 (get rid of __ in field names)
- #67102 (Add note to src/ci/docker/README.md about multiple docker images)
Failed merges:
- #67101 (use `#[allow(unused_attributes)]` to paper over incr.comp problem)
r? @ghost
diff --git a/src/ci/docker/README.md b/src/ci/docker/README.md
index a2d83ec..872f2c3 100644
--- a/src/ci/docker/README.md
+++ b/src/ci/docker/README.md
@@ -16,6 +16,13 @@
Images will output artifacts in an `obj` dir at the root of a repository.
+**NOTE**: Re-using the same `obj` dir with different docker images with
+the same target triple (e.g. `dist-x86_64-linux` and `dist-various-1`)
+may result in strange linker errors, due shared library versions differing between platforms.
+
+If you encounter any issues when using multiple Docker images, try deleting your `obj` directory
+before running your command.
+
## Filesystem layout
- Each directory, excluding `scripts` and `disabled`, corresponds to a docker image
diff --git a/src/libcore/alloc.rs b/src/libcore/alloc.rs
index 4798769..20248f7 100644
--- a/src/libcore/alloc.rs
+++ b/src/libcore/alloc.rs
@@ -53,7 +53,7 @@
impl Layout {
/// Constructs a `Layout` from a given `size` and `align`,
- /// or returns `LayoutErr` if either of the following conditions
+ /// or returns `LayoutErr` if any of the following conditions
/// are not met:
///
/// * `align` must not be zero,
@@ -137,7 +137,7 @@
#[inline]
pub fn for_value<T: ?Sized>(t: &T) -> Self {
let (size, align) = (mem::size_of_val(t), mem::align_of_val(t));
- // See rationale in `new` for why this us using an unsafe variant below
+ // See rationale in `new` for why this is using an unsafe variant below
debug_assert!(Layout::from_size_align(size, align).is_ok());
unsafe {
Layout::from_size_align_unchecked(size, align)
@@ -196,7 +196,7 @@
// valid.
//
// 2. `len + align - 1` can overflow by at most `align - 1`,
- // so the &-mask wth `!(align - 1)` will ensure that in the
+ // so the &-mask with `!(align - 1)` will ensure that in the
// case of overflow, `len_rounded_up` will itself be 0.
// Thus the returned padding, when added to `len`, yields 0,
// which trivially satisfies the alignment `align`.
diff --git a/src/libcore/convert.rs b/src/libcore/convert/mod.rs
similarity index 98%
rename from src/libcore/convert.rs
rename to src/libcore/convert/mod.rs
index 08802b3..16d5375 100644
--- a/src/libcore/convert.rs
+++ b/src/libcore/convert/mod.rs
@@ -40,6 +40,11 @@
#![stable(feature = "rust1", since = "1.0.0")]
+mod num;
+
+#[unstable(feature = "convert_float_to_int", issue = "67057")]
+pub use num::FloatToInt;
+
/// The identity function.
///
/// Two things are important to note about this function:
diff --git a/src/libcore/convert/num.rs b/src/libcore/convert/num.rs
new file mode 100644
index 0000000..0877dac
--- /dev/null
+++ b/src/libcore/convert/num.rs
@@ -0,0 +1,369 @@
+use super::{From, TryFrom};
+use crate::num::TryFromIntError;
+
+mod private {
+ /// This trait being unreachable from outside the crate
+ /// prevents other implementations of the `FloatToInt` trait,
+ /// which allows potentially adding more trait methods after the trait is `#[stable]`.
+ #[unstable(feature = "convert_float_to_int", issue = "67057")]
+ pub trait Sealed {}
+}
+
+/// Supporting trait for inherent methods of `f32` and `f64` such as `round_unchecked_to`.
+/// Typically doesn’t need to be used directly.
+#[unstable(feature = "convert_float_to_int", issue = "67057")]
+pub trait FloatToInt<Int>: private::Sealed + Sized {
+ #[cfg(not(bootstrap))]
+ #[unstable(feature = "float_approx_unchecked_to", issue = "67058")]
+ #[doc(hidden)]
+ unsafe fn approx_unchecked(self) -> Int;
+}
+
+macro_rules! impl_float_to_int {
+ ( $Float: ident => $( $Int: ident )+ ) => {
+ #[unstable(feature = "convert_float_to_int", issue = "67057")]
+ impl private::Sealed for $Float {}
+ $(
+ #[unstable(feature = "convert_float_to_int", issue = "67057")]
+ impl FloatToInt<$Int> for $Float {
+ #[cfg(not(bootstrap))]
+ #[doc(hidden)]
+ #[inline]
+ unsafe fn approx_unchecked(self) -> $Int {
+ crate::intrinsics::float_to_int_approx_unchecked(self)
+ }
+ }
+ )+
+ }
+}
+
+impl_float_to_int!(f32 => u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize);
+impl_float_to_int!(f64 => u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize);
+
+// Conversion traits for primitive integer and float types
+// Conversions T -> T are covered by a blanket impl and therefore excluded
+// Some conversions from and to usize/isize are not implemented due to portability concerns
+macro_rules! impl_from {
+ ($Small: ty, $Large: ty, #[$attr:meta], $doc: expr) => {
+ #[$attr]
+ #[doc = $doc]
+ impl From<$Small> for $Large {
+ #[inline]
+ fn from(small: $Small) -> $Large {
+ small as $Large
+ }
+ }
+ };
+ ($Small: ty, $Large: ty, #[$attr:meta]) => {
+ impl_from!($Small,
+ $Large,
+ #[$attr],
+ concat!("Converts `",
+ stringify!($Small),
+ "` to `",
+ stringify!($Large),
+ "` losslessly."));
+ }
+}
+
+macro_rules! impl_from_bool {
+ ($target: ty, #[$attr:meta]) => {
+ impl_from!(bool, $target, #[$attr], concat!("Converts a `bool` to a `",
+ stringify!($target), "`. The resulting value is `0` for `false` and `1` for `true`
+values.
+
+# Examples
+
+```
+assert_eq!(", stringify!($target), "::from(true), 1);
+assert_eq!(", stringify!($target), "::from(false), 0);
+```"));
+ };
+}
+
+// Bool -> Any
+impl_from_bool! { u8, #[stable(feature = "from_bool", since = "1.28.0")] }
+impl_from_bool! { u16, #[stable(feature = "from_bool", since = "1.28.0")] }
+impl_from_bool! { u32, #[stable(feature = "from_bool", since = "1.28.0")] }
+impl_from_bool! { u64, #[stable(feature = "from_bool", since = "1.28.0")] }
+impl_from_bool! { u128, #[stable(feature = "from_bool", since = "1.28.0")] }
+impl_from_bool! { usize, #[stable(feature = "from_bool", since = "1.28.0")] }
+impl_from_bool! { i8, #[stable(feature = "from_bool", since = "1.28.0")] }
+impl_from_bool! { i16, #[stable(feature = "from_bool", since = "1.28.0")] }
+impl_from_bool! { i32, #[stable(feature = "from_bool", since = "1.28.0")] }
+impl_from_bool! { i64, #[stable(feature = "from_bool", since = "1.28.0")] }
+impl_from_bool! { i128, #[stable(feature = "from_bool", since = "1.28.0")] }
+impl_from_bool! { isize, #[stable(feature = "from_bool", since = "1.28.0")] }
+
+// Unsigned -> Unsigned
+impl_from! { u8, u16, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { u8, u32, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { u8, u64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { u8, u128, #[stable(feature = "i128", since = "1.26.0")] }
+impl_from! { u8, usize, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { u16, u32, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { u16, u64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { u16, u128, #[stable(feature = "i128", since = "1.26.0")] }
+impl_from! { u32, u64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { u32, u128, #[stable(feature = "i128", since = "1.26.0")] }
+impl_from! { u64, u128, #[stable(feature = "i128", since = "1.26.0")] }
+
+// Signed -> Signed
+impl_from! { i8, i16, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { i8, i32, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { i8, i64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { i8, i128, #[stable(feature = "i128", since = "1.26.0")] }
+impl_from! { i8, isize, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { i16, i32, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { i16, i64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { i16, i128, #[stable(feature = "i128", since = "1.26.0")] }
+impl_from! { i32, i64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { i32, i128, #[stable(feature = "i128", since = "1.26.0")] }
+impl_from! { i64, i128, #[stable(feature = "i128", since = "1.26.0")] }
+
+// Unsigned -> Signed
+impl_from! { u8, i16, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { u8, i32, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { u8, i64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { u8, i128, #[stable(feature = "i128", since = "1.26.0")] }
+impl_from! { u16, i32, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { u16, i64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { u16, i128, #[stable(feature = "i128", since = "1.26.0")] }
+impl_from! { u32, i64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { u32, i128, #[stable(feature = "i128", since = "1.26.0")] }
+impl_from! { u64, i128, #[stable(feature = "i128", since = "1.26.0")] }
+
+// The C99 standard defines bounds on INTPTR_MIN, INTPTR_MAX, and UINTPTR_MAX
+// which imply that pointer-sized integers must be at least 16 bits:
+// https://port70.net/~nsz/c/c99/n1256.html#7.18.2.4
+impl_from! { u16, usize, #[stable(feature = "lossless_iusize_conv", since = "1.26.0")] }
+impl_from! { u8, isize, #[stable(feature = "lossless_iusize_conv", since = "1.26.0")] }
+impl_from! { i16, isize, #[stable(feature = "lossless_iusize_conv", since = "1.26.0")] }
+
+// RISC-V defines the possibility of a 128-bit address space (RV128).
+
+// CHERI proposes 256-bit “capabilities”. Unclear if this would be relevant to usize/isize.
+// https://www.cl.cam.ac.uk/research/security/ctsrd/pdfs/20171017a-cheri-poster.pdf
+// http://www.csl.sri.com/users/neumann/2012resolve-cheri.pdf
+
+
+// Note: integers can only be represented with full precision in a float if
+// they fit in the significand, which is 24 bits in f32 and 53 bits in f64.
+// Lossy float conversions are not implemented at this time.
+
+// Signed -> Float
+impl_from! { i8, f32, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
+impl_from! { i8, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
+impl_from! { i16, f32, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
+impl_from! { i16, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
+impl_from! { i32, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
+
+// Unsigned -> Float
+impl_from! { u8, f32, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
+impl_from! { u8, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
+impl_from! { u16, f32, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
+impl_from! { u16, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
+impl_from! { u32, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
+
+// Float -> Float
+impl_from! { f32, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
+
+// no possible bounds violation
+macro_rules! try_from_unbounded {
+ ($source:ty, $($target:ty),*) => {$(
+ #[stable(feature = "try_from", since = "1.34.0")]
+ impl TryFrom<$source> for $target {
+ type Error = TryFromIntError;
+
+ /// Try to create the target number type from a source
+ /// number type. This returns an error if the source value
+ /// is outside of the range of the target type.
+ #[inline]
+ fn try_from(value: $source) -> Result<Self, Self::Error> {
+ Ok(value as $target)
+ }
+ }
+ )*}
+}
+
+// only negative bounds
+macro_rules! try_from_lower_bounded {
+ ($source:ty, $($target:ty),*) => {$(
+ #[stable(feature = "try_from", since = "1.34.0")]
+ impl TryFrom<$source> for $target {
+ type Error = TryFromIntError;
+
+ /// Try to create the target number type from a source
+ /// number type. This returns an error if the source value
+ /// is outside of the range of the target type.
+ #[inline]
+ fn try_from(u: $source) -> Result<$target, TryFromIntError> {
+ if u >= 0 {
+ Ok(u as $target)
+ } else {
+ Err(TryFromIntError(()))
+ }
+ }
+ }
+ )*}
+}
+
+// unsigned to signed (only positive bound)
+macro_rules! try_from_upper_bounded {
+ ($source:ty, $($target:ty),*) => {$(
+ #[stable(feature = "try_from", since = "1.34.0")]
+ impl TryFrom<$source> for $target {
+ type Error = TryFromIntError;
+
+ /// Try to create the target number type from a source
+ /// number type. This returns an error if the source value
+ /// is outside of the range of the target type.
+ #[inline]
+ fn try_from(u: $source) -> Result<$target, TryFromIntError> {
+ if u > (<$target>::max_value() as $source) {
+ Err(TryFromIntError(()))
+ } else {
+ Ok(u as $target)
+ }
+ }
+ }
+ )*}
+}
+
+// all other cases
+macro_rules! try_from_both_bounded {
+ ($source:ty, $($target:ty),*) => {$(
+ #[stable(feature = "try_from", since = "1.34.0")]
+ impl TryFrom<$source> for $target {
+ type Error = TryFromIntError;
+
+ /// Try to create the target number type from a source
+ /// number type. This returns an error if the source value
+ /// is outside of the range of the target type.
+ #[inline]
+ fn try_from(u: $source) -> Result<$target, TryFromIntError> {
+ let min = <$target>::min_value() as $source;
+ let max = <$target>::max_value() as $source;
+ if u < min || u > max {
+ Err(TryFromIntError(()))
+ } else {
+ Ok(u as $target)
+ }
+ }
+ }
+ )*}
+}
+
+macro_rules! rev {
+ ($mac:ident, $source:ty, $($target:ty),*) => {$(
+ $mac!($target, $source);
+ )*}
+}
+
+// intra-sign conversions
+try_from_upper_bounded!(u16, u8);
+try_from_upper_bounded!(u32, u16, u8);
+try_from_upper_bounded!(u64, u32, u16, u8);
+try_from_upper_bounded!(u128, u64, u32, u16, u8);
+
+try_from_both_bounded!(i16, i8);
+try_from_both_bounded!(i32, i16, i8);
+try_from_both_bounded!(i64, i32, i16, i8);
+try_from_both_bounded!(i128, i64, i32, i16, i8);
+
+// unsigned-to-signed
+try_from_upper_bounded!(u8, i8);
+try_from_upper_bounded!(u16, i8, i16);
+try_from_upper_bounded!(u32, i8, i16, i32);
+try_from_upper_bounded!(u64, i8, i16, i32, i64);
+try_from_upper_bounded!(u128, i8, i16, i32, i64, i128);
+
+// signed-to-unsigned
+try_from_lower_bounded!(i8, u8, u16, u32, u64, u128);
+try_from_lower_bounded!(i16, u16, u32, u64, u128);
+try_from_lower_bounded!(i32, u32, u64, u128);
+try_from_lower_bounded!(i64, u64, u128);
+try_from_lower_bounded!(i128, u128);
+try_from_both_bounded!(i16, u8);
+try_from_both_bounded!(i32, u16, u8);
+try_from_both_bounded!(i64, u32, u16, u8);
+try_from_both_bounded!(i128, u64, u32, u16, u8);
+
+// usize/isize
+try_from_upper_bounded!(usize, isize);
+try_from_lower_bounded!(isize, usize);
+
+#[cfg(target_pointer_width = "16")]
+mod ptr_try_from_impls {
+ use super::TryFromIntError;
+ use crate::convert::TryFrom;
+
+ try_from_upper_bounded!(usize, u8);
+ try_from_unbounded!(usize, u16, u32, u64, u128);
+ try_from_upper_bounded!(usize, i8, i16);
+ try_from_unbounded!(usize, i32, i64, i128);
+
+ try_from_both_bounded!(isize, u8);
+ try_from_lower_bounded!(isize, u16, u32, u64, u128);
+ try_from_both_bounded!(isize, i8);
+ try_from_unbounded!(isize, i16, i32, i64, i128);
+
+ rev!(try_from_upper_bounded, usize, u32, u64, u128);
+ rev!(try_from_lower_bounded, usize, i8, i16);
+ rev!(try_from_both_bounded, usize, i32, i64, i128);
+
+ rev!(try_from_upper_bounded, isize, u16, u32, u64, u128);
+ rev!(try_from_both_bounded, isize, i32, i64, i128);
+}
+
+#[cfg(target_pointer_width = "32")]
+mod ptr_try_from_impls {
+ use super::TryFromIntError;
+ use crate::convert::TryFrom;
+
+ try_from_upper_bounded!(usize, u8, u16);
+ try_from_unbounded!(usize, u32, u64, u128);
+ try_from_upper_bounded!(usize, i8, i16, i32);
+ try_from_unbounded!(usize, i64, i128);
+
+ try_from_both_bounded!(isize, u8, u16);
+ try_from_lower_bounded!(isize, u32, u64, u128);
+ try_from_both_bounded!(isize, i8, i16);
+ try_from_unbounded!(isize, i32, i64, i128);
+
+ rev!(try_from_unbounded, usize, u32);
+ rev!(try_from_upper_bounded, usize, u64, u128);
+ rev!(try_from_lower_bounded, usize, i8, i16, i32);
+ rev!(try_from_both_bounded, usize, i64, i128);
+
+ rev!(try_from_unbounded, isize, u16);
+ rev!(try_from_upper_bounded, isize, u32, u64, u128);
+ rev!(try_from_unbounded, isize, i32);
+ rev!(try_from_both_bounded, isize, i64, i128);
+}
+
+#[cfg(target_pointer_width = "64")]
+mod ptr_try_from_impls {
+ use super::TryFromIntError;
+ use crate::convert::TryFrom;
+
+ try_from_upper_bounded!(usize, u8, u16, u32);
+ try_from_unbounded!(usize, u64, u128);
+ try_from_upper_bounded!(usize, i8, i16, i32, i64);
+ try_from_unbounded!(usize, i128);
+
+ try_from_both_bounded!(isize, u8, u16, u32);
+ try_from_lower_bounded!(isize, u64, u128);
+ try_from_both_bounded!(isize, i8, i16, i32);
+ try_from_unbounded!(isize, i64, i128);
+
+ rev!(try_from_unbounded, usize, u32, u64);
+ rev!(try_from_upper_bounded, usize, u128);
+ rev!(try_from_lower_bounded, usize, i8, i16, i32, i64);
+ rev!(try_from_both_bounded, usize, i128);
+
+ rev!(try_from_unbounded, isize, u16, u32);
+ rev!(try_from_upper_bounded, isize, u64, u128);
+ rev!(try_from_unbounded, isize, i32, i64);
+ rev!(try_from_both_bounded, isize, i128);
+}
diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs
index 19928f3..18aae59 100644
--- a/src/libcore/intrinsics.rs
+++ b/src/libcore/intrinsics.rs
@@ -1144,6 +1144,11 @@
/// May assume inputs are finite.
pub fn frem_fast<T>(a: T, b: T) -> T;
+ /// Convert with LLVM’s fptoui/fptosi, which may return undef for values out of range
+ /// https://github.com/rust-lang/rust/issues/10184
+ #[cfg(not(bootstrap))]
+ pub fn float_to_int_approx_unchecked<Float, Int>(value: Float) -> Int;
+
/// Returns the number of bits set in an integer type `T`
pub fn ctpop<T>(x: T) -> T;
diff --git a/src/libcore/num/f32.rs b/src/libcore/num/f32.rs
index 913c0f9..ac06f95 100644
--- a/src/libcore/num/f32.rs
+++ b/src/libcore/num/f32.rs
@@ -7,9 +7,10 @@
#![stable(feature = "rust1", since = "1.0.0")]
+#[cfg(not(bootstrap))]
+use crate::convert::FloatToInt;
#[cfg(not(test))]
use crate::intrinsics;
-
use crate::mem;
use crate::num::FpCategory;
@@ -400,6 +401,35 @@
intrinsics::minnumf32(self, other)
}
+ /// Rounds toward zero and converts to any primitive integer type,
+ /// assuming that the value is finite and fits in that type.
+ ///
+ /// ```
+ /// #![feature(float_approx_unchecked_to)]
+ ///
+ /// let value = 4.6_f32;
+ /// let rounded = unsafe { value.approx_unchecked_to::<u16>() };
+ /// assert_eq!(rounded, 4);
+ ///
+ /// let value = -128.9_f32;
+ /// let rounded = unsafe { value.approx_unchecked_to::<i8>() };
+ /// assert_eq!(rounded, std::i8::MIN);
+ /// ```
+ ///
+ /// # Safety
+ ///
+ /// The value must:
+ ///
+ /// * Not be `NaN`
+ /// * Not be infinite
+ /// * Be representable in the return type `Int`, after truncating off its fractional part
+ #[cfg(not(bootstrap))]
+ #[unstable(feature = "float_approx_unchecked_to", issue = "67058")]
+ #[inline]
+ pub unsafe fn approx_unchecked_to<Int>(self) -> Int where Self: FloatToInt<Int> {
+ FloatToInt::<Int>::approx_unchecked(self)
+ }
+
/// Raw transmutation to `u32`.
///
/// This is currently identical to `transmute::<f32, u32>(self)` on all platforms.
diff --git a/src/libcore/num/f64.rs b/src/libcore/num/f64.rs
index 6ca830b..794f77f 100644
--- a/src/libcore/num/f64.rs
+++ b/src/libcore/num/f64.rs
@@ -7,9 +7,10 @@
#![stable(feature = "rust1", since = "1.0.0")]
+#[cfg(not(bootstrap))]
+use crate::convert::FloatToInt;
#[cfg(not(test))]
use crate::intrinsics;
-
use crate::mem;
use crate::num::FpCategory;
@@ -413,6 +414,35 @@
intrinsics::minnumf64(self, other)
}
+ /// Rounds toward zero and converts to any primitive integer type,
+ /// assuming that the value is finite and fits in that type.
+ ///
+ /// ```
+ /// #![feature(float_approx_unchecked_to)]
+ ///
+ /// let value = 4.6_f32;
+ /// let rounded = unsafe { value.approx_unchecked_to::<u16>() };
+ /// assert_eq!(rounded, 4);
+ ///
+ /// let value = -128.9_f32;
+ /// let rounded = unsafe { value.approx_unchecked_to::<i8>() };
+ /// assert_eq!(rounded, std::i8::MIN);
+ /// ```
+ ///
+ /// # Safety
+ ///
+ /// The value must:
+ ///
+ /// * Not be `NaN`
+ /// * Not be infinite
+ /// * Be representable in the return type `Int`, after truncating off its fractional part
+ #[cfg(not(bootstrap))]
+ #[unstable(feature = "float_approx_unchecked_to", issue = "67058")]
+ #[inline]
+ pub unsafe fn approx_unchecked_to<Int>(self) -> Int where Self: FloatToInt<Int> {
+ FloatToInt::<Int>::approx_unchecked(self)
+ }
+
/// Raw transmutation to `u64`.
///
/// This is currently identical to `transmute::<f64, u64>(self)` on all platforms.
diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs
index 4313248..585f144 100644
--- a/src/libcore/num/mod.rs
+++ b/src/libcore/num/mod.rs
@@ -4,7 +4,6 @@
#![stable(feature = "rust1", since = "1.0.0")]
-use crate::convert::TryFrom;
use crate::fmt;
use crate::intrinsics;
use crate::mem;
@@ -4701,7 +4700,7 @@
/// The error type returned when a checked integral type conversion fails.
#[stable(feature = "try_from", since = "1.34.0")]
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
-pub struct TryFromIntError(());
+pub struct TryFromIntError(pub(crate) ());
impl TryFromIntError {
#[unstable(feature = "int_error_internals",
@@ -4728,206 +4727,6 @@
}
}
-// no possible bounds violation
-macro_rules! try_from_unbounded {
- ($source:ty, $($target:ty),*) => {$(
- #[stable(feature = "try_from", since = "1.34.0")]
- impl TryFrom<$source> for $target {
- type Error = TryFromIntError;
-
- /// Try to create the target number type from a source
- /// number type. This returns an error if the source value
- /// is outside of the range of the target type.
- #[inline]
- fn try_from(value: $source) -> Result<Self, Self::Error> {
- Ok(value as $target)
- }
- }
- )*}
-}
-
-// only negative bounds
-macro_rules! try_from_lower_bounded {
- ($source:ty, $($target:ty),*) => {$(
- #[stable(feature = "try_from", since = "1.34.0")]
- impl TryFrom<$source> for $target {
- type Error = TryFromIntError;
-
- /// Try to create the target number type from a source
- /// number type. This returns an error if the source value
- /// is outside of the range of the target type.
- #[inline]
- fn try_from(u: $source) -> Result<$target, TryFromIntError> {
- if u >= 0 {
- Ok(u as $target)
- } else {
- Err(TryFromIntError(()))
- }
- }
- }
- )*}
-}
-
-// unsigned to signed (only positive bound)
-macro_rules! try_from_upper_bounded {
- ($source:ty, $($target:ty),*) => {$(
- #[stable(feature = "try_from", since = "1.34.0")]
- impl TryFrom<$source> for $target {
- type Error = TryFromIntError;
-
- /// Try to create the target number type from a source
- /// number type. This returns an error if the source value
- /// is outside of the range of the target type.
- #[inline]
- fn try_from(u: $source) -> Result<$target, TryFromIntError> {
- if u > (<$target>::max_value() as $source) {
- Err(TryFromIntError(()))
- } else {
- Ok(u as $target)
- }
- }
- }
- )*}
-}
-
-// all other cases
-macro_rules! try_from_both_bounded {
- ($source:ty, $($target:ty),*) => {$(
- #[stable(feature = "try_from", since = "1.34.0")]
- impl TryFrom<$source> for $target {
- type Error = TryFromIntError;
-
- /// Try to create the target number type from a source
- /// number type. This returns an error if the source value
- /// is outside of the range of the target type.
- #[inline]
- fn try_from(u: $source) -> Result<$target, TryFromIntError> {
- let min = <$target>::min_value() as $source;
- let max = <$target>::max_value() as $source;
- if u < min || u > max {
- Err(TryFromIntError(()))
- } else {
- Ok(u as $target)
- }
- }
- }
- )*}
-}
-
-macro_rules! rev {
- ($mac:ident, $source:ty, $($target:ty),*) => {$(
- $mac!($target, $source);
- )*}
-}
-
-// intra-sign conversions
-try_from_upper_bounded!(u16, u8);
-try_from_upper_bounded!(u32, u16, u8);
-try_from_upper_bounded!(u64, u32, u16, u8);
-try_from_upper_bounded!(u128, u64, u32, u16, u8);
-
-try_from_both_bounded!(i16, i8);
-try_from_both_bounded!(i32, i16, i8);
-try_from_both_bounded!(i64, i32, i16, i8);
-try_from_both_bounded!(i128, i64, i32, i16, i8);
-
-// unsigned-to-signed
-try_from_upper_bounded!(u8, i8);
-try_from_upper_bounded!(u16, i8, i16);
-try_from_upper_bounded!(u32, i8, i16, i32);
-try_from_upper_bounded!(u64, i8, i16, i32, i64);
-try_from_upper_bounded!(u128, i8, i16, i32, i64, i128);
-
-// signed-to-unsigned
-try_from_lower_bounded!(i8, u8, u16, u32, u64, u128);
-try_from_lower_bounded!(i16, u16, u32, u64, u128);
-try_from_lower_bounded!(i32, u32, u64, u128);
-try_from_lower_bounded!(i64, u64, u128);
-try_from_lower_bounded!(i128, u128);
-try_from_both_bounded!(i16, u8);
-try_from_both_bounded!(i32, u16, u8);
-try_from_both_bounded!(i64, u32, u16, u8);
-try_from_both_bounded!(i128, u64, u32, u16, u8);
-
-// usize/isize
-try_from_upper_bounded!(usize, isize);
-try_from_lower_bounded!(isize, usize);
-
-#[cfg(target_pointer_width = "16")]
-mod ptr_try_from_impls {
- use super::TryFromIntError;
- use crate::convert::TryFrom;
-
- try_from_upper_bounded!(usize, u8);
- try_from_unbounded!(usize, u16, u32, u64, u128);
- try_from_upper_bounded!(usize, i8, i16);
- try_from_unbounded!(usize, i32, i64, i128);
-
- try_from_both_bounded!(isize, u8);
- try_from_lower_bounded!(isize, u16, u32, u64, u128);
- try_from_both_bounded!(isize, i8);
- try_from_unbounded!(isize, i16, i32, i64, i128);
-
- rev!(try_from_upper_bounded, usize, u32, u64, u128);
- rev!(try_from_lower_bounded, usize, i8, i16);
- rev!(try_from_both_bounded, usize, i32, i64, i128);
-
- rev!(try_from_upper_bounded, isize, u16, u32, u64, u128);
- rev!(try_from_both_bounded, isize, i32, i64, i128);
-}
-
-#[cfg(target_pointer_width = "32")]
-mod ptr_try_from_impls {
- use super::TryFromIntError;
- use crate::convert::TryFrom;
-
- try_from_upper_bounded!(usize, u8, u16);
- try_from_unbounded!(usize, u32, u64, u128);
- try_from_upper_bounded!(usize, i8, i16, i32);
- try_from_unbounded!(usize, i64, i128);
-
- try_from_both_bounded!(isize, u8, u16);
- try_from_lower_bounded!(isize, u32, u64, u128);
- try_from_both_bounded!(isize, i8, i16);
- try_from_unbounded!(isize, i32, i64, i128);
-
- rev!(try_from_unbounded, usize, u32);
- rev!(try_from_upper_bounded, usize, u64, u128);
- rev!(try_from_lower_bounded, usize, i8, i16, i32);
- rev!(try_from_both_bounded, usize, i64, i128);
-
- rev!(try_from_unbounded, isize, u16);
- rev!(try_from_upper_bounded, isize, u32, u64, u128);
- rev!(try_from_unbounded, isize, i32);
- rev!(try_from_both_bounded, isize, i64, i128);
-}
-
-#[cfg(target_pointer_width = "64")]
-mod ptr_try_from_impls {
- use super::TryFromIntError;
- use crate::convert::TryFrom;
-
- try_from_upper_bounded!(usize, u8, u16, u32);
- try_from_unbounded!(usize, u64, u128);
- try_from_upper_bounded!(usize, i8, i16, i32, i64);
- try_from_unbounded!(usize, i128);
-
- try_from_both_bounded!(isize, u8, u16, u32);
- try_from_lower_bounded!(isize, u64, u128);
- try_from_both_bounded!(isize, i8, i16, i32);
- try_from_unbounded!(isize, i64, i128);
-
- rev!(try_from_unbounded, usize, u32, u64);
- rev!(try_from_upper_bounded, usize, u128);
- rev!(try_from_lower_bounded, usize, i8, i16, i32, i64);
- rev!(try_from_both_bounded, usize, i128);
-
- rev!(try_from_unbounded, isize, u16, u32);
- rev!(try_from_upper_bounded, isize, u64, u128);
- rev!(try_from_unbounded, isize, i32, i64);
- rev!(try_from_both_bounded, isize, i128);
-}
-
#[doc(hidden)]
trait FromStrRadixHelper: PartialOrd + Copy {
fn min_value() -> Self;
@@ -5110,131 +4909,3 @@
#[stable(feature = "rust1", since = "1.0.0")]
pub use crate::num::dec2flt::ParseFloatError;
-
-// Conversion traits for primitive integer and float types
-// Conversions T -> T are covered by a blanket impl and therefore excluded
-// Some conversions from and to usize/isize are not implemented due to portability concerns
-macro_rules! impl_from {
- ($Small: ty, $Large: ty, #[$attr:meta], $doc: expr) => {
- #[$attr]
- #[doc = $doc]
- impl From<$Small> for $Large {
- #[inline]
- fn from(small: $Small) -> $Large {
- small as $Large
- }
- }
- };
- ($Small: ty, $Large: ty, #[$attr:meta]) => {
- impl_from!($Small,
- $Large,
- #[$attr],
- concat!("Converts `",
- stringify!($Small),
- "` to `",
- stringify!($Large),
- "` losslessly."));
- }
-}
-
-macro_rules! impl_from_bool {
- ($target: ty, #[$attr:meta]) => {
- impl_from!(bool, $target, #[$attr], concat!("Converts a `bool` to a `",
- stringify!($target), "`. The resulting value is `0` for `false` and `1` for `true`
-values.
-
-# Examples
-
-```
-assert_eq!(", stringify!($target), "::from(true), 1);
-assert_eq!(", stringify!($target), "::from(false), 0);
-```"));
- };
-}
-
-// Bool -> Any
-impl_from_bool! { u8, #[stable(feature = "from_bool", since = "1.28.0")] }
-impl_from_bool! { u16, #[stable(feature = "from_bool", since = "1.28.0")] }
-impl_from_bool! { u32, #[stable(feature = "from_bool", since = "1.28.0")] }
-impl_from_bool! { u64, #[stable(feature = "from_bool", since = "1.28.0")] }
-impl_from_bool! { u128, #[stable(feature = "from_bool", since = "1.28.0")] }
-impl_from_bool! { usize, #[stable(feature = "from_bool", since = "1.28.0")] }
-impl_from_bool! { i8, #[stable(feature = "from_bool", since = "1.28.0")] }
-impl_from_bool! { i16, #[stable(feature = "from_bool", since = "1.28.0")] }
-impl_from_bool! { i32, #[stable(feature = "from_bool", since = "1.28.0")] }
-impl_from_bool! { i64, #[stable(feature = "from_bool", since = "1.28.0")] }
-impl_from_bool! { i128, #[stable(feature = "from_bool", since = "1.28.0")] }
-impl_from_bool! { isize, #[stable(feature = "from_bool", since = "1.28.0")] }
-
-// Unsigned -> Unsigned
-impl_from! { u8, u16, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
-impl_from! { u8, u32, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
-impl_from! { u8, u64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
-impl_from! { u8, u128, #[stable(feature = "i128", since = "1.26.0")] }
-impl_from! { u8, usize, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
-impl_from! { u16, u32, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
-impl_from! { u16, u64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
-impl_from! { u16, u128, #[stable(feature = "i128", since = "1.26.0")] }
-impl_from! { u32, u64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
-impl_from! { u32, u128, #[stable(feature = "i128", since = "1.26.0")] }
-impl_from! { u64, u128, #[stable(feature = "i128", since = "1.26.0")] }
-
-// Signed -> Signed
-impl_from! { i8, i16, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
-impl_from! { i8, i32, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
-impl_from! { i8, i64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
-impl_from! { i8, i128, #[stable(feature = "i128", since = "1.26.0")] }
-impl_from! { i8, isize, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
-impl_from! { i16, i32, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
-impl_from! { i16, i64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
-impl_from! { i16, i128, #[stable(feature = "i128", since = "1.26.0")] }
-impl_from! { i32, i64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
-impl_from! { i32, i128, #[stable(feature = "i128", since = "1.26.0")] }
-impl_from! { i64, i128, #[stable(feature = "i128", since = "1.26.0")] }
-
-// Unsigned -> Signed
-impl_from! { u8, i16, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
-impl_from! { u8, i32, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
-impl_from! { u8, i64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
-impl_from! { u8, i128, #[stable(feature = "i128", since = "1.26.0")] }
-impl_from! { u16, i32, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
-impl_from! { u16, i64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
-impl_from! { u16, i128, #[stable(feature = "i128", since = "1.26.0")] }
-impl_from! { u32, i64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
-impl_from! { u32, i128, #[stable(feature = "i128", since = "1.26.0")] }
-impl_from! { u64, i128, #[stable(feature = "i128", since = "1.26.0")] }
-
-// The C99 standard defines bounds on INTPTR_MIN, INTPTR_MAX, and UINTPTR_MAX
-// which imply that pointer-sized integers must be at least 16 bits:
-// https://port70.net/~nsz/c/c99/n1256.html#7.18.2.4
-impl_from! { u16, usize, #[stable(feature = "lossless_iusize_conv", since = "1.26.0")] }
-impl_from! { u8, isize, #[stable(feature = "lossless_iusize_conv", since = "1.26.0")] }
-impl_from! { i16, isize, #[stable(feature = "lossless_iusize_conv", since = "1.26.0")] }
-
-// RISC-V defines the possibility of a 128-bit address space (RV128).
-
-// CHERI proposes 256-bit “capabilities”. Unclear if this would be relevant to usize/isize.
-// https://www.cl.cam.ac.uk/research/security/ctsrd/pdfs/20171017a-cheri-poster.pdf
-// http://www.csl.sri.com/users/neumann/2012resolve-cheri.pdf
-
-
-// Note: integers can only be represented with full precision in a float if
-// they fit in the significand, which is 24 bits in f32 and 53 bits in f64.
-// Lossy float conversions are not implemented at this time.
-
-// Signed -> Float
-impl_from! { i8, f32, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
-impl_from! { i8, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
-impl_from! { i16, f32, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
-impl_from! { i16, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
-impl_from! { i32, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
-
-// Unsigned -> Float
-impl_from! { u8, f32, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
-impl_from! { u8, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
-impl_from! { u16, f32, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
-impl_from! { u16, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
-impl_from! { u32, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
-
-// Float -> Float
-impl_from! { f32, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs
index 412300f..35017d6 100644
--- a/src/librustc/traits/error_reporting.rs
+++ b/src/librustc/traits/error_reporting.rs
@@ -2210,6 +2210,10 @@
}
let span = self.tcx.def_span(generator_did);
+ // Do not ICE on closure typeck (#66868).
+ if let None = self.tcx.hir().as_local_hir_id(generator_did) {
+ return false;
+ }
let tables = self.tcx.typeck_tables_of(generator_did);
debug!("note_obligation_cause_for_async_await: generator_did={:?} span={:?} ",
generator_did, span);
diff --git a/src/librustc_codegen_llvm/intrinsic.rs b/src/librustc_codegen_llvm/intrinsic.rs
index 9df75a8..1767ad1 100644
--- a/src/librustc_codegen_llvm/intrinsic.rs
+++ b/src/librustc_codegen_llvm/intrinsic.rs
@@ -516,9 +516,36 @@
return;
}
}
-
},
+ "float_to_int_approx_unchecked" => {
+ if float_type_width(arg_tys[0]).is_none() {
+ span_invalid_monomorphization_error(
+ tcx.sess, span,
+ &format!("invalid monomorphization of `float_to_int_approx_unchecked` \
+ intrinsic: expected basic float type, \
+ found `{}`", arg_tys[0]));
+ return;
+ }
+ match int_type_width_signed(ret_ty, self.cx) {
+ Some((width, signed)) => {
+ if signed {
+ self.fptosi(args[0].immediate(), self.cx.type_ix(width))
+ } else {
+ self.fptoui(args[0].immediate(), self.cx.type_ix(width))
+ }
+ }
+ None => {
+ span_invalid_monomorphization_error(
+ tcx.sess, span,
+ &format!("invalid monomorphization of `float_to_int_approx_unchecked` \
+ intrinsic: expected basic integer type, \
+ found `{}`", ret_ty));
+ return;
+ }
+ }
+ }
+
"discriminant_value" => {
args[0].deref(self.cx()).codegen_get_discr(self, ret_ty)
}
diff --git a/src/librustc_error_codes/error_codes.rs b/src/librustc_error_codes/error_codes.rs
index 9e4b704..9c1bec3 100644
--- a/src/librustc_error_codes/error_codes.rs
+++ b/src/librustc_error_codes/error_codes.rs
@@ -18,7 +18,6 @@
E0013: include_str!("./error_codes/E0013.md"),
E0014: include_str!("./error_codes/E0014.md"),
E0015: include_str!("./error_codes/E0015.md"),
-E0017: include_str!("./error_codes/E0017.md"),
E0019: include_str!("./error_codes/E0019.md"),
E0023: include_str!("./error_codes/E0023.md"),
E0025: include_str!("./error_codes/E0025.md"),
diff --git a/src/librustc_error_codes/error_codes/E0017.md b/src/librustc_error_codes/error_codes/E0017.md
deleted file mode 100644
index d5e6857..0000000
--- a/src/librustc_error_codes/error_codes/E0017.md
+++ /dev/null
@@ -1,20 +0,0 @@
-References in statics and constants may only refer to immutable values.
-
-Erroneous code example:
-
-```compile_fail,E0017
-static X: i32 = 1;
-const C: i32 = 2;
-
-// these three are not allowed:
-const CR: &mut i32 = &mut C;
-static STATIC_REF: &'static mut i32 = &mut X;
-static CONST_REF: &'static mut i32 = &mut C;
-```
-
-Statics are shared everywhere, and if they refer to mutable data one might
-violate memory safety since holding multiple mutable references to shared data
-is not allowed.
-
-If you really want global mutable state, try using `static mut` or a global
-`UnsafeCell`.
diff --git a/src/librustc_feature/active.rs b/src/librustc_feature/active.rs
index fc880b9..b1ae7c6 100644
--- a/src/librustc_feature/active.rs
+++ b/src/librustc_feature/active.rs
@@ -523,6 +523,9 @@
/// Allows the use of `#[cfg(sanitize = "option")]`; set when -Zsanitizer is used.
(active, cfg_sanitize, "1.41.0", Some(39699), None),
+ /// Allows using `&mut` in constant functions.
+ (active, const_mut_refs, "1.41.0", Some(57349), None),
+
// -------------------------------------------------------------------------
// feature-group-end: actual feature gates
// -------------------------------------------------------------------------
diff --git a/src/librustc_mir/transform/check_consts/ops.rs b/src/librustc_mir/transform/check_consts/ops.rs
index aec3cf0..393ae94 100644
--- a/src/librustc_mir/transform/check_consts/ops.rs
+++ b/src/librustc_mir/transform/check_consts/ops.rs
@@ -1,7 +1,6 @@
//! Concrete error types for all operations which may be invalid in a certain const context.
use rustc::hir::def_id::DefId;
-use rustc::mir::BorrowKind;
use rustc::session::config::nightly_options;
use rustc::ty::TyCtxt;
use syntax::feature_gate::feature_err;
@@ -181,38 +180,53 @@
}
#[derive(Debug)]
-pub struct MutBorrow(pub BorrowKind);
-impl NonConstOp for MutBorrow {
+pub struct CellBorrow;
+impl NonConstOp for CellBorrow {
fn emit_error(&self, item: &Item<'_, '_>, span: Span) {
- let kind = self.0;
- if let BorrowKind::Mut { .. } = kind {
- let mut err = struct_span_err!(item.tcx.sess, span, E0017,
- "references in {}s may only refer \
- to immutable values", item.const_kind());
- err.span_label(span, format!("{}s require immutable values",
- item.const_kind()));
- if item.tcx.sess.teach(&err.get_code().unwrap()) {
- err.note("References in statics and constants may only refer \
- to immutable values.\n\n\
- Statics are shared everywhere, and if they refer to \
- mutable data one might violate memory safety since \
- holding multiple mutable references to shared data \
- is not allowed.\n\n\
- If you really want global mutable state, try using \
- static mut or a global UnsafeCell.");
- }
- err.emit();
- } else {
- span_err!(item.tcx.sess, span, E0492,
- "cannot borrow a constant which may contain \
- interior mutability, create a static instead");
+ span_err!(item.tcx.sess, span, E0492,
+ "cannot borrow a constant which may contain \
+ interior mutability, create a static instead");
+ }
+}
+
+#[derive(Debug)]
+pub struct MutBorrow;
+impl NonConstOp for MutBorrow {
+ fn feature_gate(tcx: TyCtxt<'_>) -> Option<bool> {
+ Some(tcx.features().const_mut_refs)
+ }
+
+ fn emit_error(&self, item: &Item<'_, '_>, span: Span) {
+ let mut err = feature_err(
+ &item.tcx.sess.parse_sess,
+ sym::const_mut_refs,
+ span,
+ &format!("references in {}s may only refer \
+ to immutable values", item.const_kind())
+ );
+ err.span_label(span, format!("{}s require immutable values",
+ item.const_kind()));
+ if item.tcx.sess.teach(&err.get_code().unwrap()) {
+ err.note("References in statics and constants may only refer \
+ to immutable values.\n\n\
+ Statics are shared everywhere, and if they refer to \
+ mutable data one might violate memory safety since \
+ holding multiple mutable references to shared data \
+ is not allowed.\n\n\
+ If you really want global mutable state, try using \
+ static mut or a global UnsafeCell.");
}
+ err.emit();
}
}
#[derive(Debug)]
pub struct MutDeref;
-impl NonConstOp for MutDeref {}
+impl NonConstOp for MutDeref {
+ fn feature_gate(tcx: TyCtxt<'_>) -> Option<bool> {
+ Some(tcx.features().const_mut_refs)
+ }
+}
#[derive(Debug)]
pub struct Panic;
diff --git a/src/librustc_mir/transform/check_consts/validation.rs b/src/librustc_mir/transform/check_consts/validation.rs
index f44bac1..7170857 100644
--- a/src/librustc_mir/transform/check_consts/validation.rs
+++ b/src/librustc_mir/transform/check_consts/validation.rs
@@ -359,7 +359,11 @@
};
if !is_allowed {
- self.check_op(ops::MutBorrow(kind));
+ if let BorrowKind::Mut{ .. } = kind {
+ self.check_op(ops::MutBorrow);
+ } else {
+ self.check_op(ops::CellBorrow);
+ }
}
}
@@ -384,7 +388,11 @@
);
if borrowed_place_has_mut_interior {
- self.check_op(ops::MutBorrow(kind));
+ if let BorrowKind::Mut{ .. } = kind {
+ self.check_op(ops::MutBorrow);
+ } else {
+ self.check_op(ops::CellBorrow);
+ }
}
}
@@ -451,7 +459,6 @@
}
}
}
-
fn visit_projection_elem(
&mut self,
place_base: &PlaceBase<'tcx>,
diff --git a/src/librustc_mir/transform/qualify_min_const_fn.rs b/src/librustc_mir/transform/qualify_min_const_fn.rs
index 3030d2e..cf2e130 100644
--- a/src/librustc_mir/transform/qualify_min_const_fn.rs
+++ b/src/librustc_mir/transform/qualify_min_const_fn.rs
@@ -79,10 +79,14 @@
fn check_ty(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, span: Span, fn_def_id: DefId) -> McfResult {
for ty in ty.walk() {
match ty.kind {
- ty::Ref(_, _, hir::Mutability::Mutable) => return Err((
- span,
- "mutable references in const fn are unstable".into(),
- )),
+ ty::Ref(_, _, hir::Mutability::Mutable) => {
+ if !tcx.features().const_mut_refs {
+ return Err((
+ span,
+ "mutable references in const fn are unstable".into(),
+ ))
+ }
+ }
ty::Opaque(..) => return Err((span, "`impl Trait` in const fn is unstable".into())),
ty::FnPtr(..) => {
if !tcx.const_fn_is_allowed_fn_ptr(fn_def_id) {
diff --git a/src/librustc_parse/config.rs b/src/librustc_parse/config.rs
index 7dbfd98..1e9203f 100644
--- a/src/librustc_parse/config.rs
+++ b/src/librustc_parse/config.rs
@@ -8,18 +8,19 @@
//!
//! [#64197]: https://github.com/rust-lang/rust/issues/64197
-use crate::validate_attr;
+use crate::{parse_in, validate_attr};
use rustc_feature::Features;
use rustc_errors::Applicability;
use syntax::attr::HasAttrs;
use syntax::feature_gate::{feature_err, get_features};
use syntax::attr;
-use syntax::ast;
+use syntax::ast::{self, Attribute, AttrItem, MetaItem};
use syntax::edition::Edition;
use syntax::mut_visit::*;
use syntax::ptr::P;
use syntax::sess::ParseSess;
use syntax::util::map_in_place::MapInPlace;
+use syntax_pos::Span;
use syntax_pos::symbol::sym;
use smallvec::SmallVec;
@@ -72,6 +73,11 @@
}
}
+const CFG_ATTR_GRAMMAR_HELP: &str = "#[cfg_attr(condition, attribute, other_attribute, ...)]";
+const CFG_ATTR_NOTE_REF: &str = "for more information, visit \
+ <https://doc.rust-lang.org/reference/conditional-compilation.html\
+ #the-cfg_attr-attribute>";
+
impl<'a> StripUnconfigured<'a> {
pub fn configure<T: HasAttrs>(&mut self, mut node: T) -> Option<T> {
self.process_cfg_attrs(&mut node);
@@ -97,34 +103,14 @@
/// Gives a compiler warning when the `cfg_attr` contains no attributes and
/// is in the original source file. Gives a compiler error if the syntax of
/// the attribute is incorrect.
- fn process_cfg_attr(&mut self, attr: ast::Attribute) -> Vec<ast::Attribute> {
+ fn process_cfg_attr(&mut self, attr: Attribute) -> Vec<Attribute> {
if !attr.has_name(sym::cfg_attr) {
return vec![attr];
}
- if let ast::MacArgs::Empty = attr.get_normal_item().args {
- self.sess.span_diagnostic
- .struct_span_err(
- attr.span,
- "malformed `cfg_attr` attribute input",
- ).span_suggestion(
- attr.span,
- "missing condition and attribute",
- "#[cfg_attr(condition, attribute, other_attribute, ...)]".to_owned(),
- Applicability::HasPlaceholders,
- ).note("for more information, visit \
- <https://doc.rust-lang.org/reference/conditional-compilation.html\
- #the-cfg_attr-attribute>")
- .emit();
- return vec![];
- }
- let res = crate::parse_in_attr(self.sess, &attr, |p| p.parse_cfg_attr());
- let (cfg_predicate, expanded_attrs) = match res {
- Ok(result) => result,
- Err(mut e) => {
- e.emit();
- return vec![];
- }
+ let (cfg_predicate, expanded_attrs) = match self.parse_cfg_attr(&attr) {
+ None => return vec![],
+ Some(r) => r,
};
// Lint on zero attributes in source.
@@ -135,24 +121,56 @@
// At this point we know the attribute is considered used.
attr::mark_used(&attr);
- if attr::cfg_matches(&cfg_predicate, self.sess, self.features) {
- // We call `process_cfg_attr` recursively in case there's a
- // `cfg_attr` inside of another `cfg_attr`. E.g.
- // `#[cfg_attr(false, cfg_attr(true, some_attr))]`.
- expanded_attrs.into_iter()
- .flat_map(|(item, span)| self.process_cfg_attr(attr::mk_attr_from_item(
- attr.style,
- item,
- span,
- )))
- .collect()
- } else {
- vec![]
+ if !attr::cfg_matches(&cfg_predicate, self.sess, self.features) {
+ return vec![];
}
+
+ // We call `process_cfg_attr` recursively in case there's a
+ // `cfg_attr` inside of another `cfg_attr`. E.g.
+ // `#[cfg_attr(false, cfg_attr(true, some_attr))]`.
+ expanded_attrs
+ .into_iter()
+ .flat_map(|(item, span)| {
+ let attr = attr::mk_attr_from_item(attr.style, item, span);
+ self.process_cfg_attr(attr)
+ })
+ .collect()
+ }
+
+ fn parse_cfg_attr(&self, attr: &Attribute) -> Option<(MetaItem, Vec<(AttrItem, Span)>)> {
+ match attr.get_normal_item().args {
+ ast::MacArgs::Delimited(dspan, delim, ref tts) if !tts.is_empty() => {
+ let msg = "wrong `cfg_attr` delimiters";
+ validate_attr::check_meta_bad_delim(self.sess, dspan, delim, msg);
+ match parse_in(self.sess, tts.clone(), "`cfg_attr` input", |p| p.parse_cfg_attr()) {
+ Ok(r) => return Some(r),
+ Err(mut e) => e
+ .help(&format!("the valid syntax is `{}`", CFG_ATTR_GRAMMAR_HELP))
+ .note(CFG_ATTR_NOTE_REF)
+ .emit(),
+ }
+ }
+ _ => self.error_malformed_cfg_attr_missing(attr.span),
+ }
+ None
+ }
+
+ fn error_malformed_cfg_attr_missing(&self, span: Span) {
+ self.sess
+ .span_diagnostic
+ .struct_span_err(span, "malformed `cfg_attr` attribute input")
+ .span_suggestion(
+ span,
+ "missing condition and attribute",
+ CFG_ATTR_GRAMMAR_HELP.to_string(),
+ Applicability::HasPlaceholders,
+ )
+ .note(CFG_ATTR_NOTE_REF)
+ .emit();
}
/// Determines if a node with the given attributes should be included in this configuration.
- pub fn in_cfg(&self, attrs: &[ast::Attribute]) -> bool {
+ pub fn in_cfg(&self, attrs: &[Attribute]) -> bool {
attrs.iter().all(|attr| {
if !is_cfg(attr) {
return true;
@@ -199,7 +217,7 @@
}
/// Visit attributes on expression and statements (but not attributes on items in blocks).
- fn visit_expr_attrs(&mut self, attrs: &[ast::Attribute]) {
+ fn visit_expr_attrs(&mut self, attrs: &[Attribute]) {
// flag the offending attributes
for attr in attrs.iter() {
self.maybe_emit_expr_attr_err(attr);
@@ -207,7 +225,7 @@
}
/// If attributes are not allowed on expressions, emit an error for `attr`
- pub fn maybe_emit_expr_attr_err(&self, attr: &ast::Attribute) {
+ pub fn maybe_emit_expr_attr_err(&self, attr: &Attribute) {
if !self.features.map(|features| features.stmt_expr_attributes).unwrap_or(true) {
let mut err = feature_err(self.sess,
sym::stmt_expr_attributes,
@@ -350,7 +368,7 @@
}
}
-fn is_cfg(attr: &ast::Attribute) -> bool {
+fn is_cfg(attr: &Attribute) -> bool {
attr.check_name(sym::cfg)
}
@@ -359,8 +377,8 @@
pub fn process_configure_mod(
sess: &ParseSess,
cfg_mods: bool,
- attrs: &[ast::Attribute],
-) -> (bool, Vec<ast::Attribute>) {
+ attrs: &[Attribute],
+) -> (bool, Vec<Attribute>) {
// Don't perform gated feature checking.
let mut strip_unconfigured = StripUnconfigured { sess, features: None };
let mut attrs = attrs.to_owned();
diff --git a/src/librustc_parse/lib.rs b/src/librustc_parse/lib.rs
index 6905053..faff386 100644
--- a/src/librustc_parse/lib.rs
+++ b/src/librustc_parse/lib.rs
@@ -271,21 +271,13 @@
}
/// Runs the given subparser `f` on the tokens of the given `attr`'s item.
-pub fn parse_in_attr<'a, T>(
+pub fn parse_in<'a, T>(
sess: &'a ParseSess,
- attr: &ast::Attribute,
+ tts: TokenStream,
+ name: &'static str,
mut f: impl FnMut(&mut Parser<'a>) -> PResult<'a, T>,
) -> PResult<'a, T> {
- let mut parser = Parser::new(
- sess,
- // FIXME(#66940, Centril | petrochenkov): refactor this function so it doesn't
- // require reconstructing and immediately re-parsing delimiters.
- attr.get_normal_item().args.outer_tokens(),
- None,
- false,
- false,
- Some("attribute"),
- );
+ let mut parser = Parser::new(sess, tts, None, false, false, Some(name));
let result = f(&mut parser)?;
if parser.token != token::Eof {
parser.unexpected()?;
diff --git a/src/librustc_parse/parser/attr.rs b/src/librustc_parse/parser/attr.rs
index b2ae934..00fd6b8 100644
--- a/src/librustc_parse/parser/attr.rs
+++ b/src/librustc_parse/parser/attr.rs
@@ -220,7 +220,7 @@
Ok(attrs)
}
- pub(super) fn parse_unsuffixed_lit(&mut self) -> PResult<'a, ast::Lit> {
+ crate fn parse_unsuffixed_lit(&mut self) -> PResult<'a, ast::Lit> {
let lit = self.parse_lit()?;
debug!("checking if {:?} is unusuffixed", lit);
@@ -238,25 +238,36 @@
/// Parses `cfg_attr(pred, attr_item_list)` where `attr_item_list` is comma-delimited.
pub fn parse_cfg_attr(&mut self) -> PResult<'a, (ast::MetaItem, Vec<(ast::AttrItem, Span)>)> {
- self.expect(&token::OpenDelim(token::Paren))?;
-
let cfg_predicate = self.parse_meta_item()?;
self.expect(&token::Comma)?;
// Presumably, the majority of the time there will only be one attr.
let mut expanded_attrs = Vec::with_capacity(1);
-
- while !self.check(&token::CloseDelim(token::Paren)) {
- let lo = self.token.span.lo();
+ while self.token.kind != token::Eof {
+ let lo = self.token.span;
let item = self.parse_attr_item()?;
- expanded_attrs.push((item, self.prev_span.with_lo(lo)));
- self.expect_one_of(&[token::Comma], &[token::CloseDelim(token::Paren)])?;
+ expanded_attrs.push((item, lo.to(self.prev_span)));
+ if !self.eat(&token::Comma) {
+ break;
+ }
}
- self.expect(&token::CloseDelim(token::Paren))?;
Ok((cfg_predicate, expanded_attrs))
}
+ /// Matches `COMMASEP(meta_item_inner)`.
+ crate fn parse_meta_seq_top(&mut self) -> PResult<'a, Vec<ast::NestedMetaItem>> {
+ // Presumably, the majority of the time there will only be one attr.
+ let mut nmis = Vec::with_capacity(1);
+ while self.token.kind != token::Eof {
+ nmis.push(self.parse_meta_item_inner()?);
+ if !self.eat(&token::Comma) {
+ break;
+ }
+ }
+ Ok(nmis)
+ }
+
/// Matches the following grammar (per RFC 1559).
///
/// meta_item : PATH ( '=' UNSUFFIXED_LIT | '(' meta_item_inner? ')' )? ;
diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs
index ccf78e6..c3e5b39 100644
--- a/src/librustc_parse/parser/item.rs
+++ b/src/librustc_parse/parser/item.rs
@@ -1727,9 +1727,10 @@
/// Checks if current token is one of tokens which cannot be nested like `kw::Enum`. In case
/// it is, we try to parse the item and report error about nested types.
fn recover_nested_adt_item(&mut self, keyword: Symbol) -> PResult<'a, bool> {
- if self.token.is_keyword(kw::Enum) ||
+ if (self.token.is_keyword(kw::Enum) ||
self.token.is_keyword(kw::Struct) ||
- self.token.is_keyword(kw::Union)
+ self.token.is_keyword(kw::Union))
+ && self.look_ahead(1, |t| t.is_ident())
{
let kw_token = self.token.clone();
let kw_str = pprust::token_to_string(&kw_token);
diff --git a/src/librustc_parse/parser/path.rs b/src/librustc_parse/parser/path.rs
index 70c3458..5334fc4 100644
--- a/src/librustc_parse/parser/path.rs
+++ b/src/librustc_parse/parser/path.rs
@@ -3,7 +3,6 @@
use rustc_errors::{PResult, Applicability, pluralize};
use syntax::ast::{self, QSelf, Path, PathSegment, Ident, ParenthesizedArgs, AngleBracketedArgs};
use syntax::ast::{AnonConst, GenericArg, AssocTyConstraint, AssocTyConstraintKind, BlockCheckMode};
-use syntax::ast::MacArgs;
use syntax::ThinVec;
use syntax::token::{self, Token};
use syntax_pos::source_map::{Span, BytePos};
@@ -109,42 +108,6 @@
Ok(Path { segments, span: lo.to(self.prev_span) })
}
- /// Like `parse_path`, but also supports parsing `Word` meta items into paths for
- /// backwards-compatibility. This is used when parsing derive macro paths in `#[derive]`
- /// attributes.
- fn parse_path_allowing_meta(&mut self, style: PathStyle) -> PResult<'a, Path> {
- let meta_ident = match self.token.kind {
- token::Interpolated(ref nt) => match **nt {
- token::NtMeta(ref item) => match item.args {
- MacArgs::Empty => Some(item.path.clone()),
- _ => None,
- },
- _ => None,
- },
- _ => None,
- };
- if let Some(path) = meta_ident {
- self.bump();
- return Ok(path);
- }
- self.parse_path(style)
- }
-
- /// Parse a list of paths inside `#[derive(path_0, ..., path_n)]`.
- pub fn parse_derive_paths(&mut self) -> PResult<'a, Vec<Path>> {
- self.expect(&token::OpenDelim(token::Paren))?;
- let mut list = Vec::new();
- while !self.eat(&token::CloseDelim(token::Paren)) {
- let path = self.parse_path_allowing_meta(PathStyle::Mod)?;
- list.push(path);
- if !self.eat(&token::Comma) {
- self.expect(&token::CloseDelim(token::Paren))?;
- break
- }
- }
- Ok(list)
- }
-
pub(super) fn parse_path_segments(
&mut self,
segments: &mut Vec<PathSegment>,
diff --git a/src/librustc_parse/validate_attr.rs b/src/librustc_parse/validate_attr.rs
index 97e9cb8..94d3fe7 100644
--- a/src/librustc_parse/validate_attr.rs
+++ b/src/librustc_parse/validate_attr.rs
@@ -1,10 +1,13 @@
//! Meta-syntax validation logic of attributes for post-expansion.
+use crate::parse_in;
+
use rustc_errors::{PResult, Applicability};
use rustc_feature::{AttributeTemplate, BUILTIN_ATTRIBUTE_MAP};
-use syntax::ast::{self, Attribute, AttrKind, Ident, MacArgs, MetaItem, MetaItemKind};
+use syntax::ast::{self, Attribute, AttrKind, Ident, MacArgs, MacDelimiter, MetaItem, MetaItemKind};
use syntax::attr::mk_name_value_item_str;
use syntax::early_buffered_lints::ILL_FORMED_ATTRIBUTE_INPUT;
+use syntax::tokenstream::DelimSpan;
use syntax::sess::ParseSess;
use syntax_pos::{Symbol, sym};
@@ -27,9 +30,20 @@
pub fn parse_meta<'a>(sess: &'a ParseSess, attr: &Attribute) -> PResult<'a, MetaItem> {
Ok(match attr.kind {
AttrKind::Normal(ref item) => MetaItem {
- path: item.path.clone(),
- kind: super::parse_in_attr(sess, attr, |p| p.parse_meta_item_kind())?,
span: attr.span,
+ path: item.path.clone(),
+ kind: match &attr.get_normal_item().args {
+ MacArgs::Empty => MetaItemKind::Word,
+ MacArgs::Eq(_, t) => {
+ let v = parse_in(sess, t.clone(), "name value", |p| p.parse_unsuffixed_lit())?;
+ MetaItemKind::NameValue(v)
+ }
+ MacArgs::Delimited(dspan, delim, t) => {
+ check_meta_bad_delim(sess, *dspan, *delim, "wrong meta list delimiters");
+ let nmis = parse_in(sess, t.clone(), "meta list", |p| p.parse_meta_seq_top())?;
+ MetaItemKind::List(nmis)
+ }
+ }
},
AttrKind::DocComment(comment) => {
mk_name_value_item_str(Ident::new(sym::doc, attr.span), comment, attr.span)
@@ -37,6 +51,24 @@
})
}
+crate fn check_meta_bad_delim(sess: &ParseSess, span: DelimSpan, delim: MacDelimiter, msg: &str) {
+ if let ast::MacDelimiter::Parenthesis = delim {
+ return;
+ }
+
+ sess.span_diagnostic
+ .struct_span_err(span.entire(), msg)
+ .multipart_suggestion(
+ "the delimiters should be `(` and `)`",
+ vec![
+ (span.open, "(".to_string()),
+ (span.close, ")".to_string()),
+ ],
+ Applicability::MachineApplicable,
+ )
+ .emit();
+}
+
/// Checks that the given meta-item is compatible with this `AttributeTemplate`.
fn is_attr_template_compatible(template: &AttributeTemplate, meta: &ast::MetaItemKind) -> bool {
match meta {
diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs
index 901a219..253fc55 100644
--- a/src/librustc_typeck/check/coercion.rs
+++ b/src/librustc_typeck/check/coercion.rs
@@ -1284,6 +1284,10 @@
augment_error(&mut err);
}
+ if let Some(expr) = expression {
+ fcx.emit_coerce_suggestions(&mut err, expr, found, expected);
+ }
+
// Error possibly reported in `check_assign` so avoid emitting error again.
err.emit_unless(expression.filter(|e| fcx.is_assign_to_bool(e, expected))
.is_some());
diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs
index 32df6c4..16a55d2 100644
--- a/src/librustc_typeck/check/demand.rs
+++ b/src/librustc_typeck/check/demand.rs
@@ -15,6 +15,22 @@
use super::method::probe;
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
+
+ pub fn emit_coerce_suggestions(
+ &self,
+ err: &mut DiagnosticBuilder<'_>,
+ expr: &hir::Expr,
+ expr_ty: Ty<'tcx>,
+ expected: Ty<'tcx>
+ ) {
+ self.annotate_expected_due_to_let_ty(err, expr);
+ self.suggest_compatible_variants(err, expr, expected, expr_ty);
+ self.suggest_ref_or_into(err, expr, expected, expr_ty);
+ self.suggest_boxing_when_appropriate(err, expr, expected, expr_ty);
+ self.suggest_missing_await(err, expr, expected, expr_ty);
+ }
+
+
// Requires that the two types unify, and prints an error message if
// they don't.
pub fn demand_suptype(&self, sp: Span, expected: Ty<'tcx>, actual: Ty<'tcx>) {
@@ -137,11 +153,7 @@
return (expected, None)
}
- self.annotate_expected_due_to_let_ty(&mut err, expr);
- self.suggest_compatible_variants(&mut err, expr, expected, expr_ty);
- self.suggest_ref_or_into(&mut err, expr, expected, expr_ty);
- self.suggest_boxing_when_appropriate(&mut err, expr, expected, expr_ty);
- self.suggest_missing_await(&mut err, expr, expected, expr_ty);
+ self.emit_coerce_suggestions(&mut err, expr, expr_ty, expected);
(expected, Some(err))
}
diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs
index 9f034e65..b967c6e 100644
--- a/src/librustc_typeck/check/intrinsic.rs
+++ b/src/librustc_typeck/check/intrinsic.rs
@@ -336,6 +336,7 @@
(1, vec![param(0), param(0)], param(0)),
"fadd_fast" | "fsub_fast" | "fmul_fast" | "fdiv_fast" | "frem_fast" =>
(1, vec![param(0), param(0)], param(0)),
+ "float_to_int_approx_unchecked" => (2, vec![ param(0) ], param(1)),
"assume" => (0, vec![tcx.types.bool], tcx.mk_unit()),
"likely" => (0, vec![tcx.types.bool], tcx.types.bool),
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index c7a0190..a956aba 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -4584,8 +4584,6 @@
pointing_at_return_type = self.suggest_missing_return_type(
err, &fn_decl, expected, found, can_suggest);
}
- self.suggest_ref_or_into(err, expr, expected, found);
- self.suggest_boxing_when_appropriate(err, expr, expected, found);
pointing_at_return_type
}
@@ -4957,7 +4955,9 @@
ty: expected,
}));
let obligation = traits::Obligation::new(self.misc(sp), self.param_env, predicate);
+ debug!("suggest_missing_await: trying obligation {:?}", obligation);
if self.infcx.predicate_may_hold(&obligation) {
+ debug!("suggest_missing_await: obligation held: {:?}", obligation);
if let Ok(code) = self.sess().source_map().span_to_snippet(sp) {
err.span_suggestion(
sp,
@@ -4965,7 +4965,11 @@
format!("{}.await", code),
Applicability::MaybeIncorrect,
);
+ } else {
+ debug!("suggest_missing_await: no snippet for {:?}", sp);
}
+ } else {
+ debug!("suggest_missing_await: obligation did not hold: {:?}", obligation)
}
}
}
diff --git a/src/libstd/sync/mutex.rs b/src/libstd/sync/mutex.rs
index 87c2318..e90da69 100644
--- a/src/libstd/sync/mutex.rs
+++ b/src/libstd/sync/mutex.rs
@@ -143,10 +143,8 @@
#[must_use = "if unused the Mutex will immediately unlock"]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct MutexGuard<'a, T: ?Sized + 'a> {
- // funny underscores due to how Deref/DerefMut currently work (they
- // disregard field privacy).
- __lock: &'a Mutex<T>,
- __poison: poison::Guard,
+ lock: &'a Mutex<T>,
+ poison: poison::Guard,
}
#[stable(feature = "rust1", since = "1.0.0")]
@@ -417,8 +415,8 @@
unsafe fn new(lock: &'mutex Mutex<T>) -> LockResult<MutexGuard<'mutex, T>> {
poison::map_result(lock.poison.borrow(), |guard| {
MutexGuard {
- __lock: lock,
- __poison: guard,
+ lock: lock,
+ poison: guard,
}
})
}
@@ -429,14 +427,14 @@
type Target = T;
fn deref(&self) -> &T {
- unsafe { &*self.__lock.data.get() }
+ unsafe { &*self.lock.data.get() }
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> DerefMut for MutexGuard<'_, T> {
fn deref_mut(&mut self) -> &mut T {
- unsafe { &mut *self.__lock.data.get() }
+ unsafe { &mut *self.lock.data.get() }
}
}
@@ -445,8 +443,8 @@
#[inline]
fn drop(&mut self) {
unsafe {
- self.__lock.poison.done(&self.__poison);
- self.__lock.inner.raw_unlock();
+ self.lock.poison.done(&self.poison);
+ self.lock.inner.raw_unlock();
}
}
}
@@ -466,11 +464,11 @@
}
pub fn guard_lock<'a, T: ?Sized>(guard: &MutexGuard<'a, T>) -> &'a sys::Mutex {
- &guard.__lock.inner
+ &guard.lock.inner
}
pub fn guard_poison<'a, T: ?Sized>(guard: &MutexGuard<'a, T>) -> &'a poison::Flag {
- &guard.__lock.poison
+ &guard.lock.poison
}
#[cfg(all(test, not(target_os = "emscripten")))]
diff --git a/src/libstd/sync/rwlock.rs b/src/libstd/sync/rwlock.rs
index b1b56f3..c217291 100644
--- a/src/libstd/sync/rwlock.rs
+++ b/src/libstd/sync/rwlock.rs
@@ -87,7 +87,7 @@
#[must_use = "if unused the RwLock will immediately unlock"]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct RwLockReadGuard<'a, T: ?Sized + 'a> {
- __lock: &'a RwLock<T>,
+ lock: &'a RwLock<T>,
}
#[stable(feature = "rust1", since = "1.0.0")]
@@ -108,8 +108,8 @@
#[must_use = "if unused the RwLock will immediately unlock"]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct RwLockWriteGuard<'a, T: ?Sized + 'a> {
- __lock: &'a RwLock<T>,
- __poison: poison::Guard,
+ lock: &'a RwLock<T>,
+ poison: poison::Guard,
}
#[stable(feature = "rust1", since = "1.0.0")]
@@ -465,7 +465,7 @@
-> LockResult<RwLockReadGuard<'rwlock, T>> {
poison::map_result(lock.poison.borrow(), |_| {
RwLockReadGuard {
- __lock: lock,
+ lock: lock,
}
})
}
@@ -476,8 +476,8 @@
-> LockResult<RwLockWriteGuard<'rwlock, T>> {
poison::map_result(lock.poison.borrow(), |guard| {
RwLockWriteGuard {
- __lock: lock,
- __poison: guard,
+ lock: lock,
+ poison: guard,
}
})
}
@@ -487,7 +487,7 @@
impl<T: fmt::Debug> fmt::Debug for RwLockReadGuard<'_, T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("RwLockReadGuard")
- .field("lock", &self.__lock)
+ .field("lock", &self.lock)
.finish()
}
}
@@ -503,7 +503,7 @@
impl<T: fmt::Debug> fmt::Debug for RwLockWriteGuard<'_, T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("RwLockWriteGuard")
- .field("lock", &self.__lock)
+ .field("lock", &self.lock)
.finish()
}
}
@@ -520,7 +520,7 @@
type Target = T;
fn deref(&self) -> &T {
- unsafe { &*self.__lock.data.get() }
+ unsafe { &*self.lock.data.get() }
}
}
@@ -529,29 +529,29 @@
type Target = T;
fn deref(&self) -> &T {
- unsafe { &*self.__lock.data.get() }
+ unsafe { &*self.lock.data.get() }
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> DerefMut for RwLockWriteGuard<'_, T> {
fn deref_mut(&mut self) -> &mut T {
- unsafe { &mut *self.__lock.data.get() }
+ unsafe { &mut *self.lock.data.get() }
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> Drop for RwLockReadGuard<'_, T> {
fn drop(&mut self) {
- unsafe { self.__lock.inner.read_unlock(); }
+ unsafe { self.lock.inner.read_unlock(); }
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> Drop for RwLockWriteGuard<'_, T> {
fn drop(&mut self) {
- self.__lock.poison.done(&self.__poison);
- unsafe { self.__lock.inner.write_unlock(); }
+ self.lock.poison.done(&self.poison);
+ unsafe { self.lock.inner.write_unlock(); }
}
}
diff --git a/src/libsyntax_expand/proc_macro.rs b/src/libsyntax_expand/proc_macro.rs
index 8e56e2b..520488c 100644
--- a/src/libsyntax_expand/proc_macro.rs
+++ b/src/libsyntax_expand/proc_macro.rs
@@ -1,7 +1,7 @@
use crate::base::{self, *};
use crate::proc_macro_server;
-use syntax::ast::{self, ItemKind, MacArgs};
+use syntax::ast::{self, ItemKind, MetaItemKind, NestedMetaItem};
use syntax::errors::{Applicability, FatalError};
use syntax::symbol::sym;
use syntax::token;
@@ -171,34 +171,71 @@
if !attr.has_name(sym::derive) {
return true;
}
- if !attr.is_meta_item_list() {
- cx.struct_span_err(attr.span, "malformed `derive` attribute input")
- .span_suggestion(
- attr.span,
- "missing traits to be derived",
- "#[derive(Trait1, Trait2, ...)]".to_owned(),
- Applicability::HasPlaceholders,
- ).emit();
- return false;
- }
- let parse_derive_paths = |attr: &ast::Attribute| {
- if let MacArgs::Empty = attr.get_normal_item().args {
- return Ok(Vec::new());
+ // 1) First let's ensure that it's a meta item.
+ let nmis = match attr.meta_item_list() {
+ None => {
+ cx.struct_span_err(attr.span, "malformed `derive` attribute input")
+ .span_suggestion(
+ attr.span,
+ "missing traits to be derived",
+ "#[derive(Trait1, Trait2, ...)]".to_owned(),
+ Applicability::HasPlaceholders,
+ )
+ .emit();
+ return false;
}
- rustc_parse::parse_in_attr(cx.parse_sess, attr, |p| p.parse_derive_paths())
+ Some(x) => x,
};
- match parse_derive_paths(attr) {
- Ok(traits) => {
- result.extend(traits);
- true
- }
- Err(mut e) => {
- e.emit();
- false
- }
- }
+ let mut error_reported_filter_map = false;
+ let mut error_reported_map = false;
+ let traits = nmis
+ .into_iter()
+ // 2) Moreover, let's ensure we have a path and not `#[derive("foo")]`.
+ .filter_map(|nmi| match nmi {
+ NestedMetaItem::Literal(lit) => {
+ error_reported_filter_map = true;
+ cx.struct_span_err(lit.span, "expected path to a trait, found literal")
+ .help("for example, write `#[derive(Debug)]` for `Debug`")
+ .emit();
+ None
+ }
+ NestedMetaItem::MetaItem(mi) => Some(mi),
+ })
+ // 3) Finally, we only accept `#[derive($path_0, $path_1, ..)]`
+ // but not e.g. `#[derive($path_0 = "value", $path_1(abc))]`.
+ // In this case we can still at least determine that the user
+ // wanted this trait to be derived, so let's keep it.
+ .map(|mi| {
+ let mut traits_dont_accept = |title, action| {
+ error_reported_map = true;
+ let sp = mi.span.with_lo(mi.path.span.hi());
+ cx.struct_span_err(sp, title)
+ .span_suggestion(
+ sp,
+ action,
+ String::new(),
+ Applicability::MachineApplicable,
+ )
+ .emit();
+ };
+ match &mi.kind {
+ MetaItemKind::List(..) => traits_dont_accept(
+ "traits in `#[derive(...)]` don't accept arguments",
+ "remove the arguments",
+ ),
+ MetaItemKind::NameValue(..) => traits_dont_accept(
+ "traits in `#[derive(...)]` don't accept values",
+ "remove the value",
+ ),
+ MetaItemKind::Word => {}
+ }
+ mi.path
+ });
+
+ result.extend(traits);
+ !error_reported_filter_map && !error_reported_map
});
result
}
diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs
index c68e03be..e8f7a12 100644
--- a/src/libsyntax_pos/symbol.rs
+++ b/src/libsyntax_pos/symbol.rs
@@ -213,6 +213,7 @@
const_indexing,
const_in_array_repeat_expressions,
const_let,
+ const_mut_refs,
const_panic,
const_raw_ptr_deref,
const_raw_ptr_to_usize_cast,
diff --git a/src/test/compile-fail/consts/const-fn-error.rs b/src/test/compile-fail/consts/const-fn-error.rs
index 1a4fc72..5d26059 100644
--- a/src/test/compile-fail/consts/const-fn-error.rs
+++ b/src/test/compile-fail/consts/const-fn-error.rs
@@ -6,7 +6,7 @@
let mut sum = 0;
for i in 0..x {
//~^ ERROR E0015
- //~| ERROR E0017
+ //~| ERROR E0658
//~| ERROR E0080
//~| ERROR E0744
//~| ERROR E0019
diff --git a/src/test/ui/async-await/suggest-missing-await.fixed b/src/test/ui/async-await/suggest-missing-await.fixed
index 7c02a90..1ec59d9 100644
--- a/src/test/ui/async-await/suggest-missing-await.fixed
+++ b/src/test/ui/async-await/suggest-missing-await.fixed
@@ -16,4 +16,15 @@
//~| SUGGESTION x.await
}
+async fn dummy() {}
+
+#[allow(unused)]
+async fn suggest_await_in_async_fn_return() {
+ dummy().await;
+ //~^ ERROR mismatched types [E0308]
+ //~| HELP try adding a semicolon
+ //~| HELP consider using `.await` here
+ //~| SUGGESTION dummy().await
+}
+
fn main() {}
diff --git a/src/test/ui/async-await/suggest-missing-await.rs b/src/test/ui/async-await/suggest-missing-await.rs
index 91abd44..70cc1f1 100644
--- a/src/test/ui/async-await/suggest-missing-await.rs
+++ b/src/test/ui/async-await/suggest-missing-await.rs
@@ -16,4 +16,15 @@
//~| SUGGESTION x.await
}
+async fn dummy() {}
+
+#[allow(unused)]
+async fn suggest_await_in_async_fn_return() {
+ dummy()
+ //~^ ERROR mismatched types [E0308]
+ //~| HELP try adding a semicolon
+ //~| HELP consider using `.await` here
+ //~| SUGGESTION dummy().await
+}
+
fn main() {}
diff --git a/src/test/ui/async-await/suggest-missing-await.stderr b/src/test/ui/async-await/suggest-missing-await.stderr
index 7a635a3..7ab0244 100644
--- a/src/test/ui/async-await/suggest-missing-await.stderr
+++ b/src/test/ui/async-await/suggest-missing-await.stderr
@@ -10,6 +10,23 @@
= note: expected type `u32`
found opaque type `impl std::future::Future`
-error: aborting due to previous error
+error[E0308]: mismatched types
+ --> $DIR/suggest-missing-await.rs:23:5
+ |
+LL | dummy()
+ | ^^^^^^^ expected `()`, found opaque type
+ |
+ = note: expected unit type `()`
+ found opaque type `impl std::future::Future`
+help: try adding a semicolon
+ |
+LL | dummy();
+ | ^
+help: consider using `.await` here
+ |
+LL | dummy().await
+ |
+
+error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/check-static-immutable-mut-slices.stderr b/src/test/ui/check-static-immutable-mut-slices.stderr
index 4f4bf16..39da824 100644
--- a/src/test/ui/check-static-immutable-mut-slices.stderr
+++ b/src/test/ui/check-static-immutable-mut-slices.stderr
@@ -1,9 +1,12 @@
-error[E0017]: references in statics may only refer to immutable values
+error[E0658]: references in statics may only refer to immutable values
--> $DIR/check-static-immutable-mut-slices.rs:3:37
|
LL | static TEST: &'static mut [isize] = &mut [];
| ^^^^^^^ statics require immutable values
+ |
+ = note: for more information, see https://github.com/rust-lang/rust/issues/57349
+ = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
error: aborting due to previous error
-For more information about this error, try `rustc --explain E0017`.
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/conditional-compilation/cfg-attr-parse.rs b/src/test/ui/conditional-compilation/cfg-attr-parse.rs
index 93aef72..8ca31c1 100644
--- a/src/test/ui/conditional-compilation/cfg-attr-parse.rs
+++ b/src/test/ui/conditional-compilation/cfg-attr-parse.rs
@@ -1,11 +1,11 @@
// Parse `cfg_attr` with varying numbers of attributes and trailing commas
// Completely empty `cfg_attr` input
-#[cfg_attr()] //~ error: expected identifier, found `)`
+#[cfg_attr()] //~ error: malformed `cfg_attr` attribute input
struct NoConfigurationPredicate;
// Zero attributes, zero trailing comma (comma manatory here)
-#[cfg_attr(all())] //~ error: expected `,`, found `)`
+#[cfg_attr(all())] //~ error: expected `,`, found end of `cfg_attr`
struct A0C0;
// Zero attributes, one trailing comma
@@ -40,4 +40,16 @@
#[cfg_attr(all(), must_use, deprecated,,)] //~ ERROR expected identifier
struct A2C2;
+// Wrong delimiter `[`
+#[cfg_attr[all(),,]]
+//~^ ERROR wrong `cfg_attr` delimiters
+//~| ERROR expected identifier, found `,`
+struct BracketZero;
+
+// Wrong delimiter `{`
+#[cfg_attr{all(),,}]
+//~^ ERROR wrong `cfg_attr` delimiters
+//~| ERROR expected identifier, found `,`
+struct BraceZero;
+
fn main() {}
diff --git a/src/test/ui/conditional-compilation/cfg-attr-parse.stderr b/src/test/ui/conditional-compilation/cfg-attr-parse.stderr
index 3dfbd6d..3a590d3 100644
--- a/src/test/ui/conditional-compilation/cfg-attr-parse.stderr
+++ b/src/test/ui/conditional-compilation/cfg-attr-parse.stderr
@@ -1,32 +1,86 @@
-error: expected identifier, found `)`
- --> $DIR/cfg-attr-parse.rs:4:12
+error: malformed `cfg_attr` attribute input
+ --> $DIR/cfg-attr-parse.rs:4:1
|
LL | #[cfg_attr()]
- | ^ expected identifier
+ | ^^^^^^^^^^^^^ help: missing condition and attribute: `#[cfg_attr(condition, attribute, other_attribute, ...)]`
+ |
+ = note: for more information, visit <https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg_attr-attribute>
-error: expected `,`, found `)`
+error: expected `,`, found end of `cfg_attr` input
--> $DIR/cfg-attr-parse.rs:8:17
|
LL | #[cfg_attr(all())]
| ^ expected `,`
+ |
+ = help: the valid syntax is `#[cfg_attr(condition, attribute, other_attribute, ...)]`
+ = note: for more information, visit <https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg_attr-attribute>
error: expected identifier, found `,`
--> $DIR/cfg-attr-parse.rs:16:18
|
LL | #[cfg_attr(all(),,)]
| ^ expected identifier
+ |
+ = help: the valid syntax is `#[cfg_attr(condition, attribute, other_attribute, ...)]`
+ = note: for more information, visit <https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg_attr-attribute>
error: expected identifier, found `,`
--> $DIR/cfg-attr-parse.rs:28:28
|
LL | #[cfg_attr(all(), must_use,,)]
| ^ expected identifier
+ |
+ = help: the valid syntax is `#[cfg_attr(condition, attribute, other_attribute, ...)]`
+ = note: for more information, visit <https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg_attr-attribute>
error: expected identifier, found `,`
--> $DIR/cfg-attr-parse.rs:40:40
|
LL | #[cfg_attr(all(), must_use, deprecated,,)]
| ^ expected identifier
+ |
+ = help: the valid syntax is `#[cfg_attr(condition, attribute, other_attribute, ...)]`
+ = note: for more information, visit <https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg_attr-attribute>
-error: aborting due to 5 previous errors
+error: wrong `cfg_attr` delimiters
+ --> $DIR/cfg-attr-parse.rs:44:11
+ |
+LL | #[cfg_attr[all(),,]]
+ | ^^^^^^^^^
+ |
+help: the delimiters should be `(` and `)`
+ |
+LL | #[cfg_attr(all(),,)]
+ | ^ ^
+
+error: expected identifier, found `,`
+ --> $DIR/cfg-attr-parse.rs:44:18
+ |
+LL | #[cfg_attr[all(),,]]
+ | ^ expected identifier
+ |
+ = help: the valid syntax is `#[cfg_attr(condition, attribute, other_attribute, ...)]`
+ = note: for more information, visit <https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg_attr-attribute>
+
+error: wrong `cfg_attr` delimiters
+ --> $DIR/cfg-attr-parse.rs:50:11
+ |
+LL | #[cfg_attr{all(),,}]
+ | ^^^^^^^^^
+ |
+help: the delimiters should be `(` and `)`
+ |
+LL | #[cfg_attr(all(),,)]
+ | ^ ^
+
+error: expected identifier, found `,`
+ --> $DIR/cfg-attr-parse.rs:50:18
+ |
+LL | #[cfg_attr{all(),,}]
+ | ^ expected identifier
+ |
+ = help: the valid syntax is `#[cfg_attr(condition, attribute, other_attribute, ...)]`
+ = note: for more information, visit <https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg_attr-attribute>
+
+error: aborting due to 9 previous errors
diff --git a/src/test/ui/consts/const-eval/issue-65394.stderr b/src/test/ui/consts/const-eval/issue-65394.stderr
index acf5cba..54b3507 100644
--- a/src/test/ui/consts/const-eval/issue-65394.stderr
+++ b/src/test/ui/consts/const-eval/issue-65394.stderr
@@ -1,8 +1,11 @@
-error[E0017]: references in constants may only refer to immutable values
+error[E0658]: references in constants may only refer to immutable values
--> $DIR/issue-65394.rs:8:13
|
LL | let r = &mut x;
| ^^^^^^ constants require immutable values
+ |
+ = note: for more information, see https://github.com/rust-lang/rust/issues/57349
+ = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
error[E0493]: destructors cannot be evaluated at compile-time
--> $DIR/issue-65394.rs:7:9
@@ -12,5 +15,5 @@
error: aborting due to 2 previous errors
-Some errors have detailed explanations: E0017, E0493.
-For more information about an error, try `rustc --explain E0017`.
+Some errors have detailed explanations: E0493, E0658.
+For more information about an error, try `rustc --explain E0493`.
diff --git a/src/test/ui/consts/const-multi-ref.stderr b/src/test/ui/consts/const-multi-ref.stderr
index ed3837e..0809c77 100644
--- a/src/test/ui/consts/const-multi-ref.stderr
+++ b/src/test/ui/consts/const-multi-ref.stderr
@@ -1,8 +1,11 @@
-error[E0017]: references in constants may only refer to immutable values
+error[E0658]: references in constants may only refer to immutable values
--> $DIR/const-multi-ref.rs:6:13
|
LL | let p = &mut a;
| ^^^^^^ constants require immutable values
+ |
+ = note: for more information, see https://github.com/rust-lang/rust/issues/57349
+ = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead
--> $DIR/const-multi-ref.rs:16:13
@@ -12,5 +15,5 @@
error: aborting due to 2 previous errors
-Some errors have detailed explanations: E0017, E0492.
-For more information about an error, try `rustc --explain E0017`.
+Some errors have detailed explanations: E0492, E0658.
+For more information about an error, try `rustc --explain E0492`.
diff --git a/src/test/ui/consts/const-mut-refs/const_mut_refs.rs b/src/test/ui/consts/const-mut-refs/const_mut_refs.rs
new file mode 100644
index 0000000..99006a2
--- /dev/null
+++ b/src/test/ui/consts/const-mut-refs/const_mut_refs.rs
@@ -0,0 +1,36 @@
+// run-pass
+
+#![feature(const_mut_refs)]
+
+struct Foo {
+ x: usize
+}
+
+const fn foo() -> Foo {
+ Foo { x: 0 }
+}
+
+impl Foo {
+ const fn bar(&mut self) -> usize {
+ self.x = 1;
+ self.x
+ }
+
+}
+
+const fn baz(foo: &mut Foo) -> usize {
+ let x = &mut foo.x;
+ *x = 2;
+ *x
+}
+
+const fn bazz(foo: &mut Foo) -> usize {
+ foo.x = 3;
+ foo.x
+}
+
+fn main() {
+ let _: [(); foo().bar()] = [(); 1];
+ let _: [(); baz(&mut foo())] = [(); 2];
+ let _: [(); bazz(&mut foo())] = [(); 3];
+}
diff --git a/src/test/ui/consts/const-mut-refs/feature-gate-const_mut_refs.rs b/src/test/ui/consts/const-mut-refs/feature-gate-const_mut_refs.rs
new file mode 100644
index 0000000..2207599
--- /dev/null
+++ b/src/test/ui/consts/const-mut-refs/feature-gate-const_mut_refs.rs
@@ -0,0 +1,7 @@
+fn main() {
+ foo(&mut 5);
+}
+
+const fn foo(x: &mut i32) -> i32 { //~ ERROR mutable references in const fn are unstable
+ *x + 1
+}
diff --git a/src/test/ui/consts/const-mut-refs/feature-gate-const_mut_refs.stderr b/src/test/ui/consts/const-mut-refs/feature-gate-const_mut_refs.stderr
new file mode 100644
index 0000000..4fae119
--- /dev/null
+++ b/src/test/ui/consts/const-mut-refs/feature-gate-const_mut_refs.stderr
@@ -0,0 +1,12 @@
+error[E0723]: mutable references in const fn are unstable
+ --> $DIR/feature-gate-const_mut_refs.rs:5:14
+ |
+LL | const fn foo(x: &mut i32) -> i32 {
+ | ^
+ |
+ = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
+ = help: add `#![feature(const_fn)]` to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0723`.
diff --git a/src/test/ui/consts/const_let_assign3.stderr b/src/test/ui/consts/const_let_assign3.stderr
index 53b960b..7852874 100644
--- a/src/test/ui/consts/const_let_assign3.stderr
+++ b/src/test/ui/consts/const_let_assign3.stderr
@@ -4,17 +4,23 @@
LL | self.state = x;
| ^^^^^^^^^^^^^^
-error[E0017]: references in constants may only refer to immutable values
+error[E0658]: references in constants may only refer to immutable values
--> $DIR/const_let_assign3.rs:16:5
|
LL | s.foo(3);
| ^ constants require immutable values
+ |
+ = note: for more information, see https://github.com/rust-lang/rust/issues/57349
+ = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
-error[E0017]: references in constants may only refer to immutable values
+error[E0658]: references in constants may only refer to immutable values
--> $DIR/const_let_assign3.rs:22:13
|
LL | let y = &mut x;
| ^^^^^^ constants require immutable values
+ |
+ = note: for more information, see https://github.com/rust-lang/rust/issues/57349
+ = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
error[E0019]: constant contains unimplemented expression type
--> $DIR/const_let_assign3.rs:24:5
@@ -24,5 +30,5 @@
error: aborting due to 4 previous errors
-Some errors have detailed explanations: E0017, E0019.
-For more information about an error, try `rustc --explain E0017`.
+Some errors have detailed explanations: E0019, E0658.
+For more information about an error, try `rustc --explain E0019`.
diff --git a/src/test/ui/consts/miri_unleashed/mutable_const.rs b/src/test/ui/consts/miri_unleashed/mutable_const.rs
index 44b4084..972f595 100644
--- a/src/test/ui/consts/miri_unleashed/mutable_const.rs
+++ b/src/test/ui/consts/miri_unleashed/mutable_const.rs
@@ -1,6 +1,7 @@
// compile-flags: -Zunleash-the-miri-inside-of-you
#![feature(const_raw_ptr_deref)]
+#![feature(const_mut_refs)]
#![deny(const_err)]
use std::cell::UnsafeCell;
@@ -12,9 +13,7 @@
const MUTATING_BEHIND_RAW: () = {
// Test that `MUTABLE_BEHIND_RAW` is actually immutable, by doing this at const time.
unsafe {
- *MUTABLE_BEHIND_RAW = 99 //~ WARN skipping const checks
- //~^ ERROR any use of this value will cause an error
- //~^^ tried to modify constant memory
+ *MUTABLE_BEHIND_RAW = 99 //~ ERROR any use of this value will cause an error
}
};
diff --git a/src/test/ui/consts/miri_unleashed/mutable_const.stderr b/src/test/ui/consts/miri_unleashed/mutable_const.stderr
index 757f0ff..9daca76 100644
--- a/src/test/ui/consts/miri_unleashed/mutable_const.stderr
+++ b/src/test/ui/consts/miri_unleashed/mutable_const.stderr
@@ -1,30 +1,23 @@
warning: skipping const checks
- --> $DIR/mutable_const.rs:9:38
+ --> $DIR/mutable_const.rs:10:38
|
LL | const MUTABLE_BEHIND_RAW: *mut i32 = &UnsafeCell::new(42) as *const _ as *mut _;
| ^^^^^^^^^^^^^^^^^^^^
-warning: skipping const checks
- --> $DIR/mutable_const.rs:15:9
- |
-LL | *MUTABLE_BEHIND_RAW = 99
- | ^^^^^^^^^^^^^^^^^^^^^^^^
-
error: any use of this value will cause an error
- --> $DIR/mutable_const.rs:15:9
+ --> $DIR/mutable_const.rs:16:9
|
LL | / const MUTATING_BEHIND_RAW: () = {
LL | | // Test that `MUTABLE_BEHIND_RAW` is actually immutable, by doing this at const time.
LL | | unsafe {
LL | | *MUTABLE_BEHIND_RAW = 99
| | ^^^^^^^^^^^^^^^^^^^^^^^^ tried to modify constant memory
-... |
LL | | }
LL | | };
| |__-
|
note: lint level defined here
- --> $DIR/mutable_const.rs:4:9
+ --> $DIR/mutable_const.rs:5:9
|
LL | #![deny(const_err)]
| ^^^^^^^^^
diff --git a/src/test/ui/consts/miri_unleashed/mutable_references.rs b/src/test/ui/consts/miri_unleashed/mutable_references.rs
index 59dafcb..fe3c4ee 100644
--- a/src/test/ui/consts/miri_unleashed/mutable_references.rs
+++ b/src/test/ui/consts/miri_unleashed/mutable_references.rs
@@ -1,20 +1,22 @@
// compile-flags: -Zunleash-the-miri-inside-of-you
+#![feature(const_mut_refs)]
#![allow(const_err)]
use std::cell::UnsafeCell;
// a test demonstrating what things we could allow with a smarter const qualification
+// this is fine because is not possible to mutate through an immutable reference.
static FOO: &&mut u32 = &&mut 42;
-//~^ WARN: skipping const checks
+// this is fine because accessing an immutable static `BAR` is equivalent to accessing `*&BAR`
+// which puts the mutable reference behind an immutable one.
static BAR: &mut () = &mut ();
-//~^ WARN: skipping const checks
struct Foo<T>(T);
+// this is fine for the same reason as `BAR`.
static BOO: &mut Foo<()> = &mut Foo(());
-//~^ WARN: skipping const checks
struct Meh {
x: &'static UnsafeCell<i32>,
@@ -27,8 +29,8 @@
//~^ WARN: skipping const checks
};
+// this is fine for the same reason as `BAR`.
static OH_YES: &mut i32 = &mut 42;
-//~^ WARN: skipping const checks
fn main() {
unsafe {
diff --git a/src/test/ui/consts/miri_unleashed/mutable_references.stderr b/src/test/ui/consts/miri_unleashed/mutable_references.stderr
index b9c0af3..3e1300c 100644
--- a/src/test/ui/consts/miri_unleashed/mutable_references.stderr
+++ b/src/test/ui/consts/miri_unleashed/mutable_references.stderr
@@ -1,35 +1,11 @@
warning: skipping const checks
- --> $DIR/mutable_references.rs:8:26
- |
-LL | static FOO: &&mut u32 = &&mut 42;
- | ^^^^^^^
-
-warning: skipping const checks
- --> $DIR/mutable_references.rs:11:23
- |
-LL | static BAR: &mut () = &mut ();
- | ^^^^^^^
-
-warning: skipping const checks
- --> $DIR/mutable_references.rs:16:28
- |
-LL | static BOO: &mut Foo<()> = &mut Foo(());
- | ^^^^^^^^^^^^
-
-warning: skipping const checks
- --> $DIR/mutable_references.rs:26:8
+ --> $DIR/mutable_references.rs:28:8
|
LL | x: &UnsafeCell::new(42),
| ^^^^^^^^^^^^^^^^^^^^
-warning: skipping const checks
- --> $DIR/mutable_references.rs:30:27
- |
-LL | static OH_YES: &mut i32 = &mut 42;
- | ^^^^^^^
-
error[E0594]: cannot assign to `*OH_YES`, as `OH_YES` is an immutable static item
- --> $DIR/mutable_references.rs:37:5
+ --> $DIR/mutable_references.rs:39:5
|
LL | *OH_YES = 99;
| ^^^^^^^^^^^^ cannot assign
diff --git a/src/test/ui/consts/miri_unleashed/read_from_static.rs b/src/test/ui/consts/miri_unleashed/read_from_static.rs
new file mode 100644
index 0000000..821c501
--- /dev/null
+++ b/src/test/ui/consts/miri_unleashed/read_from_static.rs
@@ -0,0 +1,11 @@
+// run-pass
+// compile-flags: -Zunleash-the-miri-inside-of-you
+#![feature(const_mut_refs)]
+#![allow(const_err)]
+
+static OH_YES: &mut i32 = &mut 42;
+
+fn main() {
+ // Make sure `OH_YES` can be read.
+ assert_eq!(*OH_YES, 42);
+}
diff --git a/src/test/ui/consts/projection_qualif.mut_refs.stderr b/src/test/ui/consts/projection_qualif.mut_refs.stderr
new file mode 100644
index 0000000..2353877
--- /dev/null
+++ b/src/test/ui/consts/projection_qualif.mut_refs.stderr
@@ -0,0 +1,12 @@
+error[E0658]: dereferencing raw pointers in constants is unstable
+ --> $DIR/projection_qualif.rs:11:18
+ |
+LL | unsafe { *b = 5; }
+ | ^^^^^^
+ |
+ = note: for more information, see https://github.com/rust-lang/rust/issues/51911
+ = help: add `#![feature(const_raw_ptr_deref)]` to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/consts/projection_qualif.rs b/src/test/ui/consts/projection_qualif.rs
index dedb7db..cfe8e7f 100644
--- a/src/test/ui/consts/projection_qualif.rs
+++ b/src/test/ui/consts/projection_qualif.rs
@@ -1,11 +1,15 @@
+// revisions: stock mut_refs
+
+#![cfg_attr(mut_refs, feature(const_mut_refs))]
+
use std::cell::Cell;
const FOO: &u32 = {
let mut a = 42;
{
- let b: *mut u32 = &mut a; //~ ERROR may only refer to immutable values
+ let b: *mut u32 = &mut a; //[stock]~ ERROR may only refer to immutable values
unsafe { *b = 5; } //~ ERROR dereferencing raw pointers in constants
- //~^ contains unimplemented expression
+ //[stock]~^ contains unimplemented expression
}
&{a}
};
diff --git a/src/test/ui/consts/projection_qualif.stderr b/src/test/ui/consts/projection_qualif.stderr
deleted file mode 100644
index 0efb6bf..0000000
--- a/src/test/ui/consts/projection_qualif.stderr
+++ /dev/null
@@ -1,25 +0,0 @@
-error[E0017]: references in constants may only refer to immutable values
- --> $DIR/projection_qualif.rs:6:27
- |
-LL | let b: *mut u32 = &mut a;
- | ^^^^^^ constants require immutable values
-
-error[E0658]: dereferencing raw pointers in constants is unstable
- --> $DIR/projection_qualif.rs:7:18
- |
-LL | unsafe { *b = 5; }
- | ^^^^^^
- |
- = note: for more information, see https://github.com/rust-lang/rust/issues/51911
- = help: add `#![feature(const_raw_ptr_deref)]` to the crate attributes to enable
-
-error[E0019]: constant contains unimplemented expression type
- --> $DIR/projection_qualif.rs:7:18
- |
-LL | unsafe { *b = 5; }
- | ^^^^^^
-
-error: aborting due to 3 previous errors
-
-Some errors have detailed explanations: E0017, E0019, E0658.
-For more information about an error, try `rustc --explain E0017`.
diff --git a/src/test/ui/consts/projection_qualif.stock.stderr b/src/test/ui/consts/projection_qualif.stock.stderr
new file mode 100644
index 0000000..472d260
--- /dev/null
+++ b/src/test/ui/consts/projection_qualif.stock.stderr
@@ -0,0 +1,28 @@
+error[E0658]: references in constants may only refer to immutable values
+ --> $DIR/projection_qualif.rs:10:27
+ |
+LL | let b: *mut u32 = &mut a;
+ | ^^^^^^ constants require immutable values
+ |
+ = note: for more information, see https://github.com/rust-lang/rust/issues/57349
+ = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
+
+error[E0658]: dereferencing raw pointers in constants is unstable
+ --> $DIR/projection_qualif.rs:11:18
+ |
+LL | unsafe { *b = 5; }
+ | ^^^^^^
+ |
+ = note: for more information, see https://github.com/rust-lang/rust/issues/51911
+ = help: add `#![feature(const_raw_ptr_deref)]` to the crate attributes to enable
+
+error[E0019]: constant contains unimplemented expression type
+ --> $DIR/projection_qualif.rs:11:18
+ |
+LL | unsafe { *b = 5; }
+ | ^^^^^^
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0019, E0658.
+For more information about an error, try `rustc --explain E0019`.
diff --git a/src/test/ui/consts/static_mut_containing_mut_ref2.mut_refs.stderr b/src/test/ui/consts/static_mut_containing_mut_ref2.mut_refs.stderr
new file mode 100644
index 0000000..b43fbc8
--- /dev/null
+++ b/src/test/ui/consts/static_mut_containing_mut_ref2.mut_refs.stderr
@@ -0,0 +1,9 @@
+error[E0080]: could not evaluate static initializer
+ --> $DIR/static_mut_containing_mut_ref2.rs:7:45
+ |
+LL | pub static mut STDERR_BUFFER: () = unsafe { *(&mut STDERR_BUFFER_SPACE) = 42; };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tried to modify a static's initial value from another static's initializer
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/static_mut_containing_mut_ref2.rs b/src/test/ui/consts/static_mut_containing_mut_ref2.rs
index ef378fa..74162fb 100644
--- a/src/test/ui/consts/static_mut_containing_mut_ref2.rs
+++ b/src/test/ui/consts/static_mut_containing_mut_ref2.rs
@@ -1,7 +1,12 @@
+// revisions: stock mut_refs
+
+#![cfg_attr(mut_refs, feature(const_mut_refs))]
+
static mut STDERR_BUFFER_SPACE: u8 = 0;
pub static mut STDERR_BUFFER: () = unsafe { *(&mut STDERR_BUFFER_SPACE) = 42; };
-//~^ ERROR references in statics may only refer to immutable values
-//~| ERROR static contains unimplemented expression type
+//[mut_refs]~^ ERROR could not evaluate static initializer
+//[stock]~^^ ERROR references in statics may only refer to immutable values
+//[stock]~| ERROR static contains unimplemented expression type
fn main() {}
diff --git a/src/test/ui/consts/static_mut_containing_mut_ref2.stderr b/src/test/ui/consts/static_mut_containing_mut_ref2.stderr
deleted file mode 100644
index ca691b0..0000000
--- a/src/test/ui/consts/static_mut_containing_mut_ref2.stderr
+++ /dev/null
@@ -1,16 +0,0 @@
-error[E0017]: references in statics may only refer to immutable values
- --> $DIR/static_mut_containing_mut_ref2.rs:3:46
- |
-LL | pub static mut STDERR_BUFFER: () = unsafe { *(&mut STDERR_BUFFER_SPACE) = 42; };
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^ statics require immutable values
-
-error[E0019]: static contains unimplemented expression type
- --> $DIR/static_mut_containing_mut_ref2.rs:3:45
- |
-LL | pub static mut STDERR_BUFFER: () = unsafe { *(&mut STDERR_BUFFER_SPACE) = 42; };
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to 2 previous errors
-
-Some errors have detailed explanations: E0017, E0019.
-For more information about an error, try `rustc --explain E0017`.
diff --git a/src/test/ui/consts/static_mut_containing_mut_ref2.stock.stderr b/src/test/ui/consts/static_mut_containing_mut_ref2.stock.stderr
new file mode 100644
index 0000000..430cef9
--- /dev/null
+++ b/src/test/ui/consts/static_mut_containing_mut_ref2.stock.stderr
@@ -0,0 +1,19 @@
+error[E0658]: references in statics may only refer to immutable values
+ --> $DIR/static_mut_containing_mut_ref2.rs:7:46
+ |
+LL | pub static mut STDERR_BUFFER: () = unsafe { *(&mut STDERR_BUFFER_SPACE) = 42; };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ statics require immutable values
+ |
+ = note: for more information, see https://github.com/rust-lang/rust/issues/57349
+ = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
+
+error[E0019]: static contains unimplemented expression type
+ --> $DIR/static_mut_containing_mut_ref2.rs:7:45
+ |
+LL | pub static mut STDERR_BUFFER: () = unsafe { *(&mut STDERR_BUFFER_SPACE) = 42; };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0019, E0658.
+For more information about an error, try `rustc --explain E0019`.
diff --git a/src/test/ui/enum/union-in-enum.rs b/src/test/ui/enum/union-in-enum.rs
new file mode 100644
index 0000000..048913e
--- /dev/null
+++ b/src/test/ui/enum/union-in-enum.rs
@@ -0,0 +1,13 @@
+// This test checks that the union keyword
+// is accepted as the name of an enum variant
+// when not followed by an identifier
+// This special case exists because `union` is a contextual keyword.
+
+#![allow(warnings)]
+
+// check-pass
+
+enum A { union }
+enum B { union {} }
+enum C { union() }
+fn main(){}
diff --git a/src/test/ui/error-codes/E0017.rs b/src/test/ui/error-codes/E0017.rs
index 3bc518c..64be411 100644
--- a/src/test/ui/error-codes/E0017.rs
+++ b/src/test/ui/error-codes/E0017.rs
@@ -2,10 +2,10 @@
const C: i32 = 2;
static mut M: i32 = 3;
-const CR: &'static mut i32 = &mut C; //~ ERROR E0017
-static STATIC_REF: &'static mut i32 = &mut X; //~ ERROR E0017
+const CR: &'static mut i32 = &mut C; //~ ERROR E0658
+static STATIC_REF: &'static mut i32 = &mut X; //~ ERROR E0658
//~| ERROR E0019
//~| ERROR cannot borrow
-static CONST_REF: &'static mut i32 = &mut C; //~ ERROR E0017
-static STATIC_MUT_REF: &'static mut i32 = unsafe { &mut M }; //~ ERROR E0017
+static CONST_REF: &'static mut i32 = &mut C; //~ ERROR E0658
+static STATIC_MUT_REF: &'static mut i32 = unsafe { &mut M }; //~ ERROR E0658
fn main() {}
diff --git a/src/test/ui/error-codes/E0017.stderr b/src/test/ui/error-codes/E0017.stderr
index 8c8660a..9a87195 100644
--- a/src/test/ui/error-codes/E0017.stderr
+++ b/src/test/ui/error-codes/E0017.stderr
@@ -1,8 +1,11 @@
-error[E0017]: references in constants may only refer to immutable values
+error[E0658]: references in constants may only refer to immutable values
--> $DIR/E0017.rs:5:30
|
LL | const CR: &'static mut i32 = &mut C;
| ^^^^^^ constants require immutable values
+ |
+ = note: for more information, see https://github.com/rust-lang/rust/issues/57349
+ = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
error[E0019]: static contains unimplemented expression type
--> $DIR/E0017.rs:6:39
@@ -10,11 +13,14 @@
LL | static STATIC_REF: &'static mut i32 = &mut X;
| ^^^^^^
-error[E0017]: references in statics may only refer to immutable values
+error[E0658]: references in statics may only refer to immutable values
--> $DIR/E0017.rs:6:39
|
LL | static STATIC_REF: &'static mut i32 = &mut X;
| ^^^^^^ statics require immutable values
+ |
+ = note: for more information, see https://github.com/rust-lang/rust/issues/57349
+ = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
error[E0596]: cannot borrow immutable static item `X` as mutable
--> $DIR/E0017.rs:6:39
@@ -22,19 +28,25 @@
LL | static STATIC_REF: &'static mut i32 = &mut X;
| ^^^^^^ cannot borrow as mutable
-error[E0017]: references in statics may only refer to immutable values
+error[E0658]: references in statics may only refer to immutable values
--> $DIR/E0017.rs:9:38
|
LL | static CONST_REF: &'static mut i32 = &mut C;
| ^^^^^^ statics require immutable values
+ |
+ = note: for more information, see https://github.com/rust-lang/rust/issues/57349
+ = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
-error[E0017]: references in statics may only refer to immutable values
+error[E0658]: references in statics may only refer to immutable values
--> $DIR/E0017.rs:10:52
|
LL | static STATIC_MUT_REF: &'static mut i32 = unsafe { &mut M };
| ^^^^^^ statics require immutable values
+ |
+ = note: for more information, see https://github.com/rust-lang/rust/issues/57349
+ = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
error: aborting due to 6 previous errors
-Some errors have detailed explanations: E0017, E0019, E0596.
-For more information about an error, try `rustc --explain E0017`.
+Some errors have detailed explanations: E0019, E0596, E0658.
+For more information about an error, try `rustc --explain E0019`.
diff --git a/src/test/ui/error-codes/E0388.rs b/src/test/ui/error-codes/E0388.rs
new file mode 100644
index 0000000..5954e34
--- /dev/null
+++ b/src/test/ui/error-codes/E0388.rs
@@ -0,0 +1,10 @@
+static X: i32 = 1;
+const C: i32 = 2;
+
+const CR: &'static mut i32 = &mut C; //~ ERROR E0658
+static STATIC_REF: &'static mut i32 = &mut X; //~ ERROR E0658
+ //~| ERROR cannot borrow
+ //~| ERROR E0019
+static CONST_REF: &'static mut i32 = &mut C; //~ ERROR E0658
+
+fn main() {}
diff --git a/src/test/ui/error-codes/E0388.stderr b/src/test/ui/error-codes/E0388.stderr
new file mode 100644
index 0000000..986307d
--- /dev/null
+++ b/src/test/ui/error-codes/E0388.stderr
@@ -0,0 +1,43 @@
+error[E0658]: references in constants may only refer to immutable values
+ --> $DIR/E0388.rs:4:30
+ |
+LL | const CR: &'static mut i32 = &mut C;
+ | ^^^^^^ constants require immutable values
+ |
+ = note: for more information, see https://github.com/rust-lang/rust/issues/57349
+ = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
+
+error[E0019]: static contains unimplemented expression type
+ --> $DIR/E0388.rs:5:39
+ |
+LL | static STATIC_REF: &'static mut i32 = &mut X;
+ | ^^^^^^
+
+error[E0658]: references in statics may only refer to immutable values
+ --> $DIR/E0388.rs:5:39
+ |
+LL | static STATIC_REF: &'static mut i32 = &mut X;
+ | ^^^^^^ statics require immutable values
+ |
+ = note: for more information, see https://github.com/rust-lang/rust/issues/57349
+ = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
+
+error[E0596]: cannot borrow immutable static item `X` as mutable
+ --> $DIR/E0388.rs:5:39
+ |
+LL | static STATIC_REF: &'static mut i32 = &mut X;
+ | ^^^^^^ cannot borrow as mutable
+
+error[E0658]: references in statics may only refer to immutable values
+ --> $DIR/E0388.rs:8:38
+ |
+LL | static CONST_REF: &'static mut i32 = &mut C;
+ | ^^^^^^ statics require immutable values
+ |
+ = note: for more information, see https://github.com/rust-lang/rust/issues/57349
+ = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
+
+error: aborting due to 5 previous errors
+
+Some errors have detailed explanations: E0019, E0596, E0658.
+For more information about an error, try `rustc --explain E0019`.
diff --git a/src/test/ui/fully-qualified-type/fully-qualified-type-name4.stderr b/src/test/ui/fully-qualified-type/fully-qualified-type-name4.stderr
index b388f38..ca61fb0 100644
--- a/src/test/ui/fully-qualified-type/fully-qualified-type-name4.stderr
+++ b/src/test/ui/fully-qualified-type/fully-qualified-type-name4.stderr
@@ -4,7 +4,10 @@
LL | fn bar(x: usize) -> Option<usize> {
| ------------- expected `std::option::Option<usize>` because of return type
LL | return x;
- | ^ expected enum `std::option::Option`, found `usize`
+ | ^
+ | |
+ | expected enum `std::option::Option`, found `usize`
+ | help: try using a variant of the expected enum: `Some(x)`
|
= note: expected enum `std::option::Option<usize>`
found type `usize`
diff --git a/src/test/ui/issues/issue-17718-const-bad-values.stderr b/src/test/ui/issues/issue-17718-const-bad-values.stderr
index 8d875d3..7e4a62a 100644
--- a/src/test/ui/issues/issue-17718-const-bad-values.stderr
+++ b/src/test/ui/issues/issue-17718-const-bad-values.stderr
@@ -1,8 +1,11 @@
-error[E0017]: references in constants may only refer to immutable values
+error[E0658]: references in constants may only refer to immutable values
--> $DIR/issue-17718-const-bad-values.rs:1:34
|
LL | const C1: &'static mut [usize] = &mut [];
| ^^^^^^^ constants require immutable values
+ |
+ = note: for more information, see https://github.com/rust-lang/rust/issues/57349
+ = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
error[E0013]: constants cannot refer to statics, use a constant instead
--> $DIR/issue-17718-const-bad-values.rs:5:46
@@ -10,13 +13,16 @@
LL | const C2: &'static mut usize = unsafe { &mut S };
| ^
-error[E0017]: references in constants may only refer to immutable values
+error[E0658]: references in constants may only refer to immutable values
--> $DIR/issue-17718-const-bad-values.rs:5:41
|
LL | const C2: &'static mut usize = unsafe { &mut S };
| ^^^^^^ constants require immutable values
+ |
+ = note: for more information, see https://github.com/rust-lang/rust/issues/57349
+ = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
error: aborting due to 3 previous errors
-Some errors have detailed explanations: E0013, E0017.
+Some errors have detailed explanations: E0013, E0658.
For more information about an error, try `rustc --explain E0013`.
diff --git a/src/test/ui/issues/issue-46604.rs b/src/test/ui/issues/issue-46604.rs
index 4f1ad38..e1967eb 100644
--- a/src/test/ui/issues/issue-46604.rs
+++ b/src/test/ui/issues/issue-46604.rs
@@ -1,4 +1,4 @@
-static buf: &mut [u8] = &mut [1u8,2,3,4,5,7]; //~ ERROR E0017
+static buf: &mut [u8] = &mut [1u8,2,3,4,5,7]; //~ ERROR E0658
fn write<T: AsRef<[u8]>>(buffer: T) { }
fn main() {
diff --git a/src/test/ui/issues/issue-46604.stderr b/src/test/ui/issues/issue-46604.stderr
index c72f580..32c7ecb 100644
--- a/src/test/ui/issues/issue-46604.stderr
+++ b/src/test/ui/issues/issue-46604.stderr
@@ -1,8 +1,11 @@
-error[E0017]: references in statics may only refer to immutable values
+error[E0658]: references in statics may only refer to immutable values
--> $DIR/issue-46604.rs:1:25
|
LL | static buf: &mut [u8] = &mut [1u8,2,3,4,5,7];
| ^^^^^^^^^^^^^^^^^^^^ statics require immutable values
+ |
+ = note: for more information, see https://github.com/rust-lang/rust/issues/57349
+ = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
error[E0594]: cannot assign to `buf[_]`, as `buf` is an immutable static item
--> $DIR/issue-46604.rs:6:5
@@ -12,5 +15,5 @@
error: aborting due to 2 previous errors
-Some errors have detailed explanations: E0017, E0594.
-For more information about an error, try `rustc --explain E0017`.
+Some errors have detailed explanations: E0594, E0658.
+For more information about an error, try `rustc --explain E0594`.
diff --git a/src/test/ui/issues/issue-51632-try-desugar-incompatible-types.stderr b/src/test/ui/issues/issue-51632-try-desugar-incompatible-types.stderr
index aef6dc5..9ca983d 100644
--- a/src/test/ui/issues/issue-51632-try-desugar-incompatible-types.stderr
+++ b/src/test/ui/issues/issue-51632-try-desugar-incompatible-types.stderr
@@ -2,13 +2,18 @@
--> $DIR/issue-51632-try-desugar-incompatible-types.rs:8:5
|
LL | missing_discourses()?
- | ^^^^^^^^^^^^^^^^^^^^-
- | | |
- | | help: try removing this `?`
- | expected enum `std::result::Result`, found `isize`
+ | ^^^^^^^^^^^^^^^^^^^^^ expected enum `std::result::Result`, found `isize`
|
= note: expected enum `std::result::Result<isize, ()>`
found type `isize`
+help: try removing this `?`
+ |
+LL | missing_discourses()
+ | --
+help: try using a variant of the expected enum
+ |
+LL | Ok(missing_discourses()?)
+ |
error: aborting due to previous error
diff --git a/src/test/ui/issues/issue-59756.rs b/src/test/ui/issues/issue-59756.rs
index cccae39..d6df059 100644
--- a/src/test/ui/issues/issue-59756.rs
+++ b/src/test/ui/issues/issue-59756.rs
@@ -1,4 +1,8 @@
// run-rustfix
+// ignore-test
+//
+// FIXME: Re-enable this test once we support choosing
+// between multiple mutually exclusive suggestions for the same span
#![allow(warnings)]
diff --git a/src/test/ui/issues/issue-59756.stderr b/src/test/ui/issues/issue-59756.stderr
index 150916c..9066e57 100644
--- a/src/test/ui/issues/issue-59756.stderr
+++ b/src/test/ui/issues/issue-59756.stderr
@@ -2,13 +2,18 @@
--> $DIR/issue-59756.rs:13:5
|
LL | foo()?
- | ^^^^^-
- | | |
- | | help: try removing this `?`
- | expected enum `std::result::Result`, found struct `A`
+ | ^^^^^^ expected enum `std::result::Result`, found struct `A`
|
= note: expected enum `std::result::Result<A, B>`
found struct `A`
+help: try removing this `?`
+ |
+LL | foo()
+ | --
+help: try using a variant of the expected enum
+ |
+LL | Ok(foo()?)
+ |
error: aborting due to previous error
diff --git a/src/test/ui/malformed/malformed-derive-entry.rs b/src/test/ui/malformed/malformed-derive-entry.rs
index a6d8863..77fa2f5 100644
--- a/src/test/ui/malformed/malformed-derive-entry.rs
+++ b/src/test/ui/malformed/malformed-derive-entry.rs
@@ -1,7 +1,11 @@
-#[derive(Copy(Bad))] //~ ERROR expected one of `)`, `,`, or `::`, found `(`
+#[derive(Copy(Bad))]
+//~^ ERROR traits in `#[derive(...)]` don't accept arguments
+//~| ERROR the trait bound
struct Test1;
-#[derive(Copy="bad")] //~ ERROR expected one of `)`, `,`, or `::`, found `=`
+#[derive(Copy="bad")]
+//~^ ERROR traits in `#[derive(...)]` don't accept values
+//~| ERROR the trait bound
struct Test2;
#[derive] //~ ERROR malformed `derive` attribute input
diff --git a/src/test/ui/malformed/malformed-derive-entry.stderr b/src/test/ui/malformed/malformed-derive-entry.stderr
index 8d750b6..1f1ee39 100644
--- a/src/test/ui/malformed/malformed-derive-entry.stderr
+++ b/src/test/ui/malformed/malformed-derive-entry.stderr
@@ -1,20 +1,33 @@
-error: expected one of `)`, `,`, or `::`, found `(`
+error: traits in `#[derive(...)]` don't accept arguments
--> $DIR/malformed-derive-entry.rs:1:14
|
LL | #[derive(Copy(Bad))]
- | ^ expected one of `)`, `,`, or `::`
+ | ^^^^^ help: remove the arguments
-error: expected one of `)`, `,`, or `::`, found `=`
- --> $DIR/malformed-derive-entry.rs:4:14
+error: traits in `#[derive(...)]` don't accept values
+ --> $DIR/malformed-derive-entry.rs:6:14
|
LL | #[derive(Copy="bad")]
- | ^ expected one of `)`, `,`, or `::`
+ | ^^^^^^ help: remove the value
error: malformed `derive` attribute input
- --> $DIR/malformed-derive-entry.rs:7:1
+ --> $DIR/malformed-derive-entry.rs:11:1
|
LL | #[derive]
| ^^^^^^^^^ help: missing traits to be derived: `#[derive(Trait1, Trait2, ...)]`
-error: aborting due to 3 previous errors
+error[E0277]: the trait bound `Test1: std::clone::Clone` is not satisfied
+ --> $DIR/malformed-derive-entry.rs:1:10
+ |
+LL | #[derive(Copy(Bad))]
+ | ^^^^ the trait `std::clone::Clone` is not implemented for `Test1`
+error[E0277]: the trait bound `Test2: std::clone::Clone` is not satisfied
+ --> $DIR/malformed-derive-entry.rs:6:10
+ |
+LL | #[derive(Copy="bad")]
+ | ^^^^ the trait `std::clone::Clone` is not implemented for `Test2`
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/malformed/malformed-meta-delim.rs b/src/test/ui/malformed/malformed-meta-delim.rs
new file mode 100644
index 0000000..5b1614b
--- /dev/null
+++ b/src/test/ui/malformed/malformed-meta-delim.rs
@@ -0,0 +1,11 @@
+fn main() {}
+
+#[allow { foo_lint } ]
+//~^ ERROR wrong meta list delimiters
+//~| HELP the delimiters should be `(` and `)`
+fn delim_brace() {}
+
+#[allow [ foo_lint ] ]
+//~^ ERROR wrong meta list delimiters
+//~| HELP the delimiters should be `(` and `)`
+fn delim_bracket() {}
diff --git a/src/test/ui/malformed/malformed-meta-delim.stderr b/src/test/ui/malformed/malformed-meta-delim.stderr
new file mode 100644
index 0000000..407193d
--- /dev/null
+++ b/src/test/ui/malformed/malformed-meta-delim.stderr
@@ -0,0 +1,24 @@
+error: wrong meta list delimiters
+ --> $DIR/malformed-meta-delim.rs:3:9
+ |
+LL | #[allow { foo_lint } ]
+ | ^^^^^^^^^^^^
+ |
+help: the delimiters should be `(` and `)`
+ |
+LL | #[allow ( foo_lint ) ]
+ | ^ ^
+
+error: wrong meta list delimiters
+ --> $DIR/malformed-meta-delim.rs:8:9
+ |
+LL | #[allow [ foo_lint ] ]
+ | ^^^^^^^^^^^^
+ |
+help: the delimiters should be `(` and `)`
+ |
+LL | #[allow ( foo_lint ) ]
+ | ^ ^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/malformed/malformed-special-attrs.rs b/src/test/ui/malformed/malformed-special-attrs.rs
index e67fbdd..05b7ebe 100644
--- a/src/test/ui/malformed/malformed-special-attrs.rs
+++ b/src/test/ui/malformed/malformed-special-attrs.rs
@@ -1,7 +1,7 @@
#[cfg_attr] //~ ERROR malformed `cfg_attr` attribute
struct S1;
-#[cfg_attr = ""] //~ ERROR expected `(`, found `=`
+#[cfg_attr = ""] //~ ERROR malformed `cfg_attr` attribute
struct S2;
#[derive] //~ ERROR malformed `derive` attribute
diff --git a/src/test/ui/malformed/malformed-special-attrs.stderr b/src/test/ui/malformed/malformed-special-attrs.stderr
index 319c05e..6f535e0 100644
--- a/src/test/ui/malformed/malformed-special-attrs.stderr
+++ b/src/test/ui/malformed/malformed-special-attrs.stderr
@@ -6,11 +6,13 @@
|
= note: for more information, visit <https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg_attr-attribute>
-error: expected `(`, found `=`
- --> $DIR/malformed-special-attrs.rs:4:12
+error: malformed `cfg_attr` attribute input
+ --> $DIR/malformed-special-attrs.rs:4:1
|
LL | #[cfg_attr = ""]
- | ^ expected `(`
+ | ^^^^^^^^^^^^^^^^ help: missing condition and attribute: `#[cfg_attr(condition, attribute, other_attribute, ...)]`
+ |
+ = note: for more information, visit <https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg_attr-attribute>
error: malformed `derive` attribute input
--> $DIR/malformed-special-attrs.rs:7:1
diff --git a/src/test/ui/mismatched_types/abridged.stderr b/src/test/ui/mismatched_types/abridged.stderr
index c208187..c731306 100644
--- a/src/test/ui/mismatched_types/abridged.stderr
+++ b/src/test/ui/mismatched_types/abridged.stderr
@@ -26,7 +26,10 @@
LL | fn b() -> Option<Foo> {
| ----------- expected `std::option::Option<Foo>` because of return type
LL | Foo { bar: 1 }
- | ^^^^^^^^^^^^^^ expected enum `std::option::Option`, found struct `Foo`
+ | ^^^^^^^^^^^^^^
+ | |
+ | expected enum `std::option::Option`, found struct `Foo`
+ | help: try using a variant of the expected enum: `Some(Foo { bar: 1 })`
|
= note: expected enum `std::option::Option<Foo>`
found struct `Foo`
@@ -37,7 +40,10 @@
LL | fn c() -> Result<Foo, Bar> {
| ---------------- expected `std::result::Result<Foo, Bar>` because of return type
LL | Foo { bar: 1 }
- | ^^^^^^^^^^^^^^ expected enum `std::result::Result`, found struct `Foo`
+ | ^^^^^^^^^^^^^^
+ | |
+ | expected enum `std::result::Result`, found struct `Foo`
+ | help: try using a variant of the expected enum: `Ok(Foo { bar: 1 })`
|
= note: expected enum `std::result::Result<Foo, Bar>`
found struct `Foo`
diff --git a/src/test/ui/on-unimplemented/expected-comma-found-token.rs b/src/test/ui/on-unimplemented/expected-comma-found-token.rs
index 77c0ea1..8fb34f2 100644
--- a/src/test/ui/on-unimplemented/expected-comma-found-token.rs
+++ b/src/test/ui/on-unimplemented/expected-comma-found-token.rs
@@ -6,7 +6,7 @@
#[rustc_on_unimplemented(
message="the message"
- label="the label" //~ ERROR expected one of `)` or `,`, found `label`
+ label="the label" //~ ERROR expected `,`, found `label`
)]
trait T {}
diff --git a/src/test/ui/on-unimplemented/expected-comma-found-token.stderr b/src/test/ui/on-unimplemented/expected-comma-found-token.stderr
index 2e1d484..048b72e 100644
--- a/src/test/ui/on-unimplemented/expected-comma-found-token.stderr
+++ b/src/test/ui/on-unimplemented/expected-comma-found-token.stderr
@@ -1,11 +1,8 @@
-error: expected one of `)` or `,`, found `label`
+error: expected `,`, found `label`
--> $DIR/expected-comma-found-token.rs:9:5
|
LL | message="the message"
- | -
- | |
- | expected one of `)` or `,`
- | help: missing `,`
+ | - expected `,`
LL | label="the label"
| ^^^^^ unexpected token
diff --git a/src/test/ui/proc-macro/span-preservation.stderr b/src/test/ui/proc-macro/span-preservation.stderr
index cd6f0ea..a77e920 100644
--- a/src/test/ui/proc-macro/span-preservation.stderr
+++ b/src/test/ui/proc-macro/span-preservation.stderr
@@ -14,6 +14,11 @@
LL | match x {
LL | Some(x) => { return x },
| ^ expected `usize`, found `isize`
+ |
+help: you can convert an `isize` to `usize` and panic if the converted value wouldn't fit
+ |
+LL | Some(x) => { return x.try_into().unwrap() },
+ | ^^^^^^^^^^^^^^^^^^^^^
error[E0308]: mismatched types
--> $DIR/span-preservation.rs:33:22
diff --git a/src/test/ui/span/macro-ty-params.rs b/src/test/ui/span/macro-ty-params.rs
index b077d59..713b9eb 100644
--- a/src/test/ui/span/macro-ty-params.rs
+++ b/src/test/ui/span/macro-ty-params.rs
@@ -10,5 +10,4 @@
foo::<T>!(); //~ ERROR generic arguments in macro path
foo::<>!(); //~ ERROR generic arguments in macro path
m!(Default<>); //~ ERROR generic arguments in macro path
- //~^ ERROR unexpected generic arguments in path
}
diff --git a/src/test/ui/span/macro-ty-params.stderr b/src/test/ui/span/macro-ty-params.stderr
index 39b3edc..21683b2 100644
--- a/src/test/ui/span/macro-ty-params.stderr
+++ b/src/test/ui/span/macro-ty-params.stderr
@@ -10,17 +10,11 @@
LL | foo::<>!();
| ^^
-error: unexpected generic arguments in path
- --> $DIR/macro-ty-params.rs:12:8
- |
-LL | m!(Default<>);
- | ^^^^^^^^^
-
error: generic arguments in macro path
--> $DIR/macro-ty-params.rs:12:15
|
LL | m!(Default<>);
| ^^
-error: aborting due to 4 previous errors
+error: aborting due to 3 previous errors
diff --git a/src/test/ui/tail-typeck.stderr b/src/test/ui/tail-typeck.stderr
index eeeb258..69f8ffa 100644
--- a/src/test/ui/tail-typeck.stderr
+++ b/src/test/ui/tail-typeck.stderr
@@ -5,6 +5,11 @@
| ----- ^^^ expected `isize`, found `usize`
| |
| expected `isize` because of return type
+ |
+help: you can convert an `usize` to `isize` and panic if the converted value wouldn't fit
+ |
+LL | fn f() -> isize { return g().try_into().unwrap(); }
+ | ^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to previous error
diff --git a/src/test/ui/wrong-ret-type.stderr b/src/test/ui/wrong-ret-type.stderr
index 440620f..c1274bd 100644
--- a/src/test/ui/wrong-ret-type.stderr
+++ b/src/test/ui/wrong-ret-type.stderr
@@ -5,6 +5,11 @@
| ----- ^ expected `usize`, found `isize`
| |
| expected `usize` because of return type
+ |
+help: you can convert an `isize` to `usize` and panic if the converted value wouldn't fit
+ |
+LL | fn mk_int() -> usize { let i: isize = 3; return i.try_into().unwrap(); }
+ | ^^^^^^^^^^^^^^^^^^^^^
error: aborting due to previous error