From 662024478deb04a8c71d779b66b4bedb0bf91dbe Mon Sep 17 00:00:00 2001 From: woppopo Date: Sun, 12 Dec 2021 04:19:23 +0900 Subject: [PATCH 01/28] Make some `Clone` impls `const` --- library/core/src/clone.rs | 21 +++++++++++++++------ library/core/src/convert/mod.rs | 3 ++- library/core/src/lib.rs | 1 + library/core/src/option.rs | 6 +++++- library/core/src/ptr/non_null.rs | 3 ++- library/core/src/ptr/unique.rs | 3 ++- library/core/src/result.rs | 7 ++++++- 7 files changed, 33 insertions(+), 11 deletions(-) diff --git a/library/core/src/clone.rs b/library/core/src/clone.rs index 6f9579043c37d..1912694412b98 100644 --- a/library/core/src/clone.rs +++ b/library/core/src/clone.rs @@ -127,7 +127,11 @@ pub trait Clone: Sized { /// allocations. #[inline] #[stable(feature = "rust1", since = "1.0.0")] - fn clone_from(&mut self, source: &Self) { + #[default_method_body_is_const] + fn clone_from(&mut self, source: &Self) + where + Self: ~const Drop, + { *self = source.clone() } } @@ -178,7 +182,8 @@ mod impls { ($($t:ty)*) => { $( #[stable(feature = "rust1", since = "1.0.0")] - impl Clone for $t { + #[rustc_const_unstable(feature = "const_clone", issue = "91805")] + impl const Clone for $t { #[inline] fn clone(&self) -> Self { *self @@ -196,7 +201,8 @@ mod impls { } #[unstable(feature = "never_type", issue = "35121")] - impl Clone for ! { + #[rustc_const_unstable(feature = "const_clone", issue = "91805")] + impl const Clone for ! { #[inline] fn clone(&self) -> Self { *self @@ -204,7 +210,8 @@ mod impls { } #[stable(feature = "rust1", since = "1.0.0")] - impl Clone for *const T { + #[rustc_const_unstable(feature = "const_clone", issue = "91805")] + impl const Clone for *const T { #[inline] fn clone(&self) -> Self { *self @@ -212,7 +219,8 @@ mod impls { } #[stable(feature = "rust1", since = "1.0.0")] - impl Clone for *mut T { + #[rustc_const_unstable(feature = "const_clone", issue = "91805")] + impl const Clone for *mut T { #[inline] fn clone(&self) -> Self { *self @@ -221,7 +229,8 @@ mod impls { /// Shared references can be cloned, but mutable references *cannot*! #[stable(feature = "rust1", since = "1.0.0")] - impl Clone for &T { + #[rustc_const_unstable(feature = "const_clone", issue = "91805")] + impl const Clone for &T { #[inline] #[rustc_diagnostic_item = "noop_method_clone"] fn clone(&self) -> Self { diff --git a/library/core/src/convert/mod.rs b/library/core/src/convert/mod.rs index 5aa53deee343d..a50b8904b593e 100644 --- a/library/core/src/convert/mod.rs +++ b/library/core/src/convert/mod.rs @@ -683,7 +683,8 @@ impl AsMut for str { pub enum Infallible {} #[stable(feature = "convert_infallible", since = "1.34.0")] -impl Clone for Infallible { +#[rustc_const_unstable(feature = "const_clone", issue = "91805")] +impl const Clone for Infallible { fn clone(&self) -> Infallible { match *self {} } diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 78383b54c5d1e..4ef4740799a0b 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -106,6 +106,7 @@ #![feature(const_caller_location)] #![feature(const_cell_into_inner)] #![feature(const_char_convert)] +#![feature(const_clone)] #![feature(const_discriminant)] #![feature(const_eval_select)] #![feature(const_float_bits_conv)] diff --git a/library/core/src/option.rs b/library/core/src/option.rs index 7b9c6e43960f7..941d7e0792628 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -1668,7 +1668,11 @@ const fn expect_failed(msg: &str) -> ! { ///////////////////////////////////////////////////////////////////////////// #[stable(feature = "rust1", since = "1.0.0")] -impl Clone for Option { +#[rustc_const_unstable(feature = "const_clone", issue = "91805")] +impl const Clone for Option +where + T: ~const Clone + ~const Drop, +{ #[inline] fn clone(&self) -> Self { match self { diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs index 58110b0680943..cb268abc8eecd 100644 --- a/library/core/src/ptr/non_null.rs +++ b/library/core/src/ptr/non_null.rs @@ -635,7 +635,8 @@ impl NonNull<[T]> { } #[stable(feature = "nonnull", since = "1.25.0")] -impl Clone for NonNull { +#[rustc_const_unstable(feature = "const_clone", issue = "91805")] +impl const Clone for NonNull { #[inline] fn clone(&self) -> Self { *self diff --git a/library/core/src/ptr/unique.rs b/library/core/src/ptr/unique.rs index d650a6f974b97..ee984b7b5a4f1 100644 --- a/library/core/src/ptr/unique.rs +++ b/library/core/src/ptr/unique.rs @@ -146,7 +146,8 @@ impl Unique { } #[unstable(feature = "ptr_internals", issue = "none")] -impl Clone for Unique { +#[rustc_const_unstable(feature = "const_clone", issue = "91805")] +impl const Clone for Unique { #[inline] fn clone(&self) -> Self { *self diff --git a/library/core/src/result.rs b/library/core/src/result.rs index e6b8c8ec3385a..d639c7188c15a 100644 --- a/library/core/src/result.rs +++ b/library/core/src/result.rs @@ -1665,7 +1665,12 @@ fn unwrap_failed(msg: &str, error: &dyn fmt::Debug) -> ! { ///////////////////////////////////////////////////////////////////////////// #[stable(feature = "rust1", since = "1.0.0")] -impl Clone for Result { +#[rustc_const_unstable(feature = "const_clone", issue = "91805")] +impl const Clone for Result +where + T: ~const Clone + ~const Drop, + E: ~const Clone + ~const Drop, +{ #[inline] fn clone(&self) -> Self { match self { From 9054fbb03ab2ebb048888f4963a364d800fba056 Mon Sep 17 00:00:00 2001 From: asquared31415 <34665709+asquared31415@users.noreply.github.com> Date: Mon, 3 Jan 2022 17:12:59 -0500 Subject: [PATCH 02/28] mirror mention of intent of From --- library/core/src/convert/mod.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/library/core/src/convert/mod.rs b/library/core/src/convert/mod.rs index 1c2e673d60493..b6211900b47f4 100644 --- a/library/core/src/convert/mod.rs +++ b/library/core/src/convert/mod.rs @@ -300,7 +300,8 @@ pub trait Into: Sized { /// that encapsulate multiple error types. See the "Examples" section and [the book][book] for more /// details. /// -/// **Note: This trait must not fail**. If the conversion can fail, use [`TryFrom`]. +/// **Note: This trait must not fail**. The `From` trait is intended for perfect conversions. +/// If the conversion can fail or is not perfect, use [`TryFrom`]. /// /// # Generic Implementations /// From 04b3162764516aa2295d4d549969bae60b5d0cf9 Mon Sep 17 00:00:00 2001 From: fren_gor Date: Sun, 20 Feb 2022 01:46:55 +0100 Subject: [PATCH 03/28] Add collect_into --- library/core/src/iter/traits/iterator.rs | 71 ++++++++++++++++++++++ library/core/tests/iter/traits/iterator.rs | 8 +++ library/core/tests/lib.rs | 1 + 3 files changed, 80 insertions(+) diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index 5a361edecd9c0..9b22023b09e3e 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -1859,6 +1859,77 @@ pub trait Iterator { try_process(self, |i| i.collect()) } + /// Collects all the items from an iterator into a collection. + /// + /// This method consumes the iterator and adds all its items to the + /// passed collection. The collection is then returned, so the call chain + /// can be continued. + /// + /// This is useful when you already have a collection and wants to add + /// the iterator items to it. + /// + /// This method is a convenience method to call [Extend::extend](trait.Extend.html), + /// but instead of being called on a collection, it's called on an iterator. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(iter_collect_into)] + /// + /// let a = [1, 2, 3]; + /// let mut vec: Vec:: = vec![0, 1]; + /// + /// a.iter().map(|&x| x * 2).collect_into(&mut vec); + /// a.iter().map(|&x| x * 10).collect_into(&mut vec); + /// + /// assert_eq!(vec![0, 1, 2, 4, 6, 10, 20, 30], vec); + /// ``` + /// + /// `Vec` can have a manual set capacity to avoid reallocating it: + /// + /// ``` + /// #![feature(iter_collect_into)] + /// + /// let a = [1, 2, 3]; + /// let mut vec: Vec:: = Vec::with_capacity(6); + /// + /// a.iter().map(|&x| x * 2).collect_into(&mut vec); + /// a.iter().map(|&x| x * 10).collect_into(&mut vec); + /// + /// assert_eq!(6, vec.capacity()); + /// println!("{:?}", vec); + /// ``` + /// + /// The returned mutable reference can be used to continue the call chain: + /// + /// ``` + /// #![feature(iter_collect_into)] + /// + /// let a = [1, 2, 3]; + /// let mut vec: Vec:: = Vec::with_capacity(6); + /// + /// let count = a.iter().collect_into(&mut vec).iter().count(); + /// + /// assert_eq!(count, vec.len()); + /// println!("Vec len is {}", count); + /// + /// let count = a.iter().collect_into(&mut vec).iter().count(); + /// + /// assert_eq!(count, vec.len()); + /// println!("Vec len now is {}", count); + /// ``` + #[inline] + #[unstable(feature = "iter_collect_into", reason = "new API", issue = "none")] + fn collect_into>(self, collection: &mut E) -> &mut E + where + Self: Sized, + { + collection.extend(self); + collection + } + /// Consumes an iterator, creating two collections from it. /// /// The predicate passed to `partition()` can return `true`, or `false`. diff --git a/library/core/tests/iter/traits/iterator.rs b/library/core/tests/iter/traits/iterator.rs index cf69f0a7a4d7e..32bd68e3d2554 100644 --- a/library/core/tests/iter/traits/iterator.rs +++ b/library/core/tests/iter/traits/iterator.rs @@ -543,6 +543,14 @@ fn test_try_collect() { assert_eq!(v, Continue(vec![4, 5])); } +#[test] +fn test_collect_into() { + let a = vec![1, 2, 3, 4, 5]; + let mut b = Vec::new(); + a.iter().cloned().collect_into(&mut b); + assert!(a == b); +} + // just tests by whether or not this compiles fn _empty_impl_all_auto_traits() { use std::panic::{RefUnwindSafe, UnwindSafe}; diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index 06c7be054a038..39d8625e8bf6c 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -63,6 +63,7 @@ #![feature(slice_partition_dedup)] #![feature(int_log)] #![feature(iter_advance_by)] +#![feature(iter_collect_into)] #![feature(iter_partition_in_place)] #![feature(iter_intersperse)] #![feature(iter_is_partitioned)] From 5941fef2920a631b22e870627c67a2cd9c30dafe Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Tue, 22 Feb 2022 12:39:36 +1100 Subject: [PATCH 04/28] Constify slice indexing --- library/core/src/lib.rs | 1 + library/core/src/ops/range.rs | 2 +- library/core/src/slice/index.rs | 80 ++++++++++++++++++++++++++------- 3 files changed, 66 insertions(+), 17 deletions(-) diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index aa1ad9362a90e..bad3fb0765c7b 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -148,6 +148,7 @@ #![feature(variant_count)] #![feature(const_array_from_ref)] #![feature(const_slice_from_ref)] +#![feature(const_slice_index_impls)] // // Language features: #![feature(abi_unadjusted)] diff --git a/library/core/src/ops/range.rs b/library/core/src/ops/range.rs index 1136722067874..5029e0560b892 100644 --- a/library/core/src/ops/range.rs +++ b/library/core/src/ops/range.rs @@ -446,7 +446,7 @@ impl RangeInclusive { /// Converts to an exclusive `Range` for `SliceIndex` implementations. /// The caller is responsible for dealing with `end == usize::MAX`. #[inline] - pub(crate) fn into_slice_range(self) -> Range { + pub(crate) const fn into_slice_range(self) -> Range { // If we're not exhausted, we want to simply slice `start..end + 1`. // If we are exhausted, then slicing with `end + 1..end + 1` gives us an // empty range that is still subject to bounds-checks for that endpoint. diff --git a/library/core/src/slice/index.rs b/library/core/src/slice/index.rs index 0298bba8d329e..3931c123352ce 100644 --- a/library/core/src/slice/index.rs +++ b/library/core/src/slice/index.rs @@ -1,12 +1,14 @@ //! Indexing implementations for `[T]`. +use crate::intrinsics::const_eval_select; use crate::ops; use crate::ptr; #[stable(feature = "rust1", since = "1.0.0")] -impl ops::Index for [T] +#[rustc_const_unstable(feature = "const_slice_index_impls", issue = "none")] +impl const ops::Index for [T] where - I: SliceIndex<[T]>, + I: ~const SliceIndex<[T]>, { type Output = I::Output; @@ -17,9 +19,10 @@ where } #[stable(feature = "rust1", since = "1.0.0")] -impl ops::IndexMut for [T] +#[rustc_const_unstable(feature = "const_slice_index_impls", issue = "none")] +impl const ops::IndexMut for [T] where - I: SliceIndex<[T]>, + I: ~const SliceIndex<[T]>, { #[inline] fn index_mut(&mut self, index: I) -> &mut I::Output { @@ -27,35 +30,73 @@ where } } + #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))] #[cfg_attr(feature = "panic_immediate_abort", inline)] #[cold] #[track_caller] -fn slice_start_index_len_fail(index: usize, len: usize) -> ! { +#[rustc_const_unstable(feature = "const_slice_index_impls", issue = "none")] +const fn slice_start_index_len_fail(index: usize, len: usize) -> ! { + // SAFETY: we are just panicking here + unsafe { + const_eval_select((index, len), slice_start_index_len_fail_ct, slice_start_index_len_fail_rt) + } +} + +// FIXME const-hack +fn slice_start_index_len_fail_rt(index: usize, len: usize) -> ! { panic!("range start index {} out of range for slice of length {}", index, len); } +const fn slice_start_index_len_fail_ct(_: usize, _: usize) -> ! { + panic!("slice start index is out of range for slice"); +} + #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))] #[cfg_attr(feature = "panic_immediate_abort", inline)] #[cold] #[track_caller] -fn slice_end_index_len_fail(index: usize, len: usize) -> ! { +#[rustc_const_unstable(feature = "const_slice_index_impls", issue = "none")] +const fn slice_end_index_len_fail(index: usize, len: usize) -> ! { + // SAFETY: we are just panicking here + unsafe { + const_eval_select((index, len), slice_end_index_len_fail_ct, slice_end_index_len_fail_rt) + } +} + +// FIXME const-hack +fn slice_end_index_len_fail_rt(index: usize, len: usize) -> ! { panic!("range end index {} out of range for slice of length {}", index, len); } +const fn slice_end_index_len_fail_ct(_: usize, _: usize) -> ! { + panic!("slice end index is out of range for slice"); +} + #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))] #[cfg_attr(feature = "panic_immediate_abort", inline)] #[cold] #[track_caller] -fn slice_index_order_fail(index: usize, end: usize) -> ! { +#[rustc_const_unstable(feature = "const_slice_index_impls", issue = "none")] +const fn slice_index_order_fail(index: usize, end: usize) -> ! { + // SAFETY: we are just panicking here + unsafe { const_eval_select((index, end), slice_index_order_fail_ct, slice_index_order_fail_rt) } +} + +// FIXME const-hack +fn slice_index_order_fail_rt(index: usize, end: usize) -> ! { panic!("slice index starts at {} but ends at {}", index, end); } +const fn slice_index_order_fail_ct(_: usize, _: usize) -> ! { + panic!("slice index start is larger than end"); +} + #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))] #[cfg_attr(feature = "panic_immediate_abort", inline)] #[cold] #[track_caller] -fn slice_start_index_overflow_fail() -> ! { +const fn slice_start_index_overflow_fail() -> ! { panic!("attempted to index slice from after maximum usize"); } @@ -63,7 +104,7 @@ fn slice_start_index_overflow_fail() -> ! { #[cfg_attr(feature = "panic_immediate_abort", inline)] #[cold] #[track_caller] -fn slice_end_index_overflow_fail() -> ! { +const fn slice_end_index_overflow_fail() -> ! { panic!("attempted to index slice up to maximum usize"); } @@ -153,7 +194,8 @@ pub unsafe trait SliceIndex: private_slice_index::Sealed { } #[stable(feature = "slice_get_slice_impls", since = "1.15.0")] -unsafe impl SliceIndex<[T]> for usize { +#[rustc_const_unstable(feature = "const_slice_index_impls", issue = "none")] +unsafe impl const SliceIndex<[T]> for usize { type Output = T; #[inline] @@ -197,7 +239,8 @@ unsafe impl SliceIndex<[T]> for usize { } #[stable(feature = "slice_get_slice_impls", since = "1.15.0")] -unsafe impl SliceIndex<[T]> for ops::Range { +#[rustc_const_unstable(feature = "const_slice_index_impls", issue = "none")] +unsafe impl const SliceIndex<[T]> for ops::Range { type Output = [T]; #[inline] @@ -261,7 +304,8 @@ unsafe impl SliceIndex<[T]> for ops::Range { } #[stable(feature = "slice_get_slice_impls", since = "1.15.0")] -unsafe impl SliceIndex<[T]> for ops::RangeTo { +#[rustc_const_unstable(feature = "const_slice_index_impls", issue = "none")] +unsafe impl const SliceIndex<[T]> for ops::RangeTo { type Output = [T]; #[inline] @@ -298,7 +342,8 @@ unsafe impl SliceIndex<[T]> for ops::RangeTo { } #[stable(feature = "slice_get_slice_impls", since = "1.15.0")] -unsafe impl SliceIndex<[T]> for ops::RangeFrom { +#[rustc_const_unstable(feature = "const_slice_index_impls", issue = "none")] +unsafe impl const SliceIndex<[T]> for ops::RangeFrom { type Output = [T]; #[inline] @@ -343,7 +388,8 @@ unsafe impl SliceIndex<[T]> for ops::RangeFrom { } #[stable(feature = "slice_get_slice_impls", since = "1.15.0")] -unsafe impl SliceIndex<[T]> for ops::RangeFull { +#[rustc_const_unstable(feature = "const_slice_index_impls", issue = "none")] +unsafe impl const SliceIndex<[T]> for ops::RangeFull { type Output = [T]; #[inline] @@ -378,7 +424,8 @@ unsafe impl SliceIndex<[T]> for ops::RangeFull { } #[stable(feature = "inclusive_range", since = "1.26.0")] -unsafe impl SliceIndex<[T]> for ops::RangeInclusive { +#[rustc_const_unstable(feature = "const_slice_index_impls", issue = "none")] +unsafe impl const SliceIndex<[T]> for ops::RangeInclusive { type Output = [T]; #[inline] @@ -421,7 +468,8 @@ unsafe impl SliceIndex<[T]> for ops::RangeInclusive { } #[stable(feature = "inclusive_range", since = "1.26.0")] -unsafe impl SliceIndex<[T]> for ops::RangeToInclusive { +#[rustc_const_unstable(feature = "const_slice_index_impls", issue = "none")] +unsafe impl const SliceIndex<[T]> for ops::RangeToInclusive { type Output = [T]; #[inline] From 4654a910018cf0447db1edb2a46a0cae5f7dff8e Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Sun, 6 Mar 2022 14:00:12 +1100 Subject: [PATCH 05/28] Constify slice index for strings --- library/core/src/array/mod.rs | 10 +++++---- library/core/src/lib.rs | 3 ++- library/core/src/num/mod.rs | 2 +- library/core/src/ptr/const_ptr.rs | 5 +++-- library/core/src/ptr/mut_ptr.rs | 5 +++-- library/core/src/ptr/non_null.rs | 5 +++-- library/core/src/slice/index.rs | 31 +++++++++++++------------ library/core/src/slice/mod.rs | 20 ++++++++++------- library/core/src/str/mod.rs | 36 +++++++++++++++++++++++++----- library/core/src/str/traits.rs | 30 ++++++++++++++++--------- src/test/ui/str/str-idx.stderr | 8 +++---- src/test/ui/str/str-mut-idx.stderr | 8 +++---- 12 files changed, 104 insertions(+), 59 deletions(-) diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs index ee79021ed536e..20dfbc6347c4f 100644 --- a/library/core/src/array/mod.rs +++ b/library/core/src/array/mod.rs @@ -276,9 +276,10 @@ impl<'a, T, const N: usize> IntoIterator for &'a mut [T; N] { } #[stable(feature = "index_trait_on_arrays", since = "1.50.0")] -impl Index for [T; N] +#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] +impl const Index for [T; N] where - [T]: Index, + [T]: ~const Index, { type Output = <[T] as Index>::Output; @@ -289,9 +290,10 @@ where } #[stable(feature = "index_trait_on_arrays", since = "1.50.0")] -impl IndexMut for [T; N] +#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] +impl const IndexMut for [T; N] where - [T]: IndexMut, + [T]: ~const IndexMut, { #[inline] fn index_mut(&mut self, index: I) -> &mut Self::Output { diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index bad3fb0765c7b..674e165455916 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -148,7 +148,8 @@ #![feature(variant_count)] #![feature(const_array_from_ref)] #![feature(const_slice_from_ref)] -#![feature(const_slice_index_impls)] +#![feature(const_slice_index)] +#![feature(const_is_char_boundary)] // // Language features: #![feature(abi_unadjusted)] diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs index 72105888f9447..07fd317e07486 100644 --- a/library/core/src/num/mod.rs +++ b/library/core/src/num/mod.rs @@ -809,7 +809,7 @@ impl u8 { ascii::escape_default(self) } - pub(crate) fn is_utf8_char_boundary(self) -> bool { + pub(crate) const fn is_utf8_char_boundary(self) -> bool { // This is bit magic equivalent to: b < 128 || b >= 192 (self as i8) >= -0x40 } diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index 485a5965f4cf7..ee544b4842e86 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -1032,10 +1032,11 @@ impl *const [T] { /// } /// ``` #[unstable(feature = "slice_ptr_get", issue = "74265")] + #[rustc_const_unstable(feature = "const_slice_index", issue = "none")] #[inline] - pub unsafe fn get_unchecked(self, index: I) -> *const I::Output + pub const unsafe fn get_unchecked(self, index: I) -> *const I::Output where - I: SliceIndex<[T]>, + I: ~const SliceIndex<[T]>, { // SAFETY: the caller ensures that `self` is dereferenceable and `index` in-bounds. unsafe { index.get_unchecked(self) } diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index 1412e836ebfc2..3374b48c88c6b 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -1302,10 +1302,11 @@ impl *mut [T] { /// } /// ``` #[unstable(feature = "slice_ptr_get", issue = "74265")] + #[rustc_const_unstable(feature = "const_slice_index", issue = "none")] #[inline(always)] - pub unsafe fn get_unchecked_mut(self, index: I) -> *mut I::Output + pub const unsafe fn get_unchecked_mut(self, index: I) -> *mut I::Output where - I: SliceIndex<[T]>, + I: ~const SliceIndex<[T]>, { // SAFETY: the caller ensures that `self` is dereferenceable and `index` in-bounds. unsafe { index.get_unchecked_mut(self) } diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs index 0aa8e9960a8dd..897609410dac4 100644 --- a/library/core/src/ptr/non_null.rs +++ b/library/core/src/ptr/non_null.rs @@ -630,10 +630,11 @@ impl NonNull<[T]> { /// } /// ``` #[unstable(feature = "slice_ptr_get", issue = "74265")] + #[rustc_const_unstable(feature = "const_slice_index", issue = "none")] #[inline] - pub unsafe fn get_unchecked_mut(self, index: I) -> NonNull + pub const unsafe fn get_unchecked_mut(self, index: I) -> NonNull where - I: SliceIndex<[T]>, + I: ~const SliceIndex<[T]>, { // SAFETY: the caller ensures that `self` is dereferenceable and `index` in-bounds. // As a consequence, the resulting pointer cannot be null. diff --git a/library/core/src/slice/index.rs b/library/core/src/slice/index.rs index 3931c123352ce..7e6fbbe353889 100644 --- a/library/core/src/slice/index.rs +++ b/library/core/src/slice/index.rs @@ -5,7 +5,7 @@ use crate::ops; use crate::ptr; #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_const_unstable(feature = "const_slice_index_impls", issue = "none")] +#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] impl const ops::Index for [T] where I: ~const SliceIndex<[T]>, @@ -19,7 +19,7 @@ where } #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_const_unstable(feature = "const_slice_index_impls", issue = "none")] +#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] impl const ops::IndexMut for [T] where I: ~const SliceIndex<[T]>, @@ -30,16 +30,19 @@ where } } - #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))] #[cfg_attr(feature = "panic_immediate_abort", inline)] #[cold] #[track_caller] -#[rustc_const_unstable(feature = "const_slice_index_impls", issue = "none")] +#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] const fn slice_start_index_len_fail(index: usize, len: usize) -> ! { // SAFETY: we are just panicking here unsafe { - const_eval_select((index, len), slice_start_index_len_fail_ct, slice_start_index_len_fail_rt) + const_eval_select( + (index, len), + slice_start_index_len_fail_ct, + slice_start_index_len_fail_rt, + ) } } @@ -56,7 +59,7 @@ const fn slice_start_index_len_fail_ct(_: usize, _: usize) -> ! { #[cfg_attr(feature = "panic_immediate_abort", inline)] #[cold] #[track_caller] -#[rustc_const_unstable(feature = "const_slice_index_impls", issue = "none")] +#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] const fn slice_end_index_len_fail(index: usize, len: usize) -> ! { // SAFETY: we are just panicking here unsafe { @@ -77,7 +80,7 @@ const fn slice_end_index_len_fail_ct(_: usize, _: usize) -> ! { #[cfg_attr(feature = "panic_immediate_abort", inline)] #[cold] #[track_caller] -#[rustc_const_unstable(feature = "const_slice_index_impls", issue = "none")] +#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] const fn slice_index_order_fail(index: usize, end: usize) -> ! { // SAFETY: we are just panicking here unsafe { const_eval_select((index, end), slice_index_order_fail_ct, slice_index_order_fail_rt) } @@ -194,7 +197,7 @@ pub unsafe trait SliceIndex: private_slice_index::Sealed { } #[stable(feature = "slice_get_slice_impls", since = "1.15.0")] -#[rustc_const_unstable(feature = "const_slice_index_impls", issue = "none")] +#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] unsafe impl const SliceIndex<[T]> for usize { type Output = T; @@ -239,7 +242,7 @@ unsafe impl const SliceIndex<[T]> for usize { } #[stable(feature = "slice_get_slice_impls", since = "1.15.0")] -#[rustc_const_unstable(feature = "const_slice_index_impls", issue = "none")] +#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] unsafe impl const SliceIndex<[T]> for ops::Range { type Output = [T]; @@ -304,7 +307,7 @@ unsafe impl const SliceIndex<[T]> for ops::Range { } #[stable(feature = "slice_get_slice_impls", since = "1.15.0")] -#[rustc_const_unstable(feature = "const_slice_index_impls", issue = "none")] +#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] unsafe impl const SliceIndex<[T]> for ops::RangeTo { type Output = [T]; @@ -342,7 +345,7 @@ unsafe impl const SliceIndex<[T]> for ops::RangeTo { } #[stable(feature = "slice_get_slice_impls", since = "1.15.0")] -#[rustc_const_unstable(feature = "const_slice_index_impls", issue = "none")] +#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] unsafe impl const SliceIndex<[T]> for ops::RangeFrom { type Output = [T]; @@ -388,7 +391,7 @@ unsafe impl const SliceIndex<[T]> for ops::RangeFrom { } #[stable(feature = "slice_get_slice_impls", since = "1.15.0")] -#[rustc_const_unstable(feature = "const_slice_index_impls", issue = "none")] +#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] unsafe impl const SliceIndex<[T]> for ops::RangeFull { type Output = [T]; @@ -424,7 +427,7 @@ unsafe impl const SliceIndex<[T]> for ops::RangeFull { } #[stable(feature = "inclusive_range", since = "1.26.0")] -#[rustc_const_unstable(feature = "const_slice_index_impls", issue = "none")] +#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] unsafe impl const SliceIndex<[T]> for ops::RangeInclusive { type Output = [T]; @@ -468,7 +471,7 @@ unsafe impl const SliceIndex<[T]> for ops::RangeInclusive { } #[stable(feature = "inclusive_range", since = "1.26.0")] -#[rustc_const_unstable(feature = "const_slice_index_impls", issue = "none")] +#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] unsafe impl const SliceIndex<[T]> for ops::RangeToInclusive { type Output = [T]; diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index cd38c3a75473d..ea03dc9de9ec3 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -321,10 +321,11 @@ impl [T] { /// assert_eq!(None, v.get(0..4)); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_slice_index", issue = "none")] #[inline] - pub fn get(&self, index: I) -> Option<&I::Output> + pub const fn get(&self, index: I) -> Option<&I::Output> where - I: SliceIndex, + I: ~const SliceIndex, { index.get(self) } @@ -345,10 +346,11 @@ impl [T] { /// assert_eq!(x, &[0, 42, 2]); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_slice_index", issue = "none")] #[inline] - pub fn get_mut(&mut self, index: I) -> Option<&mut I::Output> + pub const fn get_mut(&mut self, index: I) -> Option<&mut I::Output> where - I: SliceIndex, + I: ~const SliceIndex, { index.get_mut(self) } @@ -376,10 +378,11 @@ impl [T] { /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_slice_index", issue = "none")] #[inline] - pub unsafe fn get_unchecked(&self, index: I) -> &I::Output + pub const unsafe fn get_unchecked(&self, index: I) -> &I::Output where - I: SliceIndex, + I: ~const SliceIndex, { // SAFETY: the caller must uphold most of the safety requirements for `get_unchecked`; // the slice is dereferenceable because `self` is a safe reference. @@ -412,10 +415,11 @@ impl [T] { /// assert_eq!(x, &[1, 13, 4]); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_slice_index", issue = "none")] #[inline] - pub unsafe fn get_unchecked_mut(&mut self, index: I) -> &mut I::Output + pub const unsafe fn get_unchecked_mut(&mut self, index: I) -> &mut I::Output where - I: SliceIndex, + I: ~const SliceIndex, { // SAFETY: the caller must uphold the safety requirements for `get_unchecked_mut`; // the slice is dereferenceable because `self` is a safe reference. diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs index 09709dc3cf6df..f66bab999a98a 100644 --- a/library/core/src/str/mod.rs +++ b/library/core/src/str/mod.rs @@ -79,7 +79,23 @@ use iter::{MatchesInternal, SplitNInternal}; #[inline(never)] #[cold] #[track_caller] -fn slice_error_fail(s: &str, begin: usize, end: usize) -> ! { +#[rustc_allow_const_fn_unstable(const_eval_select)] +const fn slice_error_fail(s: &str, begin: usize, end: usize) -> ! { + // SAFETY: panics for both branches + unsafe { + crate::intrinsics::const_eval_select( + (s, begin, end), + slice_error_fail_ct, + slice_error_fail_rt, + ) + } +} + +const fn slice_error_fail_ct(_: &str, _: usize, _: usize) -> ! { + panic!("failed to slice string"); +} + +fn slice_error_fail_rt(s: &str, begin: usize, end: usize) -> ! { const MAX_DISPLAY_LENGTH: usize = 256; let trunc_len = s.floor_char_boundary(MAX_DISPLAY_LENGTH); let s_trunc = &s[..trunc_len]; @@ -189,8 +205,9 @@ impl str { /// ``` #[must_use] #[stable(feature = "is_char_boundary", since = "1.9.0")] + #[rustc_const_unstable(feature = "const_is_char_boundary", issue = "none")] #[inline] - pub fn is_char_boundary(&self, index: usize) -> bool { + pub const fn is_char_boundary(&self, index: usize) -> bool { // 0 is always ok. // Test for 0 explicitly so that it can optimize out the check // easily and skip reading string data for that case. @@ -418,8 +435,9 @@ impl str { /// assert!(v.get(..42).is_none()); /// ``` #[stable(feature = "str_checked_slicing", since = "1.20.0")] + #[rustc_const_unstable(feature = "const_slice_index", issue = "none")] #[inline] - pub fn get>(&self, i: I) -> Option<&I::Output> { + pub const fn get>(&self, i: I) -> Option<&I::Output> { i.get(self) } @@ -450,8 +468,9 @@ impl str { /// assert_eq!("HEllo", v); /// ``` #[stable(feature = "str_checked_slicing", since = "1.20.0")] + #[rustc_const_unstable(feature = "const_slice_index", issue = "none")] #[inline] - pub fn get_mut>(&mut self, i: I) -> Option<&mut I::Output> { + pub const fn get_mut>(&mut self, i: I) -> Option<&mut I::Output> { i.get_mut(self) } @@ -482,8 +501,9 @@ impl str { /// } /// ``` #[stable(feature = "str_checked_slicing", since = "1.20.0")] + #[rustc_const_unstable(feature = "const_slice_index", issue = "none")] #[inline] - pub unsafe fn get_unchecked>(&self, i: I) -> &I::Output { + pub const unsafe fn get_unchecked>(&self, i: I) -> &I::Output { // SAFETY: the caller must uphold the safety contract for `get_unchecked`; // the slice is dereferenceable because `self` is a safe reference. // The returned pointer is safe because impls of `SliceIndex` have to guarantee that it is. @@ -517,8 +537,12 @@ impl str { /// } /// ``` #[stable(feature = "str_checked_slicing", since = "1.20.0")] + #[rustc_const_unstable(feature = "const_slice_index", issue = "none")] #[inline] - pub unsafe fn get_unchecked_mut>(&mut self, i: I) -> &mut I::Output { + pub const unsafe fn get_unchecked_mut>( + &mut self, + i: I, + ) -> &mut I::Output { // SAFETY: the caller must uphold the safety contract for `get_unchecked_mut`; // the slice is dereferenceable because `self` is a safe reference. // The returned pointer is safe because impls of `SliceIndex` have to guarantee that it is. diff --git a/library/core/src/str/traits.rs b/library/core/src/str/traits.rs index 952676247489f..8b6b4fa02f833 100644 --- a/library/core/src/str/traits.rs +++ b/library/core/src/str/traits.rs @@ -53,9 +53,10 @@ impl PartialOrd for str { } #[stable(feature = "rust1", since = "1.0.0")] -impl ops::Index for str +#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] +impl const ops::Index for str where - I: SliceIndex, + I: ~const SliceIndex, { type Output = I::Output; @@ -66,9 +67,10 @@ where } #[stable(feature = "rust1", since = "1.0.0")] -impl ops::IndexMut for str +#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] +impl const ops::IndexMut for str where - I: SliceIndex, + I: ~const SliceIndex, { #[inline] fn index_mut(&mut self, index: I) -> &mut I::Output { @@ -79,7 +81,7 @@ where #[inline(never)] #[cold] #[track_caller] -fn str_index_overflow_fail() -> ! { +const fn str_index_overflow_fail() -> ! { panic!("attempted to index str up to maximum usize"); } @@ -96,7 +98,8 @@ fn str_index_overflow_fail() -> ! { /// /// Equivalent to `&self[0 .. len]` or `&mut self[0 .. len]`. #[stable(feature = "str_checked_slicing", since = "1.20.0")] -unsafe impl SliceIndex for ops::RangeFull { +#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] +unsafe impl const SliceIndex for ops::RangeFull { type Output = str; #[inline] fn get(self, slice: &str) -> Option<&Self::Output> { @@ -160,7 +163,8 @@ unsafe impl SliceIndex for ops::RangeFull { /// // &s[3 .. 100]; /// ``` #[stable(feature = "str_checked_slicing", since = "1.20.0")] -unsafe impl SliceIndex for ops::Range { +#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] +unsafe impl const SliceIndex for ops::Range { type Output = str; #[inline] fn get(self, slice: &str) -> Option<&Self::Output> { @@ -247,7 +251,8 @@ unsafe impl SliceIndex for ops::Range { /// Panics if `end` does not point to the starting byte offset of a /// character (as defined by `is_char_boundary`), or if `end > len`. #[stable(feature = "str_checked_slicing", since = "1.20.0")] -unsafe impl SliceIndex for ops::RangeTo { +#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] +unsafe impl const SliceIndex for ops::RangeTo { type Output = str; #[inline] fn get(self, slice: &str) -> Option<&Self::Output> { @@ -317,7 +322,8 @@ unsafe impl SliceIndex for ops::RangeTo { /// Panics if `begin` does not point to the starting byte offset of /// a character (as defined by `is_char_boundary`), or if `begin > len`. #[stable(feature = "str_checked_slicing", since = "1.20.0")] -unsafe impl SliceIndex for ops::RangeFrom { +#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] +unsafe impl const SliceIndex for ops::RangeFrom { type Output = str; #[inline] fn get(self, slice: &str) -> Option<&Self::Output> { @@ -393,7 +399,8 @@ unsafe impl SliceIndex for ops::RangeFrom { /// to the ending byte offset of a character (`end + 1` is either a starting /// byte offset or equal to `len`), if `begin > end`, or if `end >= len`. #[stable(feature = "inclusive_range", since = "1.26.0")] -unsafe impl SliceIndex for ops::RangeInclusive { +#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] +unsafe impl const SliceIndex for ops::RangeInclusive { type Output = str; #[inline] fn get(self, slice: &str) -> Option<&Self::Output> { @@ -444,7 +451,8 @@ unsafe impl SliceIndex for ops::RangeInclusive { /// (`end + 1` is either a starting byte offset as defined by /// `is_char_boundary`, or equal to `len`), or if `end >= len`. #[stable(feature = "inclusive_range", since = "1.26.0")] -unsafe impl SliceIndex for ops::RangeToInclusive { +#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] +unsafe impl const SliceIndex for ops::RangeToInclusive { type Output = str; #[inline] fn get(self, slice: &str) -> Option<&Self::Output> { diff --git a/src/test/ui/str/str-idx.stderr b/src/test/ui/str/str-idx.stderr index 9c3c3646139dc..9ab409bbdcdf8 100644 --- a/src/test/ui/str/str-idx.stderr +++ b/src/test/ui/str/str-idx.stderr @@ -23,8 +23,8 @@ LL | let _ = s.get(4); note: required by a bound in `core::str::::get` --> $SRC_DIR/core/src/str/mod.rs:LL:COL | -LL | pub fn get>(&self, i: I) -> Option<&I::Output> { - | ^^^^^^^^^^^^^^^ required by this bound in `core::str::::get` +LL | pub const fn get>(&self, i: I) -> Option<&I::Output> { + | ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `core::str::::get` error[E0277]: the type `str` cannot be indexed by `{integer}` --> $DIR/str-idx.rs:5:29 @@ -40,8 +40,8 @@ LL | let _ = s.get_unchecked(4); note: required by a bound in `core::str::::get_unchecked` --> $SRC_DIR/core/src/str/mod.rs:LL:COL | -LL | pub unsafe fn get_unchecked>(&self, i: I) -> &I::Output { - | ^^^^^^^^^^^^^^^ required by this bound in `core::str::::get_unchecked` +LL | pub const unsafe fn get_unchecked>(&self, i: I) -> &I::Output { + | ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `core::str::::get_unchecked` error[E0277]: the type `str` cannot be indexed by `char` --> $DIR/str-idx.rs:6:17 diff --git a/src/test/ui/str/str-mut-idx.stderr b/src/test/ui/str/str-mut-idx.stderr index 2559ee9eb49b2..5956e363b0c09 100644 --- a/src/test/ui/str/str-mut-idx.stderr +++ b/src/test/ui/str/str-mut-idx.stderr @@ -47,8 +47,8 @@ LL | s.get_mut(1); note: required by a bound in `core::str::::get_mut` --> $SRC_DIR/core/src/str/mod.rs:LL:COL | -LL | pub fn get_mut>(&mut self, i: I) -> Option<&mut I::Output> { - | ^^^^^^^^^^^^^^^ required by this bound in `core::str::::get_mut` +LL | pub const fn get_mut>(&mut self, i: I) -> Option<&mut I::Output> { + | ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `core::str::::get_mut` error[E0277]: the type `str` cannot be indexed by `{integer}` --> $DIR/str-mut-idx.rs:11:25 @@ -64,8 +64,8 @@ LL | s.get_unchecked_mut(1); note: required by a bound in `core::str::::get_unchecked_mut` --> $SRC_DIR/core/src/str/mod.rs:LL:COL | -LL | pub unsafe fn get_unchecked_mut>(&mut self, i: I) -> &mut I::Output { - | ^^^^^^^^^^^^^^^ required by this bound in `core::str::::get_unchecked_mut` +LL | pub const unsafe fn get_unchecked_mut>( + | ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `core::str::::get_unchecked_mut` error[E0277]: the type `str` cannot be indexed by `char` --> $DIR/str-mut-idx.rs:13:5 From b328688d23d56a7b95ddcd994c3967a193dd25ea Mon Sep 17 00:00:00 2001 From: Jon Gjengset Date: Mon, 7 Mar 2022 16:59:10 -0800 Subject: [PATCH 06/28] Statically compile libstdc++ everywhere if asked PR #93918 made it so that `-static-libstdc++` was only set in one place, and was only set during linking, but accidentally also made it so that it is no longer passed when building LLD or sanitizers, only when building LLVM itself. This moves the logic for setting `-static-libstdc++` in the linker flags back to `configure_cmake` so that it takes effect for all CMake invocations in `native.rs`. As a side-effect, this also causes libstdc++ to be statically compiled into sanitizers and LLD if `llvm-tools-enabled` is set but `llvm-static-stdcpp` is not, even though previously it was only linked statically if `llvm-static-stdcpp` was set explicitly. But that seems more like the expected behavior anyway. --- src/bootstrap/native.rs | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs index f00c5ce5aa6f0..0fe39defae85d 100644 --- a/src/bootstrap/native.rs +++ b/src/bootstrap/native.rs @@ -259,18 +259,6 @@ impl Step for Llvm { cfg.define("LLVM_LINK_LLVM_DYLIB", "ON"); } - // For distribution we want the LLVM tools to be *statically* linked to libstdc++. - // We also do this if the user explicitly requested static libstdc++. - if builder.config.llvm_tools_enabled || builder.config.llvm_static_stdcpp { - if !target.contains("msvc") && !target.contains("netbsd") { - if target.contains("apple") { - ldflags.push_all("-static-libstdc++"); - } else { - ldflags.push_all("-Wl,-Bsymbolic -static-libstdc++"); - } - } - } - if target.starts_with("riscv") && !target.contains("freebsd") { // RISC-V GCC erroneously requires linking against // `libatomic` when using 1-byte and 2-byte C++ @@ -576,6 +564,18 @@ fn configure_cmake( ldflags.push_all(&flags); } + // For distribution we want the LLVM tools to be *statically* linked to libstdc++. + // We also do this if the user explicitly requested static libstdc++. + if builder.config.llvm_tools_enabled || builder.config.llvm_static_stdcpp { + if !target.contains("msvc") && !target.contains("netbsd") { + if target.contains("apple") { + ldflags.push_all("-static-libstdc++"); + } else { + ldflags.push_all("-Wl,-Bsymbolic -static-libstdc++"); + } + } + } + cfg.define("CMAKE_SHARED_LINKER_FLAGS", &ldflags.shared); cfg.define("CMAKE_MODULE_LINKER_FLAGS", &ldflags.module); cfg.define("CMAKE_EXE_LINKER_FLAGS", &ldflags.exe); From 0d92752b8aac53e033541d04fc7d9677d8bca227 Mon Sep 17 00:00:00 2001 From: Esteban Kuber Date: Tue, 8 Mar 2022 05:54:38 +0000 Subject: [PATCH 07/28] Suggest `if let`/`let_else` for refutable pat in `let` --- .../src/thir/pattern/check_match.rs | 86 +++++++++++++++++-- .../ui/consts/const-match-check.eval1.stderr | 10 ++- .../ui/consts/const-match-check.eval2.stderr | 10 ++- .../consts/const-match-check.matchck.stderr | 40 ++++++--- src/test/ui/empty/empty-never-array.stderr | 6 +- src/test/ui/error-codes/E0005.stderr | 8 +- .../feature-gate-exhaustive-patterns.stderr | 8 +- ...een-expanded-earlier-non-exhaustive.stderr | 10 ++- .../ui/pattern/usefulness/issue-31561.stderr | 8 +- .../non-exhaustive-defined-here.stderr | 36 +++++--- .../refutable-pattern-errors.stderr | 8 +- ...recursive-types-are-not-uninhabited.stderr | 6 +- .../ui/uninhabited/uninhabited-irrefutable.rs | 6 +- .../uninhabited-irrefutable.stderr | 12 ++- .../uninhabited-matches-feature-gated.stderr | 6 +- 15 files changed, 204 insertions(+), 56 deletions(-) diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index b80d2e52ee709..dae313da8d993 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -7,7 +7,8 @@ use super::{PatCtxt, PatternError}; use rustc_arena::TypedArena; use rustc_ast::Mutability; use rustc_errors::{ - error_code, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, + error_code, pluralize, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, + ErrorGuaranteed, }; use rustc_hir as hir; use rustc_hir::def::*; @@ -20,7 +21,7 @@ use rustc_session::lint::builtin::{ }; use rustc_session::Session; use rustc_span::source_map::Spanned; -use rustc_span::{DesugaringKind, ExpnKind, MultiSpan, Span}; +use rustc_span::{BytePos, DesugaringKind, ExpnKind, MultiSpan, Span}; crate fn check_match(tcx: TyCtxt<'_>, def_id: DefId) { let body_id = match def_id.as_local() { @@ -241,6 +242,9 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> { } let joined_patterns = joined_uncovered_patterns(&cx, &witnesses); + + let mut bindings = vec![]; + let mut err = struct_span_err!( self.tcx.sess, pat.span, @@ -257,6 +261,16 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> { false } _ => { + pat.walk(&mut |pat: &hir::Pat<'_>| { + match pat.kind { + hir::PatKind::Binding(_, _, ident, _) => { + bindings.push(ident); + } + _ => {} + } + true + }); + err.span_label(pat.span, pattern_not_covered_label(&witnesses, &joined_patterns)); true } @@ -267,13 +281,71 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> { "`let` bindings require an \"irrefutable pattern\", like a `struct` or \ an `enum` with only one variant", ); - if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) { - err.span_suggestion( - span, - "you might want to use `if let` to ignore the variant that isn't matched", - format!("if {} {{ /* */ }}", &snippet[..snippet.len() - 1]), + if self.tcx.sess.source_map().span_to_snippet(span).is_ok() { + let semi_span = span.shrink_to_hi().with_lo(span.hi() - BytePos(1)); + let start_span = span.shrink_to_lo(); + let end_span = semi_span.shrink_to_lo(); + err.multipart_suggestion( + &format!( + "you might want to use `if let` to ignore the variant{} that {} matched", + pluralize!(witnesses.len()), + match witnesses.len() { + 1 => "isn't", + _ => "aren't", + }, + ), + vec![ + match &bindings[..] { + [] => (start_span, "if ".to_string()), + [binding] => (start_span, format!("let {} = if ", binding)), + bindings => ( + start_span, + format!( + "let ({}) = if ", + bindings + .iter() + .map(|ident| ident.to_string()) + .collect::>() + .join(", ") + ), + ), + }, + match &bindings[..] { + [] => (semi_span, " { todo!() }".to_string()), + [binding] => { + (end_span, format!(" {{ {} }} else {{ todo!() }}", binding)) + } + bindings => ( + end_span, + format!( + " {{ ({}) }} else {{ todo!() }}", + bindings + .iter() + .map(|ident| ident.to_string()) + .collect::>() + .join(", ") + ), + ), + }, + ], Applicability::HasPlaceholders, ); + if cx.tcx.sess.is_nightly_build() { + err.span_suggestion_verbose( + semi_span.shrink_to_lo(), + &format!( + "alternatively, on nightly, you might want to use \ + `#![feature(let_else)]` to handle the variant{} that {} matched", + pluralize!(witnesses.len()), + match witnesses.len() { + 1 => "isn't", + _ => "aren't", + }, + ), + " else { todo!() }".to_string(), + Applicability::HasPlaceholders, + ); + } } err.note( "for more information, visit \ diff --git a/src/test/ui/consts/const-match-check.eval1.stderr b/src/test/ui/consts/const-match-check.eval1.stderr index 4141cc4ab1a48..08ee800f138d2 100644 --- a/src/test/ui/consts/const-match-check.eval1.stderr +++ b/src/test/ui/consts/const-match-check.eval1.stderr @@ -7,10 +7,14 @@ LL | A = { let 0 = 0; 0 }, = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html = note: the matched value is of type `i32` -help: you might want to use `if let` to ignore the variant that isn't matched +help: you might want to use `if let` to ignore the variants that aren't matched | -LL | A = { if let 0 = 0 { /* */ } 0 }, - | ~~~~~~~~~~~~~~~~~~~~~~ +LL | A = { if let 0 = 0 { todo!() } 0 }, + | ++ ~~~~~~~~~~~ +help: alternatively, on nightly, you might want to use `#![feature(let_else)]` to handle the variants that aren't matched + | +LL | A = { let 0 = 0 else { todo!() }; 0 }, + | ++++++++++++++++ error: aborting due to previous error diff --git a/src/test/ui/consts/const-match-check.eval2.stderr b/src/test/ui/consts/const-match-check.eval2.stderr index af86ba0cc82f8..579cb7e780007 100644 --- a/src/test/ui/consts/const-match-check.eval2.stderr +++ b/src/test/ui/consts/const-match-check.eval2.stderr @@ -7,10 +7,14 @@ LL | let x: [i32; { let 0 = 0; 0 }] = []; = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html = note: the matched value is of type `i32` -help: you might want to use `if let` to ignore the variant that isn't matched +help: you might want to use `if let` to ignore the variants that aren't matched | -LL | let x: [i32; { if let 0 = 0 { /* */ } 0 }] = []; - | ~~~~~~~~~~~~~~~~~~~~~~ +LL | let x: [i32; { if let 0 = 0 { todo!() } 0 }] = []; + | ++ ~~~~~~~~~~~ +help: alternatively, on nightly, you might want to use `#![feature(let_else)]` to handle the variants that aren't matched + | +LL | let x: [i32; { let 0 = 0 else { todo!() }; 0 }] = []; + | ++++++++++++++++ error: aborting due to previous error diff --git a/src/test/ui/consts/const-match-check.matchck.stderr b/src/test/ui/consts/const-match-check.matchck.stderr index f71490eba6135..f89bbc0d42234 100644 --- a/src/test/ui/consts/const-match-check.matchck.stderr +++ b/src/test/ui/consts/const-match-check.matchck.stderr @@ -7,10 +7,14 @@ LL | const X: i32 = { let 0 = 0; 0 }; = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html = note: the matched value is of type `i32` -help: you might want to use `if let` to ignore the variant that isn't matched +help: you might want to use `if let` to ignore the variants that aren't matched | -LL | const X: i32 = { if let 0 = 0 { /* */ } 0 }; - | ~~~~~~~~~~~~~~~~~~~~~~ +LL | const X: i32 = { if let 0 = 0 { todo!() } 0 }; + | ++ ~~~~~~~~~~~ +help: alternatively, on nightly, you might want to use `#![feature(let_else)]` to handle the variants that aren't matched + | +LL | const X: i32 = { let 0 = 0 else { todo!() }; 0 }; + | ++++++++++++++++ error[E0005]: refutable pattern in local binding: `i32::MIN..=-1_i32` and `1_i32..=i32::MAX` not covered --> $DIR/const-match-check.rs:8:23 @@ -21,10 +25,14 @@ LL | static Y: i32 = { let 0 = 0; 0 }; = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html = note: the matched value is of type `i32` -help: you might want to use `if let` to ignore the variant that isn't matched +help: you might want to use `if let` to ignore the variants that aren't matched + | +LL | static Y: i32 = { if let 0 = 0 { todo!() } 0 }; + | ++ ~~~~~~~~~~~ +help: alternatively, on nightly, you might want to use `#![feature(let_else)]` to handle the variants that aren't matched | -LL | static Y: i32 = { if let 0 = 0 { /* */ } 0 }; - | ~~~~~~~~~~~~~~~~~~~~~~ +LL | static Y: i32 = { let 0 = 0 else { todo!() }; 0 }; + | ++++++++++++++++ error[E0005]: refutable pattern in local binding: `i32::MIN..=-1_i32` and `1_i32..=i32::MAX` not covered --> $DIR/const-match-check.rs:13:26 @@ -35,10 +43,14 @@ LL | const X: i32 = { let 0 = 0; 0 }; = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html = note: the matched value is of type `i32` -help: you might want to use `if let` to ignore the variant that isn't matched +help: you might want to use `if let` to ignore the variants that aren't matched | -LL | const X: i32 = { if let 0 = 0 { /* */ } 0 }; - | ~~~~~~~~~~~~~~~~~~~~~~ +LL | const X: i32 = { if let 0 = 0 { todo!() } 0 }; + | ++ ~~~~~~~~~~~ +help: alternatively, on nightly, you might want to use `#![feature(let_else)]` to handle the variants that aren't matched + | +LL | const X: i32 = { let 0 = 0 else { todo!() }; 0 }; + | ++++++++++++++++ error[E0005]: refutable pattern in local binding: `i32::MIN..=-1_i32` and `1_i32..=i32::MAX` not covered --> $DIR/const-match-check.rs:19:26 @@ -49,10 +61,14 @@ LL | const X: i32 = { let 0 = 0; 0 }; = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html = note: the matched value is of type `i32` -help: you might want to use `if let` to ignore the variant that isn't matched +help: you might want to use `if let` to ignore the variants that aren't matched + | +LL | const X: i32 = { if let 0 = 0 { todo!() } 0 }; + | ++ ~~~~~~~~~~~ +help: alternatively, on nightly, you might want to use `#![feature(let_else)]` to handle the variants that aren't matched | -LL | const X: i32 = { if let 0 = 0 { /* */ } 0 }; - | ~~~~~~~~~~~~~~~~~~~~~~ +LL | const X: i32 = { let 0 = 0 else { todo!() }; 0 }; + | ++++++++++++++++ error: aborting due to 4 previous errors diff --git a/src/test/ui/empty/empty-never-array.stderr b/src/test/ui/empty/empty-never-array.stderr index 8dd0f377533ce..909aa73a74a38 100644 --- a/src/test/ui/empty/empty-never-array.stderr +++ b/src/test/ui/empty/empty-never-array.stderr @@ -16,8 +16,12 @@ LL | T(T, [!; 0]), = note: the matched value is of type `Helper` help: you might want to use `if let` to ignore the variant that isn't matched | -LL | if let Helper::U(u) = Helper::T(t, []) { /* */ } +LL | let u = if let Helper::U(u) = Helper::T(t, []) { u } else { todo!() }; + | ++++++++++ ++++++++++++++++++++++ +help: alternatively, on nightly, you might want to use `#![feature(let_else)]` to handle the variant that isn't matched | +LL | let Helper::U(u) = Helper::T(t, []) else { todo!() }; + | ++++++++++++++++ error: aborting due to previous error diff --git a/src/test/ui/error-codes/E0005.stderr b/src/test/ui/error-codes/E0005.stderr index 208c625a53e95..55b1112b5f8ec 100644 --- a/src/test/ui/error-codes/E0005.stderr +++ b/src/test/ui/error-codes/E0005.stderr @@ -22,8 +22,12 @@ LL | | } = note: the matched value is of type `Option` help: you might want to use `if let` to ignore the variant that isn't matched | -LL | if let Some(y) = x { /* */ } - | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +LL | let y = if let Some(y) = x { y } else { todo!() }; + | ++++++++++ ++++++++++++++++++++++ +help: alternatively, on nightly, you might want to use `#![feature(let_else)]` to handle the variant that isn't matched + | +LL | let Some(y) = x else { todo!() }; + | ++++++++++++++++ error: aborting due to previous error diff --git a/src/test/ui/feature-gates/feature-gate-exhaustive-patterns.stderr b/src/test/ui/feature-gates/feature-gate-exhaustive-patterns.stderr index c2ffda6bb72d2..21180f31bbd26 100644 --- a/src/test/ui/feature-gates/feature-gate-exhaustive-patterns.stderr +++ b/src/test/ui/feature-gates/feature-gate-exhaustive-patterns.stderr @@ -21,8 +21,12 @@ LL | | } = note: the matched value is of type `Result` help: you might want to use `if let` to ignore the variant that isn't matched | -LL | if let Ok(_x) = foo() { /* */ } - | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +LL | let _x = if let Ok(_x) = foo() { _x } else { todo!() }; + | +++++++++++ +++++++++++++++++++++++ +help: alternatively, on nightly, you might want to use `#![feature(let_else)]` to handle the variant that isn't matched + | +LL | let Ok(_x) = foo() else { todo!() }; + | ++++++++++++++++ error: aborting due to previous error diff --git a/src/test/ui/or-patterns/issue-69875-should-have-been-expanded-earlier-non-exhaustive.stderr b/src/test/ui/or-patterns/issue-69875-should-have-been-expanded-earlier-non-exhaustive.stderr index 37a35700b36d5..aa1aa4434c3fa 100644 --- a/src/test/ui/or-patterns/issue-69875-should-have-been-expanded-earlier-non-exhaustive.stderr +++ b/src/test/ui/or-patterns/issue-69875-should-have-been-expanded-earlier-non-exhaustive.stderr @@ -7,10 +7,14 @@ LL | let (0 | (1 | 2)) = 0; = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html = note: the matched value is of type `i32` -help: you might want to use `if let` to ignore the variant that isn't matched +help: you might want to use `if let` to ignore the variants that aren't matched | -LL | if let (0 | (1 | 2)) = 0 { /* */ } - | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +LL | if let (0 | (1 | 2)) = 0 { todo!() } + | ++ ~~~~~~~~~~~ +help: alternatively, on nightly, you might want to use `#![feature(let_else)]` to handle the variants that aren't matched + | +LL | let (0 | (1 | 2)) = 0 else { todo!() }; + | ++++++++++++++++ error[E0004]: non-exhaustive patterns: `i32::MIN..=-1_i32` and `3_i32..=i32::MAX` not covered --> $DIR/issue-69875-should-have-been-expanded-earlier-non-exhaustive.rs:3:11 diff --git a/src/test/ui/pattern/usefulness/issue-31561.stderr b/src/test/ui/pattern/usefulness/issue-31561.stderr index dffcfc016072f..9da6b5eeead23 100644 --- a/src/test/ui/pattern/usefulness/issue-31561.stderr +++ b/src/test/ui/pattern/usefulness/issue-31561.stderr @@ -17,10 +17,14 @@ LL | Bar, LL | Baz | ^^^ not covered = note: the matched value is of type `Thing` -help: you might want to use `if let` to ignore the variant that isn't matched +help: you might want to use `if let` to ignore the variants that aren't matched | -LL | if let Thing::Foo(y) = Thing::Foo(1) { /* */ } +LL | let y = if let Thing::Foo(y) = Thing::Foo(1) { y } else { todo!() }; + | ++++++++++ ++++++++++++++++++++++ +help: alternatively, on nightly, you might want to use `#![feature(let_else)]` to handle the variants that aren't matched | +LL | let Thing::Foo(y) = Thing::Foo(1) else { todo!() }; + | ++++++++++++++++ error: aborting due to previous error diff --git a/src/test/ui/pattern/usefulness/non-exhaustive-defined-here.stderr b/src/test/ui/pattern/usefulness/non-exhaustive-defined-here.stderr index 8f5adccea806d..f7dc070f80248 100644 --- a/src/test/ui/pattern/usefulness/non-exhaustive-defined-here.stderr +++ b/src/test/ui/pattern/usefulness/non-exhaustive-defined-here.stderr @@ -42,10 +42,14 @@ LL | B, LL | C | ^ not covered = note: the matched value is of type `E` -help: you might want to use `if let` to ignore the variant that isn't matched +help: you might want to use `if let` to ignore the variants that aren't matched + | +LL | if let E::A = e { todo!() } + | ++ ~~~~~~~~~~~ +help: alternatively, on nightly, you might want to use `#![feature(let_else)]` to handle the variants that aren't matched | -LL | if let E::A = e { /* */ } - | ~~~~~~~~~~~~~~~~~~~~~~~~~ +LL | let E::A = e else { todo!() }; + | ++++++++++++++++ error[E0004]: non-exhaustive patterns: `&B` and `&C` not covered --> $DIR/non-exhaustive-defined-here.rs:52:11 @@ -91,10 +95,14 @@ LL | B, LL | C | ^ not covered = note: the matched value is of type `&E` -help: you might want to use `if let` to ignore the variant that isn't matched +help: you might want to use `if let` to ignore the variants that aren't matched | -LL | if let E::A = e { /* */ } - | ~~~~~~~~~~~~~~~~~~~~~~~~~ +LL | if let E::A = e { todo!() } + | ++ ~~~~~~~~~~~ +help: alternatively, on nightly, you might want to use `#![feature(let_else)]` to handle the variants that aren't matched + | +LL | let E::A = e else { todo!() }; + | ++++++++++++++++ error[E0004]: non-exhaustive patterns: `&&mut &B` and `&&mut &C` not covered --> $DIR/non-exhaustive-defined-here.rs:66:11 @@ -140,10 +148,14 @@ LL | B, LL | C | ^ not covered = note: the matched value is of type `&&mut &E` -help: you might want to use `if let` to ignore the variant that isn't matched +help: you might want to use `if let` to ignore the variants that aren't matched | -LL | if let E::A = e { /* */ } +LL | if let E::A = e { todo!() } + | ++ ~~~~~~~~~~~ +help: alternatively, on nightly, you might want to use `#![feature(let_else)]` to handle the variants that aren't matched | +LL | let E::A = e else { todo!() }; + | ++++++++++++++++ error[E0004]: non-exhaustive patterns: `None` not covered --> $DIR/non-exhaustive-defined-here.rs:92:11 @@ -185,8 +197,12 @@ LL | None, = note: the matched value is of type `Opt` help: you might want to use `if let` to ignore the variant that isn't matched | -LL | if let Opt::Some(ref _x) = e { /* */ } - | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +LL | let _x = if let Opt::Some(ref _x) = e { _x } else { todo!() }; + | +++++++++++ +++++++++++++++++++++++ +help: alternatively, on nightly, you might want to use `#![feature(let_else)]` to handle the variant that isn't matched + | +LL | let Opt::Some(ref _x) = e else { todo!() }; + | ++++++++++++++++ error: aborting due to 8 previous errors diff --git a/src/test/ui/pattern/usefulness/refutable-pattern-errors.stderr b/src/test/ui/pattern/usefulness/refutable-pattern-errors.stderr index 74ec646e31cca..e3ffc092327ac 100644 --- a/src/test/ui/pattern/usefulness/refutable-pattern-errors.stderr +++ b/src/test/ui/pattern/usefulness/refutable-pattern-errors.stderr @@ -15,10 +15,14 @@ LL | let (1, (Some(1), 2..=3)) = (1, (None, 2)); = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html = note: the matched value is of type `(i32, (Option, i32))` -help: you might want to use `if let` to ignore the variant that isn't matched +help: you might want to use `if let` to ignore the variants that aren't matched | -LL | if let (1, (Some(1), 2..=3)) = (1, (None, 2)) { /* */ } +LL | if let (1, (Some(1), 2..=3)) = (1, (None, 2)) { todo!() } + | ++ ~~~~~~~~~~~ +help: alternatively, on nightly, you might want to use `#![feature(let_else)]` to handle the variants that aren't matched | +LL | let (1, (Some(1), 2..=3)) = (1, (None, 2)) else { todo!() }; + | ++++++++++++++++ error: aborting due to 2 previous errors diff --git a/src/test/ui/recursion/recursive-types-are-not-uninhabited.stderr b/src/test/ui/recursion/recursive-types-are-not-uninhabited.stderr index ded3cf3ad1d44..a9159562d9d51 100644 --- a/src/test/ui/recursion/recursive-types-are-not-uninhabited.stderr +++ b/src/test/ui/recursion/recursive-types-are-not-uninhabited.stderr @@ -21,8 +21,12 @@ LL | | } = note: the matched value is of type `Result` help: you might want to use `if let` to ignore the variant that isn't matched | -LL | if let Ok(x) = res { /* */ } +LL | let x = if let Ok(x) = res { x } else { todo!() }; + | ++++++++++ ++++++++++++++++++++++ +help: alternatively, on nightly, you might want to use `#![feature(let_else)]` to handle the variant that isn't matched | +LL | let Ok(x) = res else { todo!() }; + | ++++++++++++++++ error: aborting due to previous error diff --git a/src/test/ui/uninhabited/uninhabited-irrefutable.rs b/src/test/ui/uninhabited/uninhabited-irrefutable.rs index 48cd92719b49a..661b5486adc12 100644 --- a/src/test/ui/uninhabited/uninhabited-irrefutable.rs +++ b/src/test/ui/uninhabited/uninhabited-irrefutable.rs @@ -19,10 +19,10 @@ enum Foo { A(foo::SecretlyEmpty), B(foo::NotSoSecretlyEmpty), C(NotSoSecretlyEmpty), - D(u32), + D(u32, u32), } fn main() { - let x: Foo = Foo::D(123); - let Foo::D(_y) = x; //~ ERROR refutable pattern in local binding: `A(_)` not covered + let x: Foo = Foo::D(123, 456); + let Foo::D(_y, _z) = x; //~ ERROR refutable pattern in local binding: `A(_)` not covered } diff --git a/src/test/ui/uninhabited/uninhabited-irrefutable.stderr b/src/test/ui/uninhabited/uninhabited-irrefutable.stderr index ad19c34a40a11..c571e17a7b372 100644 --- a/src/test/ui/uninhabited/uninhabited-irrefutable.stderr +++ b/src/test/ui/uninhabited/uninhabited-irrefutable.stderr @@ -1,8 +1,8 @@ error[E0005]: refutable pattern in local binding: `A(_)` not covered --> $DIR/uninhabited-irrefutable.rs:27:9 | -LL | let Foo::D(_y) = x; - | ^^^^^^^^^^ pattern `A(_)` not covered +LL | let Foo::D(_y, _z) = x; + | ^^^^^^^^^^^^^^ pattern `A(_)` not covered | = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html @@ -16,8 +16,12 @@ LL | A(foo::SecretlyEmpty), = note: the matched value is of type `Foo` help: you might want to use `if let` to ignore the variant that isn't matched | -LL | if let Foo::D(_y) = x { /* */ } - | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +LL | let (_y, _z) = if let Foo::D(_y, _z) = x { (_y, _z) } else { todo!() }; + | +++++++++++++++++ +++++++++++++++++++++++++++++ +help: alternatively, on nightly, you might want to use `#![feature(let_else)]` to handle the variant that isn't matched + | +LL | let Foo::D(_y, _z) = x else { todo!() }; + | ++++++++++++++++ error: aborting due to previous error diff --git a/src/test/ui/uninhabited/uninhabited-matches-feature-gated.stderr b/src/test/ui/uninhabited/uninhabited-matches-feature-gated.stderr index d90075d82f47b..74216d265d034 100644 --- a/src/test/ui/uninhabited/uninhabited-matches-feature-gated.stderr +++ b/src/test/ui/uninhabited/uninhabited-matches-feature-gated.stderr @@ -132,8 +132,12 @@ LL | | } = note: the matched value is of type `Result` help: you might want to use `if let` to ignore the variant that isn't matched | -LL | if let Ok(x) = x { /* */ } +LL | let x = if let Ok(x) = x { x } else { todo!() }; + | ++++++++++ ++++++++++++++++++++++ +help: alternatively, on nightly, you might want to use `#![feature(let_else)]` to handle the variant that isn't matched | +LL | let Ok(x) = x else { todo!() }; + | ++++++++++++++++ error: aborting due to 7 previous errors From c3a998e82a50b66e8f6f97170cd9117fadf03618 Mon Sep 17 00:00:00 2001 From: Esteban Kuber Date: Tue, 8 Mar 2022 17:20:05 +0000 Subject: [PATCH 08/28] Do not suggest `let_else` if no bindings would be introduced --- .../src/thir/pattern/check_match.rs | 2 +- .../ui/consts/const-match-check.eval1.stderr | 4 ---- .../ui/consts/const-match-check.eval2.stderr | 4 ---- .../ui/consts/const-match-check.matchck.stderr | 16 ---------------- ...e-been-expanded-earlier-non-exhaustive.stderr | 4 ---- .../non-exhaustive-defined-here.stderr | 12 ------------ .../usefulness/refutable-pattern-errors.stderr | 4 ---- 7 files changed, 1 insertion(+), 45 deletions(-) diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index dae313da8d993..c94da838680e0 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -330,7 +330,7 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> { ], Applicability::HasPlaceholders, ); - if cx.tcx.sess.is_nightly_build() { + if !bindings.is_empty() && cx.tcx.sess.is_nightly_build() { err.span_suggestion_verbose( semi_span.shrink_to_lo(), &format!( diff --git a/src/test/ui/consts/const-match-check.eval1.stderr b/src/test/ui/consts/const-match-check.eval1.stderr index 08ee800f138d2..6e61dbbd8eee3 100644 --- a/src/test/ui/consts/const-match-check.eval1.stderr +++ b/src/test/ui/consts/const-match-check.eval1.stderr @@ -11,10 +11,6 @@ help: you might want to use `if let` to ignore the variants that aren't matched | LL | A = { if let 0 = 0 { todo!() } 0 }, | ++ ~~~~~~~~~~~ -help: alternatively, on nightly, you might want to use `#![feature(let_else)]` to handle the variants that aren't matched - | -LL | A = { let 0 = 0 else { todo!() }; 0 }, - | ++++++++++++++++ error: aborting due to previous error diff --git a/src/test/ui/consts/const-match-check.eval2.stderr b/src/test/ui/consts/const-match-check.eval2.stderr index 579cb7e780007..1b3b6e06c3df6 100644 --- a/src/test/ui/consts/const-match-check.eval2.stderr +++ b/src/test/ui/consts/const-match-check.eval2.stderr @@ -11,10 +11,6 @@ help: you might want to use `if let` to ignore the variants that aren't matched | LL | let x: [i32; { if let 0 = 0 { todo!() } 0 }] = []; | ++ ~~~~~~~~~~~ -help: alternatively, on nightly, you might want to use `#![feature(let_else)]` to handle the variants that aren't matched - | -LL | let x: [i32; { let 0 = 0 else { todo!() }; 0 }] = []; - | ++++++++++++++++ error: aborting due to previous error diff --git a/src/test/ui/consts/const-match-check.matchck.stderr b/src/test/ui/consts/const-match-check.matchck.stderr index f89bbc0d42234..bc8edfa7af9f4 100644 --- a/src/test/ui/consts/const-match-check.matchck.stderr +++ b/src/test/ui/consts/const-match-check.matchck.stderr @@ -11,10 +11,6 @@ help: you might want to use `if let` to ignore the variants that aren't matched | LL | const X: i32 = { if let 0 = 0 { todo!() } 0 }; | ++ ~~~~~~~~~~~ -help: alternatively, on nightly, you might want to use `#![feature(let_else)]` to handle the variants that aren't matched - | -LL | const X: i32 = { let 0 = 0 else { todo!() }; 0 }; - | ++++++++++++++++ error[E0005]: refutable pattern in local binding: `i32::MIN..=-1_i32` and `1_i32..=i32::MAX` not covered --> $DIR/const-match-check.rs:8:23 @@ -29,10 +25,6 @@ help: you might want to use `if let` to ignore the variants that aren't matched | LL | static Y: i32 = { if let 0 = 0 { todo!() } 0 }; | ++ ~~~~~~~~~~~ -help: alternatively, on nightly, you might want to use `#![feature(let_else)]` to handle the variants that aren't matched - | -LL | static Y: i32 = { let 0 = 0 else { todo!() }; 0 }; - | ++++++++++++++++ error[E0005]: refutable pattern in local binding: `i32::MIN..=-1_i32` and `1_i32..=i32::MAX` not covered --> $DIR/const-match-check.rs:13:26 @@ -47,10 +39,6 @@ help: you might want to use `if let` to ignore the variants that aren't matched | LL | const X: i32 = { if let 0 = 0 { todo!() } 0 }; | ++ ~~~~~~~~~~~ -help: alternatively, on nightly, you might want to use `#![feature(let_else)]` to handle the variants that aren't matched - | -LL | const X: i32 = { let 0 = 0 else { todo!() }; 0 }; - | ++++++++++++++++ error[E0005]: refutable pattern in local binding: `i32::MIN..=-1_i32` and `1_i32..=i32::MAX` not covered --> $DIR/const-match-check.rs:19:26 @@ -65,10 +53,6 @@ help: you might want to use `if let` to ignore the variants that aren't matched | LL | const X: i32 = { if let 0 = 0 { todo!() } 0 }; | ++ ~~~~~~~~~~~ -help: alternatively, on nightly, you might want to use `#![feature(let_else)]` to handle the variants that aren't matched - | -LL | const X: i32 = { let 0 = 0 else { todo!() }; 0 }; - | ++++++++++++++++ error: aborting due to 4 previous errors diff --git a/src/test/ui/or-patterns/issue-69875-should-have-been-expanded-earlier-non-exhaustive.stderr b/src/test/ui/or-patterns/issue-69875-should-have-been-expanded-earlier-non-exhaustive.stderr index aa1aa4434c3fa..95b22ac059482 100644 --- a/src/test/ui/or-patterns/issue-69875-should-have-been-expanded-earlier-non-exhaustive.stderr +++ b/src/test/ui/or-patterns/issue-69875-should-have-been-expanded-earlier-non-exhaustive.stderr @@ -11,10 +11,6 @@ help: you might want to use `if let` to ignore the variants that aren't matched | LL | if let (0 | (1 | 2)) = 0 { todo!() } | ++ ~~~~~~~~~~~ -help: alternatively, on nightly, you might want to use `#![feature(let_else)]` to handle the variants that aren't matched - | -LL | let (0 | (1 | 2)) = 0 else { todo!() }; - | ++++++++++++++++ error[E0004]: non-exhaustive patterns: `i32::MIN..=-1_i32` and `3_i32..=i32::MAX` not covered --> $DIR/issue-69875-should-have-been-expanded-earlier-non-exhaustive.rs:3:11 diff --git a/src/test/ui/pattern/usefulness/non-exhaustive-defined-here.stderr b/src/test/ui/pattern/usefulness/non-exhaustive-defined-here.stderr index f7dc070f80248..0f06c31c468b1 100644 --- a/src/test/ui/pattern/usefulness/non-exhaustive-defined-here.stderr +++ b/src/test/ui/pattern/usefulness/non-exhaustive-defined-here.stderr @@ -46,10 +46,6 @@ help: you might want to use `if let` to ignore the variants that aren't matched | LL | if let E::A = e { todo!() } | ++ ~~~~~~~~~~~ -help: alternatively, on nightly, you might want to use `#![feature(let_else)]` to handle the variants that aren't matched - | -LL | let E::A = e else { todo!() }; - | ++++++++++++++++ error[E0004]: non-exhaustive patterns: `&B` and `&C` not covered --> $DIR/non-exhaustive-defined-here.rs:52:11 @@ -99,10 +95,6 @@ help: you might want to use `if let` to ignore the variants that aren't matched | LL | if let E::A = e { todo!() } | ++ ~~~~~~~~~~~ -help: alternatively, on nightly, you might want to use `#![feature(let_else)]` to handle the variants that aren't matched - | -LL | let E::A = e else { todo!() }; - | ++++++++++++++++ error[E0004]: non-exhaustive patterns: `&&mut &B` and `&&mut &C` not covered --> $DIR/non-exhaustive-defined-here.rs:66:11 @@ -152,10 +144,6 @@ help: you might want to use `if let` to ignore the variants that aren't matched | LL | if let E::A = e { todo!() } | ++ ~~~~~~~~~~~ -help: alternatively, on nightly, you might want to use `#![feature(let_else)]` to handle the variants that aren't matched - | -LL | let E::A = e else { todo!() }; - | ++++++++++++++++ error[E0004]: non-exhaustive patterns: `None` not covered --> $DIR/non-exhaustive-defined-here.rs:92:11 diff --git a/src/test/ui/pattern/usefulness/refutable-pattern-errors.stderr b/src/test/ui/pattern/usefulness/refutable-pattern-errors.stderr index e3ffc092327ac..d1dacc822e942 100644 --- a/src/test/ui/pattern/usefulness/refutable-pattern-errors.stderr +++ b/src/test/ui/pattern/usefulness/refutable-pattern-errors.stderr @@ -19,10 +19,6 @@ help: you might want to use `if let` to ignore the variants that aren't matched | LL | if let (1, (Some(1), 2..=3)) = (1, (None, 2)) { todo!() } | ++ ~~~~~~~~~~~ -help: alternatively, on nightly, you might want to use `#![feature(let_else)]` to handle the variants that aren't matched - | -LL | let (1, (Some(1), 2..=3)) = (1, (None, 2)) else { todo!() }; - | ++++++++++++++++ error: aborting due to 2 previous errors From a5216cf67d93de97091b41ecba85de2e08f39863 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 8 Mar 2022 17:40:24 +0100 Subject: [PATCH 09/28] Unify inherent impl blocks by wrapping them into a div --- src/librustdoc/html/markdown.rs | 1 + src/librustdoc/html/render/mod.rs | 16 ++++++++++------ src/librustdoc/html/static/js/main.js | 2 +- src/test/rustdoc/duplicate_impls/issue-33054.rs | 2 +- 4 files changed, 13 insertions(+), 8 deletions(-) diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index 7061a9674e4fb..f2856690d257a 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -1460,6 +1460,7 @@ fn init_id_map() -> FxHashMap { map.insert("provided-methods".to_owned(), 1); map.insert("implementors".to_owned(), 1); map.insert("synthetic-implementors".to_owned(), 1); + map.insert("implementations-list".to_owned(), 1); map.insert("trait-implementations-list".to_owned(), 1); map.insert("synthetic-implementations-list".to_owned(), 1); map.insert("blanket-implementations-list".to_owned(), 1); diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 558dbb3b3965a..26f29a3524b00 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -1065,14 +1065,15 @@ fn render_assoc_items_inner( let (non_trait, traits): (Vec<_>, _) = v.iter().partition(|i| i.inner_impl().trait_.is_none()); if !non_trait.is_empty() { let mut tmp_buf = Buffer::empty_from(w); - let render_mode = match what { + let (render_mode, id) = match what { AssocItemRender::All => { tmp_buf.write_str( "

\ - Implementations\ -

", + Implementations\ + \ + ", ); - RenderMode::Normal + (RenderMode::Normal, "implementations-list".to_owned()) } AssocItemRender::DerefFor { trait_, type_, deref_mut_ } => { let id = @@ -1090,7 +1091,7 @@ fn render_assoc_items_inner( trait_ = trait_.print(cx), type_ = type_.print(cx), ); - RenderMode::ForDeref { mut_: deref_mut_ } + (RenderMode::ForDeref { mut_: deref_mut_ }, cx.derive_id(id)) } }; let mut impls_buf = Buffer::empty_from(w); @@ -1115,7 +1116,9 @@ fn render_assoc_items_inner( } if !impls_buf.is_empty() { w.push_buffer(tmp_buf); + write!(w, "
", id); w.push_buffer(impls_buf); + w.write_str("
"); } } @@ -1146,7 +1149,8 @@ fn render_assoc_items_inner( write!( w, "

\ - Trait Implementations\ + Trait Implementations\ + \

\
{}
", impls diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js index 8e1919f75d671..90592335d5ddf 100644 --- a/src/librustdoc/html/static/js/main.js +++ b/src/librustdoc/html/static/js/main.js @@ -741,7 +741,7 @@ function hideThemeButtonState() { } else { addClass(innerToggle, "will-expand"); onEachLazy(document.getElementsByClassName("rustdoc-toggle"), function(e) { - if (e.parentNode.id !== MAIN_ID || + if (e.parentNode.id !== "implementations-list" || (!hasClass(e, "implementors-toggle") && !hasClass(e, "type-contents-toggle"))) { diff --git a/src/test/rustdoc/duplicate_impls/issue-33054.rs b/src/test/rustdoc/duplicate_impls/issue-33054.rs index b018dd6cda58a..3f9a476d96e23 100644 --- a/src/test/rustdoc/duplicate_impls/issue-33054.rs +++ b/src/test/rustdoc/duplicate_impls/issue-33054.rs @@ -2,7 +2,7 @@ // @has - '//h3[@class="code-header in-band"]' 'impl Foo' // @has - '//h3[@class="code-header in-band"]' 'impl Bar for Foo' // @count - '//*[@id="trait-implementations-list"]//*[@class="impl has-srclink"]' 1 -// @count - '//*[@id="main-content"]/details/summary/*[@class="impl has-srclink"]' 1 +// @count - '//*[@id="main-content"]/div[@id="implementations-list"]/details/summary/*[@class="impl has-srclink"]' 1 // @has issue_33054/impls/bar/trait.Bar.html // @has - '//h3[@class="code-header in-band"]' 'impl Bar for Foo' // @count - '//*[@class="struct"]' 1 From fbd9c284d7f018db07da8aa6e03cffdf0ce1786b Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 8 Mar 2022 18:11:29 +0100 Subject: [PATCH 10/28] Update GUI tests for impl blocks path changes --- src/test/rustdoc-gui/docblock-table-overflow.goml | 8 ++++---- src/test/rustdoc-gui/hash-item-expansion.goml | 4 ++-- src/test/rustdoc-gui/impl-default-expansion.goml | 2 +- src/test/rustdoc-gui/toggle-docs-mobile.goml | 2 +- src/test/rustdoc-gui/toggle-docs.goml | 2 +- src/test/rustdoc/duplicate_impls/issue-33054.rs | 2 ++ 6 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/test/rustdoc-gui/docblock-table-overflow.goml b/src/test/rustdoc-gui/docblock-table-overflow.goml index a9af88189a67d..af76d2ea42760 100644 --- a/src/test/rustdoc-gui/docblock-table-overflow.goml +++ b/src/test/rustdoc-gui/docblock-table-overflow.goml @@ -12,10 +12,10 @@ assert-property: (".top-doc .docblock table", {"scrollWidth": "1573"}) // Logically, the ".docblock" and the "

" should have the same scroll width. compare-elements-property: ( - "#implementations + details .docblock", - "#implementations + details .docblock > p", + "#implementations-list > details .docblock", + "#implementations-list > details .docblock > p", ["scrollWidth"], ) -assert-property: ("#implementations + details .docblock", {"scrollWidth": "801"}) +assert-property: ("#implementations-list > details .docblock", {"scrollWidth": "801"}) // However, since there is overflow in the , its scroll width is bigger. -assert-property: ("#implementations + details .docblock table", {"scrollWidth": "1573"}) +assert-property: ("#implementations-list > details .docblock table", {"scrollWidth": "1573"}) diff --git a/src/test/rustdoc-gui/hash-item-expansion.goml b/src/test/rustdoc-gui/hash-item-expansion.goml index a680635ef8ae4..861f6928362c2 100644 --- a/src/test/rustdoc-gui/hash-item-expansion.goml +++ b/src/test/rustdoc-gui/hash-item-expansion.goml @@ -3,9 +3,9 @@ goto: file://|DOC_PATH|/test_docs/struct.Foo.html#method.borrow // In the blanket implementations list, "Borrow" is the second one, hence the ":nth(2)". assert-attribute: ("#blanket-implementations-list > details:nth-child(2)", {"open": ""}) // We first check that the impl block is open by default. -assert-attribute: ("#implementations + details", {"open": ""}) +assert-attribute: ("#implementations-list details", {"open": ""}) // To ensure that we will click on the currently hidden method. assert-text: (".sidebar-elems section .block li > a", "must_use") click: ".sidebar-elems section .block li > a" // We check that the impl block was opened as expected so that we can see the method. -assert-attribute: ("#implementations + details", {"open": ""}) +assert-attribute: ("#implementations-list > details", {"open": ""}) diff --git a/src/test/rustdoc-gui/impl-default-expansion.goml b/src/test/rustdoc-gui/impl-default-expansion.goml index 7c4496dc0cabc..6df2661e6c2bb 100644 --- a/src/test/rustdoc-gui/impl-default-expansion.goml +++ b/src/test/rustdoc-gui/impl-default-expansion.goml @@ -1,3 +1,3 @@ // This test ensures that the impl blocks are open by default. goto: file://|DOC_PATH|/test_docs/struct.Foo.html -assert-attribute: ("#main-content > details.implementors-toggle", {"open": ""}) +assert-attribute: ("#implementations-list details.implementors-toggle", {"open": ""}) diff --git a/src/test/rustdoc-gui/toggle-docs-mobile.goml b/src/test/rustdoc-gui/toggle-docs-mobile.goml index b502692300113..ee6bc3cf7675c 100644 --- a/src/test/rustdoc-gui/toggle-docs-mobile.goml +++ b/src/test/rustdoc-gui/toggle-docs-mobile.goml @@ -14,7 +14,7 @@ assert-attribute: (".top-doc", {"open": ""}) // Assert the position of the toggle on the top doc block. assert-position: (".top-doc summary::before", {"x": 4}) // Assert the position of the toggle on the impl block. -assert-position: ("#implementations + details > summary::before", {"x": 4}) +assert-position: ("#implementations-list > details > summary::before", {"x": 4}) // Assert the position of the toggle on a method. assert-position: ( "#trait-implementations-list .impl-items .method-toggle > summary::before", diff --git a/src/test/rustdoc-gui/toggle-docs.goml b/src/test/rustdoc-gui/toggle-docs.goml index 477105193d3ee..f98111484f315 100644 --- a/src/test/rustdoc-gui/toggle-docs.goml +++ b/src/test/rustdoc-gui/toggle-docs.goml @@ -24,7 +24,7 @@ wait-for: 50 assert-text: ("#toggle-all-docs", "[+]") // We check that all
are collapsed (except for the impl block ones). assert-attribute-false: ("details.rustdoc-toggle:not(.implementors-toggle)", {"open": ""}, ALL) -assert-attribute: ("details.rustdoc-toggle.implementors-toggle", {"open": ""}) +assert-attribute: ("#implementations-list > details.implementors-toggle", {"open": ""}) // We now check that the other impl blocks are collapsed. assert-attribute-false: ( "#blanket-implementations-list > details.rustdoc-toggle.implementors-toggle", diff --git a/src/test/rustdoc/duplicate_impls/issue-33054.rs b/src/test/rustdoc/duplicate_impls/issue-33054.rs index 3f9a476d96e23..84c9e4ac0cd84 100644 --- a/src/test/rustdoc/duplicate_impls/issue-33054.rs +++ b/src/test/rustdoc/duplicate_impls/issue-33054.rs @@ -1,3 +1,5 @@ +// ignore-tidy-linelength + // @has issue_33054/impls/struct.Foo.html // @has - '//h3[@class="code-header in-band"]' 'impl Foo' // @has - '//h3[@class="code-header in-band"]' 'impl Bar for Foo' From 4e067e80ebb60022d6446335b0721feed73483b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20BRANSTETT?= Date: Tue, 8 Mar 2022 23:11:37 +0100 Subject: [PATCH 11/28] Improve rustdoc book --- src/doc/rustdoc/book.toml | 4 ++ src/doc/rustdoc/src/SUMMARY.md | 15 +++--- src/doc/rustdoc/src/advanced-features.md | 22 ++++++++ src/doc/rustdoc/src/command-line-arguments.md | 30 ++--------- .../src/{passes.md => deprecated-features.md} | 4 +- src/doc/rustdoc/src/how-to-read-rustdoc.md | 4 +- src/doc/rustdoc/src/lints.md | 24 ++++----- src/doc/rustdoc/src/unstable-features.md | 51 +++++++++++++++++-- src/doc/rustdoc/src/website-features.md | 25 --------- .../documentation-tests.md | 2 +- .../linking-to-items-by-name.md | 2 +- .../the-doc-attribute.md | 4 +- .../what-to-include.md | 2 +- 13 files changed, 106 insertions(+), 83 deletions(-) rename src/doc/rustdoc/src/{passes.md => deprecated-features.md} (94%) delete mode 100644 src/doc/rustdoc/src/website-features.md rename src/doc/rustdoc/src/{ => write-documentation}/documentation-tests.md (99%) rename src/doc/rustdoc/src/{ => write-documentation}/linking-to-items-by-name.md (98%) rename src/doc/rustdoc/src/{ => write-documentation}/the-doc-attribute.md (98%) rename src/doc/rustdoc/src/{ => write-documentation}/what-to-include.md (99%) diff --git a/src/doc/rustdoc/book.toml b/src/doc/rustdoc/book.toml index 97e08416d7686..45405a11765cc 100644 --- a/src/doc/rustdoc/book.toml +++ b/src/doc/rustdoc/book.toml @@ -4,3 +4,7 @@ title = "The rustdoc book" [output.html] git-repository-url = "https://github.com/rust-lang/rust/tree/master/src/doc/rustdoc" + +[output.html.redirect] +"/the-doc-attribute.html" = "write-documentation/the-doc-attribute.html" +"/documentation-tests.html" = "write-documentation/documentation-tests.html" diff --git a/src/doc/rustdoc/src/SUMMARY.md b/src/doc/rustdoc/src/SUMMARY.md index eb18185945387..d627f5b0389f3 100644 --- a/src/doc/rustdoc/src/SUMMARY.md +++ b/src/doc/rustdoc/src/SUMMARY.md @@ -1,16 +1,15 @@ # The Rustdoc Book - [What is rustdoc?](what-is-rustdoc.md) +- [Command-line arguments](command-line-arguments.md) - [How to read rustdoc output](how-to-read-rustdoc.md) - [How to write documentation](how-to-write-documentation.md) -- [What to include (and exclude)](what-to-include.md) -- [Command-line arguments](command-line-arguments.md) -- [The `#[doc]` attribute](the-doc-attribute.md) -- [Documentation tests](documentation-tests.md) -- [Linking to items by name](linking-to-items-by-name.md) -- [Lints](lints.md) + - [What to include (and exclude)](write-documentation/what-to-include.md) + - [The `#[doc]` attribute](write-documentation/the-doc-attribute.md) + - [Linking to items by name](write-documentation/linking-to-items-by-name.md) + - [Documentation tests](write-documentation/documentation-tests.md) +- [Rustdoc-specific lints](lints.md) - [Advanced features](advanced-features.md) - [Unstable features](unstable-features.md) -- [Website features](website-features.md) -- [Passes](passes.md) +- [Deprecated features](deprecated-features.md) - [References](references.md) diff --git a/src/doc/rustdoc/src/advanced-features.md b/src/doc/rustdoc/src/advanced-features.md index 6147bd0a97a96..dbf0baec04c03 100644 --- a/src/doc/rustdoc/src/advanced-features.md +++ b/src/doc/rustdoc/src/advanced-features.md @@ -88,3 +88,25 @@ You can add multiple aliases at the same time by using a list: #[doc(alias("x", "big"))] pub struct BigX; ``` + +## Custom search engines + +If you find yourself often referencing online Rust docs you might enjoy using a custom search +engine. This allows you to use the navigation bar directly to search a `rustdoc` website. +Most browsers support this feature by letting you define a URL template containing `%s` +which will be substituted for the search term. As an example, for the standard library you could use +this template: + +```text +https://doc.rust-lang.org/stable/std/?search=%s +``` + +Note that this will take you to a results page listing all matches. If you want to navigate to the first +result right away (which is often the best match) use the following instead: + +```text +https://doc.rust-lang.org/stable/std/?search=%s&go_to_first=true +``` + +This URL adds the `go_to_first=true` query parameter which can be appended to any `rustdoc` search URL +to automatically go to the first result. diff --git a/src/doc/rustdoc/src/command-line-arguments.md b/src/doc/rustdoc/src/command-line-arguments.md index 3ce57f88938f7..2a2e51b2f6331 100644 --- a/src/doc/rustdoc/src/command-line-arguments.md +++ b/src/doc/rustdoc/src/command-line-arguments.md @@ -177,7 +177,7 @@ $ rustdoc src/lib.rs --test ``` This flag will run your code examples as tests. For more, see [the chapter -on documentation tests](documentation-tests.md). +on documentation tests](write-documentation/documentation-tests.md). See also `--test-args`. @@ -190,7 +190,7 @@ $ rustdoc src/lib.rs --test --test-args ignored ``` This flag will pass options to the test runner when running documentation tests. -For more, see [the chapter on documentation tests](documentation-tests.md). +For more, see [the chapter on documentation tests](write-documentation/documentation-tests.md). See also `--test`. @@ -336,7 +336,7 @@ $ rustdoc src/lib.rs --sysroot /path/to/sysroot Similar to `rustc --sysroot`, this lets you change the sysroot `rustdoc` uses when compiling your code. -### `--edition`: control the edition of docs and doctests +## `--edition`: control the edition of docs and doctests Using this flag looks like this: @@ -403,12 +403,12 @@ encoded as UTF-8. ## `--passes`: add more rustdoc passes This flag is **deprecated**. -For more details on passes, see [the chapter on them](passes.md). +For more details on passes, see [the chapter on them](deprecated-features.md#passes). ## `--no-defaults`: don't run default passes This flag is **deprecated**. -For more details on passes, see [the chapter on them](passes.md). +For more details on passes, see [the chapter on them](deprecated-features.md#passes). ## `-r`/`--input-format`: input format @@ -417,23 +417,3 @@ This flag is **deprecated** and **has no effect**. Rustdoc only supports Rust source code and Markdown input formats. If the file ends in `.md` or `.markdown`, `rustdoc` treats it as a Markdown file. Otherwise, it assumes that the input file is Rust. - -# Unstable command line arguments - -## `--nocapture` - -When this flag is used with `--test`, the output (stdout and stderr) of your tests won't be -captured by rustdoc. Instead, the output will be directed to your terminal, -as if you had run the test executable manually. This is especially useful -for debugging your tests! - -## `--check` - -When this flag is supplied, rustdoc will type check and lint your code, but will not generate any -documentation or run your doctests. - -Using this flag looks like: - -```bash -rustdoc -Z unstable-options --check src/lib.rs -``` diff --git a/src/doc/rustdoc/src/passes.md b/src/doc/rustdoc/src/deprecated-features.md similarity index 94% rename from src/doc/rustdoc/src/passes.md rename to src/doc/rustdoc/src/deprecated-features.md index c3c3fd3068ec4..2bc6e8fc8ae4d 100644 --- a/src/doc/rustdoc/src/passes.md +++ b/src/doc/rustdoc/src/deprecated-features.md @@ -1,4 +1,6 @@ -# Passes +# Deprecated features + +## Passes Rustdoc has a concept called "passes". These are transformations that `rustdoc` runs on your documentation before producing its final output. diff --git a/src/doc/rustdoc/src/how-to-read-rustdoc.md b/src/doc/rustdoc/src/how-to-read-rustdoc.md index 99724d859ee75..098bc1879b56f 100644 --- a/src/doc/rustdoc/src/how-to-read-rustdoc.md +++ b/src/doc/rustdoc/src/how-to-read-rustdoc.md @@ -26,7 +26,7 @@ At the top is some at-a-glance info and controls: - a button to collapse or expand the top-level documentation for that item (`[+]` or `[-]`), - a link to the source code (`[src]`), - if [configured](the-doc-attribute.html#html_no_source), + if [configured](write-documentation/the-doc-attribute.html#html_no_source), and present (the source may not be available if the documentation was created with `cargo doc --no-deps`), - and the version in which the item became stable, @@ -52,7 +52,7 @@ For example, when looking at documentation for the crate root, it shows all the crates documented in the documentation bundle, and quick links to the modules, structs, traits, functions, and macros available from the current crate. -At the top, it displays a [configurable logo](the-doc-attribute.html#html_logo_url) +At the top, it displays a [configurable logo](write-documentation/the-doc-attribute.html#html_logo_url) alongside the current crate's name and version, or the current item whose documentation is being displayed. diff --git a/src/doc/rustdoc/src/lints.md b/src/doc/rustdoc/src/lints.md index 1773c15464a94..bff01d7cb7c14 100644 --- a/src/doc/rustdoc/src/lints.md +++ b/src/doc/rustdoc/src/lints.md @@ -13,11 +13,11 @@ Note that, except for `missing_docs`, these lints are only available when runnin Here is the list of the lints provided by `rustdoc`: -## broken_intra_doc_links +## `broken_intra_doc_links` This lint **warns by default**. This lint detects when an [intra-doc link] fails to be resolved. For example: -[intra-doc link]: linking-to-items-by-name.md +[intra-doc link]: write-documentation/linking-to-items-by-name.md ```rust /// I want to link to [`Nonexistent`] but it doesn't exist! @@ -64,7 +64,7 @@ help: to link to the function, add parentheses ``` -## private_intra_doc_links +## `private_intra_doc_links` This lint **warns by default**. This lint detects when [intra-doc links] from public to private items. For example: @@ -104,9 +104,9 @@ warning: public documentation for `public` links to private item `private` = note: this link resolves only because you passed `--document-private-items`, but will break without ``` -[intra-doc links]: linking-to-items-by-name.html +[intra-doc links]: write-documentation/linking-to-items-by-name.md -## missing_docs +## `missing_docs` This lint is **allowed by default**. It detects items missing documentation. For example: @@ -130,7 +130,7 @@ warning: missing documentation for a function Note that unlike other rustdoc lints, this lint is also available from `rustc` directly. -## missing_crate_level_docs +## `missing_crate_level_docs` This lint is **allowed by default**. It detects if there is no documentation at the crate root. For example: @@ -154,7 +154,7 @@ warning in the future. This is intended as a means to introduce new users on get started, without providing overwhelming warnings like `missing_docs` might. -## missing_doc_code_examples +## `missing_doc_code_examples` This lint is **allowed by default** and is **nightly-only**. It detects when a documentation block is missing a code example. For example: @@ -190,7 +190,7 @@ To fix the lint, you need to add a code example into the documentation block: pub fn no_code_example() {} ``` -## private_doc_tests +## `private_doc_tests` This lint is **allowed by default**. It detects documentation tests when they are on a private item. For example: @@ -223,7 +223,7 @@ warning: Documentation test in private item | |___________^ ``` -## invalid_codeblock_attributes +## `invalid_codeblock_attributes` This lint **warns by default**. It detects code block attributes in documentation examples that have potentially mis-typed values. For example: @@ -259,7 +259,7 @@ warning: unknown attribute `should-panic`. Did you mean `should_panic`? In the example above, the correct form is `should_panic`. This helps detect typo mistakes for some common attributes. -## invalid_html_tags +## `invalid_html_tags` This lint is **allowed by default** and is **nightly-only**. It detects unclosed or invalid HTML tags. For example: @@ -298,7 +298,7 @@ warning: unclosed HTML tag `h1` warning: 2 warnings emitted ``` -## invalid_rust_codeblocks +## `invalid_rust_codeblocks` This lint **warns by default**. It detects Rust code blocks in documentation examples that are invalid (e.g. empty, not parsable as Rust). For example: @@ -342,7 +342,7 @@ warning: could not parse code block as Rust code = note: error from rustc: unterminated character literal ``` -## bare_urls +## `bare_urls` This lint is **warn-by-default**. It detects URLs which are not links. For example: diff --git a/src/doc/rustdoc/src/unstable-features.md b/src/doc/rustdoc/src/unstable-features.md index 141d5d2d2b2d0..537ab48bbfc12 100644 --- a/src/doc/rustdoc/src/unstable-features.md +++ b/src/doc/rustdoc/src/unstable-features.md @@ -22,7 +22,7 @@ As detailed in [the chapter on documentation tests][doctest-attributes], you can nightly, you can optionally add an error number to state that a doctest should emit a specific error number: -[doctest-attributes]: documentation-tests.html#attributes +[doctest-attributes]: write-documentation/documentation-tests.html#attributes ``````markdown ```compile_fail,E0044 @@ -45,6 +45,8 @@ and enabled with a `#![feature(...)]` attribute in your crate. ### `#[doc(cfg)]`: Recording what platforms or features are required for code to be present + * Tracking issue: [#43781](https://github.com/rust-lang/rust/issues/43781) + You can use `#[doc(cfg(...))]` to tell Rustdoc exactly which platform items appear on. This has two effects: @@ -86,6 +88,8 @@ Book][unstable-doc-cfg] and [its tracking issue][issue-doc-cfg]. ### `doc_auto_cfg`: Automatically generate `#[doc(cfg)]` + * Tracking issue: [#43781](https://github.com/rust-lang/rust/issues/43781) + `doc_auto_cfg` is an extension to the `#[doc(cfg)]` feature. With it, you don't need to add `#[doc(cfg(...)]` anymore unless you want to override the default behaviour. So if we take the previous source code: @@ -123,6 +127,8 @@ And `doc` won't show up anymore! ### Adding your trait to the "Notable traits" dialog + * Tracking issue: [#45040](https://github.com/rust-lang/rust/issues/45040) + Rustdoc keeps a list of a few traits that are believed to be "fundamental" to types that implement them. These traits are intended to be the primary interface for their implementers, and are often most of the API available to be documented @@ -146,6 +152,8 @@ and [its tracking issue][issue-notable_trait]. ### Exclude certain dependencies from documentation + * Tracking issue: [#44027](https://github.com/rust-lang/rust/issues/44027) + The standard library uses several dependencies which, in turn, use several types and traits from the standard library. In addition, there are several compiler-internal crates that are not considered to be part of the official standard library, and thus would be a distraction to include in @@ -164,8 +172,7 @@ Book][unstable-masked] and [its tracking issue][issue-masked]. [unstable-masked]: ../unstable-book/language-features/doc-masked.html [issue-masked]: https://github.com/rust-lang/rust/issues/44027 - -## Document primitives +### Document primitives This is for Rust compiler internal use only. @@ -174,7 +181,7 @@ attributes. The `#[doc(primitive)]` attribute is used by the standard library to to generate documentation for primitive types, and requires `#![feature(rustdoc_internals)]` to enable. -## Document keywords +### Document keywords This is for Rust compiler internal use only. @@ -199,6 +206,8 @@ the flag in question to Rustdoc on the command-line. To do this from Cargo, you ### `--markdown-before-content`: include rendered Markdown before the content + * Tracking issue: [#44027](https://github.com/rust-lang/rust/issues/44027) + Using this flag looks like this: ```bash @@ -241,7 +250,7 @@ attribute][doc-playground]. Please be aware that the official Rust Playground at https://play.rust-lang.org does not have every crate available, so if your examples require your crate, make sure the playground you provide has your crate available. -[doc-playground]: the-doc-attribute.html#html_playground_url +[doc-playground]: write-documentation/the-doc-attribute.html#html_playground_url If both `--playground-url` and `--markdown-playground-url` are present when rendering a standalone Markdown file, the URL given to `--markdown-playground-url` will take precedence. If both @@ -279,6 +288,8 @@ between compilations. ### `--resource-suffix`: modifying the name of CSS/JavaScript in crate docs + * Tracking issue: [#54765](https://github.com/rust-lang/rust/issues/54765) + Using this flag looks like this: ```bash @@ -331,6 +342,24 @@ Using `index-page` option enables `enable-index-page` option as well. This feature allows the generation of a default index-page which lists the generated crates. +### `--nocapture`: disable output capture for test + +When this flag is used with `--test`, the output (stdout and stderr) of your tests won't be +captured by rustdoc. Instead, the output will be directed to your terminal, +as if you had run the test executable manually. This is especially useful +for debugging your tests! + +### `--check`: only checks the documentation + +When this flag is supplied, rustdoc will type check and lint your code, but will not generate any +documentation or run your doctests. + +Using this flag looks like: + +```bash +rustdoc -Z unstable-options --check src/lib.rs +``` + ### `--static-root-path`: control how static files are loaded in HTML output Using this flag looks like this: @@ -348,6 +377,8 @@ renamed with `--resource-suffix` will load from the given path. ### `--persist-doctests`: persist doctest executables after running + * Tracking issue: [#56925](https://github.com/rust-lang/rust/issues/56925) + Using this flag looks like this: ```bash @@ -360,6 +391,8 @@ with this option, you can keep those binaries around for farther testing. ### `--show-coverage`: calculate the percentage of items with documentation + * Tracking issue: [#58154](https://github.com/rust-lang/rust/issues/58154) + Using this flag looks like this: ```bash @@ -438,6 +471,8 @@ information. ### `--enable-per-target-ignores`: allow `ignore-foo` style filters for doctests + * Tracking issue: [#64245](https://github.com/rust-lang/rust/issues/64245) + Using this flag looks like this: ```bash @@ -471,6 +506,8 @@ override `ignore`. ### `--runtool`, `--runtool-arg`: program to run tests with; args to pass to it + * Tracking issue: [#64245](https://github.com/rust-lang/rust/issues/64245) + Using these options looks like this: ```bash @@ -488,6 +525,8 @@ Another use case would be to run a test inside an emulator, or through a Virtual ### `--with-examples`: include examples of uses of items as documentation + * Tracking issue: [#88791](https://github.com/rust-lang/rust/issues/88791) + This option, combined with `--scrape-examples-target-crate` and `--scrape-examples-output-path`, is used to implement the functionality in [RFC #3123](https://github.com/rust-lang/rfcs/pull/3123). Uses of an item (currently @@ -515,6 +554,8 @@ add the `--scrape-tests` flag. ### `--check-cfg`: check configuration flags + * Tracking issue: [#82450](https://github.com/rust-lang/rust/issues/82450) + This flag accepts the same values as `rustc --check-cfg`, and uses it to check configuration flags. Using this flag looks like this: diff --git a/src/doc/rustdoc/src/website-features.md b/src/doc/rustdoc/src/website-features.md deleted file mode 100644 index 5fade4e84a992..0000000000000 --- a/src/doc/rustdoc/src/website-features.md +++ /dev/null @@ -1,25 +0,0 @@ -# Website features - -These features are about using the website generated by `rustdoc`. - -## Custom search engines - -If you find yourself often referencing online Rust docs you might enjoy using a custom search -engine. This allows you to use the navigation bar directly to search a `rustdoc` website. -Most browsers support this feature by letting you define a URL template containing `%s` -which will be substituted for the search term. As an example, for the standard library you could use -this template: - -```text -https://doc.rust-lang.org/stable/std/?search=%s -``` - -Note that this will take you to a results page listing all matches. If you want to navigate to the first -result right away (which is often the best match) use the following instead: - -```text -https://doc.rust-lang.org/stable/std/?search=%s&go_to_first=true -``` - -This URL adds the `go_to_first=true` query parameter which can be appended to any `rustdoc` search URL -to automatically go to the first result. diff --git a/src/doc/rustdoc/src/documentation-tests.md b/src/doc/rustdoc/src/write-documentation/documentation-tests.md similarity index 99% rename from src/doc/rustdoc/src/documentation-tests.md rename to src/doc/rustdoc/src/write-documentation/documentation-tests.md index 534fd19b52eb2..1cb5b049df404 100644 --- a/src/doc/rustdoc/src/documentation-tests.md +++ b/src/doc/rustdoc/src/write-documentation/documentation-tests.md @@ -269,7 +269,7 @@ By default, this will still hide `unused` warnings, since so many examples use p you can add `#![warn(unused)]` to the top of your example if you want to see unused variables or dead code warnings. You can also use [`#![doc(test(attr(warn(unused))))]`][test-attr] in the crate root to enable warnings globally. -[test-attr]: ./the-doc-attribute.md#testattr +[test-attr]: the-doc-attribute.md#testattr ## Documenting macros diff --git a/src/doc/rustdoc/src/linking-to-items-by-name.md b/src/doc/rustdoc/src/write-documentation/linking-to-items-by-name.md similarity index 98% rename from src/doc/rustdoc/src/linking-to-items-by-name.md rename to src/doc/rustdoc/src/write-documentation/linking-to-items-by-name.md index 6ca1d1153b494..36bc312b9c99a 100644 --- a/src/doc/rustdoc/src/linking-to-items-by-name.md +++ b/src/doc/rustdoc/src/write-documentation/linking-to-items-by-name.md @@ -35,7 +35,7 @@ link to `Option`. You can refer to anything in scope, and use paths, including `Self`, `self`, `super`, and `crate`. Associated items (functions, types, and constants) are supported, but [not for blanket trait implementations][#79682]. Rustdoc also supports linking to all primitives listed in -[the standard library documentation](../std/index.html#primitives). +[the standard library documentation](../../std/index.html#primitives). [#79682]: https://github.com/rust-lang/rust/pull/79682 diff --git a/src/doc/rustdoc/src/the-doc-attribute.md b/src/doc/rustdoc/src/write-documentation/the-doc-attribute.md similarity index 98% rename from src/doc/rustdoc/src/the-doc-attribute.md rename to src/doc/rustdoc/src/write-documentation/the-doc-attribute.md index c5cc84022e389..25ef8b5bb9141 100644 --- a/src/doc/rustdoc/src/the-doc-attribute.md +++ b/src/doc/rustdoc/src/write-documentation/the-doc-attribute.md @@ -38,7 +38,7 @@ but given that docs are rendered via Markdown, it will remove these newlines. Another use case is for including external files as documentation: ```rust,no_run -#[doc = include_str!("../README.md")] +#[doc = include_str!("../../README.md")] # fn f() {} ``` @@ -73,7 +73,7 @@ left hand side of the docs. #![doc(html_logo_url = "https://example.com/logo.jpg")] ``` -This will put `logo` into +This will put `logo` into your docs, where the string for the attribute goes into the `{}`. If you don't use this attribute, there will be no logo. diff --git a/src/doc/rustdoc/src/what-to-include.md b/src/doc/rustdoc/src/write-documentation/what-to-include.md similarity index 99% rename from src/doc/rustdoc/src/what-to-include.md rename to src/doc/rustdoc/src/write-documentation/what-to-include.md index 2a6b62ebfd552..35e6ccbc38807 100644 --- a/src/doc/rustdoc/src/what-to-include.md +++ b/src/doc/rustdoc/src/write-documentation/what-to-include.md @@ -122,4 +122,4 @@ Here is an example of a new theme, [Ayu]. [API Guidelines]: https://rust-lang.github.io/api-guidelines/documentation.html#rustdoc-does-not-show-unhelpful-implementation-details-c-hidden [Documentation tests]: documentation-tests.md [on this blog]: https://blog.guillaume-gomez.fr/articles/2016-09-16+Generating+doc+with+rustdoc+and+a+custom+theme -[rustdoc-lints]: lints.md +[rustdoc-lints]: ../lints.md From 40e4bd2d02508db499ebf0feb7407957abf947f6 Mon Sep 17 00:00:00 2001 From: b-naber Date: Wed, 16 Feb 2022 10:54:36 +0100 Subject: [PATCH 12/28] treat all mir::Constant values as ConstantKind::Val --- compiler/rustc_middle/src/mir/mod.rs | 30 ++++++++++++++++++- compiler/rustc_mir_build/src/build/cfg.rs | 4 +-- .../rustc_mir_build/src/build/expr/into.rs | 10 +++---- compiler/rustc_mir_build/src/build/misc.rs | 2 +- compiler/rustc_mir_build/src/thir/cx/expr.rs | 3 ++ .../src/traits/query/normalize.rs | 17 ++++++++++- 6 files changed, 56 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index aa061232d7e3c..dbc0c84695842 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -2554,7 +2554,14 @@ impl<'tcx> Constant<'tcx> { impl<'tcx> From> for ConstantKind<'tcx> { #[inline] fn from(ct: ty::Const<'tcx>) -> Self { - Self::Ty(ct) + match ct.val() { + ty::ConstKind::Value(cv) => { + // FIXME Once valtrees are introduced we need to convert those + // into `ConstValue` instances here + Self::Val(cv, ct.ty()) + } + _ => Self::Ty(ct), + } } } @@ -2635,6 +2642,27 @@ impl<'tcx> ConstantKind<'tcx> { Self::Val(val, _) => val.try_to_machine_usize(tcx), } } + + pub fn from_bool(tcx: TyCtxt<'tcx>, v: bool) -> Self { + let cv = ConstValue::from_bool(v); + Self::Val(cv, tcx.types.bool) + } + + pub fn from_zero_sized(ty: Ty<'tcx>) -> Self { + let cv = ConstValue::Scalar(Scalar::ZST); + Self::Val(cv, ty) + } + + pub fn from_usize(tcx: TyCtxt<'tcx>, n: u64) -> Self { + let ty = tcx.types.usize; + let size = tcx + .layout_of(ty::ParamEnv::empty().and(ty)) + .unwrap_or_else(|e| bug!("could not compute layout for {:?}: {:?}", ty, e)) + .size; + let cv = ConstValue::Scalar(Scalar::from_uint(n as u128, size)); + + Self::Val(cv, ty) + } } /// A collection of projections into user types. diff --git a/compiler/rustc_mir_build/src/build/cfg.rs b/compiler/rustc_mir_build/src/build/cfg.rs index f08c6405af17f..dca9a63120c32 100644 --- a/compiler/rustc_mir_build/src/build/cfg.rs +++ b/compiler/rustc_mir_build/src/build/cfg.rs @@ -2,7 +2,7 @@ use crate::build::CFG; use rustc_middle::mir::*; -use rustc_middle::ty::{self, TyCtxt}; +use rustc_middle::ty::TyCtxt; impl<'tcx> CFG<'tcx> { crate fn block_data(&self, blk: BasicBlock) -> &BasicBlockData<'tcx> { @@ -73,7 +73,7 @@ impl<'tcx> CFG<'tcx> { Rvalue::Use(Operand::Constant(Box::new(Constant { span: source_info.span, user_ty: None, - literal: ty::Const::zero_sized(tcx, tcx.types.unit).into(), + literal: ConstantKind::from_zero_sized(tcx.types.unit), }))), ); } diff --git a/compiler/rustc_mir_build/src/build/expr/into.rs b/compiler/rustc_mir_build/src/build/expr/into.rs index c706e6ef1d466..9c7c7203f47de 100644 --- a/compiler/rustc_mir_build/src/build/expr/into.rs +++ b/compiler/rustc_mir_build/src/build/expr/into.rs @@ -9,7 +9,7 @@ use rustc_hir as hir; use rustc_index::vec::Idx; use rustc_middle::mir::*; use rustc_middle::thir::*; -use rustc_middle::ty::{self, CanonicalUserTypeAnnotation}; +use rustc_middle::ty::CanonicalUserTypeAnnotation; use std::iter; impl<'a, 'tcx> Builder<'a, 'tcx> { @@ -107,7 +107,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { Constant { span: expr_span, user_ty: None, - literal: ty::Const::from_bool(this.tcx, true).into(), + literal: ConstantKind::from_bool(this.tcx, true), }, ); @@ -118,7 +118,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { Constant { span: expr_span, user_ty: None, - literal: ty::Const::from_bool(this.tcx, false).into(), + literal: ConstantKind::from_bool(this.tcx, false), }, ); @@ -183,8 +183,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { span: expr_span, user_ty: None, literal: match op { - LogicalOp::And => ty::Const::from_bool(this.tcx, false).into(), - LogicalOp::Or => ty::Const::from_bool(this.tcx, true).into(), + LogicalOp::And => ConstantKind::from_bool(this.tcx, false), + LogicalOp::Or => ConstantKind::from_bool(this.tcx, true), }, }, ); diff --git a/compiler/rustc_mir_build/src/build/misc.rs b/compiler/rustc_mir_build/src/build/misc.rs index fd5914460140a..3516eca1c1469 100644 --- a/compiler/rustc_mir_build/src/build/misc.rs +++ b/compiler/rustc_mir_build/src/build/misc.rs @@ -54,7 +54,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { Constant { span: source_info.span, user_ty: None, - literal: ty::Const::from_usize(self.tcx, value).into(), + literal: ConstantKind::from_usize(self.tcx, value), }, ); temp diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index 5a7e1d88dd03f..dc11c76e07b23 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -569,6 +569,9 @@ impl<'tcx> Cx<'tcx> { hir::ExprKind::ConstBlock(ref anon_const) => { let anon_const_def_id = self.tcx.hir().local_def_id(anon_const.hir_id); + + // FIXME Do we want to use `from_inline_const` once valtrees + // are introduced? This would create `ValTree`s that will never be used... let value = ty::Const::from_inline_const(self.tcx, anon_const_def_id); ExprKind::ConstBlock { value } diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs index 6a2bd9ce1ea91..0e05900823fce 100644 --- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs @@ -334,6 +334,21 @@ impl<'cx, 'tcx> FallibleTypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> { &mut self, constant: mir::ConstantKind<'tcx>, ) -> Result, Self::Error> { - constant.try_super_fold_with(self) + let constant_kind = match constant { + mir::ConstantKind::Ty(c) => { + let const_folded = c.try_super_fold_with(self)?; + match const_folded.val() { + ty::ConstKind::Value(cv) => { + // FIXME With Valtrees we need to convert `cv: ValTree` + // to a `ConstValue` here. + mir::ConstantKind::Val(cv, const_folded.ty()) + } + _ => mir::ConstantKind::Ty(const_folded), + } + } + mir::ConstantKind::Val(_, _) => constant.try_super_fold_with(self)?, + }; + + Ok(constant_kind) } } From 8a811a1213bb965056488d9cad8ccaf9fd207867 Mon Sep 17 00:00:00 2001 From: b-naber Date: Wed, 16 Feb 2022 10:56:01 +0100 Subject: [PATCH 13/28] bless tests --- Cargo.lock | 2 +- ...allocation2.main.ConstProp.after.64bit.mir | 32 +++---- ..._line_doc_comment_2.DeduplicateBlocks.diff | 2 +- .../inline/inline_diverging.g.Inline.diff | 2 +- .../inline/inline_generator.main.Inline.diff | 12 ++- ...line_into_box_place.main.Inline.64bit.diff | 12 +++ .../inline/issue_78442.bar.Inline.diff | 6 +- .../inline/issue_78442.bar.RevealAll.diff | 6 +- ...ue_59352.num_to_digit.PreCodegen.after.mir | 2 +- .../nll/named_lifetimes_basic.use_x.nll.0.mir | 2 +- ...egion_subtyping_basic.main.nll.0.64bit.mir | 14 +-- ...age_markers.main.RemoveStorageMarkers.diff | 2 +- .../associated-consts/defaults-cyclic-fail.rs | 2 +- .../defaults-cyclic-fail.stderr | 28 +----- ...9-assoc-const-static-recursion-impl.stderr | 37 +++----- ...onst-static-recursion-trait-default.stderr | 37 +++----- ...-assoc-const-static-recursion-trait.stderr | 37 +++----- .../borrowck/issue-88434-minimal-example.rs | 2 + .../issue-88434-minimal-example.stderr | 23 ++++- ...ssue-88434-removal-index-should-be-less.rs | 2 + ...-88434-removal-index-should-be-less.stderr | 20 +++- .../ui/const-ptr/out_of_bounds_read.stderr | 6 +- .../const-eval/const-eval-query-stack.rs | 3 +- .../const-eval/const-eval-query-stack.stderr | 22 +++-- src/test/ui/consts/const-integer-bool-ops.rs | 10 ++ .../ui/consts/const-integer-bool-ops.stderr | 95 +++++++++++++++---- .../const-mut-refs/issue-76510.64bit.stderr | 12 ++- .../ui/consts/const-mut-refs/issue-76510.rs | 1 + src/test/ui/consts/const-tup-index-span.rs | 1 + .../ui/consts/const-tup-index-span.stderr | 11 ++- src/test/ui/consts/invalid-union.64bit.stderr | 2 +- src/test/ui/consts/issue-36163.stderr | 40 ++------ src/test/ui/issues/issue-17252.stderr | 15 +-- src/test/ui/issues/issue-23302-1.stderr | 17 +--- src/test/ui/issues/issue-23302-2.stderr | 17 +--- src/test/ui/issues/issue-23302-3.stderr | 30 ++---- src/test/ui/issues/issue-41394.rs | 1 + src/test/ui/issues/issue-41394.stderr | 11 ++- src/test/ui/issues/issue-54954.rs | 2 + src/test/ui/issues/issue-54954.stderr | 18 +++- ...issue-69602-type-err-during-codegen-ice.rs | 1 + ...e-69602-type-err-during-codegen-ice.stderr | 10 +- src/test/ui/issues/issue-77919.rs | 1 + src/test/ui/issues/issue-77919.stderr | 16 +++- src/test/ui/resolve/issue-50599.rs | 1 + src/test/ui/resolve/issue-50599.stderr | 11 ++- .../ui/type/type-dependent-def-issue-49241.rs | 1 + .../type-dependent-def-issue-49241.stderr | 11 ++- 48 files changed, 358 insertions(+), 290 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4d7b62e9c559f..29ea0a0726ca5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -311,7 +311,7 @@ dependencies = [ [[package]] name = "cargo" -version = "0.62.0" +version = "0.61.0" dependencies = [ "anyhow", "atty", diff --git a/src/test/mir-opt/const_allocation2.main.ConstProp.after.64bit.mir b/src/test/mir-opt/const_allocation2.main.ConstProp.after.64bit.mir index ef651f01c9b98..e2acd610b8053 100644 --- a/src/test/mir-opt/const_allocation2.main.ConstProp.after.64bit.mir +++ b/src/test/mir-opt/const_allocation2.main.ConstProp.after.64bit.mir @@ -21,44 +21,44 @@ fn main() -> () { } alloc1 (static: FOO, size: 16, align: 8) { - ╾───────alloc28───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ + ╾───────alloc22───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ } -alloc28 (size: 72, align: 8) { - 0x00 │ 00 00 00 00 __ __ __ __ ╾───────alloc13───────╼ │ ....░░░░╾──────╼ +alloc22 (size: 72, align: 8) { + 0x00 │ 00 00 00 00 __ __ __ __ ╾───────alloc9────────╼ │ ....░░░░╾──────╼ 0x10 │ 00 00 00 00 00 00 00 00 00 00 00 00 __ __ __ __ │ ............░░░░ - 0x20 │ ╾───────alloc18───────╼ 02 00 00 00 00 00 00 00 │ ╾──────╼........ - 0x30 │ 01 00 00 00 2a 00 00 00 ╾───────alloc26───────╼ │ ....*...╾──────╼ + 0x20 │ ╾───────alloc14───────╼ 02 00 00 00 00 00 00 00 │ ╾──────╼........ + 0x30 │ 01 00 00 00 2a 00 00 00 ╾───────alloc20───────╼ │ ....*...╾──────╼ 0x40 │ 03 00 00 00 00 00 00 00 │ ........ } -alloc13 (size: 0, align: 8) {} +alloc9 (size: 0, align: 8) {} -alloc18 (size: 16, align: 8) { - ╾───────alloc16───────╼ ╾───────alloc17───────╼ │ ╾──────╼╾──────╼ +alloc14 (size: 16, align: 8) { + ╾───────alloc12───────╼ ╾───────alloc13───────╼ │ ╾──────╼╾──────╼ } -alloc16 (size: 1, align: 1) { +alloc12 (size: 1, align: 1) { 05 │ . } -alloc17 (size: 1, align: 1) { +alloc13 (size: 1, align: 1) { 06 │ . } -alloc26 (size: 24, align: 8) { - 0x00 │ ╾─────alloc22+0x3─────╼ ╾───────alloc23───────╼ │ ╾──────╼╾──────╼ - 0x10 │ ╾─────alloc25+0x2─────╼ │ ╾──────╼ +alloc20 (size: 24, align: 8) { + 0x00 │ ╾─────alloc17+0x3─────╼ ╾───────alloc18───────╼ │ ╾──────╼╾──────╼ + 0x10 │ ╾─────alloc19+0x2─────╼ │ ╾──────╼ } -alloc22 (size: 4, align: 1) { +alloc17 (size: 4, align: 1) { 2a 45 15 6f │ *E.o } -alloc23 (size: 1, align: 1) { +alloc18 (size: 1, align: 1) { 2a │ * } -alloc25 (size: 4, align: 1) { +alloc19 (size: 4, align: 1) { 2a 45 15 6f │ *E.o } diff --git a/src/test/mir-opt/deduplicate_blocks.is_line_doc_comment_2.DeduplicateBlocks.diff b/src/test/mir-opt/deduplicate_blocks.is_line_doc_comment_2.DeduplicateBlocks.diff index 372b14eb7c92a..122bef522cf4d 100644 --- a/src/test/mir-opt/deduplicate_blocks.is_line_doc_comment_2.DeduplicateBlocks.diff +++ b/src/test/mir-opt/deduplicate_blocks.is_line_doc_comment_2.DeduplicateBlocks.diff @@ -26,7 +26,7 @@ - _2 = transmute::<&str, &[u8]>(move _8) -> bb14; // scope 2 at $SRC_DIR/core/src/str/mod.rs:LL:COL + _2 = transmute::<&str, &[u8]>(move _8) -> bb12; // scope 2 at $SRC_DIR/core/src/str/mod.rs:LL:COL // mir::Constant - // + span: $SRC_DIR/core/src/str/mod.rs:LL:COL + // + span: $DIR/deduplicate_blocks.rs:3:11: 3:23 // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(&str) -> &[u8] {transmute::<&str, &[u8]>}, val: Value(Scalar()) } } diff --git a/src/test/mir-opt/inline/inline_diverging.g.Inline.diff b/src/test/mir-opt/inline/inline_diverging.g.Inline.diff index 3b9d5e727b8a3..cb79cdd3579ea 100644 --- a/src/test/mir-opt/inline/inline_diverging.g.Inline.diff +++ b/src/test/mir-opt/inline/inline_diverging.g.Inline.diff @@ -39,7 +39,7 @@ // mir::Constant - // + span: $DIR/inline-diverging.rs:16:9: 16:14 - // + literal: Const { ty: fn() -> ! {panic}, val: Value(Scalar()) } -+ // + span: $SRC_DIR/std/src/panic.rs:LL:COL ++ // + span: $DIR/inline-diverging.rs:16:9: 16:16 + // + literal: Const { ty: fn(&str) -> ! {begin_panic::<&str>}, val: Value(Scalar()) } + // mir::Constant + // + span: $SRC_DIR/std/src/panic.rs:LL:COL diff --git a/src/test/mir-opt/inline/inline_generator.main.Inline.diff b/src/test/mir-opt/inline/inline_generator.main.Inline.diff index 1d72b34f83b81..1f736301c7699 100644 --- a/src/test/mir-opt/inline/inline_generator.main.Inline.diff +++ b/src/test/mir-opt/inline/inline_generator.main.Inline.diff @@ -46,11 +46,15 @@ - bb1: { + discriminant(_4) = 0; // scope 2 at $DIR/inline-generator.rs:15:5: 15:41 _3 = &mut _4; // scope 0 at $DIR/inline-generator.rs:9:23: 9:31 -- _2 = Pin::<&mut impl Generator>::new(move _3) -> [return: bb2, unwind: bb4]; // scope 0 at $DIR/inline-generator.rs:9:14: 9:32 +- _2 = Pin::<&mut [generator@$DIR/inline-generator.rs:15:5: 15:41]>::new(move _3) -> [return: bb2, unwind: bb4]; // scope 0 at $DIR/inline-generator.rs:9:14: 9:32 - // mir::Constant - // + span: $DIR/inline-generator.rs:9:14: 9:22 - // + user_ty: UserType(0) +<<<<<<< HEAD - // + literal: Const { ty: fn(&mut impl Generator) -> Pin<&mut impl Generator> {Pin::<&mut impl Generator>::new}, val: Value(Scalar()) } +======= +- // + literal: Const { ty: fn(&mut [generator@$DIR/inline-generator.rs:15:5: 15:41]) -> Pin<&mut [generator@$DIR/inline-generator.rs:15:5: 15:41]> {Pin::<&mut [generator@$DIR/inline-generator.rs:15:5: 15:41]>::new}, val: Value(Scalar()) } +>>>>>>> a4feb9af018 (bless tests) - } - - bb2: { @@ -62,10 +66,14 @@ + StorageDead(_6); // scope 5 at $SRC_DIR/core/src/pin.rs:LL:COL + StorageDead(_5); // scope 4 at $SRC_DIR/core/src/pin.rs:LL:COL StorageDead(_3); // scope 0 at $DIR/inline-generator.rs:9:31: 9:32 -- _1 = as Generator>::resume(move _2, const false) -> [return: bb3, unwind: bb4]; // scope 0 at $DIR/inline-generator.rs:9:14: 9:46 +- _1 = <[generator@$DIR/inline-generator.rs:15:5: 15:41] as Generator>::resume(move _2, const false) -> [return: bb3, unwind: bb4]; // scope 0 at $DIR/inline-generator.rs:9:14: 9:46 - // mir::Constant - // + span: $DIR/inline-generator.rs:9:33: 9:39 +<<<<<<< HEAD - // + literal: Const { ty: for<'r> fn(Pin<&'r mut impl Generator>, bool) -> GeneratorState< as Generator>::Yield, as Generator>::Return> { as Generator>::resume}, val: Value(Scalar()) } +======= +- // + literal: Const { ty: for<'r> fn(Pin<&'r mut [generator@$DIR/inline-generator.rs:15:5: 15:41]>, bool) -> GeneratorState<<[generator@$DIR/inline-generator.rs:15:5: 15:41] as Generator>::Yield, <[generator@$DIR/inline-generator.rs:15:5: 15:41] as Generator>::Return> {<[generator@$DIR/inline-generator.rs:15:5: 15:41] as Generator>::resume}, val: Value(Scalar()) } +>>>>>>> a4feb9af018 (bless tests) + StorageLive(_7); // scope 0 at $DIR/inline-generator.rs:9:14: 9:46 + _7 = const false; // scope 0 at $DIR/inline-generator.rs:9:14: 9:46 + StorageLive(_10); // scope 0 at $DIR/inline-generator.rs:9:14: 9:46 diff --git a/src/test/mir-opt/inline/inline_into_box_place.main.Inline.64bit.diff b/src/test/mir-opt/inline/inline_into_box_place.main.Inline.64bit.diff index 0f83b0c4a27ad..f2cdd987091d6 100644 --- a/src/test/mir-opt/inline/inline_into_box_place.main.Inline.64bit.diff +++ b/src/test/mir-opt/inline/inline_into_box_place.main.Inline.64bit.diff @@ -34,7 +34,14 @@ - (*_5) = Vec::::new() -> [return: bb2, unwind: bb5]; // scope 0 at $DIR/inline-into-box-place.rs:8:33: 8:43 + StorageLive(_7); // scope 0 at $DIR/inline-into-box-place.rs:8:33: 8:43 + _7 = &mut (*_5); // scope 0 at $DIR/inline-into-box-place.rs:8:33: 8:43 +<<<<<<< HEAD + ((*_7).0: alloc::raw_vec::RawVec) = const alloc::raw_vec::RawVec:: { ptr: Unique:: { pointer: {0x4 as *const u32}, _marker: PhantomData:: }, cap: 0_usize, alloc: std::alloc::Global }; // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL +======= ++ ((*_7).0: alloc::raw_vec::RawVec) = const alloc::raw_vec::RawVec::::NEW; // scope 3 at $DIR/inline-into-box-place.rs:8:33: 8:43 ++ // ty::Const ++ // + ty: alloc::raw_vec::RawVec ++ // + val: Unevaluated(alloc::raw_vec::RawVec::::NEW, [u32], None) +>>>>>>> a4feb9af018 (bless tests) // mir::Constant - // + span: $DIR/inline-into-box-place.rs:8:33: 8:41 - // + user_ty: UserType(1) @@ -44,8 +51,13 @@ - bb2: { + // + span: $SRC_DIR/alloc/src/vec/mod.rs:LL:COL + // + user_ty: UserType(0) +<<<<<<< HEAD + // + literal: Const { ty: alloc::raw_vec::RawVec, val: Value(ByRef { alloc: Allocation { bytes: [4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [65535], len: Size { raw: 16 } }, align: Align { pow2: 3 }, mutability: Not, extra: () }, offset: Size { raw: 0 } }) } + ((*_7).1: usize) = const 0_usize; // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL +======= ++ // + literal: Const { ty: alloc::raw_vec::RawVec, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(5:77 ~ alloc[bd09]::raw_vec::{impl#0}::NEW), const_param_did: None }, substs: [u32], promoted: None }) } ++ ((*_7).1: usize) = const 0_usize; // scope 3 at $DIR/inline-into-box-place.rs:8:33: 8:43 +>>>>>>> a4feb9af018 (bless tests) + StorageDead(_7); // scope 0 at $DIR/inline-into-box-place.rs:8:33: 8:43 _1 = move _5; // scope 0 at $DIR/inline-into-box-place.rs:8:29: 8:43 StorageDead(_5); // scope 0 at $DIR/inline-into-box-place.rs:8:42: 8:43 diff --git a/src/test/mir-opt/inline/issue_78442.bar.Inline.diff b/src/test/mir-opt/inline/issue_78442.bar.Inline.diff index 9e92f025b7661..92daef637e45b 100644 --- a/src/test/mir-opt/inline/issue_78442.bar.Inline.diff +++ b/src/test/mir-opt/inline/issue_78442.bar.Inline.diff @@ -25,11 +25,11 @@ bb1: { _3 = &_4; // scope 0 at $DIR/issue-78442.rs:11:5: 11:15 StorageLive(_5); // scope 0 at $DIR/issue-78442.rs:11:5: 11:17 -- _2 = >::call(move _3, move _5) -> [return: bb2, unwind: bb4]; // scope 0 at $DIR/issue-78442.rs:11:5: 11:17 +- _2 = >::call(move _3, move _5) -> [return: bb2, unwind: bb4]; // scope 0 at $DIR/issue-78442.rs:11:5: 11:17 - // mir::Constant - // + span: $DIR/issue-78442.rs:11:5: 11:15 -- // + literal: Const { ty: for<'r> extern "rust-call" fn(&'r impl Fn(), ()) -> >::Output {>::call}, val: Value(Scalar()) } -+ _2 = move (*_3)() -> [return: bb5, unwind: bb3]; // scope 1 at $SRC_DIR/core/src/ops/function.rs:LL:COL +- // + literal: Const { ty: for<'r> extern "rust-call" fn(&'r fn() {foo}, ()) -> >::Output {>::call}, val: Value(Scalar()) } ++ _2 = move (*_3)() -> [return: bb5, unwind: bb3]; // scope 1 at $DIR/issue-78442.rs:11:5: 11:17 } bb2: { diff --git a/src/test/mir-opt/inline/issue_78442.bar.RevealAll.diff b/src/test/mir-opt/inline/issue_78442.bar.RevealAll.diff index a8ae4008cbc96..ba9da7678e723 100644 --- a/src/test/mir-opt/inline/issue_78442.bar.RevealAll.diff +++ b/src/test/mir-opt/inline/issue_78442.bar.RevealAll.diff @@ -25,10 +25,12 @@ _3 = &_4; // scope 0 at $DIR/issue-78442.rs:11:5: 11:15 StorageLive(_5); // scope 0 at $DIR/issue-78442.rs:11:5: 11:17 nop; // scope 0 at $DIR/issue-78442.rs:11:5: 11:17 - _2 = >::call(move _3, move _5) -> [return: bb2, unwind: bb4]; // scope 0 at $DIR/issue-78442.rs:11:5: 11:17 +- _2 = >::call(move _3, move _5) -> [return: bb2, unwind: bb4]; // scope 0 at $DIR/issue-78442.rs:11:5: 11:17 ++ _2 = >::call(move _3, move _5) -> [return: bb2, unwind: bb4]; // scope 0 at $DIR/issue-78442.rs:11:5: 11:17 // mir::Constant // + span: $DIR/issue-78442.rs:11:5: 11:15 - // + literal: Const { ty: for<'r> extern "rust-call" fn(&'r impl Fn(), ()) -> >::Output {>::call}, val: Value(Scalar()) } +- // + literal: Const { ty: for<'r> extern "rust-call" fn(&'r impl Fn(), ()) -> >::Output {>::call}, val: Value(Scalar()) } ++ // + literal: Const { ty: for<'r> extern "rust-call" fn(&'r fn() {foo}, ()) -> >::Output {>::call}, val: Value(Scalar()) } } bb2: { diff --git a/src/test/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.mir b/src/test/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.mir index e2051c85af215..c5c063e8cecf1 100644 --- a/src/test/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.mir +++ b/src/test/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.mir @@ -38,7 +38,7 @@ fn num_to_digit(_1: char) -> u32 { _8 = _2; // scope 1 at $SRC_DIR/core/src/char/methods.rs:LL:COL _7 = char::methods::::to_digit(move _8, const 8_u32) -> bb5; // scope 1 at $SRC_DIR/core/src/char/methods.rs:LL:COL // mir::Constant - // + span: $SRC_DIR/core/src/char/methods.rs:LL:COL + // + span: $DIR/issue-59352.rs:14:8: 14:23 // + literal: Const { ty: fn(char, u32) -> Option {char::methods::::to_digit}, val: Value(Scalar()) } } diff --git a/src/test/mir-opt/nll/named_lifetimes_basic.use_x.nll.0.mir b/src/test/mir-opt/nll/named_lifetimes_basic.use_x.nll.0.mir index 975e2ffbf01e7..9f235248ca59f 100644 --- a/src/test/mir-opt/nll/named_lifetimes_basic.use_x.nll.0.mir +++ b/src/test/mir-opt/nll/named_lifetimes_basic.use_x.nll.0.mir @@ -42,7 +42,7 @@ fn use_x(_1: &'_#6r mut i32, _2: &'_#7r u32, _3: &'_#8r u32, _4: &'_#9r u32) -> let mut _0: bool; // return place in scope 0 at $DIR/named-lifetimes-basic.rs:12:81: 12:85 bb0: { - _0 = const Const(Value(Scalar(0x01)): bool); // bb0[0]: scope 0 at $DIR/named-lifetimes-basic.rs:12:88: 12:92 + _0 = const ConstValue(Scalar(0x01): bool); // bb0[0]: scope 0 at $DIR/named-lifetimes-basic.rs:12:88: 12:92 return; // bb0[1]: scope 0 at $DIR/named-lifetimes-basic.rs:12:94: 12:94 } } diff --git a/src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.64bit.mir b/src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.64bit.mir index d6b4a0beebd65..95997b2070172 100644 --- a/src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.64bit.mir +++ b/src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.64bit.mir @@ -45,11 +45,11 @@ fn main() -> () { bb0: { StorageLive(_1); // bb0[0]: scope 0 at $DIR/region-subtyping-basic.rs:17:9: 17:14 - _1 = [const Const(Value(Scalar(0x0000000000000001)): usize), const Const(Value(Scalar(0x0000000000000002)): usize), const Const(Value(Scalar(0x0000000000000003)): usize)]; // bb0[1]: scope 0 at $DIR/region-subtyping-basic.rs:17:17: 17:26 + _1 = [const ConstValue(Scalar(0x0000000000000001): usize), const ConstValue(Scalar(0x0000000000000002): usize), const ConstValue(Scalar(0x0000000000000003): usize)]; // bb0[1]: scope 0 at $DIR/region-subtyping-basic.rs:17:17: 17:26 FakeRead(ForLet(None), _1); // bb0[2]: scope 0 at $DIR/region-subtyping-basic.rs:17:9: 17:14 StorageLive(_2); // bb0[3]: scope 1 at $DIR/region-subtyping-basic.rs:18:9: 18:10 StorageLive(_3); // bb0[4]: scope 1 at $DIR/region-subtyping-basic.rs:18:16: 18:17 - _3 = const Const(Value(Scalar(0x0000000000000000)): usize); // bb0[5]: scope 1 at $DIR/region-subtyping-basic.rs:18:16: 18:17 + _3 = const ConstValue(Scalar(0x0000000000000000): usize); // bb0[5]: scope 1 at $DIR/region-subtyping-basic.rs:18:16: 18:17 _4 = Len(_1); // bb0[6]: scope 1 at $DIR/region-subtyping-basic.rs:18:14: 18:18 _5 = Lt(_3, _4); // bb0[7]: scope 1 at $DIR/region-subtyping-basic.rs:18:14: 18:18 assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> [success: bb1, unwind: bb7]; // bb0[8]: scope 1 at $DIR/region-subtyping-basic.rs:18:14: 18:18 @@ -62,7 +62,7 @@ fn main() -> () { _6 = _2; // bb1[3]: scope 2 at $DIR/region-subtyping-basic.rs:19:13: 19:14 FakeRead(ForLet(None), _6); // bb1[4]: scope 2 at $DIR/region-subtyping-basic.rs:19:9: 19:10 StorageLive(_7); // bb1[5]: scope 3 at $DIR/region-subtyping-basic.rs:20:8: 20:12 - _7 = const Const(Value(Scalar(0x01)): bool); // bb1[6]: scope 3 at $DIR/region-subtyping-basic.rs:20:8: 20:12 + _7 = const ConstValue(Scalar(0x01): bool); // bb1[6]: scope 3 at $DIR/region-subtyping-basic.rs:20:8: 20:12 switchInt(move _7) -> [Const(Value(Scalar(0x00)): bool): bb4, otherwise: bb2]; // bb1[7]: scope 3 at $DIR/region-subtyping-basic.rs:20:8: 20:12 } @@ -70,7 +70,7 @@ fn main() -> () { StorageLive(_8); // bb2[0]: scope 3 at $DIR/region-subtyping-basic.rs:21:9: 21:18 StorageLive(_9); // bb2[1]: scope 3 at $DIR/region-subtyping-basic.rs:21:15: 21:17 _9 = (*_6); // bb2[2]: scope 3 at $DIR/region-subtyping-basic.rs:21:15: 21:17 - _8 = Const(Value(Scalar()): fn(usize) -> bool {use_x})(move _9) -> [return: bb3, unwind: bb7]; // bb2[3]: scope 3 at $DIR/region-subtyping-basic.rs:21:9: 21:18 + _8 = ConstValue(Scalar(): fn(usize) -> bool {use_x})(move _9) -> [return: bb3, unwind: bb7]; // bb2[3]: scope 3 at $DIR/region-subtyping-basic.rs:21:9: 21:18 // mir::Constant // + span: $DIR/region-subtyping-basic.rs:21:9: 21:14 // + literal: Const { ty: fn(usize) -> bool {use_x}, val: Value(Scalar()) } @@ -79,13 +79,13 @@ fn main() -> () { bb3: { StorageDead(_9); // bb3[0]: scope 3 at $DIR/region-subtyping-basic.rs:21:17: 21:18 StorageDead(_8); // bb3[1]: scope 3 at $DIR/region-subtyping-basic.rs:21:18: 21:19 - _0 = const Const(Value(Scalar()): ()); // bb3[2]: scope 3 at $DIR/region-subtyping-basic.rs:20:13: 22:6 + _0 = const ConstValue(Scalar(): ()); // bb3[2]: scope 3 at $DIR/region-subtyping-basic.rs:20:13: 22:6 goto -> bb6; // bb3[3]: scope 3 at $DIR/region-subtyping-basic.rs:20:5: 24:6 } bb4: { StorageLive(_10); // bb4[0]: scope 3 at $DIR/region-subtyping-basic.rs:23:9: 23:18 - _10 = Const(Value(Scalar()): fn(usize) -> bool {use_x})(const Const(Value(Scalar(0x0000000000000016)): usize)) -> [return: bb5, unwind: bb7]; // bb4[1]: scope 3 at $DIR/region-subtyping-basic.rs:23:9: 23:18 + _10 = ConstValue(Scalar(): fn(usize) -> bool {use_x})(const ConstValue(Scalar(0x0000000000000016): usize)) -> [return: bb5, unwind: bb7]; // bb4[1]: scope 3 at $DIR/region-subtyping-basic.rs:23:9: 23:18 // mir::Constant // + span: $DIR/region-subtyping-basic.rs:23:9: 23:14 // + literal: Const { ty: fn(usize) -> bool {use_x}, val: Value(Scalar()) } @@ -93,7 +93,7 @@ fn main() -> () { bb5: { StorageDead(_10); // bb5[0]: scope 3 at $DIR/region-subtyping-basic.rs:23:18: 23:19 - _0 = const Const(Value(Scalar()): ()); // bb5[1]: scope 3 at $DIR/region-subtyping-basic.rs:22:12: 24:6 + _0 = const ConstValue(Scalar(): ()); // bb5[1]: scope 3 at $DIR/region-subtyping-basic.rs:22:12: 24:6 goto -> bb6; // bb5[2]: scope 3 at $DIR/region-subtyping-basic.rs:20:5: 24:6 } diff --git a/src/test/mir-opt/remove_storage_markers.main.RemoveStorageMarkers.diff b/src/test/mir-opt/remove_storage_markers.main.RemoveStorageMarkers.diff index 312031b7a0ff4..ec76424afa55e 100644 --- a/src/test/mir-opt/remove_storage_markers.main.RemoveStorageMarkers.diff +++ b/src/test/mir-opt/remove_storage_markers.main.RemoveStorageMarkers.diff @@ -58,7 +58,7 @@ _14 = &mut (*_8); // scope 5 at $SRC_DIR/core/src/iter/range.rs:LL:COL _7 = as iter::range::RangeIteratorImpl>::spec_next(move _14) -> bb4; // scope 5 at $SRC_DIR/core/src/iter/range.rs:LL:COL // mir::Constant - // + span: $SRC_DIR/core/src/iter/range.rs:LL:COL + // + span: $DIR/remove_storage_markers.rs:8:14: 8:19 // + literal: Const { ty: for<'r> fn(&'r mut std::ops::Range) -> Option< as iter::range::RangeIteratorImpl>::Item> { as iter::range::RangeIteratorImpl>::spec_next}, val: Value(Scalar()) } } diff --git a/src/test/ui/associated-consts/defaults-cyclic-fail.rs b/src/test/ui/associated-consts/defaults-cyclic-fail.rs index 9fb1bbebc9610..9b899ee316a0e 100644 --- a/src/test/ui/associated-consts/defaults-cyclic-fail.rs +++ b/src/test/ui/associated-consts/defaults-cyclic-fail.rs @@ -1,9 +1,9 @@ // build-fail -//~^ ERROR cycle detected when normalizing `<() as Tr>::A` // Cyclic assoc. const defaults don't error unless *used* trait Tr { const A: u8 = Self::B; + //~^ ERROR cycle detected when const-evaluating + checking `Tr::A` const B: u8 = Self::A; } diff --git a/src/test/ui/associated-consts/defaults-cyclic-fail.stderr b/src/test/ui/associated-consts/defaults-cyclic-fail.stderr index 3fb4ab72fe6d6..550897790e9ff 100644 --- a/src/test/ui/associated-consts/defaults-cyclic-fail.stderr +++ b/src/test/ui/associated-consts/defaults-cyclic-fail.stderr @@ -1,37 +1,15 @@ -error[E0391]: cycle detected when normalizing `<() as Tr>::A` - | -note: ...which requires simplifying constant for the type system `Tr::A`... - --> $DIR/defaults-cyclic-fail.rs:6:5 - | -LL | const A: u8 = Self::B; - | ^^^^^^^^^^^^^^^^^^^^^^ -note: ...which requires simplifying constant for the type system `Tr::A`... - --> $DIR/defaults-cyclic-fail.rs:6:5 - | -LL | const A: u8 = Self::B; - | ^^^^^^^^^^^^^^^^^^^^^^ -note: ...which requires const-evaluating + checking `Tr::A`... - --> $DIR/defaults-cyclic-fail.rs:6:5 +error[E0391]: cycle detected when const-evaluating + checking `Tr::A` + --> $DIR/defaults-cyclic-fail.rs:5:5 | LL | const A: u8 = Self::B; | ^^^^^^^^^^^^^^^^^^^^^^ - = note: ...which requires normalizing `<() as Tr>::B`... -note: ...which requires simplifying constant for the type system `Tr::B`... - --> $DIR/defaults-cyclic-fail.rs:8:5 | -LL | const B: u8 = Self::A; - | ^^^^^^^^^^^^^^^^^^^^^^ -note: ...which requires simplifying constant for the type system `Tr::B`... - --> $DIR/defaults-cyclic-fail.rs:8:5 - | -LL | const B: u8 = Self::A; - | ^^^^^^^^^^^^^^^^^^^^^^ note: ...which requires const-evaluating + checking `Tr::B`... --> $DIR/defaults-cyclic-fail.rs:8:5 | LL | const B: u8 = Self::A; | ^^^^^^^^^^^^^^^^^^^^^^ - = note: ...which again requires normalizing `<() as Tr>::A`, completing the cycle + = note: ...which again requires const-evaluating + checking `Tr::A`, completing the cycle note: cycle used when const-evaluating + checking `main::promoted[1]` --> $DIR/defaults-cyclic-fail.rs:14:1 | diff --git a/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-impl.stderr b/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-impl.stderr index 61b16cb9d5811..14b09072533df 100644 --- a/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-impl.stderr +++ b/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-impl.stderr @@ -1,30 +1,9 @@ -error[E0391]: cycle detected when simplifying constant for the type system `IMPL_REF_BAR` +error[E0391]: cycle detected when const-evaluating + checking `IMPL_REF_BAR` --> $DIR/issue-24949-assoc-const-static-recursion-impl.rs:7:1 | LL | const IMPL_REF_BAR: u32 = GlobalImplRef::BAR; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: ...which requires simplifying constant for the type system `IMPL_REF_BAR`... - --> $DIR/issue-24949-assoc-const-static-recursion-impl.rs:7:1 - | -LL | const IMPL_REF_BAR: u32 = GlobalImplRef::BAR; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -note: ...which requires const-evaluating + checking `IMPL_REF_BAR`... - --> $DIR/issue-24949-assoc-const-static-recursion-impl.rs:7:1 - | -LL | const IMPL_REF_BAR: u32 = GlobalImplRef::BAR; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: ...which requires normalizing `::BAR`... -note: ...which requires simplifying constant for the type system `::BAR`... - --> $DIR/issue-24949-assoc-const-static-recursion-impl.rs:12:5 - | -LL | const BAR: u32 = IMPL_REF_BAR; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -note: ...which requires simplifying constant for the type system `::BAR`... - --> $DIR/issue-24949-assoc-const-static-recursion-impl.rs:12:5 - | -LL | const BAR: u32 = IMPL_REF_BAR; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: ...which requires const-evaluating + checking `::BAR`... --> $DIR/issue-24949-assoc-const-static-recursion-impl.rs:12:5 | @@ -35,9 +14,17 @@ note: ...which requires caching mir of ` $DIR/issue-24949-assoc-const-static-recursion-impl.rs:7:1 + | +LL | const IMPL_REF_BAR: u32 = GlobalImplRef::BAR; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: ...which again requires const-evaluating + checking `IMPL_REF_BAR`, completing the cycle +note: cycle used when simplifying constant for the type system `IMPL_REF_BAR` + --> $DIR/issue-24949-assoc-const-static-recursion-impl.rs:7:1 + | +LL | const IMPL_REF_BAR: u32 = GlobalImplRef::BAR; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait-default.stderr b/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait-default.stderr index 494dc0c0ed447..682f56a6a5575 100644 --- a/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait-default.stderr +++ b/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait-default.stderr @@ -1,30 +1,9 @@ -error[E0391]: cycle detected when simplifying constant for the type system `DEFAULT_REF_BAR` +error[E0391]: cycle detected when const-evaluating + checking `DEFAULT_REF_BAR` --> $DIR/issue-24949-assoc-const-static-recursion-trait-default.rs:11:1 | LL | const DEFAULT_REF_BAR: u32 = ::BAR; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: ...which requires simplifying constant for the type system `DEFAULT_REF_BAR`... - --> $DIR/issue-24949-assoc-const-static-recursion-trait-default.rs:11:1 - | -LL | const DEFAULT_REF_BAR: u32 = ::BAR; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -note: ...which requires const-evaluating + checking `DEFAULT_REF_BAR`... - --> $DIR/issue-24949-assoc-const-static-recursion-trait-default.rs:11:1 - | -LL | const DEFAULT_REF_BAR: u32 = ::BAR; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: ...which requires normalizing `::BAR`... -note: ...which requires simplifying constant for the type system `FooDefault::BAR`... - --> $DIR/issue-24949-assoc-const-static-recursion-trait-default.rs:8:5 - | -LL | const BAR: u32 = DEFAULT_REF_BAR; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -note: ...which requires simplifying constant for the type system `FooDefault::BAR`... - --> $DIR/issue-24949-assoc-const-static-recursion-trait-default.rs:8:5 - | -LL | const BAR: u32 = DEFAULT_REF_BAR; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: ...which requires const-evaluating + checking `FooDefault::BAR`... --> $DIR/issue-24949-assoc-const-static-recursion-trait-default.rs:8:5 | @@ -35,9 +14,17 @@ note: ...which requires caching mir of `FooDefault::BAR` for CTFE... | LL | const BAR: u32 = DEFAULT_REF_BAR; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: ...which requires normalizing `DEFAULT_REF_BAR`... - = note: ...which again requires simplifying constant for the type system `DEFAULT_REF_BAR`, completing the cycle - = note: cycle used when running analysis passes on this crate +note: ...which requires const-evaluating + checking `DEFAULT_REF_BAR`... + --> $DIR/issue-24949-assoc-const-static-recursion-trait-default.rs:11:1 + | +LL | const DEFAULT_REF_BAR: u32 = ::BAR; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: ...which again requires const-evaluating + checking `DEFAULT_REF_BAR`, completing the cycle +note: cycle used when simplifying constant for the type system `DEFAULT_REF_BAR` + --> $DIR/issue-24949-assoc-const-static-recursion-trait-default.rs:11:1 + | +LL | const DEFAULT_REF_BAR: u32 = ::BAR; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait.stderr b/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait.stderr index 4ff253bffcb32..41db7a633183b 100644 --- a/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait.stderr +++ b/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait.stderr @@ -1,30 +1,9 @@ -error[E0391]: cycle detected when simplifying constant for the type system `TRAIT_REF_BAR` +error[E0391]: cycle detected when const-evaluating + checking `TRAIT_REF_BAR` --> $DIR/issue-24949-assoc-const-static-recursion-trait.rs:7:1 | LL | const TRAIT_REF_BAR: u32 = ::BAR; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: ...which requires simplifying constant for the type system `TRAIT_REF_BAR`... - --> $DIR/issue-24949-assoc-const-static-recursion-trait.rs:7:1 - | -LL | const TRAIT_REF_BAR: u32 = ::BAR; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -note: ...which requires const-evaluating + checking `TRAIT_REF_BAR`... - --> $DIR/issue-24949-assoc-const-static-recursion-trait.rs:7:1 - | -LL | const TRAIT_REF_BAR: u32 = ::BAR; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: ...which requires normalizing `::BAR`... -note: ...which requires simplifying constant for the type system `::BAR`... - --> $DIR/issue-24949-assoc-const-static-recursion-trait.rs:12:5 - | -LL | const BAR: u32 = TRAIT_REF_BAR; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -note: ...which requires simplifying constant for the type system `::BAR`... - --> $DIR/issue-24949-assoc-const-static-recursion-trait.rs:12:5 - | -LL | const BAR: u32 = TRAIT_REF_BAR; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: ...which requires const-evaluating + checking `::BAR`... --> $DIR/issue-24949-assoc-const-static-recursion-trait.rs:12:5 | @@ -35,9 +14,17 @@ note: ...which requires caching mir of ` $DIR/issue-24949-assoc-const-static-recursion-trait.rs:7:1 + | +LL | const TRAIT_REF_BAR: u32 = ::BAR; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: ...which again requires const-evaluating + checking `TRAIT_REF_BAR`, completing the cycle +note: cycle used when simplifying constant for the type system `TRAIT_REF_BAR` + --> $DIR/issue-24949-assoc-const-static-recursion-trait.rs:7:1 + | +LL | const TRAIT_REF_BAR: u32 = ::BAR; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/borrowck/issue-88434-minimal-example.rs b/src/test/ui/borrowck/issue-88434-minimal-example.rs index 632f8dc3ad6f5..90baca253d268 100644 --- a/src/test/ui/borrowck/issue-88434-minimal-example.rs +++ b/src/test/ui/borrowck/issue-88434-minimal-example.rs @@ -1,6 +1,8 @@ // Regression test related to issue 88434 const _CONST: &() = &f(&|_| {}); +//~^ ERROR any use of this value will cause an error +//~| WARNING this was previously accepted by the compiler but is being phased out const fn f(_: &F) where diff --git a/src/test/ui/borrowck/issue-88434-minimal-example.stderr b/src/test/ui/borrowck/issue-88434-minimal-example.stderr index d9635e1ee464c..d0c60ef628e60 100644 --- a/src/test/ui/borrowck/issue-88434-minimal-example.stderr +++ b/src/test/ui/borrowck/issue-88434-minimal-example.stderr @@ -1,5 +1,9 @@ error[E0080]: evaluation of constant value failed +<<<<<<< HEAD --> $DIR/issue-88434-minimal-example.rs:9:5 +======= + --> $DIR/issue-88434-minimal-example.rs:12:5 +>>>>>>> a4feb9af018 (bless tests) | LL | const _CONST: &() = &f(&|_| {}); | ---------- inside `_CONST` at $DIR/issue-88434-minimal-example.rs:3:22 @@ -7,11 +11,28 @@ LL | const _CONST: &() = &f(&|_| {}); LL | panic!() | ^^^^^^^^ | | +<<<<<<< HEAD | the evaluated program panicked at 'explicit panic', $DIR/issue-88434-minimal-example.rs:9:5 | inside `f::<[closure@$DIR/issue-88434-minimal-example.rs:3:25: 3:31]>` at $SRC_DIR/std/src/panic.rs:LL:COL +======= + | the evaluated program panicked at 'explicit panic', $DIR/issue-88434-minimal-example.rs:12:5 + | inside `f::<[closure@$DIR/issue-88434-minimal-example.rs:4:25: 4:31]>` at $SRC_DIR/std/src/panic.rs:LL:COL +>>>>>>> a4feb9af018 (bless tests) | = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: any use of this value will cause an error + --> $DIR/issue-88434-minimal-example.rs:4:21 + | +LL | const _CONST: &() = &f(&|_| {}); + | --------------------^^^^^^^^^^^- + | | + | referenced constant has errors + | + = note: `#[deny(const_err)]` on by default + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #71800 + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0080`. diff --git a/src/test/ui/borrowck/issue-88434-removal-index-should-be-less.rs b/src/test/ui/borrowck/issue-88434-removal-index-should-be-less.rs index f0a6dcd4eb3b8..b1fc1615ece77 100644 --- a/src/test/ui/borrowck/issue-88434-removal-index-should-be-less.rs +++ b/src/test/ui/borrowck/issue-88434-removal-index-should-be-less.rs @@ -1,6 +1,8 @@ // Regression test for issue 88434 const _CONST: &[u8] = &f(&[], |_| {}); +//~^ ERROR any use of this value will cause an error +//~| WARNING this was previously const fn f(_: &[u8], _: F) -> &[u8] where diff --git a/src/test/ui/borrowck/issue-88434-removal-index-should-be-less.stderr b/src/test/ui/borrowck/issue-88434-removal-index-should-be-less.stderr index 44e244ae9cc3f..f2a381a73ef49 100644 --- a/src/test/ui/borrowck/issue-88434-removal-index-should-be-less.stderr +++ b/src/test/ui/borrowck/issue-88434-removal-index-should-be-less.stderr @@ -1,5 +1,5 @@ error[E0080]: evaluation of constant value failed - --> $DIR/issue-88434-removal-index-should-be-less.rs:9:5 + --> $DIR/issue-88434-removal-index-should-be-less.rs:12:5 | LL | const _CONST: &[u8] = &f(&[], |_| {}); | -------------- inside `_CONST` at $DIR/issue-88434-removal-index-should-be-less.rs:3:24 @@ -7,11 +7,23 @@ LL | const _CONST: &[u8] = &f(&[], |_| {}); LL | panic!() | ^^^^^^^^ | | - | the evaluated program panicked at 'explicit panic', $DIR/issue-88434-removal-index-should-be-less.rs:9:5 - | inside `f::<[closure@$DIR/issue-88434-removal-index-should-be-less.rs:3:31: 3:37]>` at $SRC_DIR/std/src/panic.rs:LL:COL + | the evaluated program panicked at 'explicit panic', $DIR/issue-88434-removal-index-should-be-less.rs:12:5 + | inside `f::<[closure@$DIR/issue-88434-removal-index-should-be-less.rs:4:31: 4:37]>` at $SRC_DIR/std/src/panic.rs:LL:COL | = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: any use of this value will cause an error + --> $DIR/issue-88434-removal-index-should-be-less.rs:4:23 + | +LL | const _CONST: &[u8] = &f(&[], |_| {}); + | ----------------------^^^^^^^^^^^^^^^- + | | + | referenced constant has errors + | + = note: `#[deny(const_err)]` on by default + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #71800 + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0080`. diff --git a/src/test/ui/const-ptr/out_of_bounds_read.stderr b/src/test/ui/const-ptr/out_of_bounds_read.stderr index 62af6a6adb644..4933ba4514db2 100644 --- a/src/test/ui/const-ptr/out_of_bounds_read.stderr +++ b/src/test/ui/const-ptr/out_of_bounds_read.stderr @@ -4,7 +4,7 @@ error[E0080]: evaluation of constant value failed LL | copy_nonoverlapping(src, tmp.as_mut_ptr(), 1); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | | - | memory access failed: alloc7 has size 4, so pointer to 4 bytes starting at offset 4 is out-of-bounds + | memory access failed: alloc5 has size 4, so pointer to 4 bytes starting at offset 4 is out-of-bounds | inside `std::ptr::read::` at $SRC_DIR/core/src/ptr/mod.rs:LL:COL | ::: $DIR/out_of_bounds_read.rs:13:33 @@ -18,7 +18,7 @@ error[E0080]: evaluation of constant value failed LL | copy_nonoverlapping(src, tmp.as_mut_ptr(), 1); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | | - | memory access failed: alloc7 has size 4, so pointer to 4 bytes starting at offset 4 is out-of-bounds + | memory access failed: alloc5 has size 4, so pointer to 4 bytes starting at offset 4 is out-of-bounds | inside `std::ptr::read::` at $SRC_DIR/core/src/ptr/mod.rs:LL:COL | ::: $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL @@ -37,7 +37,7 @@ error[E0080]: evaluation of constant value failed LL | copy_nonoverlapping(src, tmp.as_mut_ptr(), 1); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | | - | memory access failed: alloc7 has size 4, so pointer to 4 bytes starting at offset 4 is out-of-bounds + | memory access failed: alloc5 has size 4, so pointer to 4 bytes starting at offset 4 is out-of-bounds | inside `std::ptr::read::` at $SRC_DIR/core/src/ptr/mod.rs:LL:COL | ::: $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL diff --git a/src/test/ui/consts/const-eval/const-eval-query-stack.rs b/src/test/ui/consts/const-eval/const-eval-query-stack.rs index 8c3959cc11a43..c9460498951fd 100644 --- a/src/test/ui/consts/const-eval/const-eval-query-stack.rs +++ b/src/test/ui/consts/const-eval/const-eval-query-stack.rs @@ -1,4 +1,3 @@ -//~ERROR constructed but no error reported // compile-flags: -Ztreat-err-as-bug=2 // build-fail // failure-status: 101 @@ -23,5 +22,7 @@ const X: i32 = 1 / 0; //~WARN any use of this value will cause an error fn main() { let x: &'static i32 = &X; //~^ ERROR evaluation of constant value failed + //~| ERROR erroneous constant used + //~| WARNING this was previously accepted by the compiler println!("x={}", x); } diff --git a/src/test/ui/consts/const-eval/const-eval-query-stack.stderr b/src/test/ui/consts/const-eval/const-eval-query-stack.stderr index 45a3d901c9871..9e990738bbcca 100644 --- a/src/test/ui/consts/const-eval/const-eval-query-stack.stderr +++ b/src/test/ui/consts/const-eval/const-eval-query-stack.stderr @@ -1,5 +1,5 @@ warning: any use of this value will cause an error - --> $DIR/const-eval-query-stack.rs:20:16 + --> $DIR/const-eval-query-stack.rs:19:16 | LL | const X: i32 = 1 / 0; | ---------------^^^^^- @@ -7,7 +7,7 @@ LL | const X: i32 = 1 / 0; | attempt to divide `1_i32` by zero | note: the lint level is defined here - --> $DIR/const-eval-query-stack.rs:19:8 + --> $DIR/const-eval-query-stack.rs:18:8 | LL | #[warn(const_err)] | ^^^^^^^^^ @@ -15,12 +15,22 @@ LL | #[warn(const_err)] = note: for more information, see issue #71800 error[E0080]: evaluation of constant value failed - --> $DIR/const-eval-query-stack.rs:24:28 + --> $DIR/const-eval-query-stack.rs:23:28 | LL | let x: &'static i32 = &X; | ^ referenced constant has errors + +error: erroneous constant used + --> $DIR/const-eval-query-stack.rs:23:27 + | +LL | let x: &'static i32 = &X; + | ^^ referenced constant has errors + | + = note: `#[deny(const_err)]` on by default + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #71800 + query stack during panic: -#0 [try_normalize_mir_const_after_erasing_regions] normalizing `main::promoted[1]` -#1 [optimized_mir] optimizing MIR for `main` -#2 [collect_and_partition_mono_items] collect_and_partition_mono_items +#0 [optimized_mir] optimizing MIR for `main` +#1 [collect_and_partition_mono_items] collect_and_partition_mono_items end of query stack diff --git a/src/test/ui/consts/const-integer-bool-ops.rs b/src/test/ui/consts/const-integer-bool-ops.rs index 35915a7a606a4..6924956bdf706 100644 --- a/src/test/ui/consts/const-integer-bool-ops.rs +++ b/src/test/ui/consts/const-integer-bool-ops.rs @@ -6,6 +6,7 @@ const X: usize = 42 && 39; //~| ERROR mismatched types //~| expected `usize`, found `bool` const ARR: [i32; X] = [99; 34]; +//~^ ERROR evaluation of constant value failed const X1: usize = 42 || 39; //~^ ERROR mismatched types @@ -15,6 +16,7 @@ const X1: usize = 42 || 39; //~| ERROR mismatched types //~| expected `usize`, found `bool` const ARR1: [i32; X1] = [99; 47]; +//~^ ERROR evaluation of constant value failed const X2: usize = -42 || -39; //~^ ERROR mismatched types @@ -24,6 +26,7 @@ const X2: usize = -42 || -39; //~| ERROR mismatched types //~| expected `usize`, found `bool` const ARR2: [i32; X2] = [99; 18446744073709551607]; +//~^ ERROR evaluation of constant value failed const X3: usize = -42 && -39; //~^ ERROR mismatched types @@ -33,36 +36,43 @@ const X3: usize = -42 && -39; //~| ERROR mismatched types //~| expected `usize`, found `bool` const ARR3: [i32; X3] = [99; 6]; +//~^ ERROR evaluation of constant value failed const Y: usize = 42.0 == 42.0; //~^ ERROR mismatched types //~| expected `usize`, found `bool` const ARRR: [i32; Y] = [99; 1]; +//~^ ERROR evaluation of constant value failed const Y1: usize = 42.0 >= 42.0; //~^ ERROR mismatched types //~| expected `usize`, found `bool` const ARRR1: [i32; Y1] = [99; 1]; +//~^ ERROR evaluation of constant value failed const Y2: usize = 42.0 <= 42.0; //~^ ERROR mismatched types //~| expected `usize`, found `bool` const ARRR2: [i32; Y2] = [99; 1]; +//~^ ERROR evaluation of constant value failed const Y3: usize = 42.0 > 42.0; //~^ ERROR mismatched types //~| expected `usize`, found `bool` const ARRR3: [i32; Y3] = [99; 0]; +//~^ ERROR evaluation of constant value failed const Y4: usize = 42.0 < 42.0; //~^ ERROR mismatched types //~| expected `usize`, found `bool` const ARRR4: [i32; Y4] = [99; 0]; +//~^ ERROR evaluation of constant value failed const Y5: usize = 42.0 != 42.0; //~^ ERROR mismatched types //~| expected `usize`, found `bool` const ARRR5: [i32; Y5] = [99; 0]; +//~^ ERROR evaluation of constant value failed fn main() { let _ = ARR; diff --git a/src/test/ui/consts/const-integer-bool-ops.stderr b/src/test/ui/consts/const-integer-bool-ops.stderr index 4e503e5a5c0a4..9001fefd1029f 100644 --- a/src/test/ui/consts/const-integer-bool-ops.stderr +++ b/src/test/ui/consts/const-integer-bool-ops.stderr @@ -16,96 +16,157 @@ error[E0308]: mismatched types LL | const X: usize = 42 && 39; | ^^^^^^^^ expected `usize`, found `bool` +error[E0080]: evaluation of constant value failed + --> $DIR/const-integer-bool-ops.rs:8:18 + | +LL | const ARR: [i32; X] = [99; 34]; + | ^ referenced constant has errors + error[E0308]: mismatched types - --> $DIR/const-integer-bool-ops.rs:10:19 + --> $DIR/const-integer-bool-ops.rs:11:19 | LL | const X1: usize = 42 || 39; | ^^ expected `bool`, found integer error[E0308]: mismatched types - --> $DIR/const-integer-bool-ops.rs:10:25 + --> $DIR/const-integer-bool-ops.rs:11:25 | LL | const X1: usize = 42 || 39; | ^^ expected `bool`, found integer error[E0308]: mismatched types - --> $DIR/const-integer-bool-ops.rs:10:19 + --> $DIR/const-integer-bool-ops.rs:11:19 | LL | const X1: usize = 42 || 39; | ^^^^^^^^ expected `usize`, found `bool` +error[E0080]: evaluation of constant value failed + --> $DIR/const-integer-bool-ops.rs:18:19 + | +LL | const ARR1: [i32; X1] = [99; 47]; + | ^^ referenced constant has errors + error[E0308]: mismatched types - --> $DIR/const-integer-bool-ops.rs:19:19 + --> $DIR/const-integer-bool-ops.rs:21:19 | LL | const X2: usize = -42 || -39; | ^^^ expected `bool`, found integer error[E0308]: mismatched types - --> $DIR/const-integer-bool-ops.rs:19:26 + --> $DIR/const-integer-bool-ops.rs:21:26 | LL | const X2: usize = -42 || -39; | ^^^ expected `bool`, found integer error[E0308]: mismatched types - --> $DIR/const-integer-bool-ops.rs:19:19 + --> $DIR/const-integer-bool-ops.rs:21:19 | LL | const X2: usize = -42 || -39; | ^^^^^^^^^^ expected `usize`, found `bool` -error[E0308]: mismatched types +error[E0080]: evaluation of constant value failed --> $DIR/const-integer-bool-ops.rs:28:19 | +LL | const ARR2: [i32; X2] = [99; 18446744073709551607]; + | ^^ referenced constant has errors + +error[E0308]: mismatched types + --> $DIR/const-integer-bool-ops.rs:31:19 + | LL | const X3: usize = -42 && -39; | ^^^ expected `bool`, found integer error[E0308]: mismatched types - --> $DIR/const-integer-bool-ops.rs:28:26 + --> $DIR/const-integer-bool-ops.rs:31:26 | LL | const X3: usize = -42 && -39; | ^^^ expected `bool`, found integer error[E0308]: mismatched types - --> $DIR/const-integer-bool-ops.rs:28:19 + --> $DIR/const-integer-bool-ops.rs:31:19 | LL | const X3: usize = -42 && -39; | ^^^^^^^^^^ expected `usize`, found `bool` +error[E0080]: evaluation of constant value failed + --> $DIR/const-integer-bool-ops.rs:38:19 + | +LL | const ARR3: [i32; X3] = [99; 6]; + | ^^ referenced constant has errors + error[E0308]: mismatched types - --> $DIR/const-integer-bool-ops.rs:37:18 + --> $DIR/const-integer-bool-ops.rs:41:18 | LL | const Y: usize = 42.0 == 42.0; | ^^^^^^^^^^^^ expected `usize`, found `bool` +error[E0080]: evaluation of constant value failed + --> $DIR/const-integer-bool-ops.rs:44:19 + | +LL | const ARRR: [i32; Y] = [99; 1]; + | ^ referenced constant has errors + error[E0308]: mismatched types - --> $DIR/const-integer-bool-ops.rs:42:19 + --> $DIR/const-integer-bool-ops.rs:47:19 | LL | const Y1: usize = 42.0 >= 42.0; | ^^^^^^^^^^^^ expected `usize`, found `bool` +error[E0080]: evaluation of constant value failed + --> $DIR/const-integer-bool-ops.rs:50:20 + | +LL | const ARRR1: [i32; Y1] = [99; 1]; + | ^^ referenced constant has errors + error[E0308]: mismatched types - --> $DIR/const-integer-bool-ops.rs:47:19 + --> $DIR/const-integer-bool-ops.rs:53:19 | LL | const Y2: usize = 42.0 <= 42.0; | ^^^^^^^^^^^^ expected `usize`, found `bool` +error[E0080]: evaluation of constant value failed + --> $DIR/const-integer-bool-ops.rs:56:20 + | +LL | const ARRR2: [i32; Y2] = [99; 1]; + | ^^ referenced constant has errors + error[E0308]: mismatched types - --> $DIR/const-integer-bool-ops.rs:52:19 + --> $DIR/const-integer-bool-ops.rs:59:19 | LL | const Y3: usize = 42.0 > 42.0; | ^^^^^^^^^^^ expected `usize`, found `bool` +error[E0080]: evaluation of constant value failed + --> $DIR/const-integer-bool-ops.rs:62:20 + | +LL | const ARRR3: [i32; Y3] = [99; 0]; + | ^^ referenced constant has errors + error[E0308]: mismatched types - --> $DIR/const-integer-bool-ops.rs:57:19 + --> $DIR/const-integer-bool-ops.rs:65:19 | LL | const Y4: usize = 42.0 < 42.0; | ^^^^^^^^^^^ expected `usize`, found `bool` +error[E0080]: evaluation of constant value failed + --> $DIR/const-integer-bool-ops.rs:68:20 + | +LL | const ARRR4: [i32; Y4] = [99; 0]; + | ^^ referenced constant has errors + error[E0308]: mismatched types - --> $DIR/const-integer-bool-ops.rs:62:19 + --> $DIR/const-integer-bool-ops.rs:71:19 | LL | const Y5: usize = 42.0 != 42.0; | ^^^^^^^^^^^^ expected `usize`, found `bool` -error: aborting due to 18 previous errors +error[E0080]: evaluation of constant value failed + --> $DIR/const-integer-bool-ops.rs:74:20 + | +LL | const ARRR5: [i32; Y5] = [99; 0]; + | ^^ referenced constant has errors + +error: aborting due to 28 previous errors -For more information about this error, try `rustc --explain E0308`. +Some errors have detailed explanations: E0080, E0308. +For more information about an error, try `rustc --explain E0080`. diff --git a/src/test/ui/consts/const-mut-refs/issue-76510.64bit.stderr b/src/test/ui/consts/const-mut-refs/issue-76510.64bit.stderr index 61b00be345fee..0f420ae1b6b7c 100644 --- a/src/test/ui/consts/const-mut-refs/issue-76510.64bit.stderr +++ b/src/test/ui/consts/const-mut-refs/issue-76510.64bit.stderr @@ -19,7 +19,13 @@ error[E0596]: cannot borrow data in a `&` reference as mutable LL | const S: &'static mut str = &mut " hello "; | ^^^^^^^^^^^^^^ cannot borrow as mutable -error: aborting due to 3 previous errors +error[E0080]: evaluation of constant value failed + --> $DIR/issue-76510.rs:11:70 + | +LL | let s = transmute::<(*const u8, usize), &ManuallyDrop>((S.as_ptr(), 3)); + | ^ referenced constant has errors + +error: aborting due to 4 previous errors -Some errors have detailed explanations: E0596, E0658, E0764. -For more information about an error, try `rustc --explain E0596`. +Some errors have detailed explanations: E0080, E0596, E0658, E0764. +For more information about an error, try `rustc --explain E0080`. diff --git a/src/test/ui/consts/const-mut-refs/issue-76510.rs b/src/test/ui/consts/const-mut-refs/issue-76510.rs index 143d2fb6b9a3a..08cf64ee330db 100644 --- a/src/test/ui/consts/const-mut-refs/issue-76510.rs +++ b/src/test/ui/consts/const-mut-refs/issue-76510.rs @@ -9,6 +9,7 @@ const S: &'static mut str = &mut " hello "; const fn trigger() -> [(); unsafe { let s = transmute::<(*const u8, usize), &ManuallyDrop>((S.as_ptr(), 3)); + //~^ ERROR evaluation of constant value failed 0 }] { [(); 0] diff --git a/src/test/ui/consts/const-tup-index-span.rs b/src/test/ui/consts/const-tup-index-span.rs index 8057d64369a23..763263c6aeb4f 100644 --- a/src/test/ui/consts/const-tup-index-span.rs +++ b/src/test/ui/consts/const-tup-index-span.rs @@ -4,6 +4,7 @@ const TUP: (usize,) = 5usize << 64; //~^ ERROR mismatched types //~| expected tuple, found `usize` const ARR: [i32; TUP.0] = []; +//~^ ERROR evaluation of constant value failed fn main() { } diff --git a/src/test/ui/consts/const-tup-index-span.stderr b/src/test/ui/consts/const-tup-index-span.stderr index d301f8c4054c2..b178e05e27a09 100644 --- a/src/test/ui/consts/const-tup-index-span.stderr +++ b/src/test/ui/consts/const-tup-index-span.stderr @@ -11,6 +11,13 @@ help: use a trailing comma to create a tuple with one element LL | const TUP: (usize,) = (5usize << 64,); | + ++ -error: aborting due to previous error +error[E0080]: evaluation of constant value failed + --> $DIR/const-tup-index-span.rs:6:18 + | +LL | const ARR: [i32; TUP.0] = []; + | ^^^ referenced constant has errors + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0308`. +Some errors have detailed explanations: E0080, E0308. +For more information about an error, try `rustc --explain E0080`. diff --git a/src/test/ui/consts/invalid-union.64bit.stderr b/src/test/ui/consts/invalid-union.64bit.stderr index 2ca54ccf9a09e..a0225d3ffc39f 100644 --- a/src/test/ui/consts/invalid-union.64bit.stderr +++ b/src/test/ui/consts/invalid-union.64bit.stderr @@ -6,7 +6,7 @@ LL | fn main() { | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { - ╾───────alloc7────────╼ │ ╾──────╼ + ╾───────alloc6────────╼ │ ╾──────╼ } error: erroneous constant used diff --git a/src/test/ui/consts/issue-36163.stderr b/src/test/ui/consts/issue-36163.stderr index 113f86cf0f99f..9ac6c984cb0cd 100644 --- a/src/test/ui/consts/issue-36163.stderr +++ b/src/test/ui/consts/issue-36163.stderr @@ -1,48 +1,20 @@ -error[E0391]: cycle detected when simplifying constant for the type system `Foo::B::{constant#0}` +error[E0391]: cycle detected when const-evaluating + checking `Foo::B::{constant#0}` --> $DIR/issue-36163.rs:4:9 | LL | B = A, | ^ | -note: ...which requires simplifying constant for the type system `Foo::B::{constant#0}`... - --> $DIR/issue-36163.rs:4:9 - | -LL | B = A, - | ^ -note: ...which requires const-evaluating + checking `Foo::B::{constant#0}`... - --> $DIR/issue-36163.rs:4:9 - | -LL | B = A, - | ^ - = note: ...which requires normalizing `A`... -note: ...which requires simplifying constant for the type system `A`... - --> $DIR/issue-36163.rs:1:1 - | -LL | const A: isize = Foo::B as isize; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -note: ...which requires simplifying constant for the type system `A`... - --> $DIR/issue-36163.rs:1:1 - | -LL | const A: isize = Foo::B as isize; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: ...which requires const-evaluating + checking `A`... --> $DIR/issue-36163.rs:1:1 | LL | const A: isize = Foo::B as isize; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: ...which requires normalizing `A`... - = note: ...which again requires simplifying constant for the type system `Foo::B::{constant#0}`, completing the cycle -note: cycle used when collecting item types in top-level module - --> $DIR/issue-36163.rs:1:1 + = note: ...which again requires const-evaluating + checking `Foo::B::{constant#0}`, completing the cycle +note: cycle used when simplifying constant for the type system `Foo::B::{constant#0}` + --> $DIR/issue-36163.rs:4:9 | -LL | / const A: isize = Foo::B as isize; -LL | | -LL | | enum Foo { -LL | | B = A, -LL | | } -LL | | -LL | | fn main() {} - | |____________^ +LL | B = A, + | ^ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-17252.stderr b/src/test/ui/issues/issue-17252.stderr index 1148577016ab4..4856418ed6002 100644 --- a/src/test/ui/issues/issue-17252.stderr +++ b/src/test/ui/issues/issue-17252.stderr @@ -1,21 +1,10 @@ -error[E0391]: cycle detected when normalizing `FOO` - | -note: ...which requires simplifying constant for the type system `FOO`... - --> $DIR/issue-17252.rs:1:1 - | -LL | const FOO: usize = FOO; - | ^^^^^^^^^^^^^^^^^^^^^^^ -note: ...which requires simplifying constant for the type system `FOO`... +error[E0391]: cycle detected when const-evaluating + checking `FOO` --> $DIR/issue-17252.rs:1:1 | LL | const FOO: usize = FOO; | ^^^^^^^^^^^^^^^^^^^^^^^ -note: ...which requires const-evaluating + checking `FOO`... - --> $DIR/issue-17252.rs:1:1 | -LL | const FOO: usize = FOO; - | ^^^^^^^^^^^^^^^^^^^^^^^ - = note: ...which again requires normalizing `FOO`, completing the cycle + = note: ...which immediately requires const-evaluating + checking `FOO` again note: cycle used when const-evaluating + checking `main::{constant#0}` --> $DIR/issue-17252.rs:4:18 | diff --git a/src/test/ui/issues/issue-23302-1.stderr b/src/test/ui/issues/issue-23302-1.stderr index d3a1993536a00..9366050d7ecdf 100644 --- a/src/test/ui/issues/issue-23302-1.stderr +++ b/src/test/ui/issues/issue-23302-1.stderr @@ -1,26 +1,15 @@ -error[E0391]: cycle detected when simplifying constant for the type system `X::A::{constant#0}` +error[E0391]: cycle detected when const-evaluating + checking `X::A::{constant#0}` --> $DIR/issue-23302-1.rs:4:9 | LL | A = X::A as isize, | ^^^^^^^^^^^^^ | -note: ...which requires simplifying constant for the type system `X::A::{constant#0}`... + = note: ...which immediately requires const-evaluating + checking `X::A::{constant#0}` again +note: cycle used when simplifying constant for the type system `X::A::{constant#0}` --> $DIR/issue-23302-1.rs:4:9 | LL | A = X::A as isize, | ^^^^^^^^^^^^^ -note: ...which requires const-evaluating + checking `X::A::{constant#0}`... - --> $DIR/issue-23302-1.rs:4:9 - | -LL | A = X::A as isize, - | ^^^^^^^^^^^^^ - = note: ...which requires normalizing `X::A as isize`... - = note: ...which again requires simplifying constant for the type system `X::A::{constant#0}`, completing the cycle -note: cycle used when collecting item types in top-level module - --> $DIR/issue-23302-1.rs:3:1 - | -LL | enum X { - | ^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-23302-2.stderr b/src/test/ui/issues/issue-23302-2.stderr index d3b78ea1af5f5..b97ae287a47a9 100644 --- a/src/test/ui/issues/issue-23302-2.stderr +++ b/src/test/ui/issues/issue-23302-2.stderr @@ -1,26 +1,15 @@ -error[E0391]: cycle detected when simplifying constant for the type system `Y::A::{constant#0}` +error[E0391]: cycle detected when const-evaluating + checking `Y::A::{constant#0}` --> $DIR/issue-23302-2.rs:4:9 | LL | A = Y::B as isize, | ^^^^^^^^^^^^^ | -note: ...which requires simplifying constant for the type system `Y::A::{constant#0}`... + = note: ...which immediately requires const-evaluating + checking `Y::A::{constant#0}` again +note: cycle used when simplifying constant for the type system `Y::A::{constant#0}` --> $DIR/issue-23302-2.rs:4:9 | LL | A = Y::B as isize, | ^^^^^^^^^^^^^ -note: ...which requires const-evaluating + checking `Y::A::{constant#0}`... - --> $DIR/issue-23302-2.rs:4:9 - | -LL | A = Y::B as isize, - | ^^^^^^^^^^^^^ - = note: ...which requires normalizing `Y::B as isize`... - = note: ...which again requires simplifying constant for the type system `Y::A::{constant#0}`, completing the cycle -note: cycle used when collecting item types in top-level module - --> $DIR/issue-23302-2.rs:3:1 - | -LL | enum Y { - | ^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-23302-3.stderr b/src/test/ui/issues/issue-23302-3.stderr index 5233b832ecc79..1a07d4a95bcfa 100644 --- a/src/test/ui/issues/issue-23302-3.stderr +++ b/src/test/ui/issues/issue-23302-3.stderr @@ -1,38 +1,20 @@ -error[E0391]: cycle detected when simplifying constant for the type system `A` +error[E0391]: cycle detected when const-evaluating + checking `A` --> $DIR/issue-23302-3.rs:1:1 | LL | const A: i32 = B; | ^^^^^^^^^^^^^^^^^ | -note: ...which requires simplifying constant for the type system `A`... - --> $DIR/issue-23302-3.rs:1:1 - | -LL | const A: i32 = B; - | ^^^^^^^^^^^^^^^^^ -note: ...which requires const-evaluating + checking `A`... - --> $DIR/issue-23302-3.rs:1:1 - | -LL | const A: i32 = B; - | ^^^^^^^^^^^^^^^^^ - = note: ...which requires normalizing `B`... -note: ...which requires simplifying constant for the type system `B`... - --> $DIR/issue-23302-3.rs:3:1 - | -LL | const B: i32 = A; - | ^^^^^^^^^^^^^^^^^ -note: ...which requires simplifying constant for the type system `B`... +note: ...which requires const-evaluating + checking `B`... --> $DIR/issue-23302-3.rs:3:1 | LL | const B: i32 = A; | ^^^^^^^^^^^^^^^^^ -note: ...which requires const-evaluating + checking `B`... - --> $DIR/issue-23302-3.rs:3:1 + = note: ...which again requires const-evaluating + checking `A`, completing the cycle +note: cycle used when simplifying constant for the type system `A` + --> $DIR/issue-23302-3.rs:1:1 | -LL | const B: i32 = A; +LL | const A: i32 = B; | ^^^^^^^^^^^^^^^^^ - = note: ...which requires normalizing `A`... - = note: ...which again requires simplifying constant for the type system `A`, completing the cycle - = note: cycle used when running analysis passes on this crate error: aborting due to previous error diff --git a/src/test/ui/issues/issue-41394.rs b/src/test/ui/issues/issue-41394.rs index 06a330813406a..64873ac35a002 100644 --- a/src/test/ui/issues/issue-41394.rs +++ b/src/test/ui/issues/issue-41394.rs @@ -5,6 +5,7 @@ enum Foo { enum Bar { A = Foo::A as isize + //~^ ERROR evaluation of constant value failed } fn main() {} diff --git a/src/test/ui/issues/issue-41394.stderr b/src/test/ui/issues/issue-41394.stderr index fa95ca9c18a10..47a24547d4533 100644 --- a/src/test/ui/issues/issue-41394.stderr +++ b/src/test/ui/issues/issue-41394.stderr @@ -6,6 +6,13 @@ LL | A = "" + 1 | | | &str -error: aborting due to previous error +error[E0080]: evaluation of constant value failed + --> $DIR/issue-41394.rs:7:9 + | +LL | A = Foo::A as isize + | ^^^^^^^^^^^^^^^ referenced constant has errors + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0369`. +Some errors have detailed explanations: E0080, E0369. +For more information about an error, try `rustc --explain E0080`. diff --git a/src/test/ui/issues/issue-54954.rs b/src/test/ui/issues/issue-54954.rs index 42a4d5b674b22..ddd3914154147 100644 --- a/src/test/ui/issues/issue-54954.rs +++ b/src/test/ui/issues/issue-54954.rs @@ -9,6 +9,8 @@ trait Tt { } fn f(z: [f32; ARR_LEN]) -> [f32; ARR_LEN] { + //~^ ERROR evaluation of constant value failed + //~| ERROR evaluation of constant value failed z } diff --git a/src/test/ui/issues/issue-54954.stderr b/src/test/ui/issues/issue-54954.stderr index efe2ef504a2ba..6e8d3cac9a7e4 100644 --- a/src/test/ui/issues/issue-54954.stderr +++ b/src/test/ui/issues/issue-54954.stderr @@ -12,7 +12,19 @@ LL | const ARR_LEN: usize = Tt::const_val::<[i8; 123]>(); | = note: cannot satisfy `_: Tt` -error: aborting due to 2 previous errors +error[E0080]: evaluation of constant value failed + --> $DIR/issue-54954.rs:11:15 + | +LL | fn f(z: [f32; ARR_LEN]) -> [f32; ARR_LEN] { + | ^^^^^^^ referenced constant has errors + +error[E0080]: evaluation of constant value failed + --> $DIR/issue-54954.rs:11:34 + | +LL | fn f(z: [f32; ARR_LEN]) -> [f32; ARR_LEN] { + | ^^^^^^^ referenced constant has errors + +error: aborting due to 4 previous errors -Some errors have detailed explanations: E0283, E0379. -For more information about an error, try `rustc --explain E0283`. +Some errors have detailed explanations: E0080, E0283, E0379. +For more information about an error, try `rustc --explain E0080`. diff --git a/src/test/ui/issues/issue-69602-type-err-during-codegen-ice.rs b/src/test/ui/issues/issue-69602-type-err-during-codegen-ice.rs index 2c5257ce063cb..6851b67cb3b3a 100644 --- a/src/test/ui/issues/issue-69602-type-err-during-codegen-ice.rs +++ b/src/test/ui/issues/issue-69602-type-err-during-codegen-ice.rs @@ -19,4 +19,5 @@ impl TraitB for B { //~ ERROR not all trait items implemented, missing: `MyA` fn main() { let _ = [0; B::VALUE]; + //~^ ERROR evaluation of constant value failed } diff --git a/src/test/ui/issues/issue-69602-type-err-during-codegen-ice.stderr b/src/test/ui/issues/issue-69602-type-err-during-codegen-ice.stderr index 8ae0f8b804c93..cb5b397849c06 100644 --- a/src/test/ui/issues/issue-69602-type-err-during-codegen-ice.stderr +++ b/src/test/ui/issues/issue-69602-type-err-during-codegen-ice.stderr @@ -13,7 +13,13 @@ LL | type MyA: TraitA; LL | impl TraitB for B { | ^^^^^^^^^^^^^^^^^ missing `MyA` in implementation -error: aborting due to 2 previous errors +error[E0080]: evaluation of constant value failed + --> $DIR/issue-69602-type-err-during-codegen-ice.rs:21:17 + | +LL | let _ = [0; B::VALUE]; + | ^^^^^^^^ referenced constant has errors + +error: aborting due to 3 previous errors -Some errors have detailed explanations: E0046, E0437. +Some errors have detailed explanations: E0046, E0080, E0437. For more information about an error, try `rustc --explain E0046`. diff --git a/src/test/ui/issues/issue-77919.rs b/src/test/ui/issues/issue-77919.rs index 966d76d148af3..c2946ad94b0b7 100644 --- a/src/test/ui/issues/issue-77919.rs +++ b/src/test/ui/issues/issue-77919.rs @@ -1,5 +1,6 @@ fn main() { [1; >::VAL]; + //~^ ERROR evaluation of constant value failed } trait TypeVal { const VAL: T; diff --git a/src/test/ui/issues/issue-77919.stderr b/src/test/ui/issues/issue-77919.stderr index 97bd5ab36b65d..8d5d6cb037749 100644 --- a/src/test/ui/issues/issue-77919.stderr +++ b/src/test/ui/issues/issue-77919.stderr @@ -1,5 +1,5 @@ error[E0412]: cannot find type `PhantomData` in this scope - --> $DIR/issue-77919.rs:9:9 + --> $DIR/issue-77919.rs:10:9 | LL | _n: PhantomData, | ^^^^^^^^^^^ not found in this scope @@ -10,7 +10,7 @@ LL | use std::marker::PhantomData; | error[E0412]: cannot find type `VAL` in this scope - --> $DIR/issue-77919.rs:11:63 + --> $DIR/issue-77919.rs:12:63 | LL | impl TypeVal for Multiply where N: TypeVal {} | - ^^^ not found in this scope @@ -18,7 +18,7 @@ LL | impl TypeVal for Multiply where N: TypeVal {} | help: you might be missing a type parameter: `, VAL` error[E0046]: not all trait items implemented, missing: `VAL` - --> $DIR/issue-77919.rs:11:1 + --> $DIR/issue-77919.rs:12:1 | LL | const VAL: T; | ------------- `VAL` from trait @@ -26,7 +26,13 @@ LL | const VAL: T; LL | impl TypeVal for Multiply where N: TypeVal {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `VAL` in implementation -error: aborting due to 3 previous errors +error[E0080]: evaluation of constant value failed + --> $DIR/issue-77919.rs:2:9 + | +LL | [1; >::VAL]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors + +error: aborting due to 4 previous errors -Some errors have detailed explanations: E0046, E0412. +Some errors have detailed explanations: E0046, E0080, E0412. For more information about an error, try `rustc --explain E0046`. diff --git a/src/test/ui/resolve/issue-50599.rs b/src/test/ui/resolve/issue-50599.rs index 00588735b9a59..78a20cf8ebb05 100644 --- a/src/test/ui/resolve/issue-50599.rs +++ b/src/test/ui/resolve/issue-50599.rs @@ -2,4 +2,5 @@ fn main() { const N: u32 = 1_000; const M: usize = (f64::from(N) * std::f64::LOG10_2) as usize; //~ ERROR cannot find value let mut digits = [0u32; M]; + //~^ ERROR evaluation of constant value failed } diff --git a/src/test/ui/resolve/issue-50599.stderr b/src/test/ui/resolve/issue-50599.stderr index 7ec567a06f09d..effa16e55e54e 100644 --- a/src/test/ui/resolve/issue-50599.stderr +++ b/src/test/ui/resolve/issue-50599.stderr @@ -11,6 +11,13 @@ LL | use std::f32::consts::LOG10_2; LL | use std::f64::consts::LOG10_2; | -error: aborting due to previous error +error[E0080]: evaluation of constant value failed + --> $DIR/issue-50599.rs:4:29 + | +LL | let mut digits = [0u32; M]; + | ^ referenced constant has errors + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0425`. +Some errors have detailed explanations: E0080, E0425. +For more information about an error, try `rustc --explain E0080`. diff --git a/src/test/ui/type/type-dependent-def-issue-49241.rs b/src/test/ui/type/type-dependent-def-issue-49241.rs index 4b6bc6124dbf3..51bd116fbd61c 100644 --- a/src/test/ui/type/type-dependent-def-issue-49241.rs +++ b/src/test/ui/type/type-dependent-def-issue-49241.rs @@ -2,4 +2,5 @@ fn main() { let v = vec![0]; const l: usize = v.count(); //~ ERROR attempt to use a non-constant value in a constant let s: [u32; l] = v.into_iter().collect(); + //~^ ERROR evaluation of constant value failed } diff --git a/src/test/ui/type/type-dependent-def-issue-49241.stderr b/src/test/ui/type/type-dependent-def-issue-49241.stderr index 64c7687f7a882..02f267c6c8d73 100644 --- a/src/test/ui/type/type-dependent-def-issue-49241.stderr +++ b/src/test/ui/type/type-dependent-def-issue-49241.stderr @@ -6,6 +6,13 @@ LL | const l: usize = v.count(); | | | help: consider using `let` instead of `const`: `let l` -error: aborting due to previous error +error[E0080]: evaluation of constant value failed + --> $DIR/type-dependent-def-issue-49241.rs:4:18 + | +LL | let s: [u32; l] = v.into_iter().collect(); + | ^ referenced constant has errors + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0435`. +Some errors have detailed explanations: E0080, E0435. +For more information about an error, try `rustc --explain E0080`. From 26fe5506702a1f99f4b860a40d7104bfe1216bbe Mon Sep 17 00:00:00 2001 From: b-naber Date: Tue, 8 Mar 2022 15:05:50 +0100 Subject: [PATCH 14/28] normalization change and rebase --- Cargo.lock | 2 +- .../src/interpret/eval_context.rs | 8 +- .../rustc_const_eval/src/interpret/intern.rs | 2 + .../rustc_const_eval/src/interpret/memory.rs | 3 + .../src/traits/query/normalize.rs | 2 +- ...allocation2.main.ConstProp.after.64bit.mir | 32 +++---- ..._line_doc_comment_2.DeduplicateBlocks.diff | 2 +- .../inline/inline_diverging.g.Inline.diff | 2 +- .../inline/inline_generator.main.Inline.diff | 8 -- ...line_into_box_place.main.Inline.64bit.diff | 12 --- .../inline/issue_78442.bar.Inline.diff | 2 +- ...ue_59352.num_to_digit.PreCodegen.after.mir | 2 +- ...age_markers.main.RemoveStorageMarkers.diff | 2 +- .../associated-consts/defaults-cyclic-fail.rs | 2 +- .../defaults-cyclic-fail.stderr | 28 +++++- ...9-assoc-const-static-recursion-impl.stderr | 37 +++++--- ...onst-static-recursion-trait-default.stderr | 37 +++++--- ...-assoc-const-static-recursion-trait.stderr | 37 +++++--- .../borrowck/issue-88434-minimal-example.rs | 2 - .../issue-88434-minimal-example.stderr | 23 +---- ...ssue-88434-removal-index-should-be-less.rs | 2 - ...-88434-removal-index-should-be-less.stderr | 20 +--- .../ui/const-ptr/out_of_bounds_read.stderr | 6 +- .../const-eval/const-eval-query-stack.rs | 4 +- .../const-eval/const-eval-query-stack.stderr | 22 ++--- src/test/ui/consts/const-integer-bool-ops.rs | 10 -- .../ui/consts/const-integer-bool-ops.stderr | 95 ++++--------------- .../const-mut-refs/issue-76510.64bit.stderr | 12 +-- .../ui/consts/const-mut-refs/issue-76510.rs | 1 - src/test/ui/consts/const-tup-index-span.rs | 1 - .../ui/consts/const-tup-index-span.stderr | 11 +-- src/test/ui/consts/invalid-union.64bit.stderr | 2 +- src/test/ui/consts/issue-36163.stderr | 40 ++++++-- src/test/ui/issues/issue-17252.stderr | 15 ++- src/test/ui/issues/issue-23302-1.stderr | 17 +++- src/test/ui/issues/issue-23302-2.stderr | 17 +++- src/test/ui/issues/issue-23302-3.stderr | 30 ++++-- src/test/ui/issues/issue-41394.rs | 1 - src/test/ui/issues/issue-41394.stderr | 11 +-- src/test/ui/issues/issue-54954.rs | 2 - src/test/ui/issues/issue-54954.stderr | 18 +--- ...issue-69602-type-err-during-codegen-ice.rs | 1 - ...e-69602-type-err-during-codegen-ice.stderr | 10 +- src/test/ui/issues/issue-77919.rs | 1 - src/test/ui/issues/issue-77919.stderr | 16 +--- src/test/ui/resolve/issue-50599.rs | 1 - src/test/ui/resolve/issue-50599.stderr | 11 +-- .../ui/type/type-dependent-def-issue-49241.rs | 1 - .../type-dependent-def-issue-49241.stderr | 11 +-- 49 files changed, 290 insertions(+), 344 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 29ea0a0726ca5..4d7b62e9c559f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -311,7 +311,7 @@ dependencies = [ [[package]] name = "cargo" -version = "0.61.0" +version = "0.62.0" dependencies = [ "anyhow", "atty", diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs index 45ac3cd1f84a6..a8a57e6990ffd 100644 --- a/compiler/rustc_const_eval/src/interpret/eval_context.rs +++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs @@ -164,7 +164,7 @@ pub enum StackPopCleanup { } /// State of a local variable including a memoized layout -#[derive(Clone, PartialEq, Eq, HashStable)] +#[derive(Clone, Debug, PartialEq, Eq, HashStable)] pub struct LocalState<'tcx, Tag: Provenance = AllocId> { pub value: LocalValue, /// Don't modify if `Some`, this is only used to prevent computing the layout twice @@ -714,6 +714,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { self.size_and_align_of(&mplace.meta, &mplace.layout) } + #[instrument(skip(self, body, return_place, return_to_block), level = "debug")] pub fn push_stack_frame( &mut self, instance: ty::Instance<'tcx>, @@ -721,6 +722,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { return_place: Option<&PlaceTy<'tcx, M::PointerTag>>, return_to_block: StackPopCleanup, ) -> InterpResult<'tcx> { + debug!("body: {:#?}", body); // first push a stack frame so we have access to the local substs let pre_frame = Frame { body, @@ -824,6 +826,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { /// `Drop` impls for any locals that have been initialized at this point. /// The cleanup block ends with a special `Resume` terminator, which will /// cause us to continue unwinding. + #[instrument(skip(self), level = "debug")] pub(super) fn pop_stack_frame(&mut self, unwinding: bool) -> InterpResult<'tcx> { info!( "popping stack frame ({})", @@ -876,6 +879,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { return Ok(()); } + debug!("locals: {:#?}", frame.locals); + // Cleanup: deallocate all locals that are backed by an allocation. for local in &frame.locals { self.deallocate_local(local.value)?; @@ -935,6 +940,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Ok(()) } + #[instrument(skip(self), level = "debug")] fn deallocate_local(&mut self, local: LocalValue) -> InterpResult<'tcx> { if let LocalValue::Live(Operand::Indirect(MemPlace { ptr, .. })) = local { // All locals have a backing allocation, even if the allocation is empty diff --git a/compiler/rustc_const_eval/src/interpret/intern.rs b/compiler/rustc_const_eval/src/interpret/intern.rs index bacb3f6ea7fec..fa8151a1f3c3d 100644 --- a/compiler/rustc_const_eval/src/interpret/intern.rs +++ b/compiler/rustc_const_eval/src/interpret/intern.rs @@ -359,6 +359,8 @@ pub fn intern_const_alloc_recursive< // pointers, ... So we can't intern them according to their type rules let mut todo: Vec<_> = leftover_allocations.iter().cloned().collect(); + debug!(?todo); + debug!("dead_alloc_map: {:#?}", ecx.memory.dead_alloc_map); while let Some(alloc_id) = todo.pop() { if let Some((_, mut alloc)) = ecx.memory.alloc_map.remove(&alloc_id) { // We can't call the `intern_shallow` method here, as its logic is tailored to safe diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs index e100ebc4ccb28..5fe4672f17e5b 100644 --- a/compiler/rustc_const_eval/src/interpret/memory.rs +++ b/compiler/rustc_const_eval/src/interpret/memory.rs @@ -275,6 +275,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { Ok(new_ptr) } + #[instrument(skip(self), level = "debug")] pub fn deallocate( &mut self, ptr: Pointer>, @@ -305,6 +306,8 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { .into()); }; + debug!(?alloc); + if alloc.mutability == Mutability::Not { throw_ub_format!("deallocating immutable allocation {}", alloc_id); } diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs index 0e05900823fce..ed0ad5601aa40 100644 --- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs @@ -336,7 +336,7 @@ impl<'cx, 'tcx> FallibleTypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> { ) -> Result, Self::Error> { let constant_kind = match constant { mir::ConstantKind::Ty(c) => { - let const_folded = c.try_super_fold_with(self)?; + let const_folded = c.try_fold_with(self)?; match const_folded.val() { ty::ConstKind::Value(cv) => { // FIXME With Valtrees we need to convert `cv: ValTree` diff --git a/src/test/mir-opt/const_allocation2.main.ConstProp.after.64bit.mir b/src/test/mir-opt/const_allocation2.main.ConstProp.after.64bit.mir index e2acd610b8053..ef651f01c9b98 100644 --- a/src/test/mir-opt/const_allocation2.main.ConstProp.after.64bit.mir +++ b/src/test/mir-opt/const_allocation2.main.ConstProp.after.64bit.mir @@ -21,44 +21,44 @@ fn main() -> () { } alloc1 (static: FOO, size: 16, align: 8) { - ╾───────alloc22───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ + ╾───────alloc28───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ } -alloc22 (size: 72, align: 8) { - 0x00 │ 00 00 00 00 __ __ __ __ ╾───────alloc9────────╼ │ ....░░░░╾──────╼ +alloc28 (size: 72, align: 8) { + 0x00 │ 00 00 00 00 __ __ __ __ ╾───────alloc13───────╼ │ ....░░░░╾──────╼ 0x10 │ 00 00 00 00 00 00 00 00 00 00 00 00 __ __ __ __ │ ............░░░░ - 0x20 │ ╾───────alloc14───────╼ 02 00 00 00 00 00 00 00 │ ╾──────╼........ - 0x30 │ 01 00 00 00 2a 00 00 00 ╾───────alloc20───────╼ │ ....*...╾──────╼ + 0x20 │ ╾───────alloc18───────╼ 02 00 00 00 00 00 00 00 │ ╾──────╼........ + 0x30 │ 01 00 00 00 2a 00 00 00 ╾───────alloc26───────╼ │ ....*...╾──────╼ 0x40 │ 03 00 00 00 00 00 00 00 │ ........ } -alloc9 (size: 0, align: 8) {} +alloc13 (size: 0, align: 8) {} -alloc14 (size: 16, align: 8) { - ╾───────alloc12───────╼ ╾───────alloc13───────╼ │ ╾──────╼╾──────╼ +alloc18 (size: 16, align: 8) { + ╾───────alloc16───────╼ ╾───────alloc17───────╼ │ ╾──────╼╾──────╼ } -alloc12 (size: 1, align: 1) { +alloc16 (size: 1, align: 1) { 05 │ . } -alloc13 (size: 1, align: 1) { +alloc17 (size: 1, align: 1) { 06 │ . } -alloc20 (size: 24, align: 8) { - 0x00 │ ╾─────alloc17+0x3─────╼ ╾───────alloc18───────╼ │ ╾──────╼╾──────╼ - 0x10 │ ╾─────alloc19+0x2─────╼ │ ╾──────╼ +alloc26 (size: 24, align: 8) { + 0x00 │ ╾─────alloc22+0x3─────╼ ╾───────alloc23───────╼ │ ╾──────╼╾──────╼ + 0x10 │ ╾─────alloc25+0x2─────╼ │ ╾──────╼ } -alloc17 (size: 4, align: 1) { +alloc22 (size: 4, align: 1) { 2a 45 15 6f │ *E.o } -alloc18 (size: 1, align: 1) { +alloc23 (size: 1, align: 1) { 2a │ * } -alloc19 (size: 4, align: 1) { +alloc25 (size: 4, align: 1) { 2a 45 15 6f │ *E.o } diff --git a/src/test/mir-opt/deduplicate_blocks.is_line_doc_comment_2.DeduplicateBlocks.diff b/src/test/mir-opt/deduplicate_blocks.is_line_doc_comment_2.DeduplicateBlocks.diff index 122bef522cf4d..372b14eb7c92a 100644 --- a/src/test/mir-opt/deduplicate_blocks.is_line_doc_comment_2.DeduplicateBlocks.diff +++ b/src/test/mir-opt/deduplicate_blocks.is_line_doc_comment_2.DeduplicateBlocks.diff @@ -26,7 +26,7 @@ - _2 = transmute::<&str, &[u8]>(move _8) -> bb14; // scope 2 at $SRC_DIR/core/src/str/mod.rs:LL:COL + _2 = transmute::<&str, &[u8]>(move _8) -> bb12; // scope 2 at $SRC_DIR/core/src/str/mod.rs:LL:COL // mir::Constant - // + span: $DIR/deduplicate_blocks.rs:3:11: 3:23 + // + span: $SRC_DIR/core/src/str/mod.rs:LL:COL // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(&str) -> &[u8] {transmute::<&str, &[u8]>}, val: Value(Scalar()) } } diff --git a/src/test/mir-opt/inline/inline_diverging.g.Inline.diff b/src/test/mir-opt/inline/inline_diverging.g.Inline.diff index cb79cdd3579ea..3b9d5e727b8a3 100644 --- a/src/test/mir-opt/inline/inline_diverging.g.Inline.diff +++ b/src/test/mir-opt/inline/inline_diverging.g.Inline.diff @@ -39,7 +39,7 @@ // mir::Constant - // + span: $DIR/inline-diverging.rs:16:9: 16:14 - // + literal: Const { ty: fn() -> ! {panic}, val: Value(Scalar()) } -+ // + span: $DIR/inline-diverging.rs:16:9: 16:16 ++ // + span: $SRC_DIR/std/src/panic.rs:LL:COL + // + literal: Const { ty: fn(&str) -> ! {begin_panic::<&str>}, val: Value(Scalar()) } + // mir::Constant + // + span: $SRC_DIR/std/src/panic.rs:LL:COL diff --git a/src/test/mir-opt/inline/inline_generator.main.Inline.diff b/src/test/mir-opt/inline/inline_generator.main.Inline.diff index 1f736301c7699..831d73045dd63 100644 --- a/src/test/mir-opt/inline/inline_generator.main.Inline.diff +++ b/src/test/mir-opt/inline/inline_generator.main.Inline.diff @@ -50,11 +50,7 @@ - // mir::Constant - // + span: $DIR/inline-generator.rs:9:14: 9:22 - // + user_ty: UserType(0) -<<<<<<< HEAD -- // + literal: Const { ty: fn(&mut impl Generator) -> Pin<&mut impl Generator> {Pin::<&mut impl Generator>::new}, val: Value(Scalar()) } -======= - // + literal: Const { ty: fn(&mut [generator@$DIR/inline-generator.rs:15:5: 15:41]) -> Pin<&mut [generator@$DIR/inline-generator.rs:15:5: 15:41]> {Pin::<&mut [generator@$DIR/inline-generator.rs:15:5: 15:41]>::new}, val: Value(Scalar()) } ->>>>>>> a4feb9af018 (bless tests) - } - - bb2: { @@ -69,11 +65,7 @@ - _1 = <[generator@$DIR/inline-generator.rs:15:5: 15:41] as Generator>::resume(move _2, const false) -> [return: bb3, unwind: bb4]; // scope 0 at $DIR/inline-generator.rs:9:14: 9:46 - // mir::Constant - // + span: $DIR/inline-generator.rs:9:33: 9:39 -<<<<<<< HEAD -- // + literal: Const { ty: for<'r> fn(Pin<&'r mut impl Generator>, bool) -> GeneratorState< as Generator>::Yield, as Generator>::Return> { as Generator>::resume}, val: Value(Scalar()) } -======= - // + literal: Const { ty: for<'r> fn(Pin<&'r mut [generator@$DIR/inline-generator.rs:15:5: 15:41]>, bool) -> GeneratorState<<[generator@$DIR/inline-generator.rs:15:5: 15:41] as Generator>::Yield, <[generator@$DIR/inline-generator.rs:15:5: 15:41] as Generator>::Return> {<[generator@$DIR/inline-generator.rs:15:5: 15:41] as Generator>::resume}, val: Value(Scalar()) } ->>>>>>> a4feb9af018 (bless tests) + StorageLive(_7); // scope 0 at $DIR/inline-generator.rs:9:14: 9:46 + _7 = const false; // scope 0 at $DIR/inline-generator.rs:9:14: 9:46 + StorageLive(_10); // scope 0 at $DIR/inline-generator.rs:9:14: 9:46 diff --git a/src/test/mir-opt/inline/inline_into_box_place.main.Inline.64bit.diff b/src/test/mir-opt/inline/inline_into_box_place.main.Inline.64bit.diff index f2cdd987091d6..0f83b0c4a27ad 100644 --- a/src/test/mir-opt/inline/inline_into_box_place.main.Inline.64bit.diff +++ b/src/test/mir-opt/inline/inline_into_box_place.main.Inline.64bit.diff @@ -34,14 +34,7 @@ - (*_5) = Vec::::new() -> [return: bb2, unwind: bb5]; // scope 0 at $DIR/inline-into-box-place.rs:8:33: 8:43 + StorageLive(_7); // scope 0 at $DIR/inline-into-box-place.rs:8:33: 8:43 + _7 = &mut (*_5); // scope 0 at $DIR/inline-into-box-place.rs:8:33: 8:43 -<<<<<<< HEAD + ((*_7).0: alloc::raw_vec::RawVec) = const alloc::raw_vec::RawVec:: { ptr: Unique:: { pointer: {0x4 as *const u32}, _marker: PhantomData:: }, cap: 0_usize, alloc: std::alloc::Global }; // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL -======= -+ ((*_7).0: alloc::raw_vec::RawVec) = const alloc::raw_vec::RawVec::::NEW; // scope 3 at $DIR/inline-into-box-place.rs:8:33: 8:43 -+ // ty::Const -+ // + ty: alloc::raw_vec::RawVec -+ // + val: Unevaluated(alloc::raw_vec::RawVec::::NEW, [u32], None) ->>>>>>> a4feb9af018 (bless tests) // mir::Constant - // + span: $DIR/inline-into-box-place.rs:8:33: 8:41 - // + user_ty: UserType(1) @@ -51,13 +44,8 @@ - bb2: { + // + span: $SRC_DIR/alloc/src/vec/mod.rs:LL:COL + // + user_ty: UserType(0) -<<<<<<< HEAD + // + literal: Const { ty: alloc::raw_vec::RawVec, val: Value(ByRef { alloc: Allocation { bytes: [4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [65535], len: Size { raw: 16 } }, align: Align { pow2: 3 }, mutability: Not, extra: () }, offset: Size { raw: 0 } }) } + ((*_7).1: usize) = const 0_usize; // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL -======= -+ // + literal: Const { ty: alloc::raw_vec::RawVec, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(5:77 ~ alloc[bd09]::raw_vec::{impl#0}::NEW), const_param_did: None }, substs: [u32], promoted: None }) } -+ ((*_7).1: usize) = const 0_usize; // scope 3 at $DIR/inline-into-box-place.rs:8:33: 8:43 ->>>>>>> a4feb9af018 (bless tests) + StorageDead(_7); // scope 0 at $DIR/inline-into-box-place.rs:8:33: 8:43 _1 = move _5; // scope 0 at $DIR/inline-into-box-place.rs:8:29: 8:43 StorageDead(_5); // scope 0 at $DIR/inline-into-box-place.rs:8:42: 8:43 diff --git a/src/test/mir-opt/inline/issue_78442.bar.Inline.diff b/src/test/mir-opt/inline/issue_78442.bar.Inline.diff index 92daef637e45b..ea6b91cba9e58 100644 --- a/src/test/mir-opt/inline/issue_78442.bar.Inline.diff +++ b/src/test/mir-opt/inline/issue_78442.bar.Inline.diff @@ -29,7 +29,7 @@ - // mir::Constant - // + span: $DIR/issue-78442.rs:11:5: 11:15 - // + literal: Const { ty: for<'r> extern "rust-call" fn(&'r fn() {foo}, ()) -> >::Output {>::call}, val: Value(Scalar()) } -+ _2 = move (*_3)() -> [return: bb5, unwind: bb3]; // scope 1 at $DIR/issue-78442.rs:11:5: 11:17 ++ _2 = move (*_3)() -> [return: bb5, unwind: bb3]; // scope 1 at $SRC_DIR/core/src/ops/function.rs:LL:COL } bb2: { diff --git a/src/test/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.mir b/src/test/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.mir index c5c063e8cecf1..e2051c85af215 100644 --- a/src/test/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.mir +++ b/src/test/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.mir @@ -38,7 +38,7 @@ fn num_to_digit(_1: char) -> u32 { _8 = _2; // scope 1 at $SRC_DIR/core/src/char/methods.rs:LL:COL _7 = char::methods::::to_digit(move _8, const 8_u32) -> bb5; // scope 1 at $SRC_DIR/core/src/char/methods.rs:LL:COL // mir::Constant - // + span: $DIR/issue-59352.rs:14:8: 14:23 + // + span: $SRC_DIR/core/src/char/methods.rs:LL:COL // + literal: Const { ty: fn(char, u32) -> Option {char::methods::::to_digit}, val: Value(Scalar()) } } diff --git a/src/test/mir-opt/remove_storage_markers.main.RemoveStorageMarkers.diff b/src/test/mir-opt/remove_storage_markers.main.RemoveStorageMarkers.diff index ec76424afa55e..312031b7a0ff4 100644 --- a/src/test/mir-opt/remove_storage_markers.main.RemoveStorageMarkers.diff +++ b/src/test/mir-opt/remove_storage_markers.main.RemoveStorageMarkers.diff @@ -58,7 +58,7 @@ _14 = &mut (*_8); // scope 5 at $SRC_DIR/core/src/iter/range.rs:LL:COL _7 = as iter::range::RangeIteratorImpl>::spec_next(move _14) -> bb4; // scope 5 at $SRC_DIR/core/src/iter/range.rs:LL:COL // mir::Constant - // + span: $DIR/remove_storage_markers.rs:8:14: 8:19 + // + span: $SRC_DIR/core/src/iter/range.rs:LL:COL // + literal: Const { ty: for<'r> fn(&'r mut std::ops::Range) -> Option< as iter::range::RangeIteratorImpl>::Item> { as iter::range::RangeIteratorImpl>::spec_next}, val: Value(Scalar()) } } diff --git a/src/test/ui/associated-consts/defaults-cyclic-fail.rs b/src/test/ui/associated-consts/defaults-cyclic-fail.rs index 9b899ee316a0e..81b747424576c 100644 --- a/src/test/ui/associated-consts/defaults-cyclic-fail.rs +++ b/src/test/ui/associated-consts/defaults-cyclic-fail.rs @@ -1,9 +1,9 @@ // build-fail +//~^ cycle detected when normalizing `<() as Tr>::A` [E0391] // Cyclic assoc. const defaults don't error unless *used* trait Tr { const A: u8 = Self::B; - //~^ ERROR cycle detected when const-evaluating + checking `Tr::A` const B: u8 = Self::A; } diff --git a/src/test/ui/associated-consts/defaults-cyclic-fail.stderr b/src/test/ui/associated-consts/defaults-cyclic-fail.stderr index 550897790e9ff..3fb4ab72fe6d6 100644 --- a/src/test/ui/associated-consts/defaults-cyclic-fail.stderr +++ b/src/test/ui/associated-consts/defaults-cyclic-fail.stderr @@ -1,15 +1,37 @@ -error[E0391]: cycle detected when const-evaluating + checking `Tr::A` - --> $DIR/defaults-cyclic-fail.rs:5:5 +error[E0391]: cycle detected when normalizing `<() as Tr>::A` + | +note: ...which requires simplifying constant for the type system `Tr::A`... + --> $DIR/defaults-cyclic-fail.rs:6:5 + | +LL | const A: u8 = Self::B; + | ^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires simplifying constant for the type system `Tr::A`... + --> $DIR/defaults-cyclic-fail.rs:6:5 + | +LL | const A: u8 = Self::B; + | ^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires const-evaluating + checking `Tr::A`... + --> $DIR/defaults-cyclic-fail.rs:6:5 | LL | const A: u8 = Self::B; | ^^^^^^^^^^^^^^^^^^^^^^ + = note: ...which requires normalizing `<() as Tr>::B`... +note: ...which requires simplifying constant for the type system `Tr::B`... + --> $DIR/defaults-cyclic-fail.rs:8:5 | +LL | const B: u8 = Self::A; + | ^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires simplifying constant for the type system `Tr::B`... + --> $DIR/defaults-cyclic-fail.rs:8:5 + | +LL | const B: u8 = Self::A; + | ^^^^^^^^^^^^^^^^^^^^^^ note: ...which requires const-evaluating + checking `Tr::B`... --> $DIR/defaults-cyclic-fail.rs:8:5 | LL | const B: u8 = Self::A; | ^^^^^^^^^^^^^^^^^^^^^^ - = note: ...which again requires const-evaluating + checking `Tr::A`, completing the cycle + = note: ...which again requires normalizing `<() as Tr>::A`, completing the cycle note: cycle used when const-evaluating + checking `main::promoted[1]` --> $DIR/defaults-cyclic-fail.rs:14:1 | diff --git a/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-impl.stderr b/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-impl.stderr index 14b09072533df..61b16cb9d5811 100644 --- a/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-impl.stderr +++ b/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-impl.stderr @@ -1,30 +1,43 @@ -error[E0391]: cycle detected when const-evaluating + checking `IMPL_REF_BAR` +error[E0391]: cycle detected when simplifying constant for the type system `IMPL_REF_BAR` --> $DIR/issue-24949-assoc-const-static-recursion-impl.rs:7:1 | LL | const IMPL_REF_BAR: u32 = GlobalImplRef::BAR; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: ...which requires const-evaluating + checking `::BAR`... +note: ...which requires simplifying constant for the type system `IMPL_REF_BAR`... + --> $DIR/issue-24949-assoc-const-static-recursion-impl.rs:7:1 + | +LL | const IMPL_REF_BAR: u32 = GlobalImplRef::BAR; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires const-evaluating + checking `IMPL_REF_BAR`... + --> $DIR/issue-24949-assoc-const-static-recursion-impl.rs:7:1 + | +LL | const IMPL_REF_BAR: u32 = GlobalImplRef::BAR; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: ...which requires normalizing `::BAR`... +note: ...which requires simplifying constant for the type system `::BAR`... --> $DIR/issue-24949-assoc-const-static-recursion-impl.rs:12:5 | LL | const BAR: u32 = IMPL_REF_BAR; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -note: ...which requires caching mir of `::BAR` for CTFE... +note: ...which requires simplifying constant for the type system `::BAR`... --> $DIR/issue-24949-assoc-const-static-recursion-impl.rs:12:5 | LL | const BAR: u32 = IMPL_REF_BAR; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -note: ...which requires const-evaluating + checking `IMPL_REF_BAR`... - --> $DIR/issue-24949-assoc-const-static-recursion-impl.rs:7:1 +note: ...which requires const-evaluating + checking `::BAR`... + --> $DIR/issue-24949-assoc-const-static-recursion-impl.rs:12:5 | -LL | const IMPL_REF_BAR: u32 = GlobalImplRef::BAR; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: ...which again requires const-evaluating + checking `IMPL_REF_BAR`, completing the cycle -note: cycle used when simplifying constant for the type system `IMPL_REF_BAR` - --> $DIR/issue-24949-assoc-const-static-recursion-impl.rs:7:1 +LL | const BAR: u32 = IMPL_REF_BAR; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires caching mir of `::BAR` for CTFE... + --> $DIR/issue-24949-assoc-const-static-recursion-impl.rs:12:5 | -LL | const IMPL_REF_BAR: u32 = GlobalImplRef::BAR; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | const BAR: u32 = IMPL_REF_BAR; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: ...which requires normalizing `IMPL_REF_BAR`... + = note: ...which again requires simplifying constant for the type system `IMPL_REF_BAR`, completing the cycle + = note: cycle used when running analysis passes on this crate error: aborting due to previous error diff --git a/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait-default.stderr b/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait-default.stderr index 682f56a6a5575..494dc0c0ed447 100644 --- a/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait-default.stderr +++ b/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait-default.stderr @@ -1,30 +1,43 @@ -error[E0391]: cycle detected when const-evaluating + checking `DEFAULT_REF_BAR` +error[E0391]: cycle detected when simplifying constant for the type system `DEFAULT_REF_BAR` --> $DIR/issue-24949-assoc-const-static-recursion-trait-default.rs:11:1 | LL | const DEFAULT_REF_BAR: u32 = ::BAR; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: ...which requires const-evaluating + checking `FooDefault::BAR`... +note: ...which requires simplifying constant for the type system `DEFAULT_REF_BAR`... + --> $DIR/issue-24949-assoc-const-static-recursion-trait-default.rs:11:1 + | +LL | const DEFAULT_REF_BAR: u32 = ::BAR; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires const-evaluating + checking `DEFAULT_REF_BAR`... + --> $DIR/issue-24949-assoc-const-static-recursion-trait-default.rs:11:1 + | +LL | const DEFAULT_REF_BAR: u32 = ::BAR; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: ...which requires normalizing `::BAR`... +note: ...which requires simplifying constant for the type system `FooDefault::BAR`... --> $DIR/issue-24949-assoc-const-static-recursion-trait-default.rs:8:5 | LL | const BAR: u32 = DEFAULT_REF_BAR; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -note: ...which requires caching mir of `FooDefault::BAR` for CTFE... +note: ...which requires simplifying constant for the type system `FooDefault::BAR`... --> $DIR/issue-24949-assoc-const-static-recursion-trait-default.rs:8:5 | LL | const BAR: u32 = DEFAULT_REF_BAR; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -note: ...which requires const-evaluating + checking `DEFAULT_REF_BAR`... - --> $DIR/issue-24949-assoc-const-static-recursion-trait-default.rs:11:1 +note: ...which requires const-evaluating + checking `FooDefault::BAR`... + --> $DIR/issue-24949-assoc-const-static-recursion-trait-default.rs:8:5 | -LL | const DEFAULT_REF_BAR: u32 = ::BAR; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: ...which again requires const-evaluating + checking `DEFAULT_REF_BAR`, completing the cycle -note: cycle used when simplifying constant for the type system `DEFAULT_REF_BAR` - --> $DIR/issue-24949-assoc-const-static-recursion-trait-default.rs:11:1 +LL | const BAR: u32 = DEFAULT_REF_BAR; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires caching mir of `FooDefault::BAR` for CTFE... + --> $DIR/issue-24949-assoc-const-static-recursion-trait-default.rs:8:5 | -LL | const DEFAULT_REF_BAR: u32 = ::BAR; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | const BAR: u32 = DEFAULT_REF_BAR; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: ...which requires normalizing `DEFAULT_REF_BAR`... + = note: ...which again requires simplifying constant for the type system `DEFAULT_REF_BAR`, completing the cycle + = note: cycle used when running analysis passes on this crate error: aborting due to previous error diff --git a/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait.stderr b/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait.stderr index 41db7a633183b..4ff253bffcb32 100644 --- a/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait.stderr +++ b/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait.stderr @@ -1,30 +1,43 @@ -error[E0391]: cycle detected when const-evaluating + checking `TRAIT_REF_BAR` +error[E0391]: cycle detected when simplifying constant for the type system `TRAIT_REF_BAR` --> $DIR/issue-24949-assoc-const-static-recursion-trait.rs:7:1 | LL | const TRAIT_REF_BAR: u32 = ::BAR; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: ...which requires const-evaluating + checking `::BAR`... +note: ...which requires simplifying constant for the type system `TRAIT_REF_BAR`... + --> $DIR/issue-24949-assoc-const-static-recursion-trait.rs:7:1 + | +LL | const TRAIT_REF_BAR: u32 = ::BAR; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires const-evaluating + checking `TRAIT_REF_BAR`... + --> $DIR/issue-24949-assoc-const-static-recursion-trait.rs:7:1 + | +LL | const TRAIT_REF_BAR: u32 = ::BAR; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: ...which requires normalizing `::BAR`... +note: ...which requires simplifying constant for the type system `::BAR`... --> $DIR/issue-24949-assoc-const-static-recursion-trait.rs:12:5 | LL | const BAR: u32 = TRAIT_REF_BAR; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -note: ...which requires caching mir of `::BAR` for CTFE... +note: ...which requires simplifying constant for the type system `::BAR`... --> $DIR/issue-24949-assoc-const-static-recursion-trait.rs:12:5 | LL | const BAR: u32 = TRAIT_REF_BAR; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -note: ...which requires const-evaluating + checking `TRAIT_REF_BAR`... - --> $DIR/issue-24949-assoc-const-static-recursion-trait.rs:7:1 +note: ...which requires const-evaluating + checking `::BAR`... + --> $DIR/issue-24949-assoc-const-static-recursion-trait.rs:12:5 | -LL | const TRAIT_REF_BAR: u32 = ::BAR; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: ...which again requires const-evaluating + checking `TRAIT_REF_BAR`, completing the cycle -note: cycle used when simplifying constant for the type system `TRAIT_REF_BAR` - --> $DIR/issue-24949-assoc-const-static-recursion-trait.rs:7:1 +LL | const BAR: u32 = TRAIT_REF_BAR; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires caching mir of `::BAR` for CTFE... + --> $DIR/issue-24949-assoc-const-static-recursion-trait.rs:12:5 | -LL | const TRAIT_REF_BAR: u32 = ::BAR; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | const BAR: u32 = TRAIT_REF_BAR; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: ...which requires normalizing `TRAIT_REF_BAR`... + = note: ...which again requires simplifying constant for the type system `TRAIT_REF_BAR`, completing the cycle + = note: cycle used when running analysis passes on this crate error: aborting due to previous error diff --git a/src/test/ui/borrowck/issue-88434-minimal-example.rs b/src/test/ui/borrowck/issue-88434-minimal-example.rs index 90baca253d268..632f8dc3ad6f5 100644 --- a/src/test/ui/borrowck/issue-88434-minimal-example.rs +++ b/src/test/ui/borrowck/issue-88434-minimal-example.rs @@ -1,8 +1,6 @@ // Regression test related to issue 88434 const _CONST: &() = &f(&|_| {}); -//~^ ERROR any use of this value will cause an error -//~| WARNING this was previously accepted by the compiler but is being phased out const fn f(_: &F) where diff --git a/src/test/ui/borrowck/issue-88434-minimal-example.stderr b/src/test/ui/borrowck/issue-88434-minimal-example.stderr index d0c60ef628e60..d9635e1ee464c 100644 --- a/src/test/ui/borrowck/issue-88434-minimal-example.stderr +++ b/src/test/ui/borrowck/issue-88434-minimal-example.stderr @@ -1,9 +1,5 @@ error[E0080]: evaluation of constant value failed -<<<<<<< HEAD --> $DIR/issue-88434-minimal-example.rs:9:5 -======= - --> $DIR/issue-88434-minimal-example.rs:12:5 ->>>>>>> a4feb9af018 (bless tests) | LL | const _CONST: &() = &f(&|_| {}); | ---------- inside `_CONST` at $DIR/issue-88434-minimal-example.rs:3:22 @@ -11,28 +7,11 @@ LL | const _CONST: &() = &f(&|_| {}); LL | panic!() | ^^^^^^^^ | | -<<<<<<< HEAD | the evaluated program panicked at 'explicit panic', $DIR/issue-88434-minimal-example.rs:9:5 | inside `f::<[closure@$DIR/issue-88434-minimal-example.rs:3:25: 3:31]>` at $SRC_DIR/std/src/panic.rs:LL:COL -======= - | the evaluated program panicked at 'explicit panic', $DIR/issue-88434-minimal-example.rs:12:5 - | inside `f::<[closure@$DIR/issue-88434-minimal-example.rs:4:25: 4:31]>` at $SRC_DIR/std/src/panic.rs:LL:COL ->>>>>>> a4feb9af018 (bless tests) | = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info) -error: any use of this value will cause an error - --> $DIR/issue-88434-minimal-example.rs:4:21 - | -LL | const _CONST: &() = &f(&|_| {}); - | --------------------^^^^^^^^^^^- - | | - | referenced constant has errors - | - = note: `#[deny(const_err)]` on by default - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #71800 - -error: aborting due to 2 previous errors +error: aborting due to previous error For more information about this error, try `rustc --explain E0080`. diff --git a/src/test/ui/borrowck/issue-88434-removal-index-should-be-less.rs b/src/test/ui/borrowck/issue-88434-removal-index-should-be-less.rs index b1fc1615ece77..f0a6dcd4eb3b8 100644 --- a/src/test/ui/borrowck/issue-88434-removal-index-should-be-less.rs +++ b/src/test/ui/borrowck/issue-88434-removal-index-should-be-less.rs @@ -1,8 +1,6 @@ // Regression test for issue 88434 const _CONST: &[u8] = &f(&[], |_| {}); -//~^ ERROR any use of this value will cause an error -//~| WARNING this was previously const fn f(_: &[u8], _: F) -> &[u8] where diff --git a/src/test/ui/borrowck/issue-88434-removal-index-should-be-less.stderr b/src/test/ui/borrowck/issue-88434-removal-index-should-be-less.stderr index f2a381a73ef49..44e244ae9cc3f 100644 --- a/src/test/ui/borrowck/issue-88434-removal-index-should-be-less.stderr +++ b/src/test/ui/borrowck/issue-88434-removal-index-should-be-less.stderr @@ -1,5 +1,5 @@ error[E0080]: evaluation of constant value failed - --> $DIR/issue-88434-removal-index-should-be-less.rs:12:5 + --> $DIR/issue-88434-removal-index-should-be-less.rs:9:5 | LL | const _CONST: &[u8] = &f(&[], |_| {}); | -------------- inside `_CONST` at $DIR/issue-88434-removal-index-should-be-less.rs:3:24 @@ -7,23 +7,11 @@ LL | const _CONST: &[u8] = &f(&[], |_| {}); LL | panic!() | ^^^^^^^^ | | - | the evaluated program panicked at 'explicit panic', $DIR/issue-88434-removal-index-should-be-less.rs:12:5 - | inside `f::<[closure@$DIR/issue-88434-removal-index-should-be-less.rs:4:31: 4:37]>` at $SRC_DIR/std/src/panic.rs:LL:COL + | the evaluated program panicked at 'explicit panic', $DIR/issue-88434-removal-index-should-be-less.rs:9:5 + | inside `f::<[closure@$DIR/issue-88434-removal-index-should-be-less.rs:3:31: 3:37]>` at $SRC_DIR/std/src/panic.rs:LL:COL | = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info) -error: any use of this value will cause an error - --> $DIR/issue-88434-removal-index-should-be-less.rs:4:23 - | -LL | const _CONST: &[u8] = &f(&[], |_| {}); - | ----------------------^^^^^^^^^^^^^^^- - | | - | referenced constant has errors - | - = note: `#[deny(const_err)]` on by default - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #71800 - -error: aborting due to 2 previous errors +error: aborting due to previous error For more information about this error, try `rustc --explain E0080`. diff --git a/src/test/ui/const-ptr/out_of_bounds_read.stderr b/src/test/ui/const-ptr/out_of_bounds_read.stderr index 4933ba4514db2..62af6a6adb644 100644 --- a/src/test/ui/const-ptr/out_of_bounds_read.stderr +++ b/src/test/ui/const-ptr/out_of_bounds_read.stderr @@ -4,7 +4,7 @@ error[E0080]: evaluation of constant value failed LL | copy_nonoverlapping(src, tmp.as_mut_ptr(), 1); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | | - | memory access failed: alloc5 has size 4, so pointer to 4 bytes starting at offset 4 is out-of-bounds + | memory access failed: alloc7 has size 4, so pointer to 4 bytes starting at offset 4 is out-of-bounds | inside `std::ptr::read::` at $SRC_DIR/core/src/ptr/mod.rs:LL:COL | ::: $DIR/out_of_bounds_read.rs:13:33 @@ -18,7 +18,7 @@ error[E0080]: evaluation of constant value failed LL | copy_nonoverlapping(src, tmp.as_mut_ptr(), 1); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | | - | memory access failed: alloc5 has size 4, so pointer to 4 bytes starting at offset 4 is out-of-bounds + | memory access failed: alloc7 has size 4, so pointer to 4 bytes starting at offset 4 is out-of-bounds | inside `std::ptr::read::` at $SRC_DIR/core/src/ptr/mod.rs:LL:COL | ::: $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL @@ -37,7 +37,7 @@ error[E0080]: evaluation of constant value failed LL | copy_nonoverlapping(src, tmp.as_mut_ptr(), 1); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | | - | memory access failed: alloc5 has size 4, so pointer to 4 bytes starting at offset 4 is out-of-bounds + | memory access failed: alloc7 has size 4, so pointer to 4 bytes starting at offset 4 is out-of-bounds | inside `std::ptr::read::` at $SRC_DIR/core/src/ptr/mod.rs:LL:COL | ::: $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL diff --git a/src/test/ui/consts/const-eval/const-eval-query-stack.rs b/src/test/ui/consts/const-eval/const-eval-query-stack.rs index c9460498951fd..3797559a2a1a3 100644 --- a/src/test/ui/consts/const-eval/const-eval-query-stack.rs +++ b/src/test/ui/consts/const-eval/const-eval-query-stack.rs @@ -1,4 +1,5 @@ // compile-flags: -Ztreat-err-as-bug=2 +//~^ ERROR 1:1: 1:1: ty::ConstKind::Error constructed but no error reported // build-fail // failure-status: 101 // rustc-env:RUST_BACKTRACE=1 @@ -15,6 +16,7 @@ #![allow(unconditional_panic)] + #[warn(const_err)] const X: i32 = 1 / 0; //~WARN any use of this value will cause an error //~| WARN this was previously accepted by the compiler but is being phased out @@ -22,7 +24,5 @@ const X: i32 = 1 / 0; //~WARN any use of this value will cause an error fn main() { let x: &'static i32 = &X; //~^ ERROR evaluation of constant value failed - //~| ERROR erroneous constant used - //~| WARNING this was previously accepted by the compiler println!("x={}", x); } diff --git a/src/test/ui/consts/const-eval/const-eval-query-stack.stderr b/src/test/ui/consts/const-eval/const-eval-query-stack.stderr index 9e990738bbcca..f9222952edc56 100644 --- a/src/test/ui/consts/const-eval/const-eval-query-stack.stderr +++ b/src/test/ui/consts/const-eval/const-eval-query-stack.stderr @@ -1,5 +1,5 @@ warning: any use of this value will cause an error - --> $DIR/const-eval-query-stack.rs:19:16 + --> $DIR/const-eval-query-stack.rs:21:16 | LL | const X: i32 = 1 / 0; | ---------------^^^^^- @@ -7,7 +7,7 @@ LL | const X: i32 = 1 / 0; | attempt to divide `1_i32` by zero | note: the lint level is defined here - --> $DIR/const-eval-query-stack.rs:18:8 + --> $DIR/const-eval-query-stack.rs:20:8 | LL | #[warn(const_err)] | ^^^^^^^^^ @@ -15,22 +15,12 @@ LL | #[warn(const_err)] = note: for more information, see issue #71800 error[E0080]: evaluation of constant value failed - --> $DIR/const-eval-query-stack.rs:23:28 + --> $DIR/const-eval-query-stack.rs:25:28 | LL | let x: &'static i32 = &X; | ^ referenced constant has errors - -error: erroneous constant used - --> $DIR/const-eval-query-stack.rs:23:27 - | -LL | let x: &'static i32 = &X; - | ^^ referenced constant has errors - | - = note: `#[deny(const_err)]` on by default - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #71800 - query stack during panic: -#0 [optimized_mir] optimizing MIR for `main` -#1 [collect_and_partition_mono_items] collect_and_partition_mono_items +#0 [try_normalize_mir_const_after_erasing_regions] normalizing `main::promoted[1]` +#1 [optimized_mir] optimizing MIR for `main` +#2 [collect_and_partition_mono_items] collect_and_partition_mono_items end of query stack diff --git a/src/test/ui/consts/const-integer-bool-ops.rs b/src/test/ui/consts/const-integer-bool-ops.rs index 6924956bdf706..35915a7a606a4 100644 --- a/src/test/ui/consts/const-integer-bool-ops.rs +++ b/src/test/ui/consts/const-integer-bool-ops.rs @@ -6,7 +6,6 @@ const X: usize = 42 && 39; //~| ERROR mismatched types //~| expected `usize`, found `bool` const ARR: [i32; X] = [99; 34]; -//~^ ERROR evaluation of constant value failed const X1: usize = 42 || 39; //~^ ERROR mismatched types @@ -16,7 +15,6 @@ const X1: usize = 42 || 39; //~| ERROR mismatched types //~| expected `usize`, found `bool` const ARR1: [i32; X1] = [99; 47]; -//~^ ERROR evaluation of constant value failed const X2: usize = -42 || -39; //~^ ERROR mismatched types @@ -26,7 +24,6 @@ const X2: usize = -42 || -39; //~| ERROR mismatched types //~| expected `usize`, found `bool` const ARR2: [i32; X2] = [99; 18446744073709551607]; -//~^ ERROR evaluation of constant value failed const X3: usize = -42 && -39; //~^ ERROR mismatched types @@ -36,43 +33,36 @@ const X3: usize = -42 && -39; //~| ERROR mismatched types //~| expected `usize`, found `bool` const ARR3: [i32; X3] = [99; 6]; -//~^ ERROR evaluation of constant value failed const Y: usize = 42.0 == 42.0; //~^ ERROR mismatched types //~| expected `usize`, found `bool` const ARRR: [i32; Y] = [99; 1]; -//~^ ERROR evaluation of constant value failed const Y1: usize = 42.0 >= 42.0; //~^ ERROR mismatched types //~| expected `usize`, found `bool` const ARRR1: [i32; Y1] = [99; 1]; -//~^ ERROR evaluation of constant value failed const Y2: usize = 42.0 <= 42.0; //~^ ERROR mismatched types //~| expected `usize`, found `bool` const ARRR2: [i32; Y2] = [99; 1]; -//~^ ERROR evaluation of constant value failed const Y3: usize = 42.0 > 42.0; //~^ ERROR mismatched types //~| expected `usize`, found `bool` const ARRR3: [i32; Y3] = [99; 0]; -//~^ ERROR evaluation of constant value failed const Y4: usize = 42.0 < 42.0; //~^ ERROR mismatched types //~| expected `usize`, found `bool` const ARRR4: [i32; Y4] = [99; 0]; -//~^ ERROR evaluation of constant value failed const Y5: usize = 42.0 != 42.0; //~^ ERROR mismatched types //~| expected `usize`, found `bool` const ARRR5: [i32; Y5] = [99; 0]; -//~^ ERROR evaluation of constant value failed fn main() { let _ = ARR; diff --git a/src/test/ui/consts/const-integer-bool-ops.stderr b/src/test/ui/consts/const-integer-bool-ops.stderr index 9001fefd1029f..4e503e5a5c0a4 100644 --- a/src/test/ui/consts/const-integer-bool-ops.stderr +++ b/src/test/ui/consts/const-integer-bool-ops.stderr @@ -16,157 +16,96 @@ error[E0308]: mismatched types LL | const X: usize = 42 && 39; | ^^^^^^^^ expected `usize`, found `bool` -error[E0080]: evaluation of constant value failed - --> $DIR/const-integer-bool-ops.rs:8:18 - | -LL | const ARR: [i32; X] = [99; 34]; - | ^ referenced constant has errors - error[E0308]: mismatched types - --> $DIR/const-integer-bool-ops.rs:11:19 + --> $DIR/const-integer-bool-ops.rs:10:19 | LL | const X1: usize = 42 || 39; | ^^ expected `bool`, found integer error[E0308]: mismatched types - --> $DIR/const-integer-bool-ops.rs:11:25 + --> $DIR/const-integer-bool-ops.rs:10:25 | LL | const X1: usize = 42 || 39; | ^^ expected `bool`, found integer error[E0308]: mismatched types - --> $DIR/const-integer-bool-ops.rs:11:19 + --> $DIR/const-integer-bool-ops.rs:10:19 | LL | const X1: usize = 42 || 39; | ^^^^^^^^ expected `usize`, found `bool` -error[E0080]: evaluation of constant value failed - --> $DIR/const-integer-bool-ops.rs:18:19 - | -LL | const ARR1: [i32; X1] = [99; 47]; - | ^^ referenced constant has errors - error[E0308]: mismatched types - --> $DIR/const-integer-bool-ops.rs:21:19 + --> $DIR/const-integer-bool-ops.rs:19:19 | LL | const X2: usize = -42 || -39; | ^^^ expected `bool`, found integer error[E0308]: mismatched types - --> $DIR/const-integer-bool-ops.rs:21:26 + --> $DIR/const-integer-bool-ops.rs:19:26 | LL | const X2: usize = -42 || -39; | ^^^ expected `bool`, found integer error[E0308]: mismatched types - --> $DIR/const-integer-bool-ops.rs:21:19 + --> $DIR/const-integer-bool-ops.rs:19:19 | LL | const X2: usize = -42 || -39; | ^^^^^^^^^^ expected `usize`, found `bool` -error[E0080]: evaluation of constant value failed - --> $DIR/const-integer-bool-ops.rs:28:19 - | -LL | const ARR2: [i32; X2] = [99; 18446744073709551607]; - | ^^ referenced constant has errors - error[E0308]: mismatched types - --> $DIR/const-integer-bool-ops.rs:31:19 + --> $DIR/const-integer-bool-ops.rs:28:19 | LL | const X3: usize = -42 && -39; | ^^^ expected `bool`, found integer error[E0308]: mismatched types - --> $DIR/const-integer-bool-ops.rs:31:26 + --> $DIR/const-integer-bool-ops.rs:28:26 | LL | const X3: usize = -42 && -39; | ^^^ expected `bool`, found integer error[E0308]: mismatched types - --> $DIR/const-integer-bool-ops.rs:31:19 + --> $DIR/const-integer-bool-ops.rs:28:19 | LL | const X3: usize = -42 && -39; | ^^^^^^^^^^ expected `usize`, found `bool` -error[E0080]: evaluation of constant value failed - --> $DIR/const-integer-bool-ops.rs:38:19 - | -LL | const ARR3: [i32; X3] = [99; 6]; - | ^^ referenced constant has errors - error[E0308]: mismatched types - --> $DIR/const-integer-bool-ops.rs:41:18 + --> $DIR/const-integer-bool-ops.rs:37:18 | LL | const Y: usize = 42.0 == 42.0; | ^^^^^^^^^^^^ expected `usize`, found `bool` -error[E0080]: evaluation of constant value failed - --> $DIR/const-integer-bool-ops.rs:44:19 - | -LL | const ARRR: [i32; Y] = [99; 1]; - | ^ referenced constant has errors - error[E0308]: mismatched types - --> $DIR/const-integer-bool-ops.rs:47:19 + --> $DIR/const-integer-bool-ops.rs:42:19 | LL | const Y1: usize = 42.0 >= 42.0; | ^^^^^^^^^^^^ expected `usize`, found `bool` -error[E0080]: evaluation of constant value failed - --> $DIR/const-integer-bool-ops.rs:50:20 - | -LL | const ARRR1: [i32; Y1] = [99; 1]; - | ^^ referenced constant has errors - error[E0308]: mismatched types - --> $DIR/const-integer-bool-ops.rs:53:19 + --> $DIR/const-integer-bool-ops.rs:47:19 | LL | const Y2: usize = 42.0 <= 42.0; | ^^^^^^^^^^^^ expected `usize`, found `bool` -error[E0080]: evaluation of constant value failed - --> $DIR/const-integer-bool-ops.rs:56:20 - | -LL | const ARRR2: [i32; Y2] = [99; 1]; - | ^^ referenced constant has errors - error[E0308]: mismatched types - --> $DIR/const-integer-bool-ops.rs:59:19 + --> $DIR/const-integer-bool-ops.rs:52:19 | LL | const Y3: usize = 42.0 > 42.0; | ^^^^^^^^^^^ expected `usize`, found `bool` -error[E0080]: evaluation of constant value failed - --> $DIR/const-integer-bool-ops.rs:62:20 - | -LL | const ARRR3: [i32; Y3] = [99; 0]; - | ^^ referenced constant has errors - error[E0308]: mismatched types - --> $DIR/const-integer-bool-ops.rs:65:19 + --> $DIR/const-integer-bool-ops.rs:57:19 | LL | const Y4: usize = 42.0 < 42.0; | ^^^^^^^^^^^ expected `usize`, found `bool` -error[E0080]: evaluation of constant value failed - --> $DIR/const-integer-bool-ops.rs:68:20 - | -LL | const ARRR4: [i32; Y4] = [99; 0]; - | ^^ referenced constant has errors - error[E0308]: mismatched types - --> $DIR/const-integer-bool-ops.rs:71:19 + --> $DIR/const-integer-bool-ops.rs:62:19 | LL | const Y5: usize = 42.0 != 42.0; | ^^^^^^^^^^^^ expected `usize`, found `bool` -error[E0080]: evaluation of constant value failed - --> $DIR/const-integer-bool-ops.rs:74:20 - | -LL | const ARRR5: [i32; Y5] = [99; 0]; - | ^^ referenced constant has errors - -error: aborting due to 28 previous errors +error: aborting due to 18 previous errors -Some errors have detailed explanations: E0080, E0308. -For more information about an error, try `rustc --explain E0080`. +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/consts/const-mut-refs/issue-76510.64bit.stderr b/src/test/ui/consts/const-mut-refs/issue-76510.64bit.stderr index 0f420ae1b6b7c..61b00be345fee 100644 --- a/src/test/ui/consts/const-mut-refs/issue-76510.64bit.stderr +++ b/src/test/ui/consts/const-mut-refs/issue-76510.64bit.stderr @@ -19,13 +19,7 @@ error[E0596]: cannot borrow data in a `&` reference as mutable LL | const S: &'static mut str = &mut " hello "; | ^^^^^^^^^^^^^^ cannot borrow as mutable -error[E0080]: evaluation of constant value failed - --> $DIR/issue-76510.rs:11:70 - | -LL | let s = transmute::<(*const u8, usize), &ManuallyDrop>((S.as_ptr(), 3)); - | ^ referenced constant has errors - -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors -Some errors have detailed explanations: E0080, E0596, E0658, E0764. -For more information about an error, try `rustc --explain E0080`. +Some errors have detailed explanations: E0596, E0658, E0764. +For more information about an error, try `rustc --explain E0596`. diff --git a/src/test/ui/consts/const-mut-refs/issue-76510.rs b/src/test/ui/consts/const-mut-refs/issue-76510.rs index 08cf64ee330db..143d2fb6b9a3a 100644 --- a/src/test/ui/consts/const-mut-refs/issue-76510.rs +++ b/src/test/ui/consts/const-mut-refs/issue-76510.rs @@ -9,7 +9,6 @@ const S: &'static mut str = &mut " hello "; const fn trigger() -> [(); unsafe { let s = transmute::<(*const u8, usize), &ManuallyDrop>((S.as_ptr(), 3)); - //~^ ERROR evaluation of constant value failed 0 }] { [(); 0] diff --git a/src/test/ui/consts/const-tup-index-span.rs b/src/test/ui/consts/const-tup-index-span.rs index 763263c6aeb4f..8057d64369a23 100644 --- a/src/test/ui/consts/const-tup-index-span.rs +++ b/src/test/ui/consts/const-tup-index-span.rs @@ -4,7 +4,6 @@ const TUP: (usize,) = 5usize << 64; //~^ ERROR mismatched types //~| expected tuple, found `usize` const ARR: [i32; TUP.0] = []; -//~^ ERROR evaluation of constant value failed fn main() { } diff --git a/src/test/ui/consts/const-tup-index-span.stderr b/src/test/ui/consts/const-tup-index-span.stderr index b178e05e27a09..d301f8c4054c2 100644 --- a/src/test/ui/consts/const-tup-index-span.stderr +++ b/src/test/ui/consts/const-tup-index-span.stderr @@ -11,13 +11,6 @@ help: use a trailing comma to create a tuple with one element LL | const TUP: (usize,) = (5usize << 64,); | + ++ -error[E0080]: evaluation of constant value failed - --> $DIR/const-tup-index-span.rs:6:18 - | -LL | const ARR: [i32; TUP.0] = []; - | ^^^ referenced constant has errors - -error: aborting due to 2 previous errors +error: aborting due to previous error -Some errors have detailed explanations: E0080, E0308. -For more information about an error, try `rustc --explain E0080`. +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/consts/invalid-union.64bit.stderr b/src/test/ui/consts/invalid-union.64bit.stderr index a0225d3ffc39f..2ca54ccf9a09e 100644 --- a/src/test/ui/consts/invalid-union.64bit.stderr +++ b/src/test/ui/consts/invalid-union.64bit.stderr @@ -6,7 +6,7 @@ LL | fn main() { | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { - ╾───────alloc6────────╼ │ ╾──────╼ + ╾───────alloc7────────╼ │ ╾──────╼ } error: erroneous constant used diff --git a/src/test/ui/consts/issue-36163.stderr b/src/test/ui/consts/issue-36163.stderr index 9ac6c984cb0cd..113f86cf0f99f 100644 --- a/src/test/ui/consts/issue-36163.stderr +++ b/src/test/ui/consts/issue-36163.stderr @@ -1,20 +1,48 @@ -error[E0391]: cycle detected when const-evaluating + checking `Foo::B::{constant#0}` +error[E0391]: cycle detected when simplifying constant for the type system `Foo::B::{constant#0}` --> $DIR/issue-36163.rs:4:9 | LL | B = A, | ^ | +note: ...which requires simplifying constant for the type system `Foo::B::{constant#0}`... + --> $DIR/issue-36163.rs:4:9 + | +LL | B = A, + | ^ +note: ...which requires const-evaluating + checking `Foo::B::{constant#0}`... + --> $DIR/issue-36163.rs:4:9 + | +LL | B = A, + | ^ + = note: ...which requires normalizing `A`... +note: ...which requires simplifying constant for the type system `A`... + --> $DIR/issue-36163.rs:1:1 + | +LL | const A: isize = Foo::B as isize; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires simplifying constant for the type system `A`... + --> $DIR/issue-36163.rs:1:1 + | +LL | const A: isize = Foo::B as isize; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: ...which requires const-evaluating + checking `A`... --> $DIR/issue-36163.rs:1:1 | LL | const A: isize = Foo::B as isize; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: ...which again requires const-evaluating + checking `Foo::B::{constant#0}`, completing the cycle -note: cycle used when simplifying constant for the type system `Foo::B::{constant#0}` - --> $DIR/issue-36163.rs:4:9 + = note: ...which requires normalizing `A`... + = note: ...which again requires simplifying constant for the type system `Foo::B::{constant#0}`, completing the cycle +note: cycle used when collecting item types in top-level module + --> $DIR/issue-36163.rs:1:1 | -LL | B = A, - | ^ +LL | / const A: isize = Foo::B as isize; +LL | | +LL | | enum Foo { +LL | | B = A, +LL | | } +LL | | +LL | | fn main() {} + | |____________^ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-17252.stderr b/src/test/ui/issues/issue-17252.stderr index 4856418ed6002..1148577016ab4 100644 --- a/src/test/ui/issues/issue-17252.stderr +++ b/src/test/ui/issues/issue-17252.stderr @@ -1,10 +1,21 @@ -error[E0391]: cycle detected when const-evaluating + checking `FOO` +error[E0391]: cycle detected when normalizing `FOO` + | +note: ...which requires simplifying constant for the type system `FOO`... + --> $DIR/issue-17252.rs:1:1 + | +LL | const FOO: usize = FOO; + | ^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires simplifying constant for the type system `FOO`... --> $DIR/issue-17252.rs:1:1 | LL | const FOO: usize = FOO; | ^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires const-evaluating + checking `FOO`... + --> $DIR/issue-17252.rs:1:1 | - = note: ...which immediately requires const-evaluating + checking `FOO` again +LL | const FOO: usize = FOO; + | ^^^^^^^^^^^^^^^^^^^^^^^ + = note: ...which again requires normalizing `FOO`, completing the cycle note: cycle used when const-evaluating + checking `main::{constant#0}` --> $DIR/issue-17252.rs:4:18 | diff --git a/src/test/ui/issues/issue-23302-1.stderr b/src/test/ui/issues/issue-23302-1.stderr index 9366050d7ecdf..d3a1993536a00 100644 --- a/src/test/ui/issues/issue-23302-1.stderr +++ b/src/test/ui/issues/issue-23302-1.stderr @@ -1,15 +1,26 @@ -error[E0391]: cycle detected when const-evaluating + checking `X::A::{constant#0}` +error[E0391]: cycle detected when simplifying constant for the type system `X::A::{constant#0}` --> $DIR/issue-23302-1.rs:4:9 | LL | A = X::A as isize, | ^^^^^^^^^^^^^ | - = note: ...which immediately requires const-evaluating + checking `X::A::{constant#0}` again -note: cycle used when simplifying constant for the type system `X::A::{constant#0}` +note: ...which requires simplifying constant for the type system `X::A::{constant#0}`... --> $DIR/issue-23302-1.rs:4:9 | LL | A = X::A as isize, | ^^^^^^^^^^^^^ +note: ...which requires const-evaluating + checking `X::A::{constant#0}`... + --> $DIR/issue-23302-1.rs:4:9 + | +LL | A = X::A as isize, + | ^^^^^^^^^^^^^ + = note: ...which requires normalizing `X::A as isize`... + = note: ...which again requires simplifying constant for the type system `X::A::{constant#0}`, completing the cycle +note: cycle used when collecting item types in top-level module + --> $DIR/issue-23302-1.rs:3:1 + | +LL | enum X { + | ^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-23302-2.stderr b/src/test/ui/issues/issue-23302-2.stderr index b97ae287a47a9..d3b78ea1af5f5 100644 --- a/src/test/ui/issues/issue-23302-2.stderr +++ b/src/test/ui/issues/issue-23302-2.stderr @@ -1,15 +1,26 @@ -error[E0391]: cycle detected when const-evaluating + checking `Y::A::{constant#0}` +error[E0391]: cycle detected when simplifying constant for the type system `Y::A::{constant#0}` --> $DIR/issue-23302-2.rs:4:9 | LL | A = Y::B as isize, | ^^^^^^^^^^^^^ | - = note: ...which immediately requires const-evaluating + checking `Y::A::{constant#0}` again -note: cycle used when simplifying constant for the type system `Y::A::{constant#0}` +note: ...which requires simplifying constant for the type system `Y::A::{constant#0}`... --> $DIR/issue-23302-2.rs:4:9 | LL | A = Y::B as isize, | ^^^^^^^^^^^^^ +note: ...which requires const-evaluating + checking `Y::A::{constant#0}`... + --> $DIR/issue-23302-2.rs:4:9 + | +LL | A = Y::B as isize, + | ^^^^^^^^^^^^^ + = note: ...which requires normalizing `Y::B as isize`... + = note: ...which again requires simplifying constant for the type system `Y::A::{constant#0}`, completing the cycle +note: cycle used when collecting item types in top-level module + --> $DIR/issue-23302-2.rs:3:1 + | +LL | enum Y { + | ^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-23302-3.stderr b/src/test/ui/issues/issue-23302-3.stderr index 1a07d4a95bcfa..5233b832ecc79 100644 --- a/src/test/ui/issues/issue-23302-3.stderr +++ b/src/test/ui/issues/issue-23302-3.stderr @@ -1,20 +1,38 @@ -error[E0391]: cycle detected when const-evaluating + checking `A` +error[E0391]: cycle detected when simplifying constant for the type system `A` --> $DIR/issue-23302-3.rs:1:1 | LL | const A: i32 = B; | ^^^^^^^^^^^^^^^^^ | -note: ...which requires const-evaluating + checking `B`... - --> $DIR/issue-23302-3.rs:3:1 +note: ...which requires simplifying constant for the type system `A`... + --> $DIR/issue-23302-3.rs:1:1 | -LL | const B: i32 = A; +LL | const A: i32 = B; | ^^^^^^^^^^^^^^^^^ - = note: ...which again requires const-evaluating + checking `A`, completing the cycle -note: cycle used when simplifying constant for the type system `A` +note: ...which requires const-evaluating + checking `A`... --> $DIR/issue-23302-3.rs:1:1 | LL | const A: i32 = B; | ^^^^^^^^^^^^^^^^^ + = note: ...which requires normalizing `B`... +note: ...which requires simplifying constant for the type system `B`... + --> $DIR/issue-23302-3.rs:3:1 + | +LL | const B: i32 = A; + | ^^^^^^^^^^^^^^^^^ +note: ...which requires simplifying constant for the type system `B`... + --> $DIR/issue-23302-3.rs:3:1 + | +LL | const B: i32 = A; + | ^^^^^^^^^^^^^^^^^ +note: ...which requires const-evaluating + checking `B`... + --> $DIR/issue-23302-3.rs:3:1 + | +LL | const B: i32 = A; + | ^^^^^^^^^^^^^^^^^ + = note: ...which requires normalizing `A`... + = note: ...which again requires simplifying constant for the type system `A`, completing the cycle + = note: cycle used when running analysis passes on this crate error: aborting due to previous error diff --git a/src/test/ui/issues/issue-41394.rs b/src/test/ui/issues/issue-41394.rs index 64873ac35a002..06a330813406a 100644 --- a/src/test/ui/issues/issue-41394.rs +++ b/src/test/ui/issues/issue-41394.rs @@ -5,7 +5,6 @@ enum Foo { enum Bar { A = Foo::A as isize - //~^ ERROR evaluation of constant value failed } fn main() {} diff --git a/src/test/ui/issues/issue-41394.stderr b/src/test/ui/issues/issue-41394.stderr index 47a24547d4533..fa95ca9c18a10 100644 --- a/src/test/ui/issues/issue-41394.stderr +++ b/src/test/ui/issues/issue-41394.stderr @@ -6,13 +6,6 @@ LL | A = "" + 1 | | | &str -error[E0080]: evaluation of constant value failed - --> $DIR/issue-41394.rs:7:9 - | -LL | A = Foo::A as isize - | ^^^^^^^^^^^^^^^ referenced constant has errors - -error: aborting due to 2 previous errors +error: aborting due to previous error -Some errors have detailed explanations: E0080, E0369. -For more information about an error, try `rustc --explain E0080`. +For more information about this error, try `rustc --explain E0369`. diff --git a/src/test/ui/issues/issue-54954.rs b/src/test/ui/issues/issue-54954.rs index ddd3914154147..42a4d5b674b22 100644 --- a/src/test/ui/issues/issue-54954.rs +++ b/src/test/ui/issues/issue-54954.rs @@ -9,8 +9,6 @@ trait Tt { } fn f(z: [f32; ARR_LEN]) -> [f32; ARR_LEN] { - //~^ ERROR evaluation of constant value failed - //~| ERROR evaluation of constant value failed z } diff --git a/src/test/ui/issues/issue-54954.stderr b/src/test/ui/issues/issue-54954.stderr index 6e8d3cac9a7e4..efe2ef504a2ba 100644 --- a/src/test/ui/issues/issue-54954.stderr +++ b/src/test/ui/issues/issue-54954.stderr @@ -12,19 +12,7 @@ LL | const ARR_LEN: usize = Tt::const_val::<[i8; 123]>(); | = note: cannot satisfy `_: Tt` -error[E0080]: evaluation of constant value failed - --> $DIR/issue-54954.rs:11:15 - | -LL | fn f(z: [f32; ARR_LEN]) -> [f32; ARR_LEN] { - | ^^^^^^^ referenced constant has errors - -error[E0080]: evaluation of constant value failed - --> $DIR/issue-54954.rs:11:34 - | -LL | fn f(z: [f32; ARR_LEN]) -> [f32; ARR_LEN] { - | ^^^^^^^ referenced constant has errors - -error: aborting due to 4 previous errors +error: aborting due to 2 previous errors -Some errors have detailed explanations: E0080, E0283, E0379. -For more information about an error, try `rustc --explain E0080`. +Some errors have detailed explanations: E0283, E0379. +For more information about an error, try `rustc --explain E0283`. diff --git a/src/test/ui/issues/issue-69602-type-err-during-codegen-ice.rs b/src/test/ui/issues/issue-69602-type-err-during-codegen-ice.rs index 6851b67cb3b3a..2c5257ce063cb 100644 --- a/src/test/ui/issues/issue-69602-type-err-during-codegen-ice.rs +++ b/src/test/ui/issues/issue-69602-type-err-during-codegen-ice.rs @@ -19,5 +19,4 @@ impl TraitB for B { //~ ERROR not all trait items implemented, missing: `MyA` fn main() { let _ = [0; B::VALUE]; - //~^ ERROR evaluation of constant value failed } diff --git a/src/test/ui/issues/issue-69602-type-err-during-codegen-ice.stderr b/src/test/ui/issues/issue-69602-type-err-during-codegen-ice.stderr index cb5b397849c06..8ae0f8b804c93 100644 --- a/src/test/ui/issues/issue-69602-type-err-during-codegen-ice.stderr +++ b/src/test/ui/issues/issue-69602-type-err-during-codegen-ice.stderr @@ -13,13 +13,7 @@ LL | type MyA: TraitA; LL | impl TraitB for B { | ^^^^^^^^^^^^^^^^^ missing `MyA` in implementation -error[E0080]: evaluation of constant value failed - --> $DIR/issue-69602-type-err-during-codegen-ice.rs:21:17 - | -LL | let _ = [0; B::VALUE]; - | ^^^^^^^^ referenced constant has errors - -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors -Some errors have detailed explanations: E0046, E0080, E0437. +Some errors have detailed explanations: E0046, E0437. For more information about an error, try `rustc --explain E0046`. diff --git a/src/test/ui/issues/issue-77919.rs b/src/test/ui/issues/issue-77919.rs index c2946ad94b0b7..966d76d148af3 100644 --- a/src/test/ui/issues/issue-77919.rs +++ b/src/test/ui/issues/issue-77919.rs @@ -1,6 +1,5 @@ fn main() { [1; >::VAL]; - //~^ ERROR evaluation of constant value failed } trait TypeVal { const VAL: T; diff --git a/src/test/ui/issues/issue-77919.stderr b/src/test/ui/issues/issue-77919.stderr index 8d5d6cb037749..97bd5ab36b65d 100644 --- a/src/test/ui/issues/issue-77919.stderr +++ b/src/test/ui/issues/issue-77919.stderr @@ -1,5 +1,5 @@ error[E0412]: cannot find type `PhantomData` in this scope - --> $DIR/issue-77919.rs:10:9 + --> $DIR/issue-77919.rs:9:9 | LL | _n: PhantomData, | ^^^^^^^^^^^ not found in this scope @@ -10,7 +10,7 @@ LL | use std::marker::PhantomData; | error[E0412]: cannot find type `VAL` in this scope - --> $DIR/issue-77919.rs:12:63 + --> $DIR/issue-77919.rs:11:63 | LL | impl TypeVal for Multiply where N: TypeVal {} | - ^^^ not found in this scope @@ -18,7 +18,7 @@ LL | impl TypeVal for Multiply where N: TypeVal {} | help: you might be missing a type parameter: `, VAL` error[E0046]: not all trait items implemented, missing: `VAL` - --> $DIR/issue-77919.rs:12:1 + --> $DIR/issue-77919.rs:11:1 | LL | const VAL: T; | ------------- `VAL` from trait @@ -26,13 +26,7 @@ LL | const VAL: T; LL | impl TypeVal for Multiply where N: TypeVal {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `VAL` in implementation -error[E0080]: evaluation of constant value failed - --> $DIR/issue-77919.rs:2:9 - | -LL | [1; >::VAL]; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors - -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors -Some errors have detailed explanations: E0046, E0080, E0412. +Some errors have detailed explanations: E0046, E0412. For more information about an error, try `rustc --explain E0046`. diff --git a/src/test/ui/resolve/issue-50599.rs b/src/test/ui/resolve/issue-50599.rs index 78a20cf8ebb05..00588735b9a59 100644 --- a/src/test/ui/resolve/issue-50599.rs +++ b/src/test/ui/resolve/issue-50599.rs @@ -2,5 +2,4 @@ fn main() { const N: u32 = 1_000; const M: usize = (f64::from(N) * std::f64::LOG10_2) as usize; //~ ERROR cannot find value let mut digits = [0u32; M]; - //~^ ERROR evaluation of constant value failed } diff --git a/src/test/ui/resolve/issue-50599.stderr b/src/test/ui/resolve/issue-50599.stderr index effa16e55e54e..7ec567a06f09d 100644 --- a/src/test/ui/resolve/issue-50599.stderr +++ b/src/test/ui/resolve/issue-50599.stderr @@ -11,13 +11,6 @@ LL | use std::f32::consts::LOG10_2; LL | use std::f64::consts::LOG10_2; | -error[E0080]: evaluation of constant value failed - --> $DIR/issue-50599.rs:4:29 - | -LL | let mut digits = [0u32; M]; - | ^ referenced constant has errors - -error: aborting due to 2 previous errors +error: aborting due to previous error -Some errors have detailed explanations: E0080, E0425. -For more information about an error, try `rustc --explain E0080`. +For more information about this error, try `rustc --explain E0425`. diff --git a/src/test/ui/type/type-dependent-def-issue-49241.rs b/src/test/ui/type/type-dependent-def-issue-49241.rs index 51bd116fbd61c..4b6bc6124dbf3 100644 --- a/src/test/ui/type/type-dependent-def-issue-49241.rs +++ b/src/test/ui/type/type-dependent-def-issue-49241.rs @@ -2,5 +2,4 @@ fn main() { let v = vec![0]; const l: usize = v.count(); //~ ERROR attempt to use a non-constant value in a constant let s: [u32; l] = v.into_iter().collect(); - //~^ ERROR evaluation of constant value failed } diff --git a/src/test/ui/type/type-dependent-def-issue-49241.stderr b/src/test/ui/type/type-dependent-def-issue-49241.stderr index 02f267c6c8d73..64c7687f7a882 100644 --- a/src/test/ui/type/type-dependent-def-issue-49241.stderr +++ b/src/test/ui/type/type-dependent-def-issue-49241.stderr @@ -6,13 +6,6 @@ LL | const l: usize = v.count(); | | | help: consider using `let` instead of `const`: `let l` -error[E0080]: evaluation of constant value failed - --> $DIR/type-dependent-def-issue-49241.rs:4:18 - | -LL | let s: [u32; l] = v.into_iter().collect(); - | ^ referenced constant has errors - -error: aborting due to 2 previous errors +error: aborting due to previous error -Some errors have detailed explanations: E0080, E0435. -For more information about an error, try `rustc --explain E0080`. +For more information about this error, try `rustc --explain E0435`. From 5226395d6faef77a5f1dadb6235bcd99352e1843 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Sat, 5 Mar 2022 17:19:04 +0100 Subject: [PATCH 15/28] Fix soundness issue in scoped threads. --- library/std/src/thread/mod.rs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs index 5ffc86b4560fc..56baa7e445588 100644 --- a/library/std/src/thread/mod.rs +++ b/library/std/src/thread/mod.rs @@ -1293,6 +1293,23 @@ impl<'scope, T> Drop for Packet<'scope, T> { // panicked, and nobody consumed the panic payload, we make sure // the scope function will panic. let unhandled_panic = matches!(self.result.get_mut(), Some(Err(_))); + // Drop the result before decrementing the number of running + // threads, because the Drop implementation might still use things + // it borrowed from 'scope. + // This is only relevant for threads that aren't join()ed, as + // join() will take the `result` and set it to None, such that + // there is nothing left to drop here. + // If this drop panics, that just results in an abort, because + // we're outside of the outermost `catch_unwind` of our thread. + // The same happens for detached non-scoped threads when dropping + // their ignored return value (or panic payload) panics, so + // there's no need to try to do anything better. + // (And even if we tried to handle it, we'd also need to handle + // the case where the panic payload we get out of it also panics + // on drop, and so on. See issue #86027.) + *self.result.get_mut() = None; + // Now that there will be no more user code running on this thread + // that can use 'scope, mark the thread as 'finished'. scope.decrement_num_running_threads(unhandled_panic); } } From 7a481ff8a412121b0a52c51c086ae22ed7e96ab5 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Sat, 5 Mar 2022 18:07:20 +0100 Subject: [PATCH 16/28] Properly abort when thread result panics on drop. --- library/std/src/lib.rs | 10 ++++----- library/std/src/thread/mod.rs | 40 ++++++++++++++++++----------------- 2 files changed, 26 insertions(+), 24 deletions(-) diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index c35389d44f9fc..232b66230782f 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -363,6 +363,11 @@ extern crate std as realstd; #[macro_use] mod macros; +// The runtime entry point and a few unstable public functions used by the +// compiler +#[macro_use] +pub mod rt; + // The Rust prelude pub mod prelude; @@ -547,11 +552,6 @@ pub mod arch { #[stable(feature = "simd_x86", since = "1.27.0")] pub use std_detect::is_x86_feature_detected; -// The runtime entry point and a few unstable public functions used by the -// compiler -#[macro_use] -pub mod rt; - // Platform-abstraction modules mod sys; mod sys_common; diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs index 56baa7e445588..74b29454b94a4 100644 --- a/library/std/src/thread/mod.rs +++ b/library/std/src/thread/mod.rs @@ -1287,29 +1287,31 @@ unsafe impl<'scope, T: Sync> Sync for Packet<'scope, T> {} impl<'scope, T> Drop for Packet<'scope, T> { fn drop(&mut self) { + // If this packet was for a thread that ran in a scope, the thread + // panicked, and nobody consumed the panic payload, we make sure + // the scope function will panic. + let unhandled_panic = matches!(self.result.get_mut(), Some(Err(_))); + // Drop the result without causing unwinding. + // This is only relevant for threads that aren't join()ed, as + // join() will take the `result` and set it to None, such that + // there is nothing left to drop here. + // If this panics, we should handle that, because we're outside the + // outermost `catch_unwind` of our thread. + // We just abort in that case, since there's nothing else we can do. + // (And even if we tried to handle it somehow, we'd also need to handle + // the case where the panic payload we get out of it also panics on + // drop, and so on. See issue #86027.) + if let Err(_) = panic::catch_unwind(panic::AssertUnwindSafe(|| { + *self.result.get_mut() = None; + })) { + rtabort!("thread result panicked on drop"); + } // Book-keeping so the scope knows when it's done. if let Some(scope) = self.scope { - // If this packet was for a thread that ran in a scope, the thread - // panicked, and nobody consumed the panic payload, we make sure - // the scope function will panic. - let unhandled_panic = matches!(self.result.get_mut(), Some(Err(_))); - // Drop the result before decrementing the number of running - // threads, because the Drop implementation might still use things - // it borrowed from 'scope. - // This is only relevant for threads that aren't join()ed, as - // join() will take the `result` and set it to None, such that - // there is nothing left to drop here. - // If this drop panics, that just results in an abort, because - // we're outside of the outermost `catch_unwind` of our thread. - // The same happens for detached non-scoped threads when dropping - // their ignored return value (or panic payload) panics, so - // there's no need to try to do anything better. - // (And even if we tried to handle it, we'd also need to handle - // the case where the panic payload we get out of it also panics - // on drop, and so on. See issue #86027.) - *self.result.get_mut() = None; // Now that there will be no more user code running on this thread // that can use 'scope, mark the thread as 'finished'. + // It's important we only do this after the `result` has been dropped, + // since dropping it might still use things it borrowed from 'scope. scope.decrement_num_running_threads(unhandled_panic); } } From 1c06eb7c1f416055d7ede098f35bcf22cf85b7f8 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Wed, 9 Mar 2022 11:47:46 +0100 Subject: [PATCH 17/28] Remove outdated comment. --- library/std/src/thread/tests.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/library/std/src/thread/tests.rs b/library/std/src/thread/tests.rs index 3323ba36bf310..27eebd0ddf4ec 100644 --- a/library/std/src/thread/tests.rs +++ b/library/std/src/thread/tests.rs @@ -293,5 +293,3 @@ fn test_thread_id_not_equal() { assert!(thread::current().id() != spawned_id); } -// NOTE: the corresponding test for stderr is in ui/thread-stderr, due -// to the test harness apparently interfering with stderr configuration. From b97d87518d19e418220f726e774ffceadb4d33b9 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Wed, 9 Mar 2022 11:47:53 +0100 Subject: [PATCH 18/28] Add soundness test for dropping scoped thread results before joining. --- library/std/src/thread/tests.rs | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/library/std/src/thread/tests.rs b/library/std/src/thread/tests.rs index 27eebd0ddf4ec..7386fe1c442ab 100644 --- a/library/std/src/thread/tests.rs +++ b/library/std/src/thread/tests.rs @@ -4,10 +4,11 @@ use crate::mem; use crate::panic::panic_any; use crate::result; use crate::sync::{ + atomic::{AtomicBool, Ordering}, mpsc::{channel, Sender}, Arc, Barrier, }; -use crate::thread::{self, ThreadId}; +use crate::thread::{self, Scope, ThreadId}; use crate::time::Duration; use crate::time::Instant; @@ -293,3 +294,25 @@ fn test_thread_id_not_equal() { assert!(thread::current().id() != spawned_id); } +#[test] +fn test_scoped_threads_drop_result_before_join() { + let actually_finished = &AtomicBool::new(false); + struct X<'scope, 'env>(&'scope Scope<'scope, 'env>, &'env AtomicBool); + impl Drop for X<'_, '_> { + fn drop(&mut self) { + thread::sleep(Duration::from_millis(20)); + let actually_finished = self.1; + self.0.spawn(move || { + thread::sleep(Duration::from_millis(20)); + actually_finished.store(true, Ordering::Relaxed); + }); + } + } + thread::scope(|s| { + s.spawn(move || { + thread::sleep(Duration::from_millis(20)); + X(s, actually_finished) + }); + }); + assert!(actually_finished.load(Ordering::Relaxed)); +} From 491350ce75b25bdd36cdf995cd8ec370cbab3889 Mon Sep 17 00:00:00 2001 From: Raoul Strackx Date: Wed, 9 Mar 2022 12:28:02 +0100 Subject: [PATCH 19/28] Ignore `close_read_wakes_up` test on SGX platform --- library/std/src/net/tcp/tests.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/library/std/src/net/tcp/tests.rs b/library/std/src/net/tcp/tests.rs index 959fe6943f6ee..4d5cf658def0d 100644 --- a/library/std/src/net/tcp/tests.rs +++ b/library/std/src/net/tcp/tests.rs @@ -508,6 +508,7 @@ fn close_readwrite_smoke() { } #[test] +#[cfg_attr(target_env = "sgx", ignore)] fn close_read_wakes_up() { each_ip(&mut |addr| { let a = t!(TcpListener::bind(&addr)); From 18bb2dd7f140f2ca1fa2e42655d1659fe53d124e Mon Sep 17 00:00:00 2001 From: b-naber Date: Wed, 9 Mar 2022 12:16:33 +0100 Subject: [PATCH 20/28] manually bless 32-bit stderr --- .../region_subtyping_basic.main.nll.0.32bit.mir | 14 +++++++------- .../ui/consts/const-eval/const-eval-query-stack.rs | 1 - 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.32bit.mir b/src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.32bit.mir index 3ef7844ce434f..ed94a1ecf0062 100644 --- a/src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.32bit.mir +++ b/src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.32bit.mir @@ -45,11 +45,11 @@ fn main() -> () { bb0: { StorageLive(_1); // bb0[0]: scope 0 at $DIR/region-subtyping-basic.rs:17:9: 17:14 - _1 = [const Const(Value(Scalar(0x00000001)): usize), const Const(Value(Scalar(0x00000002)): usize), const Const(Value(Scalar(0x00000003)): usize)]; // bb0[1]: scope 0 at $DIR/region-subtyping-basic.rs:17:17: 17:26 + _1 = [const ConstValue(Scalar(0x00000001): usize), const ConstValue(Scalar(0x00000002): usize), const ConstValue(Scalar(0x00000003): usize)]; // bb0[1]: scope 0 at $DIR/region-subtyping-basic.rs:17:17: 17:26 FakeRead(ForLet(None), _1); // bb0[2]: scope 0 at $DIR/region-subtyping-basic.rs:17:9: 17:14 StorageLive(_2); // bb0[3]: scope 1 at $DIR/region-subtyping-basic.rs:18:9: 18:10 StorageLive(_3); // bb0[4]: scope 1 at $DIR/region-subtyping-basic.rs:18:16: 18:17 - _3 = const Const(Value(Scalar(0x00000000)): usize); // bb0[5]: scope 1 at $DIR/region-subtyping-basic.rs:18:16: 18:17 + _3 = const ConstValue(Scalar(0x00000000): usize); // bb0[5]: scope 1 at $DIR/region-subtyping-basic.rs:18:16: 18:17 _4 = Len(_1); // bb0[6]: scope 1 at $DIR/region-subtyping-basic.rs:18:14: 18:18 _5 = Lt(_3, _4); // bb0[7]: scope 1 at $DIR/region-subtyping-basic.rs:18:14: 18:18 assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> [success: bb1, unwind: bb7]; // bb0[8]: scope 1 at $DIR/region-subtyping-basic.rs:18:14: 18:18 @@ -62,7 +62,7 @@ fn main() -> () { _6 = _2; // bb1[3]: scope 2 at $DIR/region-subtyping-basic.rs:19:13: 19:14 FakeRead(ForLet(None), _6); // bb1[4]: scope 2 at $DIR/region-subtyping-basic.rs:19:9: 19:10 StorageLive(_7); // bb1[5]: scope 3 at $DIR/region-subtyping-basic.rs:20:8: 20:12 - _7 = const Const(Value(Scalar(0x01)): bool); // bb1[6]: scope 3 at $DIR/region-subtyping-basic.rs:20:8: 20:12 + _7 = const ConstValue(Scalar(0x01): bool); // bb1[6]: scope 3 at $DIR/region-subtyping-basic.rs:20:8: 20:12 switchInt(move _7) -> [Const(Value(Scalar(0x00)): bool): bb4, otherwise: bb2]; // bb1[7]: scope 3 at $DIR/region-subtyping-basic.rs:20:8: 20:12 } @@ -70,7 +70,7 @@ fn main() -> () { StorageLive(_8); // bb2[0]: scope 3 at $DIR/region-subtyping-basic.rs:21:9: 21:18 StorageLive(_9); // bb2[1]: scope 3 at $DIR/region-subtyping-basic.rs:21:15: 21:17 _9 = (*_6); // bb2[2]: scope 3 at $DIR/region-subtyping-basic.rs:21:15: 21:17 - _8 = Const(Value(Scalar()): fn(usize) -> bool {use_x})(move _9) -> [return: bb3, unwind: bb7]; // bb2[3]: scope 3 at $DIR/region-subtyping-basic.rs:21:9: 21:18 + _8 = ConstValue(Scalar(): fn(usize) -> bool {use_x})(move _9) -> [return: bb3, unwind: bb7]; // bb2[3]: scope 3 at $DIR/region-subtyping-basic.rs:21:9: 21:18 // mir::Constant // + span: $DIR/region-subtyping-basic.rs:21:9: 21:14 // + literal: Const { ty: fn(usize) -> bool {use_x}, val: Value(Scalar()) } @@ -79,13 +79,13 @@ fn main() -> () { bb3: { StorageDead(_9); // bb3[0]: scope 3 at $DIR/region-subtyping-basic.rs:21:17: 21:18 StorageDead(_8); // bb3[1]: scope 3 at $DIR/region-subtyping-basic.rs:21:18: 21:19 - _0 = const Const(Value(Scalar()): ()); // bb3[2]: scope 3 at $DIR/region-subtyping-basic.rs:20:13: 22:6 + _0 = const ConstValue(Scalar(): ()); // bb3[2]: scope 3 at $DIR/region-subtyping-basic.rs:20:13: 22:6 goto -> bb6; // bb3[3]: scope 3 at $DIR/region-subtyping-basic.rs:20:5: 24:6 } bb4: { StorageLive(_10); // bb4[0]: scope 3 at $DIR/region-subtyping-basic.rs:23:9: 23:18 - _10 = Const(Value(Scalar()): fn(usize) -> bool {use_x})(const Const(Value(Scalar(0x00000016)): usize)) -> [return: bb5, unwind: bb7]; // bb4[1]: scope 3 at $DIR/region-subtyping-basic.rs:23:9: 23:18 + _10 = ConstValue(Scalar(): fn(usize) -> bool {use_x})(const ConstValue(Scalar(0x00000016): usize)) -> [return: bb5, unwind: bb7]; // bb4[1]: scope 3 at $DIR/region-subtyping-basic.rs:23:9: 23:18 // mir::Constant // + span: $DIR/region-subtyping-basic.rs:23:9: 23:14 // + literal: Const { ty: fn(usize) -> bool {use_x}, val: Value(Scalar()) } @@ -93,7 +93,7 @@ fn main() -> () { bb5: { StorageDead(_10); // bb5[0]: scope 3 at $DIR/region-subtyping-basic.rs:23:18: 23:19 - _0 = const Const(Value(Scalar()): ()); // bb5[1]: scope 3 at $DIR/region-subtyping-basic.rs:22:12: 24:6 + _0 = const ConstValue(Scalar(): ()); // bb5[1]: scope 3 at $DIR/region-subtyping-basic.rs:22:12: 24:6 goto -> bb6; // bb5[2]: scope 3 at $DIR/region-subtyping-basic.rs:20:5: 24:6 } diff --git a/src/test/ui/consts/const-eval/const-eval-query-stack.rs b/src/test/ui/consts/const-eval/const-eval-query-stack.rs index 3797559a2a1a3..e73e54ff5f1b3 100644 --- a/src/test/ui/consts/const-eval/const-eval-query-stack.rs +++ b/src/test/ui/consts/const-eval/const-eval-query-stack.rs @@ -16,7 +16,6 @@ #![allow(unconditional_panic)] - #[warn(const_err)] const X: i32 = 1 / 0; //~WARN any use of this value will cause an error //~| WARN this was previously accepted by the compiler but is being phased out From e346920907d1dec22d2dcc19b0dc483b9a94810b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20BRANSTETT?= Date: Wed, 9 Mar 2022 11:18:28 +0100 Subject: [PATCH 21/28] Also take in account mdbook redirect in linkchecker --- src/tools/linkchecker/main.rs | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/src/tools/linkchecker/main.rs b/src/tools/linkchecker/main.rs index 46daaf42883f0..c9b1649200d9c 100644 --- a/src/tools/linkchecker/main.rs +++ b/src/tools/linkchecker/main.rs @@ -489,16 +489,22 @@ fn is_exception(file: &Path, link: &str) -> bool { /// If the given HTML file contents is an HTML redirect, this returns the /// destination path given in the redirect. fn maybe_redirect(source: &str) -> Option { - const REDIRECT: &str = "

Redirecting to Redirecting to Redirecting to... (source: &str, attr: &str, mut f: F) { From 021c3b011ab61829ca515b0c132cac7d7bef1ace Mon Sep 17 00:00:00 2001 From: b-naber Date: Wed, 9 Mar 2022 13:49:53 +0100 Subject: [PATCH 22/28] keep ERROR in message --- src/test/ui/associated-consts/defaults-cyclic-fail.rs | 2 +- src/test/ui/consts/const-eval/const-eval-query-stack.stderr | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/test/ui/associated-consts/defaults-cyclic-fail.rs b/src/test/ui/associated-consts/defaults-cyclic-fail.rs index 81b747424576c..2f1858d39b3c6 100644 --- a/src/test/ui/associated-consts/defaults-cyclic-fail.rs +++ b/src/test/ui/associated-consts/defaults-cyclic-fail.rs @@ -1,5 +1,5 @@ // build-fail -//~^ cycle detected when normalizing `<() as Tr>::A` [E0391] +//~^ ERROR cycle detected when normalizing `<() as Tr>::A` [E0391] // Cyclic assoc. const defaults don't error unless *used* trait Tr { diff --git a/src/test/ui/consts/const-eval/const-eval-query-stack.stderr b/src/test/ui/consts/const-eval/const-eval-query-stack.stderr index f9222952edc56..45a3d901c9871 100644 --- a/src/test/ui/consts/const-eval/const-eval-query-stack.stderr +++ b/src/test/ui/consts/const-eval/const-eval-query-stack.stderr @@ -1,5 +1,5 @@ warning: any use of this value will cause an error - --> $DIR/const-eval-query-stack.rs:21:16 + --> $DIR/const-eval-query-stack.rs:20:16 | LL | const X: i32 = 1 / 0; | ---------------^^^^^- @@ -7,7 +7,7 @@ LL | const X: i32 = 1 / 0; | attempt to divide `1_i32` by zero | note: the lint level is defined here - --> $DIR/const-eval-query-stack.rs:20:8 + --> $DIR/const-eval-query-stack.rs:19:8 | LL | #[warn(const_err)] | ^^^^^^^^^ @@ -15,7 +15,7 @@ LL | #[warn(const_err)] = note: for more information, see issue #71800 error[E0080]: evaluation of constant value failed - --> $DIR/const-eval-query-stack.rs:25:28 + --> $DIR/const-eval-query-stack.rs:24:28 | LL | let x: &'static i32 = &X; | ^ referenced constant has errors From e54d4ab189517efa1ef132b12443fc52de3faa8c Mon Sep 17 00:00:00 2001 From: JmPotato Date: Tue, 1 Mar 2022 13:23:30 +0800 Subject: [PATCH 23/28] Use MaybeUninit in VecDeque to remove the undefined behavior of slice Signed-off-by: JmPotato --- .../alloc/src/collections/vec_deque/iter.rs | 59 +++++++++++++------ .../alloc/src/collections/vec_deque/mod.rs | 56 ++++++++++++++---- 2 files changed, 86 insertions(+), 29 deletions(-) diff --git a/library/alloc/src/collections/vec_deque/iter.rs b/library/alloc/src/collections/vec_deque/iter.rs index edadd666edce6..253fa0b561e95 100644 --- a/library/alloc/src/collections/vec_deque/iter.rs +++ b/library/alloc/src/collections/vec_deque/iter.rs @@ -1,5 +1,6 @@ use core::fmt; use core::iter::{FusedIterator, TrustedLen, TrustedRandomAccess, TrustedRandomAccessNoCoerce}; +use core::mem::MaybeUninit; use core::ops::Try; use super::{count, wrap_index, RingSlices}; @@ -12,7 +13,7 @@ use super::{count, wrap_index, RingSlices}; /// [`iter`]: super::VecDeque::iter #[stable(feature = "rust1", since = "1.0.0")] pub struct Iter<'a, T: 'a> { - pub(crate) ring: &'a [T], + pub(crate) ring: &'a [MaybeUninit], pub(crate) tail: usize, pub(crate) head: usize, } @@ -44,7 +45,10 @@ impl<'a, T> Iterator for Iter<'a, T> { } let tail = self.tail; self.tail = wrap_index(self.tail.wrapping_add(1), self.ring.len()); - unsafe { Some(self.ring.get_unchecked(tail)) } + // Safety: + // - `self.tail` in a ring buffer is always a valid index. + // - `self.head` and `self.tail` equality is checked above. + unsafe { Some(self.ring.get_unchecked(tail).assume_init_ref()) } } #[inline] @@ -58,8 +62,13 @@ impl<'a, T> Iterator for Iter<'a, T> { F: FnMut(Acc, Self::Item) -> Acc, { let (front, back) = RingSlices::ring_slices(self.ring, self.head, self.tail); - accum = front.iter().fold(accum, &mut f); - back.iter().fold(accum, &mut f) + // Safety: + // - `self.head` and `self.tail` in a ring buffer are always valid indices. + // - `RingSlices::ring_slices` guarantees that the slices split according to `self.head` and `self.tail` are initialized. + unsafe { + accum = MaybeUninit::slice_assume_init_ref(front).iter().fold(accum, &mut f); + MaybeUninit::slice_assume_init_ref(back).iter().fold(accum, &mut f) + } } fn try_fold(&mut self, init: B, mut f: F) -> R @@ -70,17 +79,19 @@ impl<'a, T> Iterator for Iter<'a, T> { { let (mut iter, final_res); if self.tail <= self.head { - // single slice self.ring[self.tail..self.head] - iter = self.ring[self.tail..self.head].iter(); + // Safety: single slice self.ring[self.tail..self.head] is initialized. + iter = unsafe { MaybeUninit::slice_assume_init_ref(&self.ring[self.tail..self.head]) } + .iter(); final_res = iter.try_fold(init, &mut f); } else { - // two slices: self.ring[self.tail..], self.ring[..self.head] + // Safety: two slices: self.ring[self.tail..], self.ring[..self.head] both are initialized. let (front, back) = self.ring.split_at(self.tail); - let mut back_iter = back.iter(); + + let mut back_iter = unsafe { MaybeUninit::slice_assume_init_ref(back).iter() }; let res = back_iter.try_fold(init, &mut f); let len = self.ring.len(); self.tail = (self.ring.len() - back_iter.len()) & (len - 1); - iter = front[..self.head].iter(); + iter = unsafe { MaybeUninit::slice_assume_init_ref(&front[..self.head]).iter() }; final_res = iter.try_fold(res?, &mut f); } self.tail = self.head - iter.len(); @@ -109,7 +120,7 @@ impl<'a, T> Iterator for Iter<'a, T> { // that is in bounds. unsafe { let idx = wrap_index(self.tail.wrapping_add(idx), self.ring.len()); - self.ring.get_unchecked(idx) + self.ring.get_unchecked(idx).assume_init_ref() } } } @@ -122,7 +133,10 @@ impl<'a, T> DoubleEndedIterator for Iter<'a, T> { return None; } self.head = wrap_index(self.head.wrapping_sub(1), self.ring.len()); - unsafe { Some(self.ring.get_unchecked(self.head)) } + // Safety: + // - `self.head` in a ring buffer is always a valid index. + // - `self.head` and `self.tail` equality is checked above. + unsafe { Some(self.ring.get_unchecked(self.head).assume_init_ref()) } } fn rfold(self, mut accum: Acc, mut f: F) -> Acc @@ -130,8 +144,13 @@ impl<'a, T> DoubleEndedIterator for Iter<'a, T> { F: FnMut(Acc, Self::Item) -> Acc, { let (front, back) = RingSlices::ring_slices(self.ring, self.head, self.tail); - accum = back.iter().rfold(accum, &mut f); - front.iter().rfold(accum, &mut f) + // Safety: + // - `self.head` and `self.tail` in a ring buffer are always valid indices. + // - `RingSlices::ring_slices` guarantees that the slices split according to `self.head` and `self.tail` are initialized. + unsafe { + accum = MaybeUninit::slice_assume_init_ref(back).iter().rfold(accum, &mut f); + MaybeUninit::slice_assume_init_ref(front).iter().rfold(accum, &mut f) + } } fn try_rfold(&mut self, init: B, mut f: F) -> R @@ -142,16 +161,20 @@ impl<'a, T> DoubleEndedIterator for Iter<'a, T> { { let (mut iter, final_res); if self.tail <= self.head { - // single slice self.ring[self.tail..self.head] - iter = self.ring[self.tail..self.head].iter(); + // Safety: single slice self.ring[self.tail..self.head] is initialized. + iter = unsafe { + MaybeUninit::slice_assume_init_ref(&self.ring[self.tail..self.head]).iter() + }; final_res = iter.try_rfold(init, &mut f); } else { - // two slices: self.ring[self.tail..], self.ring[..self.head] + // Safety: two slices: self.ring[self.tail..], self.ring[..self.head] both are initialized. let (front, back) = self.ring.split_at(self.tail); - let mut front_iter = front[..self.head].iter(); + + let mut front_iter = + unsafe { MaybeUninit::slice_assume_init_ref(&front[..self.head]).iter() }; let res = front_iter.try_rfold(init, &mut f); self.head = front_iter.len(); - iter = back.iter(); + iter = unsafe { MaybeUninit::slice_assume_init_ref(back).iter() }; final_res = iter.try_rfold(res?, &mut f); } self.head = self.tail + iter.len(); diff --git a/library/alloc/src/collections/vec_deque/mod.rs b/library/alloc/src/collections/vec_deque/mod.rs index 7139a0fb94d76..f27cd684067f9 100644 --- a/library/alloc/src/collections/vec_deque/mod.rs +++ b/library/alloc/src/collections/vec_deque/mod.rs @@ -12,7 +12,7 @@ use core::fmt; use core::hash::{Hash, Hasher}; use core::iter::{repeat_with, FromIterator}; use core::marker::PhantomData; -use core::mem::{self, ManuallyDrop}; +use core::mem::{self, ManuallyDrop, MaybeUninit}; use core::ops::{Index, IndexMut, Range, RangeBounds}; use core::ptr::{self, NonNull}; use core::slice; @@ -181,16 +181,28 @@ impl VecDeque { } } - /// Turn ptr into a slice + /// Turn ptr into a slice, since the elements of the backing buffer may be uninitialized, + /// we will return a slice of [`MaybeUninit`]. + /// + /// See [`MaybeUninit::zeroed`][zeroed] for examples of correct and + /// incorrect usage of this method. + /// + /// [zeroed]: mem::MaybeUninit::zeroed #[inline] - unsafe fn buffer_as_slice(&self) -> &[T] { - unsafe { slice::from_raw_parts(self.ptr(), self.cap()) } + unsafe fn buffer_as_slice(&self) -> &[MaybeUninit] { + unsafe { slice::from_raw_parts(self.ptr() as *mut MaybeUninit, self.cap()) } } - /// Turn ptr into a mut slice + /// Turn ptr into a mut slice, since the elements of the backing buffer may be uninitialized, + /// we will return a slice of [`MaybeUninit`]. + /// + /// See [`MaybeUninit::zeroed`][zeroed] for examples of correct and + /// incorrect usage of this method. + /// + /// [zeroed]: mem::MaybeUninit::zeroed #[inline] - unsafe fn buffer_as_mut_slice(&mut self) -> &mut [T] { - unsafe { slice::from_raw_parts_mut(self.ptr(), self.cap()) } + unsafe fn buffer_as_mut_slice(&mut self) -> &mut [MaybeUninit] { + unsafe { slice::from_raw_parts_mut(self.ptr() as *mut MaybeUninit, self.cap()) } } /// Moves an element out of the buffer @@ -1055,9 +1067,13 @@ impl VecDeque { #[inline] #[stable(feature = "deque_extras_15", since = "1.5.0")] pub fn as_slices(&self) -> (&[T], &[T]) { + // Safety: + // - `self.head` and `self.tail` in a ring buffer are always valid indices. + // - `RingSlices::ring_slices` guarantees that the slices split according to `self.head` and `self.tail` are initialized. unsafe { let buf = self.buffer_as_slice(); - RingSlices::ring_slices(buf, self.head, self.tail) + let (front, back) = RingSlices::ring_slices(buf, self.head, self.tail); + (MaybeUninit::slice_assume_init_ref(front), MaybeUninit::slice_assume_init_ref(back)) } } @@ -1089,11 +1105,15 @@ impl VecDeque { #[inline] #[stable(feature = "deque_extras_15", since = "1.5.0")] pub fn as_mut_slices(&mut self) -> (&mut [T], &mut [T]) { + // Safety: + // - `self.head` and `self.tail` in a ring buffer are always valid indices. + // - `RingSlices::ring_slices` guarantees that the slices split according to `self.head` and `self.tail` are initialized. unsafe { let head = self.head; let tail = self.tail; let buf = self.buffer_as_mut_slice(); - RingSlices::ring_slices(buf, head, tail) + let (front, back) = RingSlices::ring_slices(buf, head, tail); + (MaybeUninit::slice_assume_init_mut(front), MaybeUninit::slice_assume_init_mut(back)) } } @@ -2327,7 +2347,14 @@ impl VecDeque { if self.is_contiguous() { let tail = self.tail; let head = self.head; - return unsafe { RingSlices::ring_slices(self.buffer_as_mut_slice(), head, tail).0 }; + // Safety: + // - `self.head` and `self.tail` in a ring buffer are always valid indices. + // - `RingSlices::ring_slices` guarantees that the slices split according to `self.head` and `self.tail` are initialized. + return unsafe { + MaybeUninit::slice_assume_init_mut( + RingSlices::ring_slices(self.buffer_as_mut_slice(), head, tail).0, + ) + }; } let buf = self.buf.ptr(); @@ -2413,7 +2440,14 @@ impl VecDeque { let tail = self.tail; let head = self.head; - unsafe { RingSlices::ring_slices(self.buffer_as_mut_slice(), head, tail).0 } + // Safety: + // - `self.head` and `self.tail` in a ring buffer are always valid indices. + // - `RingSlices::ring_slices` guarantees that the slices split according to `self.head` and `self.tail` are initialized. + unsafe { + MaybeUninit::slice_assume_init_mut( + RingSlices::ring_slices(self.buffer_as_mut_slice(), head, tail).0, + ) + } } /// Rotates the double-ended queue `mid` places to the left. From 4d56c1563c5ae75acbcb8c163296561a6e17e47a Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Wed, 9 Mar 2022 10:17:49 +0100 Subject: [PATCH 24/28] Add documentation about lifetimes to thread::scope. --- library/std/src/thread/scoped.rs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/library/std/src/thread/scoped.rs b/library/std/src/thread/scoped.rs index 4af58f1a38075..c4847b529a361 100644 --- a/library/std/src/thread/scoped.rs +++ b/library/std/src/thread/scoped.rs @@ -107,6 +107,24 @@ impl ScopeData { /// a.push(4); /// assert_eq!(x, a.len()); /// ``` +/// +/// # Lifetimes +/// +/// Scoped threads involve two lifetimes: `'scope` and `'env`. +/// +/// The `'scope` lifetime represents the lifetime of the scope itself. +/// That is: the time during which new scoped threads may be spawned, +/// and also the time during which they might still be running. +/// Once this lifetime ends, all scoped threads are joined. +/// This lifetime starts within the `scope` function, before `f` (the argument to `scope`) starts. +/// It ends after `f` returns and all scoped threads have been joined, but before `scope` returns. +/// +/// The `'env` lifetime represents the lifetime of whatever is borrowed by the scoped threads. +/// This lifetime must outlast the call to `scope`, and thus cannot be smaller than `'scope`. +/// It can be as small as the call to `scope`, meaning that anything that outlives this call, +/// such as local variables defined right before the scope, can be borrowed by the scoped threads. +/// +/// The `'env: 'scope` bound is part of the definition of the `Scope` type. #[track_caller] pub fn scope<'env, F, T>(f: F) -> T where From 6781016421e39208c4c2c644c71f07981c3bcd2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20BRANSTETT?= Date: Wed, 9 Mar 2022 16:52:38 +0100 Subject: [PATCH 25/28] Add miri to the well known conditional compilation names and values --- compiler/rustc_session/src/config.rs | 15 ++++++++----- compiler/rustc_span/src/symbol.rs | 1 + src/bootstrap/lib.rs | 1 - src/test/ui/check-cfg/well-known-names.rs | 6 +++++ src/test/ui/check-cfg/well-known-values.rs | 14 ++++++++++++ .../ui/check-cfg/well-known-values.stderr | 22 ++++++++++++++++++- 6 files changed, 52 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 221dc86c1d46d..1d36ff059de81 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -1072,6 +1072,7 @@ impl CrateCheckConfig { // NOTE: This should be kept in sync with `default_configuration` and // `fill_well_known_values` const WELL_KNOWN_NAMES: &[Symbol] = &[ + // rustc sym::unix, sym::windows, sym::target_os, @@ -1091,9 +1092,12 @@ impl CrateCheckConfig { sym::debug_assertions, sym::proc_macro, sym::test, + sym::feature, + // rustdoc sym::doc, sym::doctest, - sym::feature, + // miri + sym::miri, ]; // We only insert well-known names if `names()` was activated @@ -1128,13 +1132,14 @@ impl CrateCheckConfig { // No-values for name in [ + sym::doc, + sym::miri, sym::unix, - sym::windows, - sym::debug_assertions, - sym::proc_macro, sym::test, - sym::doc, sym::doctest, + sym::windows, + sym::proc_macro, + sym::debug_assertions, sym::target_thread_local, ] { self.values_valid.entry(name).or_default(); diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 3f44292e03425..3884578f5d46c 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -891,6 +891,7 @@ symbols! { minnumf32, minnumf64, mips_target_feature, + miri, misc, mmx_reg, modifiers, diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index ccc8516a89abf..8dfb90c0de131 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -193,7 +193,6 @@ const EXTRA_CHECK_CFGS: &[(Option, &'static str, Option<&[&'static str]>)] (None, "bootstrap", None), (Some(Mode::Rustc), "parallel_compiler", None), (Some(Mode::ToolRustc), "parallel_compiler", None), - (Some(Mode::Std), "miri", None), (Some(Mode::Std), "stdarch_intel_sde", None), (Some(Mode::Std), "no_fp_fmt_parse", None), (Some(Mode::Std), "no_global_oom_handling", None), diff --git a/src/test/ui/check-cfg/well-known-names.rs b/src/test/ui/check-cfg/well-known-names.rs index a66568a2ffdc9..e57fb69a1e05f 100644 --- a/src/test/ui/check-cfg/well-known-names.rs +++ b/src/test/ui/check-cfg/well-known-names.rs @@ -24,4 +24,10 @@ fn unix_misspell() {} #[cfg(unix)] fn unix() {} +#[cfg(miri)] +fn miri() {} + +#[cfg(doc)] +fn doc() {} + fn main() {} diff --git a/src/test/ui/check-cfg/well-known-values.rs b/src/test/ui/check-cfg/well-known-values.rs index 46004be43d812..96375dc8d3130 100644 --- a/src/test/ui/check-cfg/well-known-values.rs +++ b/src/test/ui/check-cfg/well-known-values.rs @@ -25,4 +25,18 @@ fn unix_with_value() {} #[cfg(unix)] fn unix() {} +#[cfg(miri = "miri")] +//~^ WARNING unexpected `cfg` condition value +fn miri_with_value() {} + +#[cfg(miri)] +fn miri() {} + +#[cfg(doc = "linux")] +//~^ WARNING unexpected `cfg` condition value +fn doc_with_value() {} + +#[cfg(doc)] +fn doc() {} + fn main() {} diff --git a/src/test/ui/check-cfg/well-known-values.stderr b/src/test/ui/check-cfg/well-known-values.stderr index 8eefd6aaf35ec..8b04c770fb505 100644 --- a/src/test/ui/check-cfg/well-known-values.stderr +++ b/src/test/ui/check-cfg/well-known-values.stderr @@ -29,5 +29,25 @@ LL | #[cfg(unix = "aa")] | = note: no expected value for `unix` -warning: 3 warnings emitted +warning: unexpected `cfg` condition value + --> $DIR/well-known-values.rs:28:7 + | +LL | #[cfg(miri = "miri")] + | ^^^^--------- + | | + | help: remove the value + | + = note: no expected value for `miri` + +warning: unexpected `cfg` condition value + --> $DIR/well-known-values.rs:35:7 + | +LL | #[cfg(doc = "linux")] + | ^^^---------- + | | + | help: remove the value + | + = note: no expected value for `doc` + +warning: 5 warnings emitted From 915f9a599c360d02734f553daeaa46e137bc2a63 Mon Sep 17 00:00:00 2001 From: Caio Date: Wed, 9 Mar 2022 15:04:09 -0300 Subject: [PATCH 26/28] Warn users about || in let chain expressions --- .../rustc_ast_passes/src/ast_validation.rs | 104 ++++++----- compiler/rustc_ast_passes/src/lib.rs | 6 +- .../disallowed-positions.stderr | 165 ++++++++++++------ 3 files changed, 179 insertions(+), 96 deletions(-) diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index 0cf73178d679d..8f0b12cb4feef 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -64,8 +64,8 @@ struct AstValidator<'a> { /// certain positions. is_assoc_ty_bound_banned: bool, - /// Used to allow `let` expressions in certain syntactic locations. - is_let_allowed: bool, + /// See [ForbiddenLetReason] + forbidden_let_reason: Option, lint_buffer: &'a mut LintBuffer, } @@ -103,20 +103,28 @@ impl<'a> AstValidator<'a> { self.is_tilde_const_allowed = old; } - fn with_let_allowed(&mut self, allowed: bool, f: impl FnOnce(&mut Self, bool)) { - let old = mem::replace(&mut self.is_let_allowed, allowed); + fn with_let_management( + &mut self, + forbidden_let_reason: Option, + f: impl FnOnce(&mut Self, Option), + ) { + let old = mem::replace(&mut self.forbidden_let_reason, forbidden_let_reason); f(self, old); - self.is_let_allowed = old; + self.forbidden_let_reason = old; } /// Emits an error banning the `let` expression provided in the given location. - fn ban_let_expr(&self, expr: &'a Expr) { + fn ban_let_expr(&self, expr: &'a Expr, forbidden_let_reason: ForbiddenLetReason) { let sess = &self.session; if sess.opts.unstable_features.is_nightly_build() { - sess.struct_span_err(expr.span, "`let` expressions are not supported here") - .note("only supported directly in conditions of `if`- and `while`-expressions") - .note("as well as when nested within `&&` and parentheses in those conditions") - .emit(); + let err = "`let` expressions are not supported here"; + let mut diag = sess.struct_span_err(expr.span, err); + diag.note("only supported directly in conditions of `if` and `while` expressions"); + diag.note("as well as when nested within `&&` and parentheses in those conditions"); + if let ForbiddenLetReason::ForbiddenWithOr(span) = forbidden_let_reason { + diag.span_note(span, "`||` operators are not allowed in let chain expressions"); + } + diag.emit(); } else { sess.struct_span_err(expr.span, "expected expression, found statement (`let`)") .note("variable declaration using `let` is a statement") @@ -988,39 +996,48 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } fn visit_expr(&mut self, expr: &'a Expr) { - self.with_let_allowed(false, |this, let_allowed| match &expr.kind { - ExprKind::If(cond, then, opt_else) => { - this.visit_block(then); - walk_list!(this, visit_expr, opt_else); - this.with_let_allowed(true, |this, _| this.visit_expr(cond)); - return; - } - ExprKind::Let(..) if !let_allowed => this.ban_let_expr(expr), - ExprKind::Match(expr, arms) => { - this.visit_expr(expr); - for arm in arms { - this.visit_expr(&arm.body); - this.visit_pat(&arm.pat); - walk_list!(this, visit_attribute, &arm.attrs); - if let Some(ref guard) = arm.guard { - if let ExprKind::Let(_, ref expr, _) = guard.kind { - this.with_let_allowed(true, |this, _| this.visit_expr(expr)); + self.with_let_management(Some(ForbiddenLetReason::GenericForbidden), |this, forbidden_let_reason| { + match &expr.kind { + ExprKind::Binary(Spanned { node: BinOpKind::Or, span }, lhs, rhs) => { + let forbidden_let_reason = Some(ForbiddenLetReason::ForbiddenWithOr(*span)); + this.with_let_management(forbidden_let_reason, |this, _| this.visit_expr(lhs)); + this.with_let_management(forbidden_let_reason, |this, _| this.visit_expr(rhs)); + } + ExprKind::If(cond, then, opt_else) => { + this.visit_block(then); + walk_list!(this, visit_expr, opt_else); + this.with_let_management(None, |this, _| this.visit_expr(cond)); + return; + } + ExprKind::Let(..) if let Some(elem) = forbidden_let_reason => { + this.ban_let_expr(expr, elem); + }, + ExprKind::Match(scrutinee, arms) => { + this.visit_expr(scrutinee); + for arm in arms { + this.visit_expr(&arm.body); + this.visit_pat(&arm.pat); + walk_list!(this, visit_attribute, &arm.attrs); + if let Some(guard) = &arm.guard && let ExprKind::Let(_, guard_expr, _) = &guard.kind { + this.with_let_management(None, |this, _| { + this.visit_expr(guard_expr) + }); return; } } } + ExprKind::Paren(_) | ExprKind::Binary(Spanned { node: BinOpKind::And, .. }, ..) => { + this.with_let_management(forbidden_let_reason, |this, _| visit::walk_expr(this, expr)); + return; + } + ExprKind::While(cond, then, opt_label) => { + walk_list!(this, visit_label, opt_label); + this.visit_block(then); + this.with_let_management(None, |this, _| this.visit_expr(cond)); + return; + } + _ => visit::walk_expr(this, expr), } - ExprKind::Paren(_) | ExprKind::Binary(Spanned { node: BinOpKind::And, .. }, ..) => { - this.with_let_allowed(let_allowed, |this, _| visit::walk_expr(this, expr)); - return; - } - ExprKind::While(cond, then, opt_label) => { - walk_list!(this, visit_label, opt_label); - this.visit_block(then); - this.with_let_allowed(true, |this, _| this.visit_expr(cond)); - return; - } - _ => visit::walk_expr(this, expr), }); } @@ -1772,10 +1789,19 @@ pub fn check_crate(session: &Session, krate: &Crate, lints: &mut LintBuffer) -> is_tilde_const_allowed: false, is_impl_trait_banned: false, is_assoc_ty_bound_banned: false, - is_let_allowed: false, + forbidden_let_reason: Some(ForbiddenLetReason::GenericForbidden), lint_buffer: lints, }; visit::walk_crate(&mut validator, krate); validator.has_proc_macro_decls } + +/// Used to forbid `let` expressions in certain syntactic locations. +#[derive(Clone, Copy)] +enum ForbiddenLetReason { + /// A let chain with the `||` operator + ForbiddenWithOr(Span), + /// `let` is not valid and the source environment is not important + GenericForbidden, +} diff --git a/compiler/rustc_ast_passes/src/lib.rs b/compiler/rustc_ast_passes/src/lib.rs index 876dd7f757c5a..9d52c32885db0 100644 --- a/compiler/rustc_ast_passes/src/lib.rs +++ b/compiler/rustc_ast_passes/src/lib.rs @@ -4,11 +4,13 @@ //! //! The crate also contains other misc AST visitors, e.g. `node_count` and `show_span`. -#![feature(iter_is_partitioned)] +#![allow(rustc::potential_query_instability)] #![feature(box_patterns)] +#![feature(if_let_guard)] +#![feature(iter_is_partitioned)] +#![feature(let_chains)] #![feature(let_else)] #![recursion_limit = "256"] -#![allow(rustc::potential_query_instability)] pub mod ast_validation; pub mod feature_gate; diff --git a/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr b/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr index 897de54a7bf8c..dd090a3a5483d 100644 --- a/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr +++ b/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr @@ -15,7 +15,7 @@ error: `let` expressions are not supported here LL | if &let 0 = 0 {} | ^^^^^^^^^ | - = note: only supported directly in conditions of `if`- and `while`-expressions + = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here @@ -24,7 +24,7 @@ error: `let` expressions are not supported here LL | if !let 0 = 0 {} | ^^^^^^^^^ | - = note: only supported directly in conditions of `if`- and `while`-expressions + = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here @@ -33,7 +33,7 @@ error: `let` expressions are not supported here LL | if *let 0 = 0 {} | ^^^^^^^^^ | - = note: only supported directly in conditions of `if`- and `while`-expressions + = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here @@ -42,7 +42,7 @@ error: `let` expressions are not supported here LL | if -let 0 = 0 {} | ^^^^^^^^^ | - = note: only supported directly in conditions of `if`- and `while`-expressions + = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here @@ -51,7 +51,7 @@ error: `let` expressions are not supported here LL | if (let 0 = 0)? {} | ^^^^^^^^^ | - = note: only supported directly in conditions of `if`- and `while`-expressions + = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here @@ -60,8 +60,13 @@ error: `let` expressions are not supported here LL | if true || let 0 = 0 {} | ^^^^^^^^^ | - = note: only supported directly in conditions of `if`- and `while`-expressions + = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions +note: `||` operators are not allowed in let chain expressions + --> $DIR/disallowed-positions.rs:47:13 + | +LL | if true || let 0 = 0 {} + | ^^ error: `let` expressions are not supported here --> $DIR/disallowed-positions.rs:48:17 @@ -69,8 +74,13 @@ error: `let` expressions are not supported here LL | if (true || let 0 = 0) {} | ^^^^^^^^^ | - = note: only supported directly in conditions of `if`- and `while`-expressions + = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions +note: `||` operators are not allowed in let chain expressions + --> $DIR/disallowed-positions.rs:48:14 + | +LL | if (true || let 0 = 0) {} + | ^^ error: `let` expressions are not supported here --> $DIR/disallowed-positions.rs:49:25 @@ -78,8 +88,13 @@ error: `let` expressions are not supported here LL | if true && (true || let 0 = 0) {} | ^^^^^^^^^ | - = note: only supported directly in conditions of `if`- and `while`-expressions + = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions +note: `||` operators are not allowed in let chain expressions + --> $DIR/disallowed-positions.rs:49:22 + | +LL | if true && (true || let 0 = 0) {} + | ^^ error: `let` expressions are not supported here --> $DIR/disallowed-positions.rs:50:25 @@ -87,8 +102,13 @@ error: `let` expressions are not supported here LL | if true || (true && let 0 = 0) {} | ^^^^^^^^^ | - = note: only supported directly in conditions of `if`- and `while`-expressions + = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions +note: `||` operators are not allowed in let chain expressions + --> $DIR/disallowed-positions.rs:50:13 + | +LL | if true || (true && let 0 = 0) {} + | ^^ error: `let` expressions are not supported here --> $DIR/disallowed-positions.rs:53:12 @@ -96,7 +116,7 @@ error: `let` expressions are not supported here LL | if x = let 0 = 0 {} | ^^^^^^^^^ | - = note: only supported directly in conditions of `if`- and `while`-expressions + = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here @@ -105,7 +125,7 @@ error: `let` expressions are not supported here LL | if true..(let 0 = 0) {} | ^^^^^^^^^ | - = note: only supported directly in conditions of `if`- and `while`-expressions + = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here @@ -114,7 +134,7 @@ error: `let` expressions are not supported here LL | if ..(let 0 = 0) {} | ^^^^^^^^^ | - = note: only supported directly in conditions of `if`- and `while`-expressions + = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here @@ -123,7 +143,7 @@ error: `let` expressions are not supported here LL | if (let 0 = 0).. {} | ^^^^^^^^^ | - = note: only supported directly in conditions of `if`- and `while`-expressions + = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here @@ -132,7 +152,7 @@ error: `let` expressions are not supported here LL | if let Range { start: _, end: _ } = true..true && false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: only supported directly in conditions of `if`- and `while`-expressions + = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here @@ -141,7 +161,7 @@ error: `let` expressions are not supported here LL | if let Range { start: _, end: _ } = true..true || false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: only supported directly in conditions of `if`- and `while`-expressions + = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here @@ -150,7 +170,7 @@ error: `let` expressions are not supported here LL | if let Range { start: F, end } = F..|| true {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: only supported directly in conditions of `if`- and `while`-expressions + = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here @@ -159,7 +179,7 @@ error: `let` expressions are not supported here LL | if let Range { start: true, end } = t..&&false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: only supported directly in conditions of `if`- and `while`-expressions + = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here @@ -168,7 +188,7 @@ error: `let` expressions are not supported here LL | if let true = let true = true {} | ^^^^^^^^^^^^^^^ | - = note: only supported directly in conditions of `if`- and `while`-expressions + = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here @@ -177,7 +197,7 @@ error: `let` expressions are not supported here LL | while &let 0 = 0 {} | ^^^^^^^^^ | - = note: only supported directly in conditions of `if`- and `while`-expressions + = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here @@ -186,7 +206,7 @@ error: `let` expressions are not supported here LL | while !let 0 = 0 {} | ^^^^^^^^^ | - = note: only supported directly in conditions of `if`- and `while`-expressions + = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here @@ -195,7 +215,7 @@ error: `let` expressions are not supported here LL | while *let 0 = 0 {} | ^^^^^^^^^ | - = note: only supported directly in conditions of `if`- and `while`-expressions + = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here @@ -204,7 +224,7 @@ error: `let` expressions are not supported here LL | while -let 0 = 0 {} | ^^^^^^^^^ | - = note: only supported directly in conditions of `if`- and `while`-expressions + = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here @@ -213,7 +233,7 @@ error: `let` expressions are not supported here LL | while (let 0 = 0)? {} | ^^^^^^^^^ | - = note: only supported directly in conditions of `if`- and `while`-expressions + = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here @@ -222,8 +242,13 @@ error: `let` expressions are not supported here LL | while true || let 0 = 0 {} | ^^^^^^^^^ | - = note: only supported directly in conditions of `if`- and `while`-expressions + = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions +note: `||` operators are not allowed in let chain expressions + --> $DIR/disallowed-positions.rs:111:16 + | +LL | while true || let 0 = 0 {} + | ^^ error: `let` expressions are not supported here --> $DIR/disallowed-positions.rs:112:20 @@ -231,8 +256,13 @@ error: `let` expressions are not supported here LL | while (true || let 0 = 0) {} | ^^^^^^^^^ | - = note: only supported directly in conditions of `if`- and `while`-expressions + = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions +note: `||` operators are not allowed in let chain expressions + --> $DIR/disallowed-positions.rs:112:17 + | +LL | while (true || let 0 = 0) {} + | ^^ error: `let` expressions are not supported here --> $DIR/disallowed-positions.rs:113:28 @@ -240,8 +270,13 @@ error: `let` expressions are not supported here LL | while true && (true || let 0 = 0) {} | ^^^^^^^^^ | - = note: only supported directly in conditions of `if`- and `while`-expressions + = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions +note: `||` operators are not allowed in let chain expressions + --> $DIR/disallowed-positions.rs:113:25 + | +LL | while true && (true || let 0 = 0) {} + | ^^ error: `let` expressions are not supported here --> $DIR/disallowed-positions.rs:114:28 @@ -249,8 +284,13 @@ error: `let` expressions are not supported here LL | while true || (true && let 0 = 0) {} | ^^^^^^^^^ | - = note: only supported directly in conditions of `if`- and `while`-expressions + = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions +note: `||` operators are not allowed in let chain expressions + --> $DIR/disallowed-positions.rs:114:16 + | +LL | while true || (true && let 0 = 0) {} + | ^^ error: `let` expressions are not supported here --> $DIR/disallowed-positions.rs:117:15 @@ -258,7 +298,7 @@ error: `let` expressions are not supported here LL | while x = let 0 = 0 {} | ^^^^^^^^^ | - = note: only supported directly in conditions of `if`- and `while`-expressions + = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here @@ -267,7 +307,7 @@ error: `let` expressions are not supported here LL | while true..(let 0 = 0) {} | ^^^^^^^^^ | - = note: only supported directly in conditions of `if`- and `while`-expressions + = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here @@ -276,7 +316,7 @@ error: `let` expressions are not supported here LL | while ..(let 0 = 0) {} | ^^^^^^^^^ | - = note: only supported directly in conditions of `if`- and `while`-expressions + = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here @@ -285,7 +325,7 @@ error: `let` expressions are not supported here LL | while (let 0 = 0).. {} | ^^^^^^^^^ | - = note: only supported directly in conditions of `if`- and `while`-expressions + = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here @@ -294,7 +334,7 @@ error: `let` expressions are not supported here LL | while let Range { start: _, end: _ } = true..true && false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: only supported directly in conditions of `if`- and `while`-expressions + = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here @@ -303,7 +343,7 @@ error: `let` expressions are not supported here LL | while let Range { start: _, end: _ } = true..true || false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: only supported directly in conditions of `if`- and `while`-expressions + = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here @@ -312,7 +352,7 @@ error: `let` expressions are not supported here LL | while let Range { start: F, end } = F..|| true {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: only supported directly in conditions of `if`- and `while`-expressions + = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here @@ -321,7 +361,7 @@ error: `let` expressions are not supported here LL | while let Range { start: true, end } = t..&&false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: only supported directly in conditions of `if`- and `while`-expressions + = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here @@ -330,7 +370,7 @@ error: `let` expressions are not supported here LL | while let true = let true = true {} | ^^^^^^^^^^^^^^^ | - = note: only supported directly in conditions of `if`- and `while`-expressions + = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here @@ -339,7 +379,7 @@ error: `let` expressions are not supported here LL | &let 0 = 0; | ^^^^^^^^^ | - = note: only supported directly in conditions of `if`- and `while`-expressions + = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here @@ -348,7 +388,7 @@ error: `let` expressions are not supported here LL | !let 0 = 0; | ^^^^^^^^^ | - = note: only supported directly in conditions of `if`- and `while`-expressions + = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here @@ -357,7 +397,7 @@ error: `let` expressions are not supported here LL | *let 0 = 0; | ^^^^^^^^^ | - = note: only supported directly in conditions of `if`- and `while`-expressions + = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here @@ -366,7 +406,7 @@ error: `let` expressions are not supported here LL | -let 0 = 0; | ^^^^^^^^^ | - = note: only supported directly in conditions of `if`- and `while`-expressions + = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here @@ -375,7 +415,7 @@ error: `let` expressions are not supported here LL | (let 0 = 0)?; | ^^^^^^^^^ | - = note: only supported directly in conditions of `if`- and `while`-expressions + = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here @@ -384,8 +424,13 @@ error: `let` expressions are not supported here LL | true || let 0 = 0; | ^^^^^^^^^ | - = note: only supported directly in conditions of `if`- and `while`-expressions + = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions +note: `||` operators are not allowed in let chain expressions + --> $DIR/disallowed-positions.rs:184:10 + | +LL | true || let 0 = 0; + | ^^ error: `let` expressions are not supported here --> $DIR/disallowed-positions.rs:185:14 @@ -393,8 +438,13 @@ error: `let` expressions are not supported here LL | (true || let 0 = 0); | ^^^^^^^^^ | - = note: only supported directly in conditions of `if`- and `while`-expressions + = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions +note: `||` operators are not allowed in let chain expressions + --> $DIR/disallowed-positions.rs:185:11 + | +LL | (true || let 0 = 0); + | ^^ error: `let` expressions are not supported here --> $DIR/disallowed-positions.rs:186:22 @@ -402,8 +452,13 @@ error: `let` expressions are not supported here LL | true && (true || let 0 = 0); | ^^^^^^^^^ | - = note: only supported directly in conditions of `if`- and `while`-expressions + = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions +note: `||` operators are not allowed in let chain expressions + --> $DIR/disallowed-positions.rs:186:19 + | +LL | true && (true || let 0 = 0); + | ^^ error: `let` expressions are not supported here --> $DIR/disallowed-positions.rs:189:9 @@ -411,7 +466,7 @@ error: `let` expressions are not supported here LL | x = let 0 = 0; | ^^^^^^^^^ | - = note: only supported directly in conditions of `if`- and `while`-expressions + = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here @@ -420,7 +475,7 @@ error: `let` expressions are not supported here LL | true..(let 0 = 0); | ^^^^^^^^^ | - = note: only supported directly in conditions of `if`- and `while`-expressions + = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here @@ -429,7 +484,7 @@ error: `let` expressions are not supported here LL | ..(let 0 = 0); | ^^^^^^^^^ | - = note: only supported directly in conditions of `if`- and `while`-expressions + = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here @@ -438,7 +493,7 @@ error: `let` expressions are not supported here LL | (let 0 = 0)..; | ^^^^^^^^^ | - = note: only supported directly in conditions of `if`- and `while`-expressions + = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here @@ -447,7 +502,7 @@ error: `let` expressions are not supported here LL | (let Range { start: _, end: _ } = true..true || false); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: only supported directly in conditions of `if`- and `while`-expressions + = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here @@ -456,7 +511,7 @@ error: `let` expressions are not supported here LL | (let true = let true = true); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: only supported directly in conditions of `if`- and `while`-expressions + = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here @@ -465,7 +520,7 @@ error: `let` expressions are not supported here LL | &let 0 = 0 | ^^^^^^^^^ | - = note: only supported directly in conditions of `if`- and `while`-expressions + = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here @@ -474,7 +529,7 @@ error: `let` expressions are not supported here LL | true && let 1 = 1 | ^^^^^^^^^ | - = note: only supported directly in conditions of `if`- and `while`-expressions + = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here @@ -483,7 +538,7 @@ error: `let` expressions are not supported here LL | true && let 1 = 1 | ^^^^^^^^^ | - = note: only supported directly in conditions of `if`- and `while`-expressions + = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here @@ -492,7 +547,7 @@ error: `let` expressions are not supported here LL | true && let 1 = 1 | ^^^^^^^^^ | - = note: only supported directly in conditions of `if`- and `while`-expressions + = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions error: `let` expressions are not supported here @@ -501,7 +556,7 @@ error: `let` expressions are not supported here LL | true && let 1 = 1 | ^^^^^^^^^ | - = note: only supported directly in conditions of `if`- and `while`-expressions + = note: only supported directly in conditions of `if` and `while` expressions = note: as well as when nested within `&&` and parentheses in those conditions error[E0308]: mismatched types From 8073a88f35728289ef535cca5cf13302faba5972 Mon Sep 17 00:00:00 2001 From: Caio Date: Wed, 9 Mar 2022 16:46:23 -0300 Subject: [PATCH 27/28] Implement macro meta-variable expressions --- compiler/rustc_ast/src/util/literal.rs | 2 +- compiler/rustc_expand/src/lib.rs | 1 + compiler/rustc_expand/src/mbe.rs | 16 +- compiler/rustc_expand/src/mbe/macro_check.rs | 4 + compiler/rustc_expand/src/mbe/macro_parser.rs | 13 +- compiler/rustc_expand/src/mbe/macro_rules.rs | 20 +- compiler/rustc_expand/src/mbe/metavar_expr.rs | 157 ++++++++ compiler/rustc_expand/src/mbe/quoted.rs | 123 ++++-- compiler/rustc_expand/src/mbe/transcribe.rs | 27 ++ compiler/rustc_feature/src/active.rs | 2 + compiler/rustc_span/src/symbol.rs | 1 + .../dollar-dollar-has-correct-behavior.rs | 28 ++ .../feature-gate-macro_metavar_expr.rs | 14 + .../rfc-3086-metavar-expr/required-feature.rs | 9 + .../required-feature.stderr | 12 + .../rfc-3086-metavar-expr/syntax-errors.rs | 148 +++++++ .../syntax-errors.stderr | 367 ++++++++++++++++++ 17 files changed, 900 insertions(+), 44 deletions(-) create mode 100644 compiler/rustc_expand/src/mbe/metavar_expr.rs create mode 100644 src/test/ui/macros/rfc-3086-metavar-expr/dollar-dollar-has-correct-behavior.rs create mode 100644 src/test/ui/macros/rfc-3086-metavar-expr/feature-gate-macro_metavar_expr.rs create mode 100644 src/test/ui/macros/rfc-3086-metavar-expr/required-feature.rs create mode 100644 src/test/ui/macros/rfc-3086-metavar-expr/required-feature.stderr create mode 100644 src/test/ui/macros/rfc-3086-metavar-expr/syntax-errors.rs create mode 100644 src/test/ui/macros/rfc-3086-metavar-expr/syntax-errors.stderr diff --git a/compiler/rustc_ast/src/util/literal.rs b/compiler/rustc_ast/src/util/literal.rs index 231dd72af2c7d..9c18f55c03b4d 100644 --- a/compiler/rustc_ast/src/util/literal.rs +++ b/compiler/rustc_ast/src/util/literal.rs @@ -23,7 +23,7 @@ pub enum LitError { impl LitKind { /// Converts literal token into a semantic literal. - fn from_lit_token(lit: token::Lit) -> Result { + pub fn from_lit_token(lit: token::Lit) -> Result { let token::Lit { kind, symbol, suffix } = lit; if suffix.is_some() && !kind.may_have_suffix() { return Err(LitError::InvalidSuffix); diff --git a/compiler/rustc_expand/src/lib.rs b/compiler/rustc_expand/src/lib.rs index b024524aa2968..8a9efe01368e3 100644 --- a/compiler/rustc_expand/src/lib.rs +++ b/compiler/rustc_expand/src/lib.rs @@ -3,6 +3,7 @@ #![feature(crate_visibility_modifier)] #![feature(decl_macro)] #![feature(if_let_guard)] +#![feature(let_chains)] #![feature(let_else)] #![feature(proc_macro_diagnostic)] #![feature(proc_macro_internals)] diff --git a/compiler/rustc_expand/src/mbe.rs b/compiler/rustc_expand/src/mbe.rs index 5244ac36bba5d..3d4c77aba7339 100644 --- a/compiler/rustc_expand/src/mbe.rs +++ b/compiler/rustc_expand/src/mbe.rs @@ -6,17 +6,17 @@ crate mod macro_check; crate mod macro_parser; crate mod macro_rules; +crate mod metavar_expr; crate mod quoted; crate mod transcribe; +use metavar_expr::MetaVarExpr; use rustc_ast::token::{self, NonterminalKind, Token, TokenKind}; use rustc_ast::tokenstream::DelimSpan; - +use rustc_data_structures::sync::Lrc; use rustc_span::symbol::Ident; use rustc_span::Span; -use rustc_data_structures::sync::Lrc; - /// Contains the sub-token-trees of a "delimited" token tree, such as the contents of `(`. Note /// that the delimiter itself might be `NoDelim`. #[derive(Clone, PartialEq, Encodable, Decodable, Debug)] @@ -73,8 +73,8 @@ enum KleeneOp { ZeroOrOne, } -/// Similar to `tokenstream::TokenTree`, except that `$i`, `$i:ident`, and `$(...)` -/// are "first-class" token trees. Useful for parsing macros. +/// Similar to `tokenstream::TokenTree`, except that `$i`, `$i:ident`, `$(...)`, +/// and `${...}` are "first-class" token trees. Useful for parsing macros. #[derive(Debug, Clone, PartialEq, Encodable, Decodable)] enum TokenTree { Token(Token), @@ -85,6 +85,8 @@ enum TokenTree { MetaVar(Span, Ident), /// e.g., `$var:expr`. This is only used in the left hand side of MBE macros. MetaVarDecl(Span, Ident /* name to bind */, Option), + /// A meta-variable expression inside `${...}` + MetaVarExpr(DelimSpan, MetaVarExpr), } impl TokenTree { @@ -139,7 +141,9 @@ impl TokenTree { TokenTree::Token(Token { span, .. }) | TokenTree::MetaVar(span, _) | TokenTree::MetaVarDecl(span, _, _) => span, - TokenTree::Delimited(span, _) | TokenTree::Sequence(span, _) => span.entire(), + TokenTree::Delimited(span, _) + | TokenTree::MetaVarExpr(span, _) + | TokenTree::Sequence(span, _) => span.entire(), } } diff --git a/compiler/rustc_expand/src/mbe/macro_check.rs b/compiler/rustc_expand/src/mbe/macro_check.rs index 3497e5ad543a1..88e1169322093 100644 --- a/compiler/rustc_expand/src/mbe/macro_check.rs +++ b/compiler/rustc_expand/src/mbe/macro_check.rs @@ -278,6 +278,8 @@ fn check_binders( binders.insert(name, BinderInfo { span, ops: ops.into() }); } } + // `MetaVarExpr` can not appear in the LHS of a macro arm + TokenTree::MetaVarExpr(..) => {} TokenTree::Delimited(_, ref del) => { for tt in &del.tts { check_binders(sess, node_id, tt, macros, binders, ops, valid); @@ -335,6 +337,8 @@ fn check_occurrences( let name = MacroRulesNormalizedIdent::new(name); check_ops_is_prefix(sess, node_id, macros, binders, ops, span, name); } + // FIXME(c410-f3r) Check token (https://github.com/rust-lang/rust/issues/93902) + TokenTree::MetaVarExpr(..) => {} TokenTree::Delimited(_, ref del) => { check_nested_occurrences(sess, node_id, &del.tts, macros, binders, ops, valid); } diff --git a/compiler/rustc_expand/src/mbe/macro_parser.rs b/compiler/rustc_expand/src/mbe/macro_parser.rs index bb36dfd793d4a..04137086088dd 100644 --- a/compiler/rustc_expand/src/mbe/macro_parser.rs +++ b/compiler/rustc_expand/src/mbe/macro_parser.rs @@ -200,7 +200,7 @@ struct MatcherPos<'root, 'tt> { // This type is used a lot. Make sure it doesn't unintentionally get bigger. #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] -rustc_data_structures::static_assert_size!(MatcherPos<'_, '_>, 192); +rustc_data_structures::static_assert_size!(MatcherPos<'_, '_>, 240); impl<'root, 'tt> MatcherPos<'root, 'tt> { /// Generates the top-level matcher position in which the "dot" is before the first token of @@ -321,10 +321,13 @@ pub(super) fn count_names(ms: &[TokenTree]) -> usize { ms.iter().fold(0, |count, elt| { count + match *elt { - TokenTree::Sequence(_, ref seq) => seq.num_captures, TokenTree::Delimited(_, ref delim) => count_names(&delim.tts), TokenTree::MetaVar(..) => 0, TokenTree::MetaVarDecl(..) => 1, + // FIXME(c410-f3r) MetaVarExpr should be handled instead of being ignored + // https://github.com/rust-lang/rust/issues/9390 + TokenTree::MetaVarExpr(..) => 0, + TokenTree::Sequence(_, ref seq) => seq.num_captures, TokenTree::Token(..) => 0, } }) @@ -436,7 +439,9 @@ fn nameize>( } Occupied(..) => return Err((sp, format!("duplicated bind name: {}", bind_name))), }, - TokenTree::MetaVar(..) | TokenTree::Token(..) => (), + // FIXME(c410-f3r) MetaVar and MetaVarExpr should be handled instead of being ignored + // https://github.com/rust-lang/rust/issues/9390 + TokenTree::MetaVar(..) | TokenTree::MetaVarExpr(..) | TokenTree::Token(..) => {} } Ok(()) @@ -650,7 +655,7 @@ fn inner_parse_loop<'root, 'tt>( // rules. NOTE that this is not necessarily an error unless _all_ items in // `cur_items` end up doing this. There may still be some other matchers that do // end up working out. - TokenTree::Token(..) | TokenTree::MetaVar(..) => {} + TokenTree::Token(..) | TokenTree::MetaVar(..) | TokenTree::MetaVarExpr(..) => {} } } } diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs index 62ea3aa76a46c..c3b1b34aa29b9 100644 --- a/compiler/rustc_expand/src/mbe/macro_rules.rs +++ b/compiler/rustc_expand/src/mbe/macro_rules.rs @@ -580,7 +580,10 @@ fn check_lhs_no_empty_seq(sess: &ParseSess, tts: &[mbe::TokenTree]) -> bool { use mbe::TokenTree; for tt in tts { match *tt { - TokenTree::Token(..) | TokenTree::MetaVar(..) | TokenTree::MetaVarDecl(..) => (), + TokenTree::Token(..) + | TokenTree::MetaVar(..) + | TokenTree::MetaVarDecl(..) + | TokenTree::MetaVarExpr(..) => (), TokenTree::Delimited(_, ref del) => { if !check_lhs_no_empty_seq(sess, &del.tts) { return false; @@ -669,7 +672,10 @@ impl FirstSets { let mut first = TokenSet::empty(); for tt in tts.iter().rev() { match *tt { - TokenTree::Token(..) | TokenTree::MetaVar(..) | TokenTree::MetaVarDecl(..) => { + TokenTree::Token(..) + | TokenTree::MetaVar(..) + | TokenTree::MetaVarDecl(..) + | TokenTree::MetaVarExpr(..) => { first.replace_with(tt.clone()); } TokenTree::Delimited(span, ref delimited) => { @@ -731,7 +737,10 @@ impl FirstSets { for tt in tts.iter() { assert!(first.maybe_empty); match *tt { - TokenTree::Token(..) | TokenTree::MetaVar(..) | TokenTree::MetaVarDecl(..) => { + TokenTree::Token(..) + | TokenTree::MetaVar(..) + | TokenTree::MetaVarDecl(..) + | TokenTree::MetaVarExpr(..) => { first.add_one(tt.clone()); return first; } @@ -907,7 +916,10 @@ fn check_matcher_core( // First, update `last` so that it corresponds to the set // of NT tokens that might end the sequence `... token`. match *token { - TokenTree::Token(..) | TokenTree::MetaVar(..) | TokenTree::MetaVarDecl(..) => { + TokenTree::Token(..) + | TokenTree::MetaVar(..) + | TokenTree::MetaVarDecl(..) + | TokenTree::MetaVarExpr(..) => { if token_can_be_followed_by_any(token) { // don't need to track tokens that work with any, last.replace_with_irrelevant(); diff --git a/compiler/rustc_expand/src/mbe/metavar_expr.rs b/compiler/rustc_expand/src/mbe/metavar_expr.rs new file mode 100644 index 0000000000000..6c5a755da6f40 --- /dev/null +++ b/compiler/rustc_expand/src/mbe/metavar_expr.rs @@ -0,0 +1,157 @@ +use rustc_ast::token; +use rustc_ast::tokenstream::{Cursor, TokenStream, TokenTree}; +use rustc_ast::{LitIntType, LitKind}; +use rustc_ast_pretty::pprust; +use rustc_errors::{Applicability, PResult}; +use rustc_session::parse::ParseSess; +use rustc_span::symbol::Ident; +use rustc_span::Span; + +/// A meta-variable expression, for expansions based on properties of meta-variables. +#[derive(Debug, Clone, PartialEq, Encodable, Decodable)] +crate enum MetaVarExpr { + /// The number of repetitions of an identifier, optionally limited to a number + /// of outer-most repetition depths. If the depth limit is `None` then the depth is unlimited. + Count(Ident, Option), + + /// Ignore a meta-variable for repetition without expansion. + Ignore(Ident), + + /// The index of the repetition at a particular depth, where 0 is the inner-most + /// repetition. The `usize` is the depth. + Index(usize), + + /// The length of the repetition at a particular depth, where 0 is the inner-most + /// repetition. The `usize` is the depth. + Length(usize), +} + +impl MetaVarExpr { + /// Attempt to parse a meta-variable expression from a token stream. + crate fn parse<'sess>( + input: &TokenStream, + outer_span: Span, + sess: &'sess ParseSess, + ) -> PResult<'sess, MetaVarExpr> { + let mut tts = input.trees(); + let ident = parse_ident(&mut tts, sess, outer_span)?; + let Some(TokenTree::Delimited(_, token::Paren, args)) = tts.next() else { + let msg = "meta-variable expression parameter must be wrapped in parentheses"; + return Err(sess.span_diagnostic.struct_span_err(ident.span, msg)); + }; + check_trailing_token(&mut tts, sess)?; + let mut iter = args.trees(); + let rslt = match &*ident.as_str() { + "count" => parse_count(&mut iter, sess, ident.span)?, + "ignore" => MetaVarExpr::Ignore(parse_ident(&mut iter, sess, ident.span)?), + "index" => MetaVarExpr::Index(parse_depth(&mut iter, sess, ident.span)?), + "length" => MetaVarExpr::Length(parse_depth(&mut iter, sess, ident.span)?), + _ => { + let err_msg = "unrecognized meta-variable expression"; + let mut err = sess.span_diagnostic.struct_span_err(ident.span, err_msg); + err.span_suggestion( + ident.span, + "supported expressions are count, ignore, index and length", + String::new(), + Applicability::MachineApplicable, + ); + return Err(err); + } + }; + check_trailing_token(&mut iter, sess)?; + Ok(rslt) + } + + crate fn ident(&self) -> Option<&Ident> { + match self { + MetaVarExpr::Count(ident, _) | MetaVarExpr::Ignore(ident) => Some(&ident), + MetaVarExpr::Index(..) | MetaVarExpr::Length(..) => None, + } + } +} + +// Checks if there are any remaining tokens. For example, `${ignore(ident ... a b c ...)}` +fn check_trailing_token<'sess>(iter: &mut Cursor, sess: &'sess ParseSess) -> PResult<'sess, ()> { + if let Some(tt) = iter.next() { + let mut diag = sess.span_diagnostic.struct_span_err( + tt.span(), + &format!("unexpected token: {}", pprust::tt_to_string(&tt)), + ); + diag.span_note(tt.span(), "meta-variable expression must not have trailing tokens"); + Err(diag) + } else { + Ok(()) + } +} + +/// Parse a meta-variable `count` expression: `count(ident[, depth])` +fn parse_count<'sess>( + iter: &mut Cursor, + sess: &'sess ParseSess, + span: Span, +) -> PResult<'sess, MetaVarExpr> { + let ident = parse_ident(iter, sess, span)?; + let depth = if try_eat_comma(iter) { Some(parse_depth(iter, sess, span)?) } else { None }; + Ok(MetaVarExpr::Count(ident, depth)) +} + +/// Parses the depth used by index(depth) and length(depth). +fn parse_depth<'sess>( + iter: &mut Cursor, + sess: &'sess ParseSess, + span: Span, +) -> PResult<'sess, usize> { + let Some(tt) = iter.next() else { return Ok(0) }; + let TokenTree::Token(token::Token { + kind: token::TokenKind::Literal(lit), .. + }) = tt else { + return Err(sess.span_diagnostic.struct_span_err( + span, + "meta-variable expression depth must be a literal" + )); + }; + if let Ok(lit_kind) = LitKind::from_lit_token(lit) + && let LitKind::Int(n_u128, LitIntType::Unsuffixed) = lit_kind + && let Ok(n_usize) = usize::try_from(n_u128) + { + Ok(n_usize) + } + else { + let msg = "only unsuffixes integer literals are supported in meta-variable expressions"; + Err(sess.span_diagnostic.struct_span_err(span, msg)) + } +} + +/// Parses an generic ident +fn parse_ident<'sess>( + iter: &mut Cursor, + sess: &'sess ParseSess, + span: Span, +) -> PResult<'sess, Ident> { + let err_fn = |msg| sess.span_diagnostic.struct_span_err(span, msg); + if let Some(tt) = iter.next() && let TokenTree::Token(token) = tt { + if let Some((elem, false)) = token.ident() { + return Ok(elem); + } + let token_str = pprust::token_to_string(&token); + let mut err = err_fn(&format!("expected identifier, found `{}`", &token_str)); + err.span_suggestion( + token.span, + &format!("try removing `{}`", &token_str), + String::new(), + Applicability::MaybeIncorrect, + ); + return Err(err); + } + Err(err_fn("expected identifier")) +} + +/// Tries to move the iterator forward returning `true` if there is a comma. If not, then the +/// iterator is not modified and the result is `false`. +fn try_eat_comma(iter: &mut Cursor) -> bool { + if let Some(TokenTree::Token(token::Token { kind: token::Comma, .. })) = iter.look_ahead(0) { + let _ = iter.next(); + return true; + } + false +} diff --git a/compiler/rustc_expand/src/mbe/quoted.rs b/compiler/rustc_expand/src/mbe/quoted.rs index dedc6c618b9a4..12c5dac9e0bf4 100644 --- a/compiler/rustc_expand/src/mbe/quoted.rs +++ b/compiler/rustc_expand/src/mbe/quoted.rs @@ -1,13 +1,13 @@ use crate::mbe::macro_parser; -use crate::mbe::{Delimited, KleeneOp, KleeneToken, SequenceRepetition, TokenTree}; +use crate::mbe::{Delimited, KleeneOp, KleeneToken, MetaVarExpr, SequenceRepetition, TokenTree}; use rustc_ast::token::{self, Token}; use rustc_ast::tokenstream; use rustc_ast::{NodeId, DUMMY_NODE_ID}; use rustc_ast_pretty::pprust; use rustc_feature::Features; -use rustc_session::parse::ParseSess; -use rustc_span::symbol::{kw, Ident}; +use rustc_session::parse::{feature_err, ParseSess}; +use rustc_span::symbol::{kw, sym, Ident}; use rustc_span::edition::Edition; use rustc_span::{Span, SyntaxContext}; @@ -25,22 +25,22 @@ const VALID_FRAGMENT_NAMES_MSG: &str = "valid fragment specifiers are \ /// # Parameters /// /// - `input`: a token stream to read from, the contents of which we are parsing. -/// - `expect_matchers`: `parse` can be used to parse either the "patterns" or the "body" of a -/// macro. Both take roughly the same form _except_ that in a pattern, metavars are declared with -/// their "matcher" type. For example `$var:expr` or `$id:ident`. In this example, `expr` and -/// `ident` are "matchers". They are not present in the body of a macro rule -- just in the -/// pattern, so we pass a parameter to indicate whether to expect them or not. +/// - `parsing_patterns`: `parse` can be used to parse either the "patterns" or the "body" of a +/// macro. Both take roughly the same form _except_ that: +/// - In a pattern, metavars are declared with their "matcher" type. For example `$var:expr` or +/// `$id:ident`. In this example, `expr` and `ident` are "matchers". They are not present in the +/// body of a macro rule -- just in the pattern. +/// - Metavariable expressions are only valid in the "body", not the "pattern". /// - `sess`: the parsing session. Any errors will be emitted to this session. /// - `node_id`: the NodeId of the macro we are parsing. /// - `features`: language features so we can do feature gating. -/// - `edition`: the edition of the crate defining the macro /// /// # Returns /// /// A collection of `self::TokenTree`. There may also be some errors emitted to `sess`. pub(super) fn parse( input: tokenstream::TokenStream, - expect_matchers: bool, + parsing_patterns: bool, sess: &ParseSess, node_id: NodeId, features: &Features, @@ -55,9 +55,9 @@ pub(super) fn parse( while let Some(tree) = trees.next() { // Given the parsed tree, if there is a metavar and we are expecting matchers, actually // parse out the matcher (i.e., in `$id:ident` this would parse the `:` and `ident`). - let tree = parse_tree(tree, &mut trees, expect_matchers, sess, node_id, features, edition); + let tree = parse_tree(tree, &mut trees, parsing_patterns, sess, node_id, features, edition); match tree { - TokenTree::MetaVar(start_sp, ident) if expect_matchers => { + TokenTree::MetaVar(start_sp, ident) if parsing_patterns => { let span = match trees.next() { Some(tokenstream::TokenTree::Token(Token { kind: token::Colon, span })) => { match trees.next() { @@ -118,6 +118,14 @@ pub(super) fn parse( result } +/// Asks for the `macro_metavar_expr` feature if it is not already declared +fn maybe_emit_macro_metavar_expr_feature(features: &Features, sess: &ParseSess, span: Span) { + if !features.macro_metavar_expr { + let msg = "meta-variable expressions are unstable"; + feature_err(&sess, sym::macro_metavar_expr, span, msg).emit(); + } +} + /// Takes a `tokenstream::TokenTree` and returns a `self::TokenTree`. Specifically, this takes a /// generic `TokenTree`, such as is used in the rest of the compiler, and returns a `TokenTree` /// for use in parsing a macro. @@ -129,14 +137,13 @@ pub(super) fn parse( /// - `tree`: the tree we wish to convert. /// - `outer_trees`: an iterator over trees. We may need to read more tokens from it in order to finish /// converting `tree` -/// - `expect_matchers`: same as for `parse` (see above). +/// - `parsing_patterns`: same as [parse]. /// - `sess`: the parsing session. Any errors will be emitted to this session. /// - `features`: language features so we can do feature gating. -/// - `edition` - the edition of the crate defining the macro fn parse_tree( tree: tokenstream::TokenTree, outer_trees: &mut impl Iterator, - expect_matchers: bool, + parsing_patterns: bool, sess: &ParseSess, node_id: NodeId, features: &Features, @@ -158,24 +165,57 @@ fn parse_tree( } match next { - // `tree` is followed by a delimited set of token trees. This indicates the beginning - // of a repetition sequence in the macro (e.g. `$(pat)*`). - Some(tokenstream::TokenTree::Delimited(span, delim, tts)) => { - // Must have `(` not `{` or `[` - if delim != token::Paren { - let tok = pprust::token_kind_to_string(&token::OpenDelim(delim)); - let msg = format!("expected `(`, found `{}`", tok); - sess.span_diagnostic.span_err(span.entire(), &msg); + // `tree` is followed by a delimited set of token trees. + Some(tokenstream::TokenTree::Delimited(delim_span, delim, tts)) => { + if parsing_patterns { + if delim != token::Paren { + span_dollar_dollar_or_metavar_in_the_lhs_err( + sess, + &Token { kind: token::OpenDelim(delim), span: delim_span.entire() }, + ); + } + } else { + match delim { + token::Brace => { + // The delimiter is `{`. This indicates the beginning + // of a meta-variable expression (e.g. `${count(ident)}`). + // Try to parse the meta-variable expression. + match MetaVarExpr::parse(&tts, delim_span.entire(), sess) { + Err(mut err) => { + err.emit(); + // Returns early the same read `$` to avoid spanning + // unrelated diagnostics that could be performed afterwards + return TokenTree::token(token::Dollar, span); + } + Ok(elem) => { + maybe_emit_macro_metavar_expr_feature( + features, + sess, + delim_span.entire(), + ); + return TokenTree::MetaVarExpr(delim_span, elem); + } + } + } + token::Paren => {} + _ => { + let tok = pprust::token_kind_to_string(&token::OpenDelim(delim)); + let msg = format!("expected `(` or `{{`, found `{}`", tok); + sess.span_diagnostic.span_err(delim_span.entire(), &msg); + } + } } - // Parse the contents of the sequence itself - let sequence = parse(tts, expect_matchers, sess, node_id, features, edition); + // If we didn't find a metavar expression above, then we must have a + // repetition sequence in the macro (e.g. `$(pat)*`). Parse the + // contents of the sequence itself + let sequence = parse(tts, parsing_patterns, sess, node_id, features, edition); // Get the Kleene operator and optional separator let (separator, kleene) = - parse_sep_and_kleene_op(&mut trees, span.entire(), sess); + parse_sep_and_kleene_op(&mut trees, delim_span.entire(), sess); // Count the number of captured "names" (i.e., named metavars) let name_captures = macro_parser::count_names(&sequence); TokenTree::Sequence( - span, + delim_span, Lrc::new(SequenceRepetition { tts: sequence, separator, @@ -197,7 +237,20 @@ fn parse_tree( } } - // `tree` is followed by a random token. This is an error. + // `tree` is followed by another `$`. This is an escaped `$`. + Some(tokenstream::TokenTree::Token(Token { kind: token::Dollar, span })) => { + if parsing_patterns { + span_dollar_dollar_or_metavar_in_the_lhs_err( + sess, + &Token { kind: token::Dollar, span }, + ); + } else { + maybe_emit_macro_metavar_expr_feature(features, sess, span); + } + TokenTree::token(token::Dollar, span) + } + + // `tree` is followed by some other token. This is an error. Some(tokenstream::TokenTree::Token(token)) => { let msg = format!( "expected identifier, found `{}`", @@ -221,7 +274,7 @@ fn parse_tree( span, Lrc::new(Delimited { delim, - tts: parse(tts, expect_matchers, sess, node_id, features, edition), + tts: parse(tts, parsing_patterns, sess, node_id, features, edition), }), ), } @@ -309,3 +362,15 @@ fn parse_sep_and_kleene_op( // Return a dummy (None, KleeneToken::new(KleeneOp::ZeroOrMore, span)) } + +// `$$` or a meta-variable is the lhs of a macro but shouldn't. +// +// For example, `macro_rules! foo { ( ${length()} ) => {} }` +fn span_dollar_dollar_or_metavar_in_the_lhs_err<'sess>(sess: &'sess ParseSess, token: &Token) { + sess.span_diagnostic + .span_err(token.span, &format!("unexpected token: {}", pprust::token_to_string(token))); + sess.span_diagnostic.span_note_without_error( + token.span, + "`$$` and meta-variable expressions are not allowed inside macro parameter definitions", + ); +} diff --git a/compiler/rustc_expand/src/mbe/transcribe.rs b/compiler/rustc_expand/src/mbe/transcribe.rs index 760dea77f9c2b..b8d8394754134 100644 --- a/compiler/rustc_expand/src/mbe/transcribe.rs +++ b/compiler/rustc_expand/src/mbe/transcribe.rs @@ -255,6 +255,11 @@ pub(super) fn transcribe<'a>( } } + // Replace meta-variable expressions with the result of their expansion. + mbe::TokenTree::MetaVarExpr(sp, expr) => { + transcribe_metavar_expr(cx, expr, interp, &repeats, &mut result, &sp)?; + } + // If we are entering a new delimiter, we push its contents to the `stack` to be // processed, and we push all of the currently produced results to the `result_stack`. // We will produce all of the results of the inside of the `Delimited` and then we will @@ -391,6 +396,28 @@ fn lockstep_iter_size( _ => LockstepIterSize::Unconstrained, } } + TokenTree::MetaVarExpr(_, ref expr) => { + let default_rslt = LockstepIterSize::Unconstrained; + let Some(ident) = expr.ident() else { return default_rslt; }; + let name = MacroRulesNormalizedIdent::new(ident.clone()); + match lookup_cur_matched(name, interpolations, repeats) { + Some(MatchedSeq(ref ads)) => { + default_rslt.with(LockstepIterSize::Constraint(ads.len(), name)) + } + _ => default_rslt, + } + } TokenTree::Token(..) => LockstepIterSize::Unconstrained, } } + +fn transcribe_metavar_expr<'a>( + _cx: &ExtCtxt<'a>, + _expr: mbe::MetaVarExpr, + _interp: &FxHashMap, + _repeats: &[(usize, usize)], + _result: &mut Vec, + _sp: &DelimSpan, +) -> PResult<'a, ()> { + Ok(()) +} diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index a69d28b184aed..a91f05587b277 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -426,6 +426,8 @@ declare_features! ( (active, link_cfg, "1.14.0", Some(37406), None), /// Allows using `reason` in lint attributes and the `#[expect(lint)]` lint check. (active, lint_reasons, "1.31.0", Some(54503), None), + /// Give access to additional metadata about declarative macro meta-variables. + (active, macro_metavar_expr, "1.61.0", Some(83527), None), /// Allows `#[marker]` on certain traits allowing overlapping implementations. (active, marker_trait_attr, "1.30.0", Some(29864), None), /// A minimal, sound subset of specialization intended to be used by the diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 3f44292e03425..0d87233d9d79d 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -845,6 +845,7 @@ symbols! { macro_export, macro_lifetime_matcher, macro_literal_matcher, + macro_metavar_expr, macro_reexport, macro_use, macro_vis_matcher, diff --git a/src/test/ui/macros/rfc-3086-metavar-expr/dollar-dollar-has-correct-behavior.rs b/src/test/ui/macros/rfc-3086-metavar-expr/dollar-dollar-has-correct-behavior.rs new file mode 100644 index 0000000000000..ed94c27cf05ca --- /dev/null +++ b/src/test/ui/macros/rfc-3086-metavar-expr/dollar-dollar-has-correct-behavior.rs @@ -0,0 +1,28 @@ +// run-pass + +#![feature(macro_metavar_expr)] + +macro_rules! nested { + ( $a:ident ) => { + macro_rules! $a { + ( $$( $b:ident ),* ) => { + $$( + macro_rules! $b { + ( $$$$( $c:ident ),* ) => { + $$$$( + fn $c() -> &'static str { stringify!($c) } + ),* + }; + } + )* + }; + } + }; +} + +fn main() { + nested!(a); + a!(b); + b!(c); + assert_eq!(c(), "c"); +} diff --git a/src/test/ui/macros/rfc-3086-metavar-expr/feature-gate-macro_metavar_expr.rs b/src/test/ui/macros/rfc-3086-metavar-expr/feature-gate-macro_metavar_expr.rs new file mode 100644 index 0000000000000..6434ecc7e092d --- /dev/null +++ b/src/test/ui/macros/rfc-3086-metavar-expr/feature-gate-macro_metavar_expr.rs @@ -0,0 +1,14 @@ +// run-pass + +#![feature(macro_metavar_expr)] + +macro_rules! ignore { + ( $( $i:ident ),* ) => {{ + let array: [i32; 0] = [$( ${ignore(i)} )*]; + array + }}; +} + +fn main() { + assert_eq!(ignore!(a, b, c), []); +} diff --git a/src/test/ui/macros/rfc-3086-metavar-expr/required-feature.rs b/src/test/ui/macros/rfc-3086-metavar-expr/required-feature.rs new file mode 100644 index 0000000000000..cff6f29a15386 --- /dev/null +++ b/src/test/ui/macros/rfc-3086-metavar-expr/required-feature.rs @@ -0,0 +1,9 @@ +macro_rules! count { + ( $( $e:stmt ),* ) => { + ${ count(e) } + //~^ ERROR meta-variable expressions are unstable + }; +} + +fn main() { +} diff --git a/src/test/ui/macros/rfc-3086-metavar-expr/required-feature.stderr b/src/test/ui/macros/rfc-3086-metavar-expr/required-feature.stderr new file mode 100644 index 0000000000000..f573194479314 --- /dev/null +++ b/src/test/ui/macros/rfc-3086-metavar-expr/required-feature.stderr @@ -0,0 +1,12 @@ +error[E0658]: meta-variable expressions are unstable + --> $DIR/required-feature.rs:3:10 + | +LL | ${ count(e) } + | ^^^^^^^^^^^^ + | + = note: see issue #83527 for more information + = help: add `#![feature(macro_metavar_expr)]` 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/macros/rfc-3086-metavar-expr/syntax-errors.rs b/src/test/ui/macros/rfc-3086-metavar-expr/syntax-errors.rs new file mode 100644 index 0000000000000..ea73fd0813c5b --- /dev/null +++ b/src/test/ui/macros/rfc-3086-metavar-expr/syntax-errors.rs @@ -0,0 +1,148 @@ +#![feature(macro_metavar_expr)] + +// `curly` = Right hand side curly brackets +// `no_rhs_dollar` = No dollar sign at the right hand side meta variable "function" +// `round` = Left hand side round brackets + +macro_rules! curly__no_rhs_dollar__round { + ( $( $i:ident ),* ) => { ${ count(i) } }; +} + +macro_rules! curly__no_rhs_dollar__no_round { + ( $i:ident ) => { ${ count(i) } }; +} + +macro_rules! curly__rhs_dollar__round { + ( $( $i:ident ),* ) => { ${ count($i) } }; + //~^ ERROR expected identifier, found `$` + //~| ERROR expected expression, found `$` +} + +macro_rules! curly__rhs_dollar__no_round { + ( $i:ident ) => { ${ count($i) } }; + //~^ ERROR expected identifier, found `$` + //~| ERROR expected expression, found `$` +} + +macro_rules! no_curly__no_rhs_dollar__round { + ( $( $i:ident ),* ) => { count(i) }; + //~^ ERROR cannot find function `count` in this scope + //~| ERROR cannot find value `i` in this scope +} + +macro_rules! no_curly__no_rhs_dollar__no_round { + ( $i:ident ) => { count(i) }; + //~^ ERROR cannot find function `count` in this scope + //~| ERROR cannot find value `i` in this scope +} + +macro_rules! no_curly__rhs_dollar__round { + ( $( $i:ident ),* ) => { count($i) }; + //~^ ERROR variable 'i' is still repeating at this depth +} + +macro_rules! no_curly__rhs_dollar__no_round { + ( $i:ident ) => { count($i) }; + //~^ ERROR cannot find function `count` in this scope +} + +// Other scenarios + +macro_rules! dollar_dollar_in_the_lhs { + ( $$ $a:ident ) => { + //~^ ERROR unexpected token: $ + }; +} + +macro_rules! extra_garbage_after_metavar { + ( $( $i:ident ),* ) => { + ${count() a b c} + //~^ ERROR unexpected token: a + //~| ERROR expected expression, found `$` + ${count(i a b c)} + //~^ ERROR unexpected token: a + ${count(i, 1 a b c)} + //~^ ERROR unexpected token: a + ${count(i) a b c} + //~^ ERROR unexpected token: a + + ${ignore(i) a b c} + //~^ ERROR unexpected token: a + ${ignore(i a b c)} + //~^ ERROR unexpected token: a + + ${index() a b c} + //~^ ERROR unexpected token: a + ${index(1 a b c)} + //~^ ERROR unexpected token: a + + ${index() a b c} + //~^ ERROR unexpected token: a + ${index(1 a b c)} + //~^ ERROR unexpected token: a + }; +} + +const IDX: usize = 1; +macro_rules! metavar_depth_is_not_literal { + ( $( $i:ident ),* ) => { ${ index(IDX) } }; + //~^ ERROR meta-variable expression depth must be a literal + //~| ERROR expected expression, found `$` +} + +macro_rules! metavar_in_the_lhs { + ( ${ length() } ) => { + //~^ ERROR unexpected token: { + //~| ERROR expected one of: `*`, `+`, or `?` + }; +} + +macro_rules! metavar_token_without_ident { + ( $( $i:ident ),* ) => { ${ ignore() } }; + //~^ ERROR expected identifier + //~| ERROR expected expression, found `$` +} + +macro_rules! metavar_with_literal_suffix { + ( $( $i:ident ),* ) => { ${ index(1u32) } }; + //~^ ERROR only unsuffixes integer literals are supported in meta-variable expressions + //~| ERROR expected expression, found `$` +} + +macro_rules! metavar_without_parens { + ( $( $i:ident ),* ) => { ${ count{i} } }; + //~^ ERROR meta-variable expression parameter must be wrapped in parentheses + //~| ERROR expected expression, found `$` +} + +macro_rules! open_brackets_without_tokens { + ( $( $i:ident ),* ) => { ${ {} } }; + //~^ ERROR expected expression, found `$` + //~| ERROR expected identifier +} + +macro_rules! unknown_metavar { + ( $( $i:ident ),* ) => { ${ aaaaaaaaaaaaaa(i) } }; + //~^ ERROR unrecognized meta-variable expression + //~| ERROR expected expression +} + +fn main() { + curly__no_rhs_dollar__round!(a, b, c); + curly__no_rhs_dollar__no_round!(a); + curly__rhs_dollar__round!(a, b, c); + curly__rhs_dollar__no_round!(a); + no_curly__no_rhs_dollar__round!(a, b, c); + no_curly__no_rhs_dollar__no_round!(a); + no_curly__rhs_dollar__round!(a, b, c); + no_curly__rhs_dollar__no_round!(a); + //~^ ERROR cannot find value `a` in this scope + + extra_garbage_after_metavar!(a); + unknown_metavar!(a); + metavar_without_parens!(a); + metavar_token_without_ident!(a); + metavar_depth_is_not_literal!(a); + metavar_with_literal_suffix!(a); + open_brackets_without_tokens!(a) +} diff --git a/src/test/ui/macros/rfc-3086-metavar-expr/syntax-errors.stderr b/src/test/ui/macros/rfc-3086-metavar-expr/syntax-errors.stderr new file mode 100644 index 0000000000000..dc8b7a668c4ee --- /dev/null +++ b/src/test/ui/macros/rfc-3086-metavar-expr/syntax-errors.stderr @@ -0,0 +1,367 @@ +error: expected identifier, found `$` + --> $DIR/syntax-errors.rs:16:33 + | +LL | ( $( $i:ident ),* ) => { ${ count($i) } }; + | ^^^^^ - help: try removing `$` + +error: expected identifier, found `$` + --> $DIR/syntax-errors.rs:22:26 + | +LL | ( $i:ident ) => { ${ count($i) } }; + | ^^^^^ - help: try removing `$` + +error: unexpected token: $ + --> $DIR/syntax-errors.rs:52:8 + | +LL | ( $$ $a:ident ) => { + | ^ + +note: `$$` and meta-variable expressions are not allowed inside macro parameter definitions + --> $DIR/syntax-errors.rs:52:8 + | +LL | ( $$ $a:ident ) => { + | ^ + +error: unexpected token: a + --> $DIR/syntax-errors.rs:59:19 + | +LL | ${count() a b c} + | ^ + | +note: meta-variable expression must not have trailing tokens + --> $DIR/syntax-errors.rs:59:19 + | +LL | ${count() a b c} + | ^ + +error: unexpected token: a + --> $DIR/syntax-errors.rs:62:19 + | +LL | ${count(i a b c)} + | ^ + | +note: meta-variable expression must not have trailing tokens + --> $DIR/syntax-errors.rs:62:19 + | +LL | ${count(i a b c)} + | ^ + +error: unexpected token: a + --> $DIR/syntax-errors.rs:64:22 + | +LL | ${count(i, 1 a b c)} + | ^ + | +note: meta-variable expression must not have trailing tokens + --> $DIR/syntax-errors.rs:64:22 + | +LL | ${count(i, 1 a b c)} + | ^ + +error: unexpected token: a + --> $DIR/syntax-errors.rs:66:20 + | +LL | ${count(i) a b c} + | ^ + | +note: meta-variable expression must not have trailing tokens + --> $DIR/syntax-errors.rs:66:20 + | +LL | ${count(i) a b c} + | ^ + +error: unexpected token: a + --> $DIR/syntax-errors.rs:69:21 + | +LL | ${ignore(i) a b c} + | ^ + | +note: meta-variable expression must not have trailing tokens + --> $DIR/syntax-errors.rs:69:21 + | +LL | ${ignore(i) a b c} + | ^ + +error: unexpected token: a + --> $DIR/syntax-errors.rs:71:20 + | +LL | ${ignore(i a b c)} + | ^ + | +note: meta-variable expression must not have trailing tokens + --> $DIR/syntax-errors.rs:71:20 + | +LL | ${ignore(i a b c)} + | ^ + +error: unexpected token: a + --> $DIR/syntax-errors.rs:74:19 + | +LL | ${index() a b c} + | ^ + | +note: meta-variable expression must not have trailing tokens + --> $DIR/syntax-errors.rs:74:19 + | +LL | ${index() a b c} + | ^ + +error: unexpected token: a + --> $DIR/syntax-errors.rs:76:19 + | +LL | ${index(1 a b c)} + | ^ + | +note: meta-variable expression must not have trailing tokens + --> $DIR/syntax-errors.rs:76:19 + | +LL | ${index(1 a b c)} + | ^ + +error: unexpected token: a + --> $DIR/syntax-errors.rs:79:19 + | +LL | ${index() a b c} + | ^ + | +note: meta-variable expression must not have trailing tokens + --> $DIR/syntax-errors.rs:79:19 + | +LL | ${index() a b c} + | ^ + +error: unexpected token: a + --> $DIR/syntax-errors.rs:81:19 + | +LL | ${index(1 a b c)} + | ^ + | +note: meta-variable expression must not have trailing tokens + --> $DIR/syntax-errors.rs:81:19 + | +LL | ${index(1 a b c)} + | ^ + +error: meta-variable expression depth must be a literal + --> $DIR/syntax-errors.rs:88:33 + | +LL | ( $( $i:ident ),* ) => { ${ index(IDX) } }; + | ^^^^^ + +error: unexpected token: { + --> $DIR/syntax-errors.rs:94:8 + | +LL | ( ${ length() } ) => { + | ^^^^^^^^^^^^ + +note: `$$` and meta-variable expressions are not allowed inside macro parameter definitions + --> $DIR/syntax-errors.rs:94:8 + | +LL | ( ${ length() } ) => { + | ^^^^^^^^^^^^ + +error: expected one of: `*`, `+`, or `?` + --> $DIR/syntax-errors.rs:94:8 + | +LL | ( ${ length() } ) => { + | ^^^^^^^^^^^^ + +error: expected identifier + --> $DIR/syntax-errors.rs:101:33 + | +LL | ( $( $i:ident ),* ) => { ${ ignore() } }; + | ^^^^^^ + +error: only unsuffixes integer literals are supported in meta-variable expressions + --> $DIR/syntax-errors.rs:107:33 + | +LL | ( $( $i:ident ),* ) => { ${ index(1u32) } }; + | ^^^^^ + +error: meta-variable expression parameter must be wrapped in parentheses + --> $DIR/syntax-errors.rs:113:33 + | +LL | ( $( $i:ident ),* ) => { ${ count{i} } }; + | ^^^^^ + +error: expected identifier + --> $DIR/syntax-errors.rs:119:31 + | +LL | ( $( $i:ident ),* ) => { ${ {} } }; + | ^^^^^^ + +error: unrecognized meta-variable expression + --> $DIR/syntax-errors.rs:125:33 + | +LL | ( $( $i:ident ),* ) => { ${ aaaaaaaaaaaaaa(i) } }; + | ^^^^^^^^^^^^^^ help: supported expressions are count, ignore, index and length + +error: expected expression, found `$` + --> $DIR/syntax-errors.rs:16:30 + | +LL | ( $( $i:ident ),* ) => { ${ count($i) } }; + | ^ expected expression +... +LL | curly__rhs_dollar__round!(a, b, c); + | ---------------------------------- in this macro invocation + | + = note: this error originates in the macro `curly__rhs_dollar__round` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: expected expression, found `$` + --> $DIR/syntax-errors.rs:22:23 + | +LL | ( $i:ident ) => { ${ count($i) } }; + | ^ expected expression +... +LL | curly__rhs_dollar__no_round!(a); + | ------------------------------- in this macro invocation + | + = note: this error originates in the macro `curly__rhs_dollar__no_round` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: variable 'i' is still repeating at this depth + --> $DIR/syntax-errors.rs:40:36 + | +LL | ( $( $i:ident ),* ) => { count($i) }; + | ^^ + +error: expected expression, found `$` + --> $DIR/syntax-errors.rs:59:9 + | +LL | ${count() a b c} + | ^ expected expression +... +LL | extra_garbage_after_metavar!(a); + | ------------------------------- in this macro invocation + | + = note: this error originates in the macro `extra_garbage_after_metavar` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: expected expression, found `$` + --> $DIR/syntax-errors.rs:125:30 + | +LL | ( $( $i:ident ),* ) => { ${ aaaaaaaaaaaaaa(i) } }; + | ^ expected expression +... +LL | unknown_metavar!(a); + | ------------------- in this macro invocation + | + = note: this error originates in the macro `unknown_metavar` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: expected expression, found `$` + --> $DIR/syntax-errors.rs:113:30 + | +LL | ( $( $i:ident ),* ) => { ${ count{i} } }; + | ^ expected expression +... +LL | metavar_without_parens!(a); + | -------------------------- in this macro invocation + | + = note: this error originates in the macro `metavar_without_parens` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: expected expression, found `$` + --> $DIR/syntax-errors.rs:101:30 + | +LL | ( $( $i:ident ),* ) => { ${ ignore() } }; + | ^ expected expression +... +LL | metavar_token_without_ident!(a); + | ------------------------------- in this macro invocation + | + = note: this error originates in the macro `metavar_token_without_ident` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: expected expression, found `$` + --> $DIR/syntax-errors.rs:88:30 + | +LL | ( $( $i:ident ),* ) => { ${ index(IDX) } }; + | ^ expected expression +... +LL | metavar_depth_is_not_literal!(a); + | -------------------------------- in this macro invocation + | + = note: this error originates in the macro `metavar_depth_is_not_literal` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: expected expression, found `$` + --> $DIR/syntax-errors.rs:107:30 + | +LL | ( $( $i:ident ),* ) => { ${ index(1u32) } }; + | ^ expected expression +... +LL | metavar_with_literal_suffix!(a); + | ------------------------------- in this macro invocation + | + = note: this error originates in the macro `metavar_with_literal_suffix` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: expected expression, found `$` + --> $DIR/syntax-errors.rs:119:30 + | +LL | ( $( $i:ident ),* ) => { ${ {} } }; + | ^ expected expression +... +LL | open_brackets_without_tokens!(a) + | -------------------------------- in this macro invocation + | + = note: this error originates in the macro `open_brackets_without_tokens` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0425]: cannot find function `count` in this scope + --> $DIR/syntax-errors.rs:28:30 + | +LL | ( $( $i:ident ),* ) => { count(i) }; + | ^^^^^ not found in this scope +... +LL | no_curly__no_rhs_dollar__round!(a, b, c); + | ---------------------------------------- in this macro invocation + | + = note: this error originates in the macro `no_curly__no_rhs_dollar__round` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0425]: cannot find value `i` in this scope + --> $DIR/syntax-errors.rs:28:36 + | +LL | ( $( $i:ident ),* ) => { count(i) }; + | ^ not found in this scope +... +LL | no_curly__no_rhs_dollar__round!(a, b, c); + | ---------------------------------------- in this macro invocation + | + = note: this error originates in the macro `no_curly__no_rhs_dollar__round` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0425]: cannot find function `count` in this scope + --> $DIR/syntax-errors.rs:34:23 + | +LL | ( $i:ident ) => { count(i) }; + | ^^^^^ not found in this scope +... +LL | no_curly__no_rhs_dollar__no_round!(a); + | ------------------------------------- in this macro invocation + | + = note: this error originates in the macro `no_curly__no_rhs_dollar__no_round` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0425]: cannot find value `i` in this scope + --> $DIR/syntax-errors.rs:34:29 + | +LL | ( $i:ident ) => { count(i) }; + | ^ not found in this scope +... +LL | no_curly__no_rhs_dollar__no_round!(a); + | ------------------------------------- in this macro invocation + | + = note: this error originates in the macro `no_curly__no_rhs_dollar__no_round` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0425]: cannot find function `count` in this scope + --> $DIR/syntax-errors.rs:45:23 + | +LL | ( $i:ident ) => { count($i) }; + | ^^^^^ not found in this scope +... +LL | no_curly__rhs_dollar__no_round!(a); + | ---------------------------------- in this macro invocation + | + = note: this error originates in the macro `no_curly__rhs_dollar__no_round` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0425]: cannot find value `a` in this scope + --> $DIR/syntax-errors.rs:138:37 + | +LL | no_curly__rhs_dollar__no_round!(a); + | ^ not found in this scope + +error: aborting due to 37 previous errors + +For more information about this error, try `rustc --explain E0425`. From 63eddb3e68355c3c6739b6fa3c3d37f106408922 Mon Sep 17 00:00:00 2001 From: fren_gor Date: Wed, 9 Mar 2022 21:12:07 +0100 Subject: [PATCH 28/28] Add tracking issue --- library/core/src/iter/traits/iterator.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index 9b22023b09e3e..458f6903c0248 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -1921,7 +1921,7 @@ pub trait Iterator { /// println!("Vec len now is {}", count); /// ``` #[inline] - #[unstable(feature = "iter_collect_into", reason = "new API", issue = "none")] + #[unstable(feature = "iter_collect_into", reason = "new API", issue = "94780")] fn collect_into>(self, collection: &mut E) -> &mut E where Self: Sized,