From 97bd49bf2d1d7604dc0a5040edb2a550adf5497b Mon Sep 17 00:00:00 2001 From: Alan Egerton Date: Tue, 14 Jun 2022 21:57:57 +0100 Subject: [PATCH 001/586] Clarify `[T]::select_nth_unstable*` return values MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In cases where the nth element is not unique within the slice, it is not correct to say that the values in the returned triplet include ones for "all elements" less/greater than that at the given index: indeed one (or more) such values would then laso contain values equal to that at the given index. The text proposed here clarifies exactly what is returned, but in so doing it is also documenting an implementation detail that previously wasn't detailed: namely that the return slices are slices into the reordered slice. I don't think this can be contentious, because the lifetimes of those returned slices are bound to that of the original (now reordered) slice—so there really isn't any other reasonable implementation that could have this behaviour; but nevertheless it's probably best if @rust-lang/libs-api give it a nod? Fixes #97982 r? m-ou-se @rustbot label +A-docs C-bug +T-libs-api --- library/core/src/slice/mod.rs | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index 77fd1ec2b8ea2..409918952237e 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -2628,9 +2628,10 @@ impl [T] { /// less than or equal to any value at a position `j > index`. Additionally, this reordering is /// unstable (i.e. any number of equal elements may end up at position `index`), in-place /// (i.e. does not allocate), and *O*(*n*) worst-case. This function is also/ known as "kth - /// element" in other libraries. It returns a triplet of the following values: all elements less - /// than the one at the given index, the value at the given index, and all elements greater than - /// the one at the given index. + /// element" in other libraries. It returns a triplet of the following from the reordered slice: + /// the subslice prior to `index`, the element at `index`, and the subslice after `index`; + /// accordingly, the values in those two subslices will respectively all be less-than-or-equal-to + /// and greater-than-or-equal-to the value of the element at `index`. /// /// # Current implementation /// @@ -2675,10 +2676,11 @@ impl [T] { /// less than or equal to any value at a position `j > index` using the comparator function. /// Additionally, this reordering is unstable (i.e. any number of equal elements may end up at /// position `index`), in-place (i.e. does not allocate), and *O*(*n*) worst-case. This function - /// is also known as "kth element" in other libraries. It returns a triplet of the following - /// values: all elements less than the one at the given index, the value at the given index, - /// and all elements greater than the one at the given index, using the provided comparator - /// function. + /// is also known as "kth element" in other libraries. It returns a triplet of the following from + /// the slice reordered according to the provided comparator function: the subslice prior to + /// `index`, the element at `index`, and the subslice after `index`; accordingly, the values in + /// those two subslices will respectively all be less-than-or-equal-to and greater-than-or-equal-to + /// the value of the element at `index`. /// /// # Current implementation /// @@ -2727,10 +2729,11 @@ impl [T] { /// less than or equal to any value at a position `j > index` using the key extraction function. /// Additionally, this reordering is unstable (i.e. any number of equal elements may end up at /// position `index`), in-place (i.e. does not allocate), and *O*(*n*) worst-case. This function - /// is also known as "kth element" in other libraries. It returns a triplet of the following - /// values: all elements less than the one at the given index, the value at the given index, and - /// all elements greater than the one at the given index, using the provided key extraction - /// function. + /// is also known as "kth element" in other libraries. It returns a triplet of the following from + /// the slice reordered according to the provided key extraction function: the subslice prior to + /// `index`, the element at `index`, and the subslice after `index`; accordingly, the values in + /// those two subslices will respectively all be less-than-or-equal-to and greater-than-or-equal-to + /// the value of the element at `index`. /// /// # Current implementation /// From 5dcc418f62e14580a319b2b8ec24645abbc1569e Mon Sep 17 00:00:00 2001 From: Kevin Reid Date: Fri, 17 Jun 2022 19:46:01 -0700 Subject: [PATCH 002/586] Document the conditional existence of `alloc::sync` and `alloc::task`. The wording is copied from `std::sync::atomic::AtomicPtr`, with additional advice on how to `#[cfg]` for it. --- library/alloc/src/sync.rs | 9 +++++++++ library/alloc/src/task.rs | 6 ++++++ 2 files changed, 15 insertions(+) diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index 55d51e0a3c4cf..d91217f341abd 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -3,6 +3,10 @@ //! Thread-safe reference-counting pointers. //! //! See the [`Arc`][Arc] documentation for more details. +//! +//! **Note**: This module is only available on platforms that support atomic +//! loads and stores of pointers. This may be detected at compile time using +//! `#[cfg(target_has_atomic = "ptr")]`. use core::any::Any; use core::borrow; @@ -82,6 +86,11 @@ macro_rules! acquire { /// [`Mutex`][mutex], [`RwLock`][rwlock], or one of the [`Atomic`][atomic] /// types. /// +/// **Note**: This type is only available on platforms that support atomic +/// loads and stores of pointers, which includes all platforms that support +/// the `std` crate but not all those which only support [`alloc`](crate). +/// This may be detected at compile time using `#[cfg(target_has_atomic = "ptr")]`. +/// /// ## Thread Safety /// /// Unlike [`Rc`], `Arc` uses atomic operations for its reference diff --git a/library/alloc/src/task.rs b/library/alloc/src/task.rs index 528ee4ff1542c..9d8e309a978d9 100644 --- a/library/alloc/src/task.rs +++ b/library/alloc/src/task.rs @@ -1,5 +1,11 @@ #![stable(feature = "wake_trait", since = "1.51.0")] + //! Types and Traits for working with asynchronous tasks. +//! +//! **Note**: This module is only available on platforms that support atomic +//! loads and stores of pointers. This may be detected at compile time using +//! `#[cfg(target_has_atomic = "ptr")]`. + use core::mem::ManuallyDrop; use core::task::{RawWaker, RawWakerVTable, Waker}; From 513eda0f7bd1461fab01d7c26eb2ecfa364420cd Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Mon, 27 Jun 2022 12:37:06 +0200 Subject: [PATCH 003/586] make Condvar, Mutex, RwLock const constructors work with unsupported impl --- library/std/src/sys/unsupported/locks/condvar.rs | 1 + library/std/src/sys/unsupported/locks/mutex.rs | 1 + library/std/src/sys/unsupported/locks/rwlock.rs | 1 + library/std/src/sys_common/condvar.rs | 1 + library/std/src/sys_common/condvar/check.rs | 1 + library/std/src/sys_common/mutex.rs | 1 + library/std/src/sys_common/rwlock.rs | 1 + 7 files changed, 7 insertions(+) diff --git a/library/std/src/sys/unsupported/locks/condvar.rs b/library/std/src/sys/unsupported/locks/condvar.rs index e703fd0d26993..527a26a12bcec 100644 --- a/library/std/src/sys/unsupported/locks/condvar.rs +++ b/library/std/src/sys/unsupported/locks/condvar.rs @@ -7,6 +7,7 @@ pub type MovableCondvar = Condvar; impl Condvar { #[inline] + #[rustc_const_stable(feature = "const_locks", since = "1.63.0")] pub const fn new() -> Condvar { Condvar {} } diff --git a/library/std/src/sys/unsupported/locks/mutex.rs b/library/std/src/sys/unsupported/locks/mutex.rs index d7cb12e0cf9a4..81b49c64caeb5 100644 --- a/library/std/src/sys/unsupported/locks/mutex.rs +++ b/library/std/src/sys/unsupported/locks/mutex.rs @@ -12,6 +12,7 @@ unsafe impl Sync for Mutex {} // no threads on this platform impl Mutex { #[inline] + #[rustc_const_stable(feature = "const_locks", since = "1.63.0")] pub const fn new() -> Mutex { Mutex { locked: Cell::new(false) } } diff --git a/library/std/src/sys/unsupported/locks/rwlock.rs b/library/std/src/sys/unsupported/locks/rwlock.rs index aca5fb7152c99..5292691b95557 100644 --- a/library/std/src/sys/unsupported/locks/rwlock.rs +++ b/library/std/src/sys/unsupported/locks/rwlock.rs @@ -12,6 +12,7 @@ unsafe impl Sync for RwLock {} // no threads on this platform impl RwLock { #[inline] + #[rustc_const_stable(feature = "const_locks", since = "1.63.0")] pub const fn new() -> RwLock { RwLock { mode: Cell::new(0) } } diff --git a/library/std/src/sys_common/condvar.rs b/library/std/src/sys_common/condvar.rs index f3ac1061b8935..8bc5b24115d16 100644 --- a/library/std/src/sys_common/condvar.rs +++ b/library/std/src/sys_common/condvar.rs @@ -15,6 +15,7 @@ pub struct Condvar { impl Condvar { /// Creates a new condition variable for use. #[inline] + #[rustc_const_stable(feature = "const_locks", since = "1.63.0")] pub const fn new() -> Self { Self { inner: imp::MovableCondvar::new(), check: CondvarCheck::new() } } diff --git a/library/std/src/sys_common/condvar/check.rs b/library/std/src/sys_common/condvar/check.rs index ce8f36704877f..4ac9e62bf8695 100644 --- a/library/std/src/sys_common/condvar/check.rs +++ b/library/std/src/sys_common/condvar/check.rs @@ -50,6 +50,7 @@ pub struct NoCheck; #[allow(dead_code)] impl NoCheck { + #[rustc_const_stable(feature = "const_locks", since = "1.63.0")] pub const fn new() -> Self { Self } diff --git a/library/std/src/sys_common/mutex.rs b/library/std/src/sys_common/mutex.rs index 48479f5bdb3f7..7b9f7ef548785 100644 --- a/library/std/src/sys_common/mutex.rs +++ b/library/std/src/sys_common/mutex.rs @@ -61,6 +61,7 @@ unsafe impl Sync for MovableMutex {} impl MovableMutex { /// Creates a new mutex. #[inline] + #[rustc_const_stable(feature = "const_locks", since = "1.63.0")] pub const fn new() -> Self { Self(imp::MovableMutex::new()) } diff --git a/library/std/src/sys_common/rwlock.rs b/library/std/src/sys_common/rwlock.rs index ba56f3a8f1b52..34e9a91e87485 100644 --- a/library/std/src/sys_common/rwlock.rs +++ b/library/std/src/sys_common/rwlock.rs @@ -75,6 +75,7 @@ pub struct MovableRwLock(imp::MovableRwLock); impl MovableRwLock { /// Creates a new reader-writer lock for use. #[inline] + #[rustc_const_stable(feature = "const_locks", since = "1.63.0")] pub const fn new() -> Self { Self(imp::MovableRwLock::new()) } From eac1e30bd8620446c123b4f0d2c0ea054acdee56 Mon Sep 17 00:00:00 2001 From: Antoine PLASKOWSKI Date: Sat, 9 Jul 2022 23:28:22 +0200 Subject: [PATCH 004/586] Add T to PhantomData impl Debug --- library/core/src/fmt/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs index 6c3bb7229e51f..a3b3ced779fdb 100644 --- a/library/core/src/fmt/mod.rs +++ b/library/core/src/fmt/mod.rs @@ -2598,7 +2598,7 @@ impl Debug for () { #[stable(feature = "rust1", since = "1.0.0")] impl Debug for PhantomData { fn fmt(&self, f: &mut Formatter<'_>) -> Result { - f.debug_struct("PhantomData").finish() + write!(f, "PhantomData<{}>", crate::any::type_name::()) } } From 9cd66be2351099d2a74aeb67ccb13e148dfdf114 Mon Sep 17 00:00:00 2001 From: Duarte Nunes Date: Wed, 13 Jul 2022 14:22:50 -0300 Subject: [PATCH 005/586] docs: be less harsh in wording for Vec::from_raw_parts In particular, be clear that it is sound to specify memory not originating from a previous `Vec` allocation. That is already suggested in other parts of the documentation about zero-alloc conversions to Box<[T]>. Incorporate a constraint from `slice::from_raw_parts` that was missing but needs to be fulfilled, since a `Vec` can be converted into a slice. --- library/alloc/src/vec/mod.rs | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index fa9f2131c0c1d..aa822b1f923df 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -490,8 +490,6 @@ impl Vec { /// This is highly unsafe, due to the number of invariants that aren't /// checked: /// - /// * `ptr` needs to have been previously allocated via [`String`]/`Vec` - /// (at least, it's highly likely to be incorrect if it wasn't). /// * `T` needs to have the same alignment as what `ptr` was allocated with. /// (`T` having a less strict alignment is not sufficient, the alignment really /// needs to be equal to satisfy the [`dealloc`] requirement that memory must be @@ -500,6 +498,12 @@ impl Vec { /// to be the same size as the pointer was allocated with. (Because similar to /// alignment, [`dealloc`] must be called with the same layout `size`.) /// * `length` needs to be less than or equal to `capacity`. + /// * `capacity` needs to be the capacity that the pointer was allocated with. + /// * The allocated size in bytes must be no larger than `isize::MAX`. + /// See the safety documentation of [`pointer::offset`]. + /// + /// To ensure these requirements are easily met, ensure `ptr` has previously + /// been allocated via `Vec`. /// /// Violating these may cause problems like corrupting the allocator's /// internal data structures. For example it is normally **not** safe @@ -648,14 +652,20 @@ impl Vec { /// This is highly unsafe, due to the number of invariants that aren't /// checked: /// - /// * `ptr` needs to have been previously allocated via [`String`]/`Vec` - /// (at least, it's highly likely to be incorrect if it wasn't). - /// * `T` needs to have the same size and alignment as what `ptr` was allocated with. + /// * `T` needs to have the same alignment as what `ptr` was allocated with. /// (`T` having a less strict alignment is not sufficient, the alignment really /// needs to be equal to satisfy the [`dealloc`] requirement that memory must be /// allocated and deallocated with the same layout.) + /// * The size of `T` times the `capacity` (ie. the allocated size in bytes) needs + /// to be the same size as the pointer was allocated with. (Because similar to + /// alignment, [`dealloc`] must be called with the same layout `size`.) /// * `length` needs to be less than or equal to `capacity`. /// * `capacity` needs to be the capacity that the pointer was allocated with. + /// * The allocated size in bytes must be no larger than `isize::MAX`. + /// See the safety documentation of [`pointer::offset`]. + /// + /// To ensure these requirements are easily met, ensure `ptr` has previously + /// been allocated via `Vec`. /// /// Violating these may cause problems like corrupting the allocator's /// internal data structures. For example it is **not** safe From c9ec7aa0d7013bab63477adc77a94163a0df2c32 Mon Sep 17 00:00:00 2001 From: Duarte Nunes Date: Wed, 13 Jul 2022 19:46:04 -0300 Subject: [PATCH 006/586] changes to wording --- library/alloc/src/vec/mod.rs | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index aa822b1f923df..17342cacd760e 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -483,7 +483,7 @@ impl Vec { Self::with_capacity_in(capacity, Global) } - /// Creates a `Vec` directly from the raw components of another vector. + /// Creates a `Vec` directly from a pointer, a capacity, and a length. /// /// # Safety /// @@ -498,12 +498,14 @@ impl Vec { /// to be the same size as the pointer was allocated with. (Because similar to /// alignment, [`dealloc`] must be called with the same layout `size`.) /// * `length` needs to be less than or equal to `capacity`. + /// * The first `length` values must be properly initialized values of type `T`. /// * `capacity` needs to be the capacity that the pointer was allocated with. - /// * The allocated size in bytes must be no larger than `isize::MAX`. + /// * The allocated size in bytes must be no larger than `isize::MAX`. /// See the safety documentation of [`pointer::offset`]. /// - /// To ensure these requirements are easily met, ensure `ptr` has previously - /// been allocated via `Vec`. + /// These requirements are always uphead by any `ptr` that has been allocated + /// via `Vec`. Other allocation sources are allowed if the invariants are + /// upheld. /// /// Violating these may cause problems like corrupting the allocator's /// internal data structures. For example it is normally **not** safe @@ -645,7 +647,8 @@ impl Vec { Vec { buf: RawVec::with_capacity_in(capacity, alloc), len: 0 } } - /// Creates a `Vec` directly from the raw components of another vector. + /// Creates a `Vec` directly from a pointer, a capacity, a length, + /// and an allocator. /// /// # Safety /// @@ -660,12 +663,14 @@ impl Vec { /// to be the same size as the pointer was allocated with. (Because similar to /// alignment, [`dealloc`] must be called with the same layout `size`.) /// * `length` needs to be less than or equal to `capacity`. - /// * `capacity` needs to be the capacity that the pointer was allocated with. - /// * The allocated size in bytes must be no larger than `isize::MAX`. + /// * The first `length` values must be properly initialized values of type `T`. + /// * `capacity` needs to [fit] the layout size that the pointer was allocated with. + /// * The allocated size in bytes must be no larger than `isize::MAX`. /// See the safety documentation of [`pointer::offset`]. /// - /// To ensure these requirements are easily met, ensure `ptr` has previously - /// been allocated via `Vec`. + /// These requirements are always uphead by any `ptr` that has been allocated + /// via `Vec`. Other allocation sources are allowed if the invariants are + /// upheld. /// /// Violating these may cause problems like corrupting the allocator's /// internal data structures. For example it is **not** safe @@ -683,6 +688,7 @@ impl Vec { /// /// [`String`]: crate::string::String /// [`dealloc`]: crate::alloc::GlobalAlloc::dealloc + /// [*fit*]: crate::alloc::Allocator#memory-fitting /// /// # Examples /// From 050115c0d4115fb31c056ae858384ef48a77239d Mon Sep 17 00:00:00 2001 From: Duarte Nunes Date: Wed, 13 Jul 2022 21:49:31 -0300 Subject: [PATCH 007/586] typo --- library/alloc/src/vec/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 17342cacd760e..6b544c7025007 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -503,7 +503,7 @@ impl Vec { /// * The allocated size in bytes must be no larger than `isize::MAX`. /// See the safety documentation of [`pointer::offset`]. /// - /// These requirements are always uphead by any `ptr` that has been allocated + /// These requirements are always upheld by any `ptr` that has been allocated /// via `Vec`. Other allocation sources are allowed if the invariants are /// upheld. /// @@ -668,7 +668,7 @@ impl Vec { /// * The allocated size in bytes must be no larger than `isize::MAX`. /// See the safety documentation of [`pointer::offset`]. /// - /// These requirements are always uphead by any `ptr` that has been allocated + /// These requirements are always upheld by any `ptr` that has been allocated /// via `Vec`. Other allocation sources are allowed if the invariants are /// upheld. /// From 8d35ab38067ede0b2816e0177d1d0e0869e89136 Mon Sep 17 00:00:00 2001 From: Duarte Nunes Date: Wed, 13 Jul 2022 22:04:15 -0300 Subject: [PATCH 008/586] rustdoc --- library/alloc/src/vec/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 6b544c7025007..fcfb88b18c7e9 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -664,7 +664,7 @@ impl Vec { /// alignment, [`dealloc`] must be called with the same layout `size`.) /// * `length` needs to be less than or equal to `capacity`. /// * The first `length` values must be properly initialized values of type `T`. - /// * `capacity` needs to [fit] the layout size that the pointer was allocated with. + /// * `capacity` needs to [*fit*] the layout size that the pointer was allocated with. /// * The allocated size in bytes must be no larger than `isize::MAX`. /// See the safety documentation of [`pointer::offset`]. /// From a85ee3ed9130de6b263de0b05e67b04e644f269e Mon Sep 17 00:00:00 2001 From: Duarte Nunes Date: Thu, 14 Jul 2022 11:47:06 -0300 Subject: [PATCH 009/586] add code examples --- library/alloc/src/vec/mod.rs | 51 +++++++++++++++++++++++++++++++++++- 1 file changed, 50 insertions(+), 1 deletion(-) diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index fcfb88b18c7e9..ae99772450e21 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -557,6 +557,32 @@ impl Vec { /// assert_eq!(rebuilt, [4, 5, 6]); /// } /// ``` + /// + /// Using memory that was allocated elsewhere: + /// + /// ```rust + /// #![feature(allocator_api)] + /// + /// use std::alloc::{AllocError, Allocator, Global, Layout}; + /// + /// fn main() { + /// let layout = Layout::array::(16).expect("overflow cannot happen"); + /// + /// let vec = unsafe { + /// let mem = match Global.allocate(layout) { + /// Ok(mem) => mem.cast::().as_ptr(), + /// Err(AllocError) => return, + /// }; + /// + /// mem.write(1_000_000); + /// + /// Vec::from_raw_parts_in(mem, 1, 16, Global) + /// }; + /// + /// assert_eq!(vec, &[1_000_000]); + /// assert_eq!(vec.capacity(), 16); + /// } + /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub unsafe fn from_raw_parts(ptr: *mut T, length: usize, capacity: usize) -> Self { @@ -669,7 +695,7 @@ impl Vec { /// See the safety documentation of [`pointer::offset`]. /// /// These requirements are always upheld by any `ptr` that has been allocated - /// via `Vec`. Other allocation sources are allowed if the invariants are + /// via `Vec`. Other allocation sources are allowed if the invariants are /// upheld. /// /// Violating these may cause problems like corrupting the allocator's @@ -727,6 +753,29 @@ impl Vec { /// assert_eq!(rebuilt, [4, 5, 6]); /// } /// ``` + /// + /// Using memory that was allocated elsewhere: + /// + /// ```rust + /// use std::alloc::{alloc, Layout}; + /// + /// fn main() { + /// let layout = Layout::array::(16).expect("overflow cannot happen"); + /// let vec = unsafe { + /// let mem = alloc(layout).cast::(); + /// if mem.is_null() { + /// return; + /// } + /// + /// mem.write(1_000_000); + /// + /// Vec::from_raw_parts(mem, 1, 16) + /// }; + /// + /// assert_eq!(vec, &[1_000_000]); + /// assert_eq!(vec.capacity(), 16); + /// } + /// ``` #[inline] #[unstable(feature = "allocator_api", issue = "32838")] pub unsafe fn from_raw_parts_in(ptr: *mut T, length: usize, capacity: usize, alloc: A) -> Self { From 551d921de0f13c54093ab4f6a3adbe69292e091a Mon Sep 17 00:00:00 2001 From: Jan Behrens Date: Tue, 19 Jul 2022 11:40:40 +0200 Subject: [PATCH 010/586] docs: Improve AsRef / AsMut docs on blanket impls - Explicitly mention that `AsRef` and `AsMut` do not auto-dereference generally for all dereferencable types (but only if inner type is a shared and/or mutable reference) - Give advice to not use `AsRef` or `AsMut` for the sole purpose of dereferencing - Suggest providing a transitive `AsRef` or `AsMut` implementation for types which implement `Deref` - Add new section "Reflexivity" in documentation comments for `AsRef` and `AsMut` - Provide better example for `AsMut` - Added heading "Relation to `Borrow`" in `AsRef`'s docs to improve structure Issue #45742 and a corresponding FIXME in the libcore suggest that `AsRef` and `AsMut` should provide a blanket implementation over `Deref`. As that is difficult to realize at the moment, this commit updates the documentation to better describe the status-quo and to give advice on how to use `AsRef` and `AsMut`. --- library/core/src/convert/mod.rs | 177 ++++++++++++++++++++++++++++---- 1 file changed, 159 insertions(+), 18 deletions(-) diff --git a/library/core/src/convert/mod.rs b/library/core/src/convert/mod.rs index b30c8a4aeabdd..dd0d6478c3a20 100644 --- a/library/core/src/convert/mod.rs +++ b/library/core/src/convert/mod.rs @@ -25,6 +25,7 @@ //! # Generic Implementations //! //! - [`AsRef`] and [`AsMut`] auto-dereference if the inner type is a reference +//! (but not generally for all [dereferenceable types][core::ops::Deref]) //! - [`From`]` for T` implies [`Into`]` for U` //! - [`TryFrom`]` for T` implies [`TryInto`]` for U` //! - [`From`] and [`Into`] are reflexive, which means that all types can @@ -108,10 +109,12 @@ pub const fn identity(x: T) -> T { /// If you need to do a costly conversion it is better to implement [`From`] with type /// `&T` or write a custom function. /// +/// # Relation to `Borrow` +/// /// `AsRef` has the same signature as [`Borrow`], but [`Borrow`] is different in a few aspects: /// /// - Unlike `AsRef`, [`Borrow`] has a blanket impl for any `T`, and can be used to accept either -/// a reference or a value. +/// a reference or a value. (See also note on `AsRef`'s reflexibility below.) /// - [`Borrow`] also requires that [`Hash`], [`Eq`] and [`Ord`] for a borrowed value are /// equivalent to those of the owned value. For this reason, if you want to /// borrow only a single field of a struct you can implement `AsRef`, but not [`Borrow`]. @@ -121,9 +124,55 @@ pub const fn identity(x: T) -> T { /// /// # Generic Implementations /// -/// - `AsRef` auto-dereferences if the inner type is a reference or a mutable -/// reference (e.g.: `foo.as_ref()` will work the same if `foo` has type -/// `&mut Foo` or `&&mut Foo`) +/// `AsRef` auto-dereferences if the inner type is a reference or a mutable reference +/// (e.g.: `foo.as_ref()` will work the same if `foo` has type `&mut Foo` or `&&mut Foo`). +/// +/// Note that due to historic reasons, the above currently does not hold generally for all +/// [dereferenceable types], e.g. `foo.as_ref()` will *not* work the same as +/// `Box::new(foo).as_ref()`. Instead, many smart pointers provide an `as_ref` implementation which +/// simply returns a reference to the [pointed-to value] (but do not perform a cheap +/// reference-to-reference conversion for that value). However, [`AsRef::as_ref`] should not be +/// used for the sole purpose of dereferencing; instead ['`Deref` coercion'] can be used: +/// +/// [dereferenceable types]: core::ops::Deref +/// [pointed-to value]: core::ops::Deref::Target +/// ['`Deref` coercion']: core::ops::Deref#more-on-deref-coercion +/// +/// ``` +/// let x = Box::new(5i32); +/// // Avoid this: +/// // let y: &i32 = x.as_ref(); +/// // Better just write: +/// let y: &i32 = &x; +/// ``` +/// +/// Types which implement [`Deref`][core::ops::Deref] should consider implementing `AsRef` as +/// follows: +/// +/// ``` +/// impl AsRef for SomeType +/// where +/// T: ?Sized, +/// ::Target: AsRef, +/// { +/// fn as_ref(&self) -> &T { +/// self.deref().as_ref() +/// } +/// } +/// ``` +/// +/// # Reflexivity +/// +/// Ideally, `AsRef` would be reflexive, that is there is an `impl AsRef for T`, with +/// [`as_ref`][AsRef::as_ref] simply returning its argument unchanged. +/// Such a blanket implementation is currently *not* provided due to technical restrictions of +/// Rust's type system (it would be overlapping with another existing blanket implementation for +/// `&T where T: AsRef` which allows `AsRef` to auto-dereference, see "Generic Implementations" +/// above). +/// +/// A trivial implementation of `AsRef for T` must be added explicitly for a particular type `T` +/// where needed or desired. Note, however, that not all types from `std` contain such an +/// implementation, and those cannot be added by external code due to orphan rules. /// /// # Examples /// @@ -170,29 +219,121 @@ pub trait AsRef { /// /// # Generic Implementations /// -/// - `AsMut` auto-dereferences if the inner type is a mutable reference -/// (e.g.: `foo.as_mut()` will work the same if `foo` has type `&mut Foo` -/// or `&mut &mut Foo`) +/// `AsMut` auto-dereferences if the inner type is a mutable reference +/// (e.g.: `foo.as_mut()` will work the same if `foo` has type `&mut Foo` or `&mut &mut Foo`). +/// +/// Note that due to historic reasons, the above currently does not hold generally for all +/// [mutably dereferenceable types], e.g. `foo.as_mut()` will *not* work the same as +/// `Box::new(foo).as_mut()`. Instead, many smart pointers provide an `as_mut` implementation which +/// simply returns a reference to the [pointed-to value] (but do not perform a cheap +/// reference-to-reference conversion for that value). However, [`AsMut::as_mut`] should not be +/// used for the sole purpose of mutable dereferencing; instead ['`Deref` coercion'] can be used: +/// +/// [mutably dereferenceable types]: core::ops::DerefMut +/// [pointed-to value]: core::ops::Deref::Target +/// ['`Deref` coercion']: core::ops::DerefMut#more-on-deref-coercion +/// +/// ``` +/// let mut x = Box::new(5i32); +/// // Avoid this: +/// // let y: &mut i32 = x.as_mut(); +/// // Better just write: +/// let y: &mut i32 = &mut x; +/// ``` +/// +/// Types which implement [`DerefMut`](core::ops::DerefMut) should consider to add an +/// implementation of `AsMut` as follows: +/// +/// ``` +/// impl AsMut for SomeType +/// where +/// ::Target: AsMut, +/// { +/// fn as_mut(&mut self) -> &mut T { +/// self.deref_mut().as_mut() +/// } +/// } +/// ``` +/// +/// # Reflexivity +/// +/// Ideally, `AsMut` would be reflexive, that is there is an `impl AsMut for T`, with +/// [`as_mut`][AsMut::as_mut] simply returning its argument unchanged. +/// Such a blanket implementation is currently *not* provided due to technical restrictions of +/// Rust's type system (it would be overlapping with another existing blanket implementation for +/// `&mut T where T: AsMut` which allows `AsMut` to auto-dereference, see "Generic +/// Implementations" above). +/// +/// A trivial implementation of `AsMut for T` must be added explicitly for a particular type `T` +/// where needed or desired. Note, however, that not all types from `std` contain such an +/// implementation, and those cannot be added by external code due to orphan rules. /// /// # Examples /// -/// Using `AsMut` as trait bound for a generic function we can accept all mutable references -/// that can be converted to type `&mut T`. Because [`Box`] implements `AsMut` we can -/// write a function `add_one` that takes all arguments that can be converted to `&mut u64`. -/// Because [`Box`] implements `AsMut`, `add_one` accepts arguments of type -/// `&mut Box` as well: +/// Using `AsMut` as trait bound for a generic function, we can accept all mutable references that +/// can be converted to type `&mut T`. Unlike [dereference], which has a single [target type], +/// there can be multiple implementations of `AsMut` for a type. In particular, `Vec` implements +/// both `AsMut>` and `AsMut<[T]>`. +/// +/// In the following, the example functions `caesar` and `null_terminate` provide a generic +/// interface which work with any type that can be converted by cheap mutable-to-mutable conversion +/// into a byte slice or byte `Vec`, respectively. +/// +/// [dereference]: core::ops::DerefMut +/// [target type]: core::ops::Deref::Target /// /// ``` -/// fn add_one>(num: &mut T) { -/// *num.as_mut() += 1; +/// struct Document { +/// info: String, +/// content: Vec, /// } /// -/// let mut boxed_num = Box::new(0); -/// add_one(&mut boxed_num); -/// assert_eq!(*boxed_num, 1); +/// impl AsMut for Document +/// where +/// Vec: AsMut, +/// { +/// fn as_mut(&mut self) -> &mut T { +/// self.content.as_mut() +/// } +/// } +/// +/// fn caesar>(data: &mut T, key: u8) { +/// for byte in data.as_mut() { +/// *byte = byte.wrapping_add(key); +/// } +/// } +/// +/// fn null_terminate>>(data: &mut T) { +/// // Using a non-generic inner function, which contains most of the +/// // functionality, helps to minimize monomorphization overhead. +/// fn doit(data: &mut Vec) { +/// let len = data.len(); +/// if len == 0 || data[len-1] != 0 { +/// data.push(0); +/// } +/// } +/// doit(data.as_mut()); +/// } +/// +/// fn main() { +/// let mut v: Vec = vec![1, 2, 3]; +/// caesar(&mut v, 5); +/// assert_eq!(v, [6, 7, 8]); +/// null_terminate(&mut v); +/// assert_eq!(v, [6, 7, 8, 0]); +/// let mut doc = Document { +/// info: String::from("Example"), +/// content: vec![17, 19, 8], +/// }; +/// caesar(&mut doc, 1); +/// assert_eq!(doc.content, [18, 20, 9]); +/// null_terminate(&mut doc); +/// assert_eq!(doc.content, [18, 20, 9, 0]); +/// } /// ``` /// -/// [`Box`]: ../../std/boxed/struct.Box.html +/// Note, however, that APIs don't need to be generic. In many cases taking a `&mut [u8]` or +/// `&mut Vec`, for example, is the better choice (callers need to pass the correct type then). #[stable(feature = "rust1", since = "1.0.0")] #[cfg_attr(not(test), rustc_diagnostic_item = "AsMut")] pub trait AsMut { From 9f68e3ef1b3bc0a7f1ce4d7ff7fc74bcaa2d42ad Mon Sep 17 00:00:00 2001 From: Jan Behrens Date: Tue, 19 Jul 2022 23:24:51 +0200 Subject: [PATCH 011/586] fixup! docs: Improve AsRef / AsMut docs on blanket impls Fixed examples in sections "Generic Implementations" of `AsRef`'s and `AsMut`'s doc comments, which failed tests. --- library/core/src/convert/mod.rs | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/library/core/src/convert/mod.rs b/library/core/src/convert/mod.rs index dd0d6478c3a20..e75e32855d1bb 100644 --- a/library/core/src/convert/mod.rs +++ b/library/core/src/convert/mod.rs @@ -150,6 +150,14 @@ pub const fn identity(x: T) -> T { /// follows: /// /// ``` +/// # use core::ops::Deref; +/// # struct SomeType; +/// # impl Deref for SomeType { +/// # type Target = [u8]; +/// # fn deref(&self) -> &[u8] { +/// # &[] +/// # } +/// # } /// impl AsRef for SomeType /// where /// T: ?Sized, @@ -245,6 +253,19 @@ pub trait AsRef { /// implementation of `AsMut` as follows: /// /// ``` +/// # use core::ops::{Deref, DerefMut}; +/// # struct SomeType; +/// # impl Deref for SomeType { +/// # type Target = [u8]; +/// # fn deref(&self) -> &[u8] { +/// # &[] +/// # } +/// # } +/// # impl DerefMut for SomeType { +/// # fn deref_mut(&mut self) -> &mut [u8] { +/// # &mut [] +/// # } +/// # } /// impl AsMut for SomeType /// where /// ::Target: AsMut, From e4a259b5e480ea5b444384f9ff9cd862a46a9d16 Mon Sep 17 00:00:00 2001 From: Jan Behrens Date: Tue, 19 Jul 2022 23:53:40 +0200 Subject: [PATCH 012/586] fixup! docs: Improve AsRef / AsMut docs on blanket impls Better conform to Rust API Documentation Conventions --- library/core/src/convert/mod.rs | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/library/core/src/convert/mod.rs b/library/core/src/convert/mod.rs index e75e32855d1bb..bdd862f39c801 100644 --- a/library/core/src/convert/mod.rs +++ b/library/core/src/convert/mod.rs @@ -146,8 +146,9 @@ pub const fn identity(x: T) -> T { /// let y: &i32 = &x; /// ``` /// -/// Types which implement [`Deref`][core::ops::Deref] should consider implementing `AsRef` as -/// follows: +/// Types which implement [`Deref`] should consider implementing `AsRef` as follows: +/// +/// [`Deref`]: core::ops::Deref /// /// ``` /// # use core::ops::Deref; @@ -172,12 +173,14 @@ pub const fn identity(x: T) -> T { /// # Reflexivity /// /// Ideally, `AsRef` would be reflexive, that is there is an `impl AsRef for T`, with -/// [`as_ref`][AsRef::as_ref] simply returning its argument unchanged. +/// [`as_ref`] simply returning its argument unchanged. /// Such a blanket implementation is currently *not* provided due to technical restrictions of /// Rust's type system (it would be overlapping with another existing blanket implementation for /// `&T where T: AsRef` which allows `AsRef` to auto-dereference, see "Generic Implementations" /// above). /// +/// [`as_ref`]: AsRef::as_ref +/// /// A trivial implementation of `AsRef for T` must be added explicitly for a particular type `T` /// where needed or desired. Note, however, that not all types from `std` contain such an /// implementation, and those cannot be added by external code due to orphan rules. @@ -249,8 +252,10 @@ pub trait AsRef { /// let y: &mut i32 = &mut x; /// ``` /// -/// Types which implement [`DerefMut`](core::ops::DerefMut) should consider to add an -/// implementation of `AsMut` as follows: +/// Types which implement [`DerefMut`] should consider to add an implementation of `AsMut` as +/// follows: +/// +/// [`DerefMut`]: core::ops::DerefMut /// /// ``` /// # use core::ops::{Deref, DerefMut}; @@ -279,12 +284,14 @@ pub trait AsRef { /// # Reflexivity /// /// Ideally, `AsMut` would be reflexive, that is there is an `impl AsMut for T`, with -/// [`as_mut`][AsMut::as_mut] simply returning its argument unchanged. +/// [`as_mut`] simply returning its argument unchanged. /// Such a blanket implementation is currently *not* provided due to technical restrictions of /// Rust's type system (it would be overlapping with another existing blanket implementation for /// `&mut T where T: AsMut` which allows `AsMut` to auto-dereference, see "Generic /// Implementations" above). /// +/// [`as_mut`]: AsMut::as_mut +/// /// A trivial implementation of `AsMut for T` must be added explicitly for a particular type `T` /// where needed or desired. Note, however, that not all types from `std` contain such an /// implementation, and those cannot be added by external code due to orphan rules. @@ -298,7 +305,7 @@ pub trait AsRef { /// /// In the following, the example functions `caesar` and `null_terminate` provide a generic /// interface which work with any type that can be converted by cheap mutable-to-mutable conversion -/// into a byte slice or byte `Vec`, respectively. +/// into a byte slice (`[u8]`) or byte vector (`Vec`), respectively. /// /// [dereference]: core::ops::DerefMut /// [target type]: core::ops::Deref::Target From e6b761b902fe80ba454368d078fb834554981109 Mon Sep 17 00:00:00 2001 From: Jan Behrens Date: Thu, 21 Jul 2022 16:40:14 +0200 Subject: [PATCH 013/586] fixup! docs: Improve AsRef / AsMut docs on blanket impls Changed wording in sections on "Reflexivity": replaced "that is there is" with "i.e. there would be" and removed comma before "with" Reason: "there is" somewhat contradicted the "would be" hypothetical. A slightly redundant wording has now been chosen for better clarity. The comma seemed to be superfluous. --- library/core/src/convert/mod.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/library/core/src/convert/mod.rs b/library/core/src/convert/mod.rs index bdd862f39c801..e2be262e311d6 100644 --- a/library/core/src/convert/mod.rs +++ b/library/core/src/convert/mod.rs @@ -172,8 +172,8 @@ pub const fn identity(x: T) -> T { /// /// # Reflexivity /// -/// Ideally, `AsRef` would be reflexive, that is there is an `impl AsRef for T`, with -/// [`as_ref`] simply returning its argument unchanged. +/// Ideally, `AsRef` would be reflexive, i.e. there would be an `impl AsRef for T` +/// with [`as_ref`] simply returning its argument unchanged. /// Such a blanket implementation is currently *not* provided due to technical restrictions of /// Rust's type system (it would be overlapping with another existing blanket implementation for /// `&T where T: AsRef` which allows `AsRef` to auto-dereference, see "Generic Implementations" @@ -283,8 +283,8 @@ pub trait AsRef { /// /// # Reflexivity /// -/// Ideally, `AsMut` would be reflexive, that is there is an `impl AsMut for T`, with -/// [`as_mut`] simply returning its argument unchanged. +/// Ideally, `AsMut` would be reflexive, i.e. there would be an `impl AsMut for T` +/// with [`as_mut`] simply returning its argument unchanged. /// Such a blanket implementation is currently *not* provided due to technical restrictions of /// Rust's type system (it would be overlapping with another existing blanket implementation for /// `&mut T where T: AsMut` which allows `AsMut` to auto-dereference, see "Generic From bcf780e2ba00dbe5a81502ef541dbc0f4fb76ebb Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Fri, 22 Jul 2022 08:50:31 -0700 Subject: [PATCH 014/586] Recover error strings on Unix from_lossy_utf8 Some language settings can result in unreliable UTF-8 being produced. This can result in failing to emit the error string, panicking instead. from_lossy_utf8 allows us to assume these strings usually will be fine. --- library/std/src/sys/unix/os.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/library/std/src/sys/unix/os.rs b/library/std/src/sys/unix/os.rs index 7252ad321844b..3009a9b1f01ca 100644 --- a/library/std/src/sys/unix/os.rs +++ b/library/std/src/sys/unix/os.rs @@ -125,7 +125,9 @@ pub fn error_string(errno: i32) -> String { } let p = p as *const _; - str::from_utf8(CStr::from_ptr(p).to_bytes()).unwrap().to_owned() + // We can't always expect a UTF-8 environment. When we don't get that luxury, + // it's better to give a low-quality error message than none at all. + String::from_utf8_lossy(CStr::from_ptr(p).to_bytes()).into() } } From 698a3c679811fbde878148e742a6db591a13d89e Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Sat, 13 Aug 2022 02:08:24 +0200 Subject: [PATCH 015/586] Tweak `FpCategory` example order. --- library/core/src/num/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs index f481399fdcf92..fce52a54949b6 100644 --- a/library/core/src/num/mod.rs +++ b/library/core/src/num/mod.rs @@ -936,8 +936,8 @@ impl usize { /// assert_eq!(num.classify(), FpCategory::Normal); /// assert_eq!(inf.classify(), FpCategory::Infinite); /// assert_eq!(zero.classify(), FpCategory::Zero); -/// assert_eq!(nan.classify(), FpCategory::Nan); /// assert_eq!(sub.classify(), FpCategory::Subnormal); +/// assert_eq!(nan.classify(), FpCategory::Nan); /// ``` #[derive(Copy, Clone, PartialEq, Eq, Debug)] #[stable(feature = "rust1", since = "1.0.0")] From fa91980d2d686d3f426a2cae1d0e8fd6825d2d94 Mon Sep 17 00:00:00 2001 From: Matthew Kelly Date: Fri, 19 Aug 2022 06:27:31 -0400 Subject: [PATCH 016/586] Add long description and test for E0311 Adds a long description and unit test for the E0311 compiler error. --- compiler/rustc_error_codes/src/error_codes.rs | 2 +- .../src/error_codes/E0311.md | 49 +++++++++++++++++++ src/test/ui/error-codes/E0311.rs | 18 +++++++ src/test/ui/error-codes/E0311.stderr | 45 +++++++++++++++++ 4 files changed, 113 insertions(+), 1 deletion(-) create mode 100644 compiler/rustc_error_codes/src/error_codes/E0311.md create mode 100644 src/test/ui/error-codes/E0311.rs create mode 100644 src/test/ui/error-codes/E0311.stderr diff --git a/compiler/rustc_error_codes/src/error_codes.rs b/compiler/rustc_error_codes/src/error_codes.rs index 854625579ee7b..1e86d159668ff 100644 --- a/compiler/rustc_error_codes/src/error_codes.rs +++ b/compiler/rustc_error_codes/src/error_codes.rs @@ -159,6 +159,7 @@ E0307: include_str!("./error_codes/E0307.md"), E0308: include_str!("./error_codes/E0308.md"), E0309: include_str!("./error_codes/E0309.md"), E0310: include_str!("./error_codes/E0310.md"), +E0311: include_str!("./error_codes/E0311.md"), E0312: include_str!("./error_codes/E0312.md"), E0316: include_str!("./error_codes/E0316.md"), E0317: include_str!("./error_codes/E0317.md"), @@ -568,7 +569,6 @@ E0790: include_str!("./error_codes/E0790.md"), // E0300, // unexpanded macro // E0304, // expected signed integer constant // E0305, // expected constant - E0311, // thing may not live long enough E0313, // lifetime of borrowed pointer outlives lifetime of captured // variable // E0314, // closure outlives stack frame diff --git a/compiler/rustc_error_codes/src/error_codes/E0311.md b/compiler/rustc_error_codes/src/error_codes/E0311.md new file mode 100644 index 0000000000000..8b5daaaa17865 --- /dev/null +++ b/compiler/rustc_error_codes/src/error_codes/E0311.md @@ -0,0 +1,49 @@ +E0311 occurs when there is insufficient information for the rust compiler to +prove that some time has a long enough lifetime. + +Erroneous code example: + +```compile_fail, E0311 +use std::borrow::BorrowMut; + +trait NestedBorrowMut { + fn nested_borrow_mut(&mut self) -> &mut V; +} + +impl NestedBorrowMut for T +where + T: BorrowMut, + U: BorrowMut, // missing lifetime specifier here --> compile fail +{ + fn nested_borrow_mut(&mut self) -> &mut V { + self.borrow_mut().borrow_mut() + } +} +``` + +In this example we have a trait that borrows some inner data element of type V +from an outer type T, through an intermediate type U. The compiler is unable to +prove that the livetime of U is long enough to support the reference, so it +throws E0311. To fix the issue we can explicitly add lifetime specifiers to the +trait, which link the lifetimes of the various data types and allow the code +to compile. + +Working implementation of the `NestedBorrowMut` trait: + +``` +use std::borrow::BorrowMut; + +trait NestedBorrowMut<'a, U, V> { + fn nested_borrow_mut(& 'a mut self) -> &'a mut V; +} + +impl<'a, T, U, V> NestedBorrowMut<'a, U, V> for T +where + T: BorrowMut, + U: BorrowMut + 'a, +{ + fn nested_borrow_mut(&'a mut self) -> &'a mut V { + self.borrow_mut().borrow_mut() + } +} +``` diff --git a/src/test/ui/error-codes/E0311.rs b/src/test/ui/error-codes/E0311.rs new file mode 100644 index 0000000000000..eb9a473e9a2d1 --- /dev/null +++ b/src/test/ui/error-codes/E0311.rs @@ -0,0 +1,18 @@ +use std::borrow::BorrowMut; + +trait NestedBorrowMut { + fn nested_borrow_mut(&mut self) -> &mut V; +} + +impl NestedBorrowMut for T +where + T: BorrowMut, + U: BorrowMut, // Error is caused by missing lifetime here +{ + fn nested_borrow_mut(&mut self) -> &mut V { + let u_ref = self.borrow_mut(); //~ ERROR E0311 + u_ref.borrow_mut() //~ ERROR E0311 + } +} + +fn main() {} diff --git a/src/test/ui/error-codes/E0311.stderr b/src/test/ui/error-codes/E0311.stderr new file mode 100644 index 0000000000000..a219a6352adc8 --- /dev/null +++ b/src/test/ui/error-codes/E0311.stderr @@ -0,0 +1,45 @@ +error[E0311]: the parameter type `U` may not live long enough + --> $DIR/E0311.rs:13:21 + | +LL | let u_ref = self.borrow_mut(); + | ^^^^^^^^^^^^^^^^^ + | +note: the parameter type `U` must be valid for the anonymous lifetime defined here... + --> $DIR/E0311.rs:12:26 + | +LL | fn nested_borrow_mut(&mut self) -> &mut V { + | ^^^^^^^^^ +note: ...so that the type `U` will meet its required lifetime bounds + --> $DIR/E0311.rs:13:21 + | +LL | let u_ref = self.borrow_mut(); + | ^^^^^^^^^^^^^^^^^ +help: consider adding an explicit lifetime bound... + | +LL | U: BorrowMut + 'a, // Error is caused by missing lifetime here + | ++++ + +error[E0311]: the parameter type `U` may not live long enough + --> $DIR/E0311.rs:14:9 + | +LL | u_ref.borrow_mut() + | ^^^^^^^^^^^^^^^^^^ + | +note: the parameter type `U` must be valid for the anonymous lifetime defined here... + --> $DIR/E0311.rs:12:26 + | +LL | fn nested_borrow_mut(&mut self) -> &mut V { + | ^^^^^^^^^ +note: ...so that the type `U` will meet its required lifetime bounds + --> $DIR/E0311.rs:14:9 + | +LL | u_ref.borrow_mut() + | ^^^^^^^^^^^^^^^^^^ +help: consider adding an explicit lifetime bound... + | +LL | U: BorrowMut + 'a, // Error is caused by missing lifetime here + | ++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0311`. From 08fa70e5c5beb8d84c528d8effb481c4f830b28d Mon Sep 17 00:00:00 2001 From: Matthew Kelly Date: Fri, 19 Aug 2022 07:06:47 -0400 Subject: [PATCH 017/586] fix updated stderr outputs --- .../lifetimes/missing-lifetimes-in-signature-2.stderr | 1 + .../suggestions/lifetimes/missing-lifetimes-in-signature.stderr | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature-2.stderr b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature-2.stderr index 0212c2d712cb3..5dcbb86cbdf79 100644 --- a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature-2.stderr +++ b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature-2.stderr @@ -27,3 +27,4 @@ LL | fn func(foo: &Foo, t: T) { error: aborting due to previous error +For more information about this error, try `rustc --explain E0311`. diff --git a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr index 0d749f04bea77..bd5b3b5340ab3 100644 --- a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr +++ b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr @@ -162,5 +162,5 @@ LL | G: Get + 'a, error: aborting due to 8 previous errors -Some errors have detailed explanations: E0261, E0309, E0621, E0700. +Some errors have detailed explanations: E0261, E0309, E0311, E0621, E0700. For more information about an error, try `rustc --explain E0261`. From 63de1ec0706ddbb8e4d3aacba71ad47308d8dfa9 Mon Sep 17 00:00:00 2001 From: Matthew Kelly Date: Fri, 19 Aug 2022 09:34:20 -0400 Subject: [PATCH 018/586] Apply suggestions from code review Co-authored-by: Guillaume Gomez --- .../src/error_codes/E0311.md | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_error_codes/src/error_codes/E0311.md b/compiler/rustc_error_codes/src/error_codes/E0311.md index 8b5daaaa17865..a5975c4f472be 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0311.md +++ b/compiler/rustc_error_codes/src/error_codes/E0311.md @@ -1,9 +1,9 @@ -E0311 occurs when there is insufficient information for the rust compiler to +This error occurs when there is insufficient information for the rust compiler to prove that some time has a long enough lifetime. Erroneous code example: -```compile_fail, E0311 +```compile_fail,E0311 use std::borrow::BorrowMut; trait NestedBorrowMut { @@ -13,7 +13,7 @@ trait NestedBorrowMut { impl NestedBorrowMut for T where T: BorrowMut, - U: BorrowMut, // missing lifetime specifier here --> compile fail + U: BorrowMut, // error: missing lifetime specifier { fn nested_borrow_mut(&mut self) -> &mut V { self.borrow_mut().borrow_mut() @@ -21,12 +21,11 @@ where } ``` -In this example we have a trait that borrows some inner data element of type V -from an outer type T, through an intermediate type U. The compiler is unable to -prove that the livetime of U is long enough to support the reference, so it -throws E0311. To fix the issue we can explicitly add lifetime specifiers to the -trait, which link the lifetimes of the various data types and allow the code -to compile. +In this example we have a trait that borrows some inner data element of type `V` +from an outer type `T`, through an intermediate type `U`. The compiler is unable to +prove that the livetime of `U` is long enough to support the reference. To fix the +issue we can explicitly add lifetime specifiers to the `NestedBorrowMut` trait, which +link the lifetimes of the various data types and allow the code to compile. Working implementation of the `NestedBorrowMut` trait: @@ -40,7 +39,7 @@ trait NestedBorrowMut<'a, U, V> { impl<'a, T, U, V> NestedBorrowMut<'a, U, V> for T where T: BorrowMut, - U: BorrowMut + 'a, + U: BorrowMut + 'a, // Adding lifetime specifier { fn nested_borrow_mut(&'a mut self) -> &'a mut V { self.borrow_mut().borrow_mut() From a9cefd04411611e72417ee2762979e300aac8749 Mon Sep 17 00:00:00 2001 From: Matthew Kelly Date: Fri, 19 Aug 2022 10:53:14 -0400 Subject: [PATCH 019/586] fix line lengths --- compiler/rustc_error_codes/src/error_codes/E0311.md | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_error_codes/src/error_codes/E0311.md b/compiler/rustc_error_codes/src/error_codes/E0311.md index a5975c4f472be..9477a0b1fb76a 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0311.md +++ b/compiler/rustc_error_codes/src/error_codes/E0311.md @@ -1,5 +1,5 @@ -This error occurs when there is insufficient information for the rust compiler to -prove that some time has a long enough lifetime. +This error occurs when there is insufficient information for the rust compiler +to prove that some time has a long enough lifetime. Erroneous code example: @@ -22,10 +22,11 @@ where ``` In this example we have a trait that borrows some inner data element of type `V` -from an outer type `T`, through an intermediate type `U`. The compiler is unable to -prove that the livetime of `U` is long enough to support the reference. To fix the -issue we can explicitly add lifetime specifiers to the `NestedBorrowMut` trait, which -link the lifetimes of the various data types and allow the code to compile. +from an outer type `T`, through an intermediate type `U`. The compiler is unable +to prove that the livetime of `U` is long enough to support the reference. To +fix the issue we can explicitly add lifetime specifiers to the `NestedBorrowMut` +trait, which link the lifetimes of the various data types and allow the code to +compile. Working implementation of the `NestedBorrowMut` trait: From db2b4a3a7e4f75699d767311bf8b49a7c2946892 Mon Sep 17 00:00:00 2001 From: Tim Vermeulen Date: Sun, 21 Aug 2022 12:18:36 +0200 Subject: [PATCH 020/586] Use internal iteration in `Iterator::{cmp_by, partial_cmp_by, eq_by}` --- library/core/benches/iter.rs | 7 ++ library/core/src/iter/traits/iterator.rs | 143 +++++++++++++---------- 2 files changed, 88 insertions(+), 62 deletions(-) diff --git a/library/core/benches/iter.rs b/library/core/benches/iter.rs index 0abe20e4ca3b2..4b40485d207c8 100644 --- a/library/core/benches/iter.rs +++ b/library/core/benches/iter.rs @@ -363,6 +363,13 @@ fn bench_partial_cmp(b: &mut Bencher) { b.iter(|| (0..100000).map(black_box).partial_cmp((0..100000).map(black_box))) } +#[bench] +fn bench_chain_partial_cmp(b: &mut Bencher) { + b.iter(|| { + (0..50000).chain(50000..100000).map(black_box).partial_cmp((0..100000).map(black_box)) + }) +} + #[bench] fn bench_lt(b: &mut Bencher) { b.iter(|| (0..100000).map(black_box).lt((0..100000).map(black_box))) diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index b2d08f4b0f67b..45be7bdd8dba5 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -3461,36 +3461,27 @@ pub trait Iterator { /// assert_eq!(xs.iter().cmp_by(&ys, |&x, &y| (2 * x).cmp(&y)), Ordering::Greater); /// ``` #[unstable(feature = "iter_order_by", issue = "64295")] - fn cmp_by(mut self, other: I, mut cmp: F) -> Ordering + fn cmp_by(self, other: I, cmp: F) -> Ordering where Self: Sized, I: IntoIterator, F: FnMut(Self::Item, I::Item) -> Ordering, { - let mut other = other.into_iter(); - - loop { - let x = match self.next() { - None => { - if other.next().is_none() { - return Ordering::Equal; - } else { - return Ordering::Less; - } - } - Some(val) => val, - }; - - let y = match other.next() { - None => return Ordering::Greater, - Some(val) => val, - }; - - match cmp(x, y) { - Ordering::Equal => (), - non_eq => return non_eq, + #[inline] + fn compare(mut cmp: F) -> impl FnMut(X, Y) -> ControlFlow + where + F: FnMut(X, Y) -> Ordering, + { + move |x, y| match cmp(x, y) { + Ordering::Equal => ControlFlow::CONTINUE, + non_eq => ControlFlow::Break(non_eq), } } + + match iter_compare(self, other.into_iter(), compare(cmp)) { + ControlFlow::Continue(ord) => ord, + ControlFlow::Break(ord) => ord, + } } /// [Lexicographically](Ord#lexicographical-comparison) compares the elements of this [`Iterator`] with those @@ -3546,36 +3537,27 @@ pub trait Iterator { /// ); /// ``` #[unstable(feature = "iter_order_by", issue = "64295")] - fn partial_cmp_by(mut self, other: I, mut partial_cmp: F) -> Option + fn partial_cmp_by(self, other: I, partial_cmp: F) -> Option where Self: Sized, I: IntoIterator, F: FnMut(Self::Item, I::Item) -> Option, { - let mut other = other.into_iter(); - - loop { - let x = match self.next() { - None => { - if other.next().is_none() { - return Some(Ordering::Equal); - } else { - return Some(Ordering::Less); - } - } - Some(val) => val, - }; - - let y = match other.next() { - None => return Some(Ordering::Greater), - Some(val) => val, - }; - - match partial_cmp(x, y) { - Some(Ordering::Equal) => (), - non_eq => return non_eq, + #[inline] + fn compare(mut partial_cmp: F) -> impl FnMut(X, Y) -> ControlFlow> + where + F: FnMut(X, Y) -> Option, + { + move |x, y| match partial_cmp(x, y) { + Some(Ordering::Equal) => ControlFlow::CONTINUE, + non_eq => ControlFlow::Break(non_eq), } } + + match iter_compare(self, other.into_iter(), compare(partial_cmp)) { + ControlFlow::Continue(ord) => Some(ord), + ControlFlow::Break(ord) => ord, + } } /// Determines if the elements of this [`Iterator`] are equal to those of @@ -3613,29 +3595,26 @@ pub trait Iterator { /// assert!(xs.iter().eq_by(&ys, |&x, &y| x * x == y)); /// ``` #[unstable(feature = "iter_order_by", issue = "64295")] - fn eq_by(mut self, other: I, mut eq: F) -> bool + fn eq_by(self, other: I, eq: F) -> bool where Self: Sized, I: IntoIterator, F: FnMut(Self::Item, I::Item) -> bool, { - let mut other = other.into_iter(); - - loop { - let x = match self.next() { - None => return other.next().is_none(), - Some(val) => val, - }; - - let y = match other.next() { - None => return false, - Some(val) => val, - }; - - if !eq(x, y) { - return false; + #[inline] + fn compare(mut eq: F) -> impl FnMut(X, Y) -> ControlFlow<()> + where + F: FnMut(X, Y) -> bool, + { + move |x, y| { + if eq(x, y) { ControlFlow::CONTINUE } else { ControlFlow::BREAK } } } + + match iter_compare(self, other.into_iter(), compare(eq)) { + ControlFlow::Continue(ord) => ord == Ordering::Equal, + ControlFlow::Break(()) => false, + } } /// Determines if the elements of this [`Iterator`] are unequal to those of @@ -3860,6 +3839,46 @@ pub trait Iterator { } } +/// Compares two iterators element-wise using the given function. +/// +/// If `ControlFlow::CONTINUE` is returned from the function, the comparison moves on to the next +/// elements of both iterators. Returning `ControlFlow::Break(x)` short-circuits the iteration and +/// returns `ControlFlow::Break(x)`. If one of the iterators runs out of elements, +/// `ControlFlow::Continue(ord)` is returned where `ord` is the result of comparing the lengths of +/// the iterators. +/// +/// Isolates the logic shared by ['cmp_by'](Iterator::cmp_by), +/// ['partial_cmp_by'](Iterator::partial_cmp_by), and ['eq_by'](Iterator::eq_by). +#[inline] +fn iter_compare(mut a: A, mut b: B, f: F) -> ControlFlow +where + A: Iterator, + B: Iterator, + F: FnMut(A::Item, B::Item) -> ControlFlow, +{ + #[inline] + fn compare<'a, B, X, T>( + b: &'a mut B, + mut f: impl FnMut(X, B::Item) -> ControlFlow + 'a, + ) -> impl FnMut(X) -> ControlFlow> + 'a + where + B: Iterator, + { + move |x| match b.next() { + None => ControlFlow::Break(ControlFlow::Continue(Ordering::Greater)), + Some(y) => f(x, y).map_break(ControlFlow::Break), + } + } + + match a.try_for_each(compare(&mut b, f)) { + ControlFlow::Continue(()) => ControlFlow::Continue(match b.next() { + None => Ordering::Equal, + Some(_) => Ordering::Less, + }), + ControlFlow::Break(x) => x, + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl Iterator for &mut I { type Item = I::Item; From 6e83da1a2d2332c6a68f83200067d3a7897b73e8 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 22 Aug 2022 04:15:05 +0000 Subject: [PATCH 021/586] Don't drop parent substs when we have no generic parameters --- compiler/rustc_typeck/src/astconv/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs index 5bb02bc246caf..6bd38c36c2c1b 100644 --- a/compiler/rustc_typeck/src/astconv/mod.rs +++ b/compiler/rustc_typeck/src/astconv/mod.rs @@ -365,7 +365,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // here and so associated type bindings will be handled regardless of whether there are any // non-`Self` generic parameters. if generics.params.is_empty() { - return (tcx.intern_substs(&[]), arg_count); + return (tcx.intern_substs(parent_substs), arg_count); } struct SubstsForAstPathCtxt<'a, 'tcx> { From 102c61f11076d4cd71a117c358f4bdf93054d08e Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 22 Aug 2022 04:28:40 +0000 Subject: [PATCH 022/586] Simplify create_substs_for_associated_item --- compiler/rustc_typeck/src/astconv/mod.rs | 29 +++++++----------- .../rustc_typeck/src/check/fn_ctxt/mod.rs | 1 - compiler/rustc_typeck/src/collect.rs | 1 - .../ui/structs/struct-path-associated-type.rs | 4 +-- .../struct-path-associated-type.stderr | 30 +++++++++++++------ 5 files changed, 33 insertions(+), 32 deletions(-) diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs index 6bd38c36c2c1b..7cedec8987a57 100644 --- a/compiler/rustc_typeck/src/astconv/mod.rs +++ b/compiler/rustc_typeck/src/astconv/mod.rs @@ -591,7 +591,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { pub(crate) fn create_substs_for_associated_item( &self, - tcx: TyCtxt<'tcx>, span: Span, item_def_id: DefId, item_segment: &hir::PathSegment<'_>, @@ -601,22 +600,16 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { "create_substs_for_associated_item(span: {:?}, item_def_id: {:?}, item_segment: {:?}", span, item_def_id, item_segment ); - if tcx.generics_of(item_def_id).params.is_empty() { - self.prohibit_generics(slice::from_ref(item_segment).iter(), |_| {}); - - parent_substs - } else { - self.create_substs_for_ast_path( - span, - item_def_id, - parent_substs, - item_segment, - item_segment.args(), - item_segment.infer_args, - None, - ) - .0 - } + self.create_substs_for_ast_path( + span, + item_def_id, + parent_substs, + item_segment, + item_segment.args(), + item_segment.infer_args, + None, + ) + .0 } /// Instantiates the path for the given trait reference, assuming that it's @@ -1129,7 +1122,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { }; let substs_trait_ref_and_assoc_item = self.create_substs_for_associated_item( - tcx, path_span, assoc_item.def_id, &item_segment, @@ -2105,7 +2097,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { self.ast_path_to_mono_trait_ref(span, trait_def_id, self_ty, trait_segment, false); let item_substs = self.create_substs_for_associated_item( - tcx, span, item_def_id, item_segment, diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/mod.rs b/compiler/rustc_typeck/src/check/fn_ctxt/mod.rs index e008d50aa514a..62a61075231aa 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/mod.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/mod.rs @@ -279,7 +279,6 @@ impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> { let item_substs = >::create_substs_for_associated_item( self, - self.tcx, span, item_def_id, item_segment, diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index 970b39dc845af..1048f8b1475ee 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -430,7 +430,6 @@ impl<'tcx> AstConv<'tcx> for ItemCtxt<'tcx> { if let Some(trait_ref) = poly_trait_ref.no_bound_vars() { let item_substs = >::create_substs_for_associated_item( self, - self.tcx, span, item_def_id, item_segment, diff --git a/src/test/ui/structs/struct-path-associated-type.rs b/src/test/ui/structs/struct-path-associated-type.rs index f88572f8419c0..2dd7174a9bed8 100644 --- a/src/test/ui/structs/struct-path-associated-type.rs +++ b/src/test/ui/structs/struct-path-associated-type.rs @@ -13,7 +13,7 @@ fn f() { //~^ ERROR expected struct, variant or union type, found associated type let z = T::A:: {}; //~^ ERROR expected struct, variant or union type, found associated type - //~| ERROR type arguments are not allowed on this type + //~| ERROR this associated type takes 0 generic arguments but 1 generic argument was supplied match S { T::A {} => {} //~^ ERROR expected struct, variant or union type, found associated type @@ -22,7 +22,7 @@ fn f() { fn g>() { let s = T::A {}; // OK - let z = T::A:: {}; //~ ERROR type arguments are not allowed on this type + let z = T::A:: {}; //~ ERROR this associated type takes 0 generic arguments but 1 generic argument was supplied match S { T::A {} => {} // OK } diff --git a/src/test/ui/structs/struct-path-associated-type.stderr b/src/test/ui/structs/struct-path-associated-type.stderr index bdce0e1b331b8..abb445214f362 100644 --- a/src/test/ui/structs/struct-path-associated-type.stderr +++ b/src/test/ui/structs/struct-path-associated-type.stderr @@ -4,13 +4,19 @@ error[E0071]: expected struct, variant or union type, found associated type LL | let s = T::A {}; | ^^^^ not a struct -error[E0109]: type arguments are not allowed on this type - --> $DIR/struct-path-associated-type.rs:14:20 +error[E0107]: this associated type takes 0 generic arguments but 1 generic argument was supplied + --> $DIR/struct-path-associated-type.rs:14:16 | LL | let z = T::A:: {}; - | - ^^ type argument not allowed + | ^------ help: remove these generics | | - | not allowed on this type + | expected 0 generic arguments + | +note: associated type defined here, with 0 generic parameters + --> $DIR/struct-path-associated-type.rs:4:10 + | +LL | type A; + | ^ error[E0071]: expected struct, variant or union type, found associated type --> $DIR/struct-path-associated-type.rs:14:13 @@ -24,13 +30,19 @@ error[E0071]: expected struct, variant or union type, found associated type LL | T::A {} => {} | ^^^^ not a struct -error[E0109]: type arguments are not allowed on this type - --> $DIR/struct-path-associated-type.rs:25:20 +error[E0107]: this associated type takes 0 generic arguments but 1 generic argument was supplied + --> $DIR/struct-path-associated-type.rs:25:16 | LL | let z = T::A:: {}; - | - ^^ type argument not allowed + | ^------ help: remove these generics | | - | not allowed on this type + | expected 0 generic arguments + | +note: associated type defined here, with 0 generic parameters + --> $DIR/struct-path-associated-type.rs:4:10 + | +LL | type A; + | ^ error[E0223]: ambiguous associated type --> $DIR/struct-path-associated-type.rs:32:13 @@ -52,5 +64,5 @@ LL | S::A {} => {} error: aborting due to 8 previous errors -Some errors have detailed explanations: E0071, E0109, E0223. +Some errors have detailed explanations: E0071, E0107, E0223. For more information about an error, try `rustc --explain E0071`. From dbcc4095560a3ddcbdfe3359641b4da00634dcde Mon Sep 17 00:00:00 2001 From: Matthew Kelly Date: Tue, 23 Aug 2022 05:19:04 -0400 Subject: [PATCH 023/586] Improve E0311.md description --- .../src/error_codes/E0311.md | 37 +++++++++++++++---- 1 file changed, 29 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_error_codes/src/error_codes/E0311.md b/compiler/rustc_error_codes/src/error_codes/E0311.md index 9477a0b1fb76a..00b23c420529f 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0311.md +++ b/compiler/rustc_error_codes/src/error_codes/E0311.md @@ -21,14 +21,35 @@ where } ``` -In this example we have a trait that borrows some inner data element of type `V` -from an outer type `T`, through an intermediate type `U`. The compiler is unable -to prove that the livetime of `U` is long enough to support the reference. To -fix the issue we can explicitly add lifetime specifiers to the `NestedBorrowMut` -trait, which link the lifetimes of the various data types and allow the code to -compile. - -Working implementation of the `NestedBorrowMut` trait: +Why doesn't this code compile? The problem has to do with Rust's rules for +lifetime elision in functions (Chapter 10.3 in the Rust book). One of the +inputs is a reference to `self`, so the compiler attempts to assign the +the same lifetime to the `&mut self` input and `&mut V` output to the +`nested_borrow_mut()` function. The problem is that there is no way for the +compiler to directly figure out how these two lifetimes are related in the +implementation of the function. We're implementing the `NextedBorrowMut` +trait for a type `T`, so the `&mut self` reference has the lifetime of `T`. +We know that `T` implements the `BorrowMut` trait returning a reference to `U`, +and that `U` implements the `BorrowMut` trait returning a reference to `V`. +The key is that we have not told the compiler that those two `U` lifetimes +are the same: for all it knows, we could be that the first `BorrowMut` trait +on `T` works with a lifetime `'a` and the second `BorrowMut` trait on `U` +works on a lifetime `'b`. + +The fix here is to add explicit lifetime annotations that tell the compiler +that the lifetime of the output is in fact the same as the lifetime of the +input (`self`). There are three references involved, to objects of type `T` +(`self`), `U` (the intermediate type), and `V` (the return type). In the +working code below, we see that all have been given the same lifetime `'a`: +- `&'a mut self` in the function argument list for `T` +- `U: BorrowMut + 'a` in the trait bounds for `U` +- `&'a mut V` in the function return for `V`. + +The compiler can the check that the implementation of the +`nested_borrow_mut()` function satisfies these lifetimes. There are two +functions being called inside of `nested_borrow_mut()`, both of which are +the `borrow_mut()` function, which promises that the output lifetime is +the same as the input lifetime (see lifetime elision rules), which checks out. ``` use std::borrow::BorrowMut; From 231e3a041512027b13c87b07fe2a22c89b290adb Mon Sep 17 00:00:00 2001 From: Matthew Kelly Date: Tue, 23 Aug 2022 05:26:47 -0400 Subject: [PATCH 024/586] actually fix typo this time --- compiler/rustc_error_codes/src/error_codes/E0311.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_error_codes/src/error_codes/E0311.md b/compiler/rustc_error_codes/src/error_codes/E0311.md index 00b23c420529f..e73d5f16f9bf3 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0311.md +++ b/compiler/rustc_error_codes/src/error_codes/E0311.md @@ -1,5 +1,5 @@ This error occurs when there is insufficient information for the rust compiler -to prove that some time has a long enough lifetime. +to prove that a type has a long enough lifetime. Erroneous code example: From dd7c48e52937dade956379f3faf7a1bff1b95a5f Mon Sep 17 00:00:00 2001 From: Matthew Kelly Date: Wed, 24 Aug 2022 20:44:09 -0400 Subject: [PATCH 025/586] Improve description again -- update summary based on review -- rewrite explanation to be more clear and correct --- .../src/error_codes/E0311.md | 73 ++++++++++--------- src/test/ui/error-codes/E0311.rs | 3 +- src/test/ui/error-codes/E0311.stderr | 12 +-- 3 files changed, 47 insertions(+), 41 deletions(-) diff --git a/compiler/rustc_error_codes/src/error_codes/E0311.md b/compiler/rustc_error_codes/src/error_codes/E0311.md index e73d5f16f9bf3..a9d44dcdcee82 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0311.md +++ b/compiler/rustc_error_codes/src/error_codes/E0311.md @@ -1,5 +1,5 @@ -This error occurs when there is insufficient information for the rust compiler -to prove that a type has a long enough lifetime. +This error occurs when there is an unsatisfied outlives bound on a generic +type parameter or associated type. Erroneous code example: @@ -13,58 +13,63 @@ trait NestedBorrowMut { impl NestedBorrowMut for T where T: BorrowMut, - U: BorrowMut, // error: missing lifetime specifier + U: BorrowMut, { fn nested_borrow_mut(&mut self) -> &mut V { - self.borrow_mut().borrow_mut() + let u_ref = self.borrow_mut(); + let v_ref = u_ref.borrow_mut(); + v_ref } } ``` -Why doesn't this code compile? The problem has to do with Rust's rules for -lifetime elision in functions (Chapter 10.3 in the Rust book). One of the -inputs is a reference to `self`, so the compiler attempts to assign the -the same lifetime to the `&mut self` input and `&mut V` output to the -`nested_borrow_mut()` function. The problem is that there is no way for the -compiler to directly figure out how these two lifetimes are related in the -implementation of the function. We're implementing the `NextedBorrowMut` -trait for a type `T`, so the `&mut self` reference has the lifetime of `T`. -We know that `T` implements the `BorrowMut` trait returning a reference to `U`, -and that `U` implements the `BorrowMut` trait returning a reference to `V`. -The key is that we have not told the compiler that those two `U` lifetimes -are the same: for all it knows, we could be that the first `BorrowMut` trait -on `T` works with a lifetime `'a` and the second `BorrowMut` trait on `U` -works on a lifetime `'b`. +Why doesn't this code compile? It helps to look at the lifetime bounds that +the compiler is automatically adding ("Lifetime Ellision", Chapter 10.3 in the +Rust book) to the `nested_borrow_mut` and `borrow_mut` functions. In both cases +the input is a reference to `self`, so the compiler attempts to assign the +the same lifetime to the input and output. -The fix here is to add explicit lifetime annotations that tell the compiler -that the lifetime of the output is in fact the same as the lifetime of the -input (`self`). There are three references involved, to objects of type `T` -(`self`), `U` (the intermediate type), and `V` (the return type). In the -working code below, we see that all have been given the same lifetime `'a`: -- `&'a mut self` in the function argument list for `T` -- `U: BorrowMut + 'a` in the trait bounds for `U` -- `&'a mut V` in the function return for `V`. +Looking specifically at `nested_borrow_mut`, +we see that there are three object references to keep track of, +along with their associated lifetimes: +- `self` (which is a `&mut T`) +- `u_ref` (which is a `&mut U`) +- `v_ref` (which is a `&mut V`) -The compiler can the check that the implementation of the -`nested_borrow_mut()` function satisfies these lifetimes. There are two -functions being called inside of `nested_borrow_mut()`, both of which are -the `borrow_mut()` function, which promises that the output lifetime is -the same as the input lifetime (see lifetime elision rules), which checks out. +The `borrow_mut()` method implicitly requires that that the input and output +have the same lifetime bounds. Thus: +```rust + let u_ref = self.borrow_mut(); + let v_ref = u_ref.borrow_mut(); ``` + +Imply that `u_ref` and `self` must share a lifetime bound, and also that +`v_ref` and `u_ref` share a lifetime bound. The problem is that the function +signature for `nested_borrow_mut` only gives the compiler information about the +lifetimes of `self` and `v_ref` -- nothing about `u_ref`. + +The way to fix this error is then to explicitly tell the compiler that the +lifetime of `u_ref` is the same as `self` and `v_ref`, which then allows it +to satisfy the two lifetime bound requirements described above. + +Here is the working version of the code: +```rust use std::borrow::BorrowMut; trait NestedBorrowMut<'a, U, V> { - fn nested_borrow_mut(& 'a mut self) -> &'a mut V; + fn nested_borrow_mut(&'a mut self) -> &'a mut V; } impl<'a, T, U, V> NestedBorrowMut<'a, U, V> for T where T: BorrowMut, - U: BorrowMut + 'a, // Adding lifetime specifier + U: BorrowMut + 'a, { fn nested_borrow_mut(&'a mut self) -> &'a mut V { - self.borrow_mut().borrow_mut() + let u_ref = self.borrow_mut(); + let v_ref = u_ref.borrow_mut(); + v_ref } } ``` diff --git a/src/test/ui/error-codes/E0311.rs b/src/test/ui/error-codes/E0311.rs index eb9a473e9a2d1..95f8602306cde 100644 --- a/src/test/ui/error-codes/E0311.rs +++ b/src/test/ui/error-codes/E0311.rs @@ -11,7 +11,8 @@ where { fn nested_borrow_mut(&mut self) -> &mut V { let u_ref = self.borrow_mut(); //~ ERROR E0311 - u_ref.borrow_mut() //~ ERROR E0311 + let v_ref = u_ref.borrow_mut(); //~ ERROR E0311 + v_ref } } diff --git a/src/test/ui/error-codes/E0311.stderr b/src/test/ui/error-codes/E0311.stderr index a219a6352adc8..2cf6404f2f1c0 100644 --- a/src/test/ui/error-codes/E0311.stderr +++ b/src/test/ui/error-codes/E0311.stderr @@ -20,10 +20,10 @@ LL | U: BorrowMut + 'a, // Error is caused by missing lifetime here | ++++ error[E0311]: the parameter type `U` may not live long enough - --> $DIR/E0311.rs:14:9 + --> $DIR/E0311.rs:14:21 | -LL | u_ref.borrow_mut() - | ^^^^^^^^^^^^^^^^^^ +LL | let v_ref = u_ref.borrow_mut(); + | ^^^^^^^^^^^^^^^^^^ | note: the parameter type `U` must be valid for the anonymous lifetime defined here... --> $DIR/E0311.rs:12:26 @@ -31,10 +31,10 @@ note: the parameter type `U` must be valid for the anonymous lifetime defined he LL | fn nested_borrow_mut(&mut self) -> &mut V { | ^^^^^^^^^ note: ...so that the type `U` will meet its required lifetime bounds - --> $DIR/E0311.rs:14:9 + --> $DIR/E0311.rs:14:21 | -LL | u_ref.borrow_mut() - | ^^^^^^^^^^^^^^^^^^ +LL | let v_ref = u_ref.borrow_mut(); + | ^^^^^^^^^^^^^^^^^^ help: consider adding an explicit lifetime bound... | LL | U: BorrowMut + 'a, // Error is caused by missing lifetime here From fc02eee8f6b433c8485086d3e97ae499b53b240b Mon Sep 17 00:00:00 2001 From: Matthew Kelly Date: Wed, 24 Aug 2022 20:50:02 -0400 Subject: [PATCH 026/586] fix wrapping --- compiler/rustc_error_codes/src/error_codes/E0311.md | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_error_codes/src/error_codes/E0311.md b/compiler/rustc_error_codes/src/error_codes/E0311.md index a9d44dcdcee82..9521adc252225 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0311.md +++ b/compiler/rustc_error_codes/src/error_codes/E0311.md @@ -29,22 +29,21 @@ Rust book) to the `nested_borrow_mut` and `borrow_mut` functions. In both cases the input is a reference to `self`, so the compiler attempts to assign the the same lifetime to the input and output. -Looking specifically at `nested_borrow_mut`, -we see that there are three object references to keep track of, -along with their associated lifetimes: +Looking specifically at `nested_borrow_mut`, we see that there are three object +references to keep track of, along with their associated lifetimes: - `self` (which is a `&mut T`) - `u_ref` (which is a `&mut U`) - `v_ref` (which is a `&mut V`) The `borrow_mut()` method implicitly requires that that the input and output -have the same lifetime bounds. Thus: +have the same lifetime bounds. Thus the lines: ```rust let u_ref = self.borrow_mut(); let v_ref = u_ref.borrow_mut(); ``` -Imply that `u_ref` and `self` must share a lifetime bound, and also that +imply that `u_ref` and `self` must share a lifetime bound, and also that `v_ref` and `u_ref` share a lifetime bound. The problem is that the function signature for `nested_borrow_mut` only gives the compiler information about the lifetimes of `self` and `v_ref` -- nothing about `u_ref`. From 4f194a76c8482ffcd16526a08b1dc489a5a75e96 Mon Sep 17 00:00:00 2001 From: Matthew Kelly Date: Thu, 25 Aug 2022 05:43:59 -0400 Subject: [PATCH 027/586] Fix rust-doc error There was a partial rust code block in the readme that was invalid because of a missing line. I inlined the code snippet into the text to fix the error. This also improves readability a bit. --- .../src/error_codes/E0311.md | 27 ++++++++----------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/compiler/rustc_error_codes/src/error_codes/E0311.md b/compiler/rustc_error_codes/src/error_codes/E0311.md index 9521adc252225..f8c04d54db70a 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0311.md +++ b/compiler/rustc_error_codes/src/error_codes/E0311.md @@ -25,35 +25,30 @@ where Why doesn't this code compile? It helps to look at the lifetime bounds that the compiler is automatically adding ("Lifetime Ellision", Chapter 10.3 in the -Rust book) to the `nested_borrow_mut` and `borrow_mut` functions. In both cases -the input is a reference to `self`, so the compiler attempts to assign the +Rust book) to the `nested_borrow_mut()` and `borrow_mut()` functions. In both +cases the input is a reference to `self`, so the compiler attempts to assign the same lifetime to the input and output. -Looking specifically at `nested_borrow_mut`, we see that there are three object -references to keep track of, along with their associated lifetimes: +Looking specifically at `nested_borrow_mut()`, we see that there are three +object references to keep track of, along with their associated lifetimes: - `self` (which is a `&mut T`) - `u_ref` (which is a `&mut U`) - `v_ref` (which is a `&mut V`) The `borrow_mut()` method implicitly requires that that the input and output -have the same lifetime bounds. Thus the lines: - -```rust - let u_ref = self.borrow_mut(); - let v_ref = u_ref.borrow_mut(); -``` - -imply that `u_ref` and `self` must share a lifetime bound, and also that -`v_ref` and `u_ref` share a lifetime bound. The problem is that the function -signature for `nested_borrow_mut` only gives the compiler information about the -lifetimes of `self` and `v_ref` -- nothing about `u_ref`. +have the same lifetime bounds. Thus the lines: `let u_ref = self.borrow_mut();` +and `let v_ref = u_ref.borrow_mut();` in `nested_borrow_mut()` above imply that +`u_ref` and `self` must share a lifetime bound, and also that `v_ref` and +`u_ref` share a lifetime bound. The problem is that the function signature for +`nested_borrow_mut()` only gives the compiler information about the lifetimes +of `self` and `v_ref` -- nothing about `u_ref`. The way to fix this error is then to explicitly tell the compiler that the lifetime of `u_ref` is the same as `self` and `v_ref`, which then allows it to satisfy the two lifetime bound requirements described above. Here is the working version of the code: -```rust +``` use std::borrow::BorrowMut; trait NestedBorrowMut<'a, U, V> { From de3e95b56c3c1af339a6c13dc8875599e553aa98 Mon Sep 17 00:00:00 2001 From: Matthew Kelly Date: Fri, 26 Aug 2022 15:01:49 -0400 Subject: [PATCH 028/586] Review updates: simpler MWE and docs - use the simpler minimum working example from the review - add an alterate "fix" that helps make the cause of the error more clear - attempt to add an improved description of what is going on --- .../src/error_codes/E0311.md | 83 ++++++++----------- src/test/ui/error-codes/E0311.rs | 18 +--- src/test/ui/error-codes/E0311.stderr | 51 ++++-------- 3 files changed, 52 insertions(+), 100 deletions(-) diff --git a/compiler/rustc_error_codes/src/error_codes/E0311.md b/compiler/rustc_error_codes/src/error_codes/E0311.md index f8c04d54db70a..b1fa61d365c73 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0311.md +++ b/compiler/rustc_error_codes/src/error_codes/E0311.md @@ -1,69 +1,52 @@ -This error occurs when there is an unsatisfied outlives bound on a generic -type parameter or associated type. +This error occurs when there is an unsatisfied outlives bound involving an +elided region on a generic type parameter or associated type. Erroneous code example: ```compile_fail,E0311 -use std::borrow::BorrowMut; - -trait NestedBorrowMut { - fn nested_borrow_mut(&mut self) -> &mut V; +fn no_restriction(x: &()) -> &() { + with_restriction::(x) } -impl NestedBorrowMut for T -where - T: BorrowMut, - U: BorrowMut, -{ - fn nested_borrow_mut(&mut self) -> &mut V { - let u_ref = self.borrow_mut(); - let v_ref = u_ref.borrow_mut(); - v_ref - } +fn with_restriction<'a, T: 'a>(x: &'a ()) -> &'a () { + x } ``` -Why doesn't this code compile? It helps to look at the lifetime bounds that -the compiler is automatically adding ("Lifetime Ellision", Chapter 10.3 in the -Rust book) to the `nested_borrow_mut()` and `borrow_mut()` functions. In both -cases the input is a reference to `self`, so the compiler attempts to assign -the same lifetime to the input and output. +Why doesn't this code compile? It helps to look at the lifetime bounds that are +automatically adding by the compiler. For more details see the Rust +Documentation for Lifetime Elision: +https://doc.rust-lang.org/reference/lifetime-elision.html] -Looking specifically at `nested_borrow_mut()`, we see that there are three -object references to keep track of, along with their associated lifetimes: -- `self` (which is a `&mut T`) -- `u_ref` (which is a `&mut U`) -- `v_ref` (which is a `&mut V`) +There are two lifetimes being passed into the `no_restriction()` function: one +associated with the generic type `T` parameter and the other with the input +argument `x`. The compiler does not know which of these lifetimes can be +assigned to the output reference, so we get an error. -The `borrow_mut()` method implicitly requires that that the input and output -have the same lifetime bounds. Thus the lines: `let u_ref = self.borrow_mut();` -and `let v_ref = u_ref.borrow_mut();` in `nested_borrow_mut()` above imply that -`u_ref` and `self` must share a lifetime bound, and also that `v_ref` and -`u_ref` share a lifetime bound. The problem is that the function signature for -`nested_borrow_mut()` only gives the compiler information about the lifetimes -of `self` and `v_ref` -- nothing about `u_ref`. +One way to "fix" this code would be to remove the generic type argument `T`. +In this case, the lifetime elision works because there is a single input +lifetime, which is associated with `x`. -The way to fix this error is then to explicitly tell the compiler that the -lifetime of `u_ref` is the same as `self` and `v_ref`, which then allows it -to satisfy the two lifetime bound requirements described above. +``` +fn no_restriction(x: &()) -> &() { + with_restriction(x) +} -Here is the working version of the code: +fn with_restriction<'a>(x: &'a ()) -> &'a () { + x +} ``` -use std::borrow::BorrowMut; -trait NestedBorrowMut<'a, U, V> { - fn nested_borrow_mut(&'a mut self) -> &'a mut V; +The "correct" way to resolve this error is to explicitly tell the compiler +which input lifetime should be assigned to the output. In this case we give +both the generic type `T` parameter and the argument `x` the same lifetime +requirement as the output reference, producing a working version of the code: +``` +fn no_restriction<'a, T: 'a>(x: &'a ()) -> &'a () { + with_restriction::(x) } -impl<'a, T, U, V> NestedBorrowMut<'a, U, V> for T -where - T: BorrowMut, - U: BorrowMut + 'a, -{ - fn nested_borrow_mut(&'a mut self) -> &'a mut V { - let u_ref = self.borrow_mut(); - let v_ref = u_ref.borrow_mut(); - v_ref - } +fn with_restriction<'a, T: 'a>(x: &'a ()) -> &'a () { + x } ``` diff --git a/src/test/ui/error-codes/E0311.rs b/src/test/ui/error-codes/E0311.rs index 95f8602306cde..566b518b4331d 100644 --- a/src/test/ui/error-codes/E0311.rs +++ b/src/test/ui/error-codes/E0311.rs @@ -1,19 +1,9 @@ -use std::borrow::BorrowMut; - -trait NestedBorrowMut { - fn nested_borrow_mut(&mut self) -> &mut V; +fn no_restriction(x: &()) -> &() { + with_restriction::(x) //~ ERROR E0311 } -impl NestedBorrowMut for T -where - T: BorrowMut, - U: BorrowMut, // Error is caused by missing lifetime here -{ - fn nested_borrow_mut(&mut self) -> &mut V { - let u_ref = self.borrow_mut(); //~ ERROR E0311 - let v_ref = u_ref.borrow_mut(); //~ ERROR E0311 - v_ref - } +fn with_restriction<'a, T: 'a>(x: &'a ()) -> &'a () { + x } fn main() {} diff --git a/src/test/ui/error-codes/E0311.stderr b/src/test/ui/error-codes/E0311.stderr index 2cf6404f2f1c0..bc0182555af86 100644 --- a/src/test/ui/error-codes/E0311.stderr +++ b/src/test/ui/error-codes/E0311.stderr @@ -1,45 +1,24 @@ -error[E0311]: the parameter type `U` may not live long enough - --> $DIR/E0311.rs:13:21 +error[E0311]: the parameter type `T` may not live long enough + --> $DIR/E0311.rs:2:5 | -LL | let u_ref = self.borrow_mut(); - | ^^^^^^^^^^^^^^^^^ +LL | with_restriction::(x) + | ^^^^^^^^^^^^^^^^^^^^^ | -note: the parameter type `U` must be valid for the anonymous lifetime defined here... - --> $DIR/E0311.rs:12:26 +note: the parameter type `T` must be valid for the anonymous lifetime defined here... + --> $DIR/E0311.rs:1:25 | -LL | fn nested_borrow_mut(&mut self) -> &mut V { - | ^^^^^^^^^ -note: ...so that the type `U` will meet its required lifetime bounds - --> $DIR/E0311.rs:13:21 +LL | fn no_restriction(x: &()) -> &() { + | ^^^ +note: ...so that the type `T` will meet its required lifetime bounds + --> $DIR/E0311.rs:2:5 | -LL | let u_ref = self.borrow_mut(); - | ^^^^^^^^^^^^^^^^^ +LL | with_restriction::(x) + | ^^^^^^^^^^^^^^^^^^^^^ help: consider adding an explicit lifetime bound... | -LL | U: BorrowMut + 'a, // Error is caused by missing lifetime here - | ++++ +LL | fn no_restriction(x: &()) -> &() { + | ++++ -error[E0311]: the parameter type `U` may not live long enough - --> $DIR/E0311.rs:14:21 - | -LL | let v_ref = u_ref.borrow_mut(); - | ^^^^^^^^^^^^^^^^^^ - | -note: the parameter type `U` must be valid for the anonymous lifetime defined here... - --> $DIR/E0311.rs:12:26 - | -LL | fn nested_borrow_mut(&mut self) -> &mut V { - | ^^^^^^^^^ -note: ...so that the type `U` will meet its required lifetime bounds - --> $DIR/E0311.rs:14:21 - | -LL | let v_ref = u_ref.borrow_mut(); - | ^^^^^^^^^^^^^^^^^^ -help: consider adding an explicit lifetime bound... - | -LL | U: BorrowMut + 'a, // Error is caused by missing lifetime here - | ++++ - -error: aborting due to 2 previous errors +error: aborting due to previous error For more information about this error, try `rustc --explain E0311`. From deadf071edf4b397523739e41b6006ee278d5341 Mon Sep 17 00:00:00 2001 From: Matthew Kelly Date: Sat, 27 Aug 2022 14:36:17 -0400 Subject: [PATCH 029/586] fix trailing `]` --- compiler/rustc_error_codes/src/error_codes/E0311.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_error_codes/src/error_codes/E0311.md b/compiler/rustc_error_codes/src/error_codes/E0311.md index b1fa61d365c73..bc75a1f7f5e6a 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0311.md +++ b/compiler/rustc_error_codes/src/error_codes/E0311.md @@ -16,7 +16,7 @@ fn with_restriction<'a, T: 'a>(x: &'a ()) -> &'a () { Why doesn't this code compile? It helps to look at the lifetime bounds that are automatically adding by the compiler. For more details see the Rust Documentation for Lifetime Elision: -https://doc.rust-lang.org/reference/lifetime-elision.html] +https://doc.rust-lang.org/reference/lifetime-elision.html. There are two lifetimes being passed into the `no_restriction()` function: one associated with the generic type `T` parameter and the other with the input From 4a443dfb8227d407ff3f0542cb6e688833708ba9 Mon Sep 17 00:00:00 2001 From: Matthew Kelly Date: Mon, 29 Aug 2022 06:05:01 -0400 Subject: [PATCH 030/586] review updates to E0311 description --- .../src/error_codes/E0311.md | 38 ++++++++----------- 1 file changed, 15 insertions(+), 23 deletions(-) diff --git a/compiler/rustc_error_codes/src/error_codes/E0311.md b/compiler/rustc_error_codes/src/error_codes/E0311.md index bc75a1f7f5e6a..638c3e0a4373f 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0311.md +++ b/compiler/rustc_error_codes/src/error_codes/E0311.md @@ -14,33 +14,25 @@ fn with_restriction<'a, T: 'a>(x: &'a ()) -> &'a () { ``` Why doesn't this code compile? It helps to look at the lifetime bounds that are -automatically adding by the compiler. For more details see the Rust -Documentation for Lifetime Elision: -https://doc.rust-lang.org/reference/lifetime-elision.html. +automatically added by the compiler. For more details see the documentation for +[lifetime elision]( https://doc.rust-lang.org/reference/lifetime-elision.html). -There are two lifetimes being passed into the `no_restriction()` function: one -associated with the generic type `T` parameter and the other with the input -argument `x`. The compiler does not know which of these lifetimes can be -assigned to the output reference, so we get an error. +The compiler elides the lifetime of `x` and the return type to some arbitrary +lifetime `'anon` in `no_restriction()`. The only information available to the +compiler is that `'anon` is valid for the duration of the function. When +calling `with_restriction()`, the compiler requires the completely unrelated +type parameter `T` to outlive `'anon` because of the `T: 'a bound` in +`with_restriction()`. This causes an error because `T` is not required to +outlive `'anon` in `no_restriction()`. -One way to "fix" this code would be to remove the generic type argument `T`. -In this case, the lifetime elision works because there is a single input -lifetime, which is associated with `x`. +If `no_restriction()` were to use `&T` instead of `&()` as an argument, the +compiler would have added an implied bound [implied +bound](https://rust-lang.github.io/rfcs/2089-implied-bounds.html), causing this +to compile. -``` -fn no_restriction(x: &()) -> &() { - with_restriction(x) -} - -fn with_restriction<'a>(x: &'a ()) -> &'a () { - x -} -``` +This error can be resolved by explicitly naming the elided lifetime for `x` and +then explicily requiring that the generic parameter `T` outlives that lifetime: -The "correct" way to resolve this error is to explicitly tell the compiler -which input lifetime should be assigned to the output. In this case we give -both the generic type `T` parameter and the argument `x` the same lifetime -requirement as the output reference, producing a working version of the code: ``` fn no_restriction<'a, T: 'a>(x: &'a ()) -> &'a () { with_restriction::(x) From c846a2af8ddaa14ff2c2da25bc97bbd8d4284df2 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Tue, 14 Jun 2022 10:44:14 -0700 Subject: [PATCH 031/586] Make `std::os::fd` public. `std::os::fd` defines types like `OwnedFd` and `RawFd` and is common between Unix and non-Unix platforms that share a basic file-descriptor concept. Rust currently uses this internally to simplify its own code, but it would be useful for external users in the same way, so make it public. This means that `OwnedFd` etc. will all appear in three places, for example on unix platforms: - `std::os::fd::OwnedFd` - `std::os::unix::io::OwnedFd` - `std::os::unix::prelude::OwnedFd` --- library/std/src/os/fd/mod.rs | 14 ++++++++++++-- library/std/src/os/fd/owned.rs | 5 +---- library/std/src/os/fd/raw.rs | 15 +++------------ library/std/src/os/mod.rs | 2 +- library/std/src/os/unix/io/fd.rs | 8 -------- library/std/src/os/unix/io/mod.rs | 11 +++++------ library/std/src/os/unix/io/raw.rs | 6 ------ library/std/src/os/unix/io/{fd => }/tests.rs | 0 library/std/src/os/wasi/io/mod.rs | 8 +------- 9 files changed, 23 insertions(+), 46 deletions(-) delete mode 100644 library/std/src/os/unix/io/fd.rs delete mode 100644 library/std/src/os/unix/io/raw.rs rename library/std/src/os/unix/io/{fd => }/tests.rs (100%) diff --git a/library/std/src/os/fd/mod.rs b/library/std/src/os/fd/mod.rs index a456947534a45..8043d1a53d279 100644 --- a/library/std/src/os/fd/mod.rs +++ b/library/std/src/os/fd/mod.rs @@ -1,16 +1,26 @@ //! Owned and borrowed Unix-like file descriptors. +//! +//! This module is supported on Unix platforms, and also some non-Unix +//! platforms which use a similar file descriptor system for referencing OS +//! resources. #![stable(feature = "io_safety", since = "1.63.0")] #![deny(unsafe_op_in_unsafe_fn)] // `RawFd`, `AsRawFd`, etc. -pub mod raw; +mod raw; // `OwnedFd`, `AsFd`, etc. -pub mod owned; +mod owned; // Implementations for `AsRawFd` etc. for network types. mod net; #[cfg(test)] mod tests; + +// Export the types and traits for the public API. +#[stable(feature = "io_safety", since = "1.63.0")] +pub use owned::*; +#[stable(feature = "rust1", since = "1.0.0")] +pub use raw::*; diff --git a/library/std/src/os/fd/owned.rs b/library/std/src/os/fd/owned.rs index a463bc41db7aa..3a1b04a83fa79 100644 --- a/library/std/src/os/fd/owned.rs +++ b/library/std/src/os/fd/owned.rs @@ -205,10 +205,7 @@ pub trait AsFd { /// ```rust,no_run /// use std::fs::File; /// # use std::io; - /// # #[cfg(target_os = "wasi")] - /// # use std::os::wasi::io::{AsFd, BorrowedFd}; - /// # #[cfg(unix)] - /// # use std::os::unix::io::{AsFd, BorrowedFd}; + /// # use std::os::fd::{AsFd, BorrowedFd}; /// /// let mut f = File::open("foo.txt")?; /// # #[cfg(any(unix, target_os = "wasi"))] diff --git a/library/std/src/os/fd/raw.rs b/library/std/src/os/fd/raw.rs index 1b3d110426feb..42a9effcf92ab 100644 --- a/library/std/src/os/fd/raw.rs +++ b/library/std/src/os/fd/raw.rs @@ -42,10 +42,7 @@ pub trait AsRawFd { /// ```no_run /// use std::fs::File; /// # use std::io; - /// #[cfg(unix)] - /// use std::os::unix::io::{AsRawFd, RawFd}; - /// #[cfg(target_os = "wasi")] - /// use std::os::wasi::io::{AsRawFd, RawFd}; + /// use std::os::fd::{AsRawFd, RawFd}; /// /// let mut f = File::open("foo.txt")?; /// // Note that `raw_fd` is only valid as long as `f` exists. @@ -83,10 +80,7 @@ pub trait FromRawFd { /// ```no_run /// use std::fs::File; /// # use std::io; - /// #[cfg(unix)] - /// use std::os::unix::io::{FromRawFd, IntoRawFd, RawFd}; - /// #[cfg(target_os = "wasi")] - /// use std::os::wasi::io::{FromRawFd, IntoRawFd, RawFd}; + /// use std::os::fd::{FromRawFd, IntoRawFd, RawFd}; /// /// let f = File::open("foo.txt")?; /// # #[cfg(any(unix, target_os = "wasi"))] @@ -121,10 +115,7 @@ pub trait IntoRawFd { /// ```no_run /// use std::fs::File; /// # use std::io; - /// #[cfg(unix)] - /// use std::os::unix::io::{IntoRawFd, RawFd}; - /// #[cfg(target_os = "wasi")] - /// use std::os::wasi::io::{IntoRawFd, RawFd}; + /// use std::os::fd::{IntoRawFd, RawFd}; /// /// let f = File::open("foo.txt")?; /// #[cfg(any(unix, target_os = "wasi"))] diff --git a/library/std/src/os/mod.rs b/library/std/src/os/mod.rs index 18c64b5100764..f62f5af774f0e 100644 --- a/library/std/src/os/mod.rs +++ b/library/std/src/os/mod.rs @@ -147,7 +147,7 @@ pub mod solid; pub mod vxworks; #[cfg(any(unix, target_os = "wasi", doc))] -mod fd; +pub mod fd; #[cfg(any(target_os = "linux", target_os = "android", doc))] mod net; diff --git a/library/std/src/os/unix/io/fd.rs b/library/std/src/os/unix/io/fd.rs deleted file mode 100644 index d4cb696459b7e..0000000000000 --- a/library/std/src/os/unix/io/fd.rs +++ /dev/null @@ -1,8 +0,0 @@ -//! Owned and borrowed file descriptors. - -// Tests for this module -#[cfg(test)] -mod tests; - -#[stable(feature = "io_safety", since = "1.63.0")] -pub use crate::os::fd::owned::*; diff --git a/library/std/src/os/unix/io/mod.rs b/library/std/src/os/unix/io/mod.rs index 3ab5606f8897d..25b5dbff14f30 100644 --- a/library/std/src/os/unix/io/mod.rs +++ b/library/std/src/os/unix/io/mod.rs @@ -77,10 +77,9 @@ #![stable(feature = "rust1", since = "1.0.0")] -mod fd; -mod raw; - -#[stable(feature = "io_safety", since = "1.63.0")] -pub use fd::*; #[stable(feature = "rust1", since = "1.0.0")] -pub use raw::*; +pub use crate::os::fd::*; + +// Tests for this module +#[cfg(test)] +mod tests; diff --git a/library/std/src/os/unix/io/raw.rs b/library/std/src/os/unix/io/raw.rs deleted file mode 100644 index a4d2ba797d9c4..0000000000000 --- a/library/std/src/os/unix/io/raw.rs +++ /dev/null @@ -1,6 +0,0 @@ -//! Unix-specific extensions to general I/O primitives. - -#![stable(feature = "rust1", since = "1.0.0")] - -#[stable(feature = "rust1", since = "1.0.0")] -pub use crate::os::fd::raw::*; diff --git a/library/std/src/os/unix/io/fd/tests.rs b/library/std/src/os/unix/io/tests.rs similarity index 100% rename from library/std/src/os/unix/io/fd/tests.rs rename to library/std/src/os/unix/io/tests.rs diff --git a/library/std/src/os/wasi/io/mod.rs b/library/std/src/os/wasi/io/mod.rs index 6c884e2eaf471..d528590d75b9a 100644 --- a/library/std/src/os/wasi/io/mod.rs +++ b/library/std/src/os/wasi/io/mod.rs @@ -1,12 +1,6 @@ //! WASI-specific extensions to general I/O primitives. -#![deny(unsafe_op_in_unsafe_fn)] #![unstable(feature = "wasi_ext", issue = "71213")] -mod fd; -mod raw; - -#[unstable(feature = "wasi_ext", issue = "71213")] -pub use fd::*; #[unstable(feature = "wasi_ext", issue = "71213")] -pub use raw::*; +pub use crate::os::fd::*; From 09bbc4224f36e05245e63d1766364ea821c83cd3 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Tue, 21 Jun 2022 21:09:20 -0700 Subject: [PATCH 032/586] Update asrawfd.js. --- src/test/rustdoc-js-std/asrawfd.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/test/rustdoc-js-std/asrawfd.js b/src/test/rustdoc-js-std/asrawfd.js index fd228a59099e9..369a34f9c6eb7 100644 --- a/src/test/rustdoc-js-std/asrawfd.js +++ b/src/test/rustdoc-js-std/asrawfd.js @@ -6,9 +6,9 @@ const EXPECTED = { 'others': [ // Reproduction test for https://github.com/rust-lang/rust/issues/78724 // Validate that type alias methods get the correct path. - { 'path': 'std::os::unix::io::AsRawFd', 'name': 'as_raw_fd' }, - { 'path': 'std::os::wasi::io::AsRawFd', 'name': 'as_raw_fd' }, + { 'path': 'std::os::fd::AsRawFd', 'name': 'as_raw_fd' }, + { 'path': 'std::os::fd::AsRawFd', 'name': 'as_raw_fd' }, { 'path': 'std::os::linux::process::PidFd', 'name': 'as_raw_fd' }, - { 'path': 'std::os::unix::io::RawFd', 'name': 'as_raw_fd' }, + { 'path': 'std::os::fd::RawFd', 'name': 'as_raw_fd' }, ], }; From bda12629c3d0926c14b9fbe3f814972f8d50043c Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Wed, 29 Jun 2022 19:07:43 -0700 Subject: [PATCH 033/586] Clarify that the `fd` module is supported on Unix and WASI. --- library/std/src/os/fd/mod.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/library/std/src/os/fd/mod.rs b/library/std/src/os/fd/mod.rs index 8043d1a53d279..91dbe44878b1e 100644 --- a/library/std/src/os/fd/mod.rs +++ b/library/std/src/os/fd/mod.rs @@ -1,8 +1,7 @@ //! Owned and borrowed Unix-like file descriptors. //! -//! This module is supported on Unix platforms, and also some non-Unix -//! platforms which use a similar file descriptor system for referencing OS -//! resources. +//! This module is supported on Unix platforms and WASI, which both use a +//! similar file descriptor system for referencing OS resources. #![stable(feature = "io_safety", since = "1.63.0")] #![deny(unsafe_op_in_unsafe_fn)] From 7d80510c16bd2172427aff61e5d929aa695cdfa5 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Tue, 23 Aug 2022 11:57:13 -0700 Subject: [PATCH 034/586] Re-introduce `unstable` attributes. Add `#[unstable(feature = "os_fd", issue = "98699")]` to the new `pub use` declarations. --- library/std/src/os/fd/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/std/src/os/fd/mod.rs b/library/std/src/os/fd/mod.rs index 91dbe44878b1e..c6aa7c77dbc41 100644 --- a/library/std/src/os/fd/mod.rs +++ b/library/std/src/os/fd/mod.rs @@ -19,7 +19,7 @@ mod net; mod tests; // Export the types and traits for the public API. -#[stable(feature = "io_safety", since = "1.63.0")] +#[unstable(feature = "os_fd", issue = "98699")] pub use owned::*; -#[stable(feature = "rust1", since = "1.0.0")] +#[unstable(feature = "os_fd", issue = "98699")] pub use raw::*; From 5ed178741358db3258d804f332d82e497b7eb11a Mon Sep 17 00:00:00 2001 From: dAxpeDDa Date: Tue, 30 Aug 2022 11:21:07 +0200 Subject: [PATCH 035/586] Implement `Ready::into_inner()` --- library/core/src/future/ready.rs | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/library/core/src/future/ready.rs b/library/core/src/future/ready.rs index 48f20f90a3253..a07b63fb62b90 100644 --- a/library/core/src/future/ready.rs +++ b/library/core/src/future/ready.rs @@ -24,6 +24,30 @@ impl Future for Ready { } } +impl Ready { + /// Consumes the `Ready`, returning the wrapped value. + /// + /// # Panics + /// + /// Will panic if this [`Ready`] was already polled to completion. + /// + /// # Examples + /// + /// ``` + /// #![feature(ready_into_inner)] + /// use std::future; + /// + /// let a = future::ready(1); + /// assert_eq!(a.into_inner(), 1); + /// ``` + #[unstable(feature = "ready_into_inner", issue = "101196")] + #[must_use] + #[inline] + pub fn into_inner(self) -> T { + self.0.expect("Called `into_inner()` on `Ready` after completion") + } +} + /// Creates a future that is immediately ready with a value. /// /// Futures created through this function are functionally similar to those From a7f3ba9c135fff78728eb7790aae7907a7621922 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Fri, 2 Sep 2022 15:35:41 -0700 Subject: [PATCH 036/586] Fix compilation of the doc tests on Windows. --- library/std/src/os/fd/owned.rs | 1 + library/std/src/os/fd/raw.rs | 3 +++ 2 files changed, 4 insertions(+) diff --git a/library/std/src/os/fd/owned.rs b/library/std/src/os/fd/owned.rs index 3a1b04a83fa79..37250e6a0ae44 100644 --- a/library/std/src/os/fd/owned.rs +++ b/library/std/src/os/fd/owned.rs @@ -205,6 +205,7 @@ pub trait AsFd { /// ```rust,no_run /// use std::fs::File; /// # use std::io; + /// # #[cfg(any(unix, target_os = "wasi"))] /// # use std::os::fd::{AsFd, BorrowedFd}; /// /// let mut f = File::open("foo.txt")?; diff --git a/library/std/src/os/fd/raw.rs b/library/std/src/os/fd/raw.rs index 42a9effcf92ab..f92a05066706d 100644 --- a/library/std/src/os/fd/raw.rs +++ b/library/std/src/os/fd/raw.rs @@ -42,6 +42,7 @@ pub trait AsRawFd { /// ```no_run /// use std::fs::File; /// # use std::io; + /// #[cfg(any(unix, target_os = "wasi"))] /// use std::os::fd::{AsRawFd, RawFd}; /// /// let mut f = File::open("foo.txt")?; @@ -80,6 +81,7 @@ pub trait FromRawFd { /// ```no_run /// use std::fs::File; /// # use std::io; + /// #[cfg(any(unix, target_os = "wasi"))] /// use std::os::fd::{FromRawFd, IntoRawFd, RawFd}; /// /// let f = File::open("foo.txt")?; @@ -115,6 +117,7 @@ pub trait IntoRawFd { /// ```no_run /// use std::fs::File; /// # use std::io; + /// #[cfg(any(unix, target_os = "wasi"))] /// use std::os::fd::{IntoRawFd, RawFd}; /// /// let f = File::open("foo.txt")?; From a2cdbf89637cd38fa5f1badbbc26b049a14345dd Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Sun, 21 Aug 2022 02:06:41 +0400 Subject: [PATCH 037/586] Make code worling w/ pointers in `library/std/src/sys/sgx/abi/usercalls/alloc.rs` nicer - Use `.addr()` instead of `as`-cast - Use `add` instead of `offset` and remove some `as isize` casts by doing that - Remove some casts --- .../std/src/sys/sgx/abi/usercalls/alloc.rs | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/library/std/src/sys/sgx/abi/usercalls/alloc.rs b/library/std/src/sys/sgx/abi/usercalls/alloc.rs index 5409bd1777c2a..0d934318c22a4 100644 --- a/library/std/src/sys/sgx/abi/usercalls/alloc.rs +++ b/library/std/src/sys/sgx/abi/usercalls/alloc.rs @@ -316,9 +316,9 @@ where // | small1 | Chunk smaller than 8 bytes // +--------+ fn region_as_aligned_chunks(ptr: *const u8, len: usize) -> (usize, usize, usize) { - let small0_size = if ptr as usize % 8 == 0 { 0 } else { 8 - ptr as usize % 8 }; - let small1_size = (len - small0_size as usize) % 8; - let big_size = len - small0_size as usize - small1_size as usize; + let small0_size = if ptr.is_aligned_to(8) { 0 } else { 8 - ptr.addr() % 8 }; + let small1_size = (len - small0_size) % 8; + let big_size = len - small0_size - small1_size; (small0_size, big_size, small1_size) } @@ -364,8 +364,8 @@ pub(crate) unsafe fn copy_to_userspace(src: *const u8, dst: *mut u8, len: usize) mfence lfence ", - val = in(reg_byte) *src.offset(off as isize), - dst = in(reg) dst.offset(off as isize), + val = in(reg_byte) *src.add(off), + dst = in(reg) dst.add(off), seg_sel = in(reg) &mut seg_sel, options(nostack, att_syntax) ); @@ -378,8 +378,8 @@ pub(crate) unsafe fn copy_to_userspace(src: *const u8, dst: *mut u8, len: usize) assert!(is_enclave_range(src, len)); assert!(is_user_range(dst, len)); assert!(len < isize::MAX as usize); - assert!(!(src as usize).overflowing_add(len).1); - assert!(!(dst as usize).overflowing_add(len).1); + assert!(!src.addr().overflowing_add(len).1); + assert!(!dst.addr().overflowing_add(len).1); if len < 8 { // Can't align on 8 byte boundary: copy safely byte per byte @@ -404,17 +404,17 @@ pub(crate) unsafe fn copy_to_userspace(src: *const u8, dst: *mut u8, len: usize) unsafe { // Copy small0 - copy_bytewise_to_userspace(src, dst, small0_size as _); + copy_bytewise_to_userspace(src, dst, small0_size); // Copy big - let big_src = src.offset(small0_size as _); - let big_dst = dst.offset(small0_size as _); - copy_quadwords(big_src as _, big_dst, big_size); + let big_src = src.add(small0_size); + let big_dst = dst.add(small0_size); + copy_quadwords(big_src, big_dst, big_size); // Copy small1 - let small1_src = src.offset(big_size as isize + small0_size as isize); - let small1_dst = dst.offset(big_size as isize + small0_size as isize); - copy_bytewise_to_userspace(small1_src, small1_dst, small1_size as _); + let small1_src = src.add(big_size + small0_size); + let small1_dst = dst.add(big_size + small0_size); + copy_bytewise_to_userspace(small1_src, small1_dst, small1_size); } } } From 495fa48790fad465edcdb7965d349617854a86c3 Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Sun, 21 Aug 2022 02:16:51 +0400 Subject: [PATCH 038/586] use `pointer::add` in memchr impl --- library/core/src/slice/memchr.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/core/src/slice/memchr.rs b/library/core/src/slice/memchr.rs index dffeaf6a834e7..d8a4fd6c1ce02 100644 --- a/library/core/src/slice/memchr.rs +++ b/library/core/src/slice/memchr.rs @@ -124,8 +124,8 @@ pub fn memrchr(x: u8, text: &[u8]) -> Option { // SAFETY: offset starts at len - suffix.len(), as long as it is greater than // min_aligned_offset (prefix.len()) the remaining distance is at least 2 * chunk_bytes. unsafe { - let u = *(ptr.offset(offset as isize - 2 * chunk_bytes as isize) as *const Chunk); - let v = *(ptr.offset(offset as isize - chunk_bytes as isize) as *const Chunk); + let u = *(ptr.add(offset - 2 * chunk_bytes) as *const Chunk); + let v = *(ptr.add(offset - chunk_bytes) as *const Chunk); // Break if there is a matching byte. let zu = contains_zero_byte(u ^ repeated_x); From 31b71816cd66d53b544902f38b7043c773d3ecda Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Sun, 21 Aug 2022 02:18:16 +0400 Subject: [PATCH 039/586] Replace `offset` with `add` in `fmt/num.rs` & remove some casts --- library/core/src/fmt/num.rs | 124 ++++++++++++++++++------------------ 1 file changed, 62 insertions(+), 62 deletions(-) diff --git a/library/core/src/fmt/num.rs b/library/core/src/fmt/num.rs index 25789d37c2696..b11ed6b0b42ab 100644 --- a/library/core/src/fmt/num.rs +++ b/library/core/src/fmt/num.rs @@ -211,7 +211,7 @@ macro_rules! impl_Display { fn $name(mut n: $u, is_nonnegative: bool, f: &mut fmt::Formatter<'_>) -> fmt::Result { // 2^128 is about 3*10^38, so 39 gives an extra byte of space let mut buf = [MaybeUninit::::uninit(); 39]; - let mut curr = buf.len() as isize; + let mut curr = buf.len(); let buf_ptr = MaybeUninit::slice_as_mut_ptr(&mut buf); let lut_ptr = DEC_DIGITS_LUT.as_ptr(); @@ -228,7 +228,7 @@ macro_rules! impl_Display { // eagerly decode 4 characters at a time while n >= 10000 { - let rem = (n % 10000) as isize; + let rem = (n % 10000) as usize; n /= 10000; let d1 = (rem / 100) << 1; @@ -238,29 +238,29 @@ macro_rules! impl_Display { // We are allowed to copy to `buf_ptr[curr..curr + 3]` here since // otherwise `curr < 0`. But then `n` was originally at least `10000^10` // which is `10^40 > 2^128 > n`. - ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(curr), 2); - ptr::copy_nonoverlapping(lut_ptr.offset(d2), buf_ptr.offset(curr + 2), 2); + ptr::copy_nonoverlapping(lut_ptr.add(d1), buf_ptr.add(curr), 2); + ptr::copy_nonoverlapping(lut_ptr.add(d2), buf_ptr.add(curr + 2), 2); } // if we reach here numbers are <= 9999, so at most 4 chars long - let mut n = n as isize; // possibly reduce 64bit math + let mut n = n as usize; // possibly reduce 64bit math // decode 2 more chars, if > 2 chars if n >= 100 { let d1 = (n % 100) << 1; n /= 100; curr -= 2; - ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(curr), 2); + ptr::copy_nonoverlapping(lut_ptr.add(d1), buf_ptr.add(curr), 2); } // decode last 1 or 2 chars if n < 10 { curr -= 1; - *buf_ptr.offset(curr) = (n as u8) + b'0'; + *buf_ptr.add(curr) = (n as u8) + b'0'; } else { let d1 = n << 1; curr -= 2; - ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(curr), 2); + ptr::copy_nonoverlapping(lut_ptr.add(d1), buf_ptr.add(curr), 2); } } @@ -268,7 +268,7 @@ macro_rules! impl_Display { // UTF-8 since `DEC_DIGITS_LUT` is let buf_slice = unsafe { str::from_utf8_unchecked( - slice::from_raw_parts(buf_ptr.offset(curr), buf.len() - curr as usize)) + slice::from_raw_parts(buf_ptr.add(curr), buf.len() - curr)) }; f.pad_integral(is_nonnegative, "", buf_slice) } @@ -339,18 +339,18 @@ macro_rules! impl_Exp { // Since `curr` always decreases by the number of digits copied, this means // that `curr >= 0`. let mut buf = [MaybeUninit::::uninit(); 40]; - let mut curr = buf.len() as isize; //index for buf + let mut curr = buf.len(); //index for buf let buf_ptr = MaybeUninit::slice_as_mut_ptr(&mut buf); let lut_ptr = DEC_DIGITS_LUT.as_ptr(); // decode 2 chars at a time while n >= 100 { - let d1 = ((n % 100) as isize) << 1; + let d1 = ((n % 100) << 1) as usize; curr -= 2; // SAFETY: `d1 <= 198`, so we can copy from `lut_ptr[d1..d1 + 2]` since // `DEC_DIGITS_LUT` has a length of 200. unsafe { - ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(curr), 2); + ptr::copy_nonoverlapping(lut_ptr.add(d1), buf_ptr.add(curr), 2); } n /= 100; exponent += 2; @@ -362,7 +362,7 @@ macro_rules! impl_Exp { curr -= 1; // SAFETY: Safe since `40 > curr >= 0` (see comment) unsafe { - *buf_ptr.offset(curr) = (n as u8 % 10_u8) + b'0'; + *buf_ptr.add(curr) = (n as u8 % 10_u8) + b'0'; } n /= 10; exponent += 1; @@ -372,7 +372,7 @@ macro_rules! impl_Exp { curr -= 1; // SAFETY: Safe since `40 > curr >= 0` unsafe { - *buf_ptr.offset(curr) = b'.'; + *buf_ptr.add(curr) = b'.'; } } @@ -380,10 +380,10 @@ macro_rules! impl_Exp { let buf_slice = unsafe { // decode last character curr -= 1; - *buf_ptr.offset(curr) = (n as u8) + b'0'; + *buf_ptr.add(curr) = (n as u8) + b'0'; let len = buf.len() - curr as usize; - slice::from_raw_parts(buf_ptr.offset(curr), len) + slice::from_raw_parts(buf_ptr.add(curr), len) }; // stores 'e' (or 'E') and the up to 2-digit exponent @@ -392,13 +392,13 @@ macro_rules! impl_Exp { // SAFETY: In either case, `exp_buf` is written within bounds and `exp_ptr[..len]` // is contained within `exp_buf` since `len <= 3`. let exp_slice = unsafe { - *exp_ptr.offset(0) = if upper { b'E' } else { b'e' }; + *exp_ptr.add(0) = if upper { b'E' } else { b'e' }; let len = if exponent < 10 { - *exp_ptr.offset(1) = (exponent as u8) + b'0'; + *exp_ptr.add(1) = (exponent as u8) + b'0'; 2 } else { let off = exponent << 1; - ptr::copy_nonoverlapping(lut_ptr.offset(off), exp_ptr.offset(1), 2); + ptr::copy_nonoverlapping(lut_ptr.add(off), exp_ptr.add(1), 2); 3 }; slice::from_raw_parts(exp_ptr, len) @@ -479,7 +479,7 @@ mod imp { impl_Exp!(i128, u128 as u128 via to_u128 named exp_u128); /// Helper function for writing a u64 into `buf` going from last to first, with `curr`. -fn parse_u64_into(mut n: u64, buf: &mut [MaybeUninit; N], curr: &mut isize) { +fn parse_u64_into(mut n: u64, buf: &mut [MaybeUninit; N], curr: &mut usize) { let buf_ptr = MaybeUninit::slice_as_mut_ptr(buf); let lut_ptr = DEC_DIGITS_LUT.as_ptr(); assert!(*curr > 19); @@ -494,41 +494,41 @@ fn parse_u64_into(mut n: u64, buf: &mut [MaybeUninit; N], cu n /= 1e16 as u64; // Some of these are nops but it looks more elegant this way. - let d1 = ((to_parse / 1e14 as u64) % 100) << 1; - let d2 = ((to_parse / 1e12 as u64) % 100) << 1; - let d3 = ((to_parse / 1e10 as u64) % 100) << 1; - let d4 = ((to_parse / 1e8 as u64) % 100) << 1; - let d5 = ((to_parse / 1e6 as u64) % 100) << 1; - let d6 = ((to_parse / 1e4 as u64) % 100) << 1; - let d7 = ((to_parse / 1e2 as u64) % 100) << 1; - let d8 = ((to_parse / 1e0 as u64) % 100) << 1; + let d1 = (((to_parse / 1e14 as u64) % 100) << 1) as usize; + let d2 = (((to_parse / 1e12 as u64) % 100) << 1) as usize; + let d3 = (((to_parse / 1e10 as u64) % 100) << 1) as usize; + let d4 = (((to_parse / 1e8 as u64) % 100) << 1) as usize; + let d5 = (((to_parse / 1e6 as u64) % 100) << 1) as usize; + let d6 = (((to_parse / 1e4 as u64) % 100) << 1) as usize; + let d7 = (((to_parse / 1e2 as u64) % 100) << 1) as usize; + let d8 = (((to_parse / 1e0 as u64) % 100) << 1) as usize; *curr -= 16; - ptr::copy_nonoverlapping(lut_ptr.offset(d1 as isize), buf_ptr.offset(*curr + 0), 2); - ptr::copy_nonoverlapping(lut_ptr.offset(d2 as isize), buf_ptr.offset(*curr + 2), 2); - ptr::copy_nonoverlapping(lut_ptr.offset(d3 as isize), buf_ptr.offset(*curr + 4), 2); - ptr::copy_nonoverlapping(lut_ptr.offset(d4 as isize), buf_ptr.offset(*curr + 6), 2); - ptr::copy_nonoverlapping(lut_ptr.offset(d5 as isize), buf_ptr.offset(*curr + 8), 2); - ptr::copy_nonoverlapping(lut_ptr.offset(d6 as isize), buf_ptr.offset(*curr + 10), 2); - ptr::copy_nonoverlapping(lut_ptr.offset(d7 as isize), buf_ptr.offset(*curr + 12), 2); - ptr::copy_nonoverlapping(lut_ptr.offset(d8 as isize), buf_ptr.offset(*curr + 14), 2); + ptr::copy_nonoverlapping(lut_ptr.add(d1), buf_ptr.add(*curr + 0), 2); + ptr::copy_nonoverlapping(lut_ptr.add(d2), buf_ptr.add(*curr + 2), 2); + ptr::copy_nonoverlapping(lut_ptr.add(d3), buf_ptr.add(*curr + 4), 2); + ptr::copy_nonoverlapping(lut_ptr.add(d4), buf_ptr.add(*curr + 6), 2); + ptr::copy_nonoverlapping(lut_ptr.add(d5), buf_ptr.add(*curr + 8), 2); + ptr::copy_nonoverlapping(lut_ptr.add(d6), buf_ptr.add(*curr + 10), 2); + ptr::copy_nonoverlapping(lut_ptr.add(d7), buf_ptr.add(*curr + 12), 2); + ptr::copy_nonoverlapping(lut_ptr.add(d8), buf_ptr.add(*curr + 14), 2); } if n >= 1e8 as u64 { let to_parse = n % 1e8 as u64; n /= 1e8 as u64; // Some of these are nops but it looks more elegant this way. - let d1 = ((to_parse / 1e6 as u64) % 100) << 1; - let d2 = ((to_parse / 1e4 as u64) % 100) << 1; - let d3 = ((to_parse / 1e2 as u64) % 100) << 1; - let d4 = ((to_parse / 1e0 as u64) % 100) << 1; + let d1 = (((to_parse / 1e6 as u64) % 100) << 1) as usize; + let d2 = (((to_parse / 1e4 as u64) % 100) << 1) as usize; + let d3 = (((to_parse / 1e2 as u64) % 100) << 1) as usize; + let d4 = (((to_parse / 1e0 as u64) % 100) << 1) as usize; *curr -= 8; - ptr::copy_nonoverlapping(lut_ptr.offset(d1 as isize), buf_ptr.offset(*curr + 0), 2); - ptr::copy_nonoverlapping(lut_ptr.offset(d2 as isize), buf_ptr.offset(*curr + 2), 2); - ptr::copy_nonoverlapping(lut_ptr.offset(d3 as isize), buf_ptr.offset(*curr + 4), 2); - ptr::copy_nonoverlapping(lut_ptr.offset(d4 as isize), buf_ptr.offset(*curr + 6), 2); + ptr::copy_nonoverlapping(lut_ptr.add(d1), buf_ptr.add(*curr + 0), 2); + ptr::copy_nonoverlapping(lut_ptr.add(d2), buf_ptr.add(*curr + 2), 2); + ptr::copy_nonoverlapping(lut_ptr.add(d3), buf_ptr.add(*curr + 4), 2); + ptr::copy_nonoverlapping(lut_ptr.add(d4), buf_ptr.add(*curr + 6), 2); } // `n` < 1e8 < (1 << 32) let mut n = n as u32; @@ -536,31 +536,31 @@ fn parse_u64_into(mut n: u64, buf: &mut [MaybeUninit; N], cu let to_parse = n % 1e4 as u32; n /= 1e4 as u32; - let d1 = (to_parse / 100) << 1; - let d2 = (to_parse % 100) << 1; + let d1 = ((to_parse / 100) << 1) as usize; + let d2 = ((to_parse % 100) << 1) as usize; *curr -= 4; - ptr::copy_nonoverlapping(lut_ptr.offset(d1 as isize), buf_ptr.offset(*curr + 0), 2); - ptr::copy_nonoverlapping(lut_ptr.offset(d2 as isize), buf_ptr.offset(*curr + 2), 2); + ptr::copy_nonoverlapping(lut_ptr.add(d1), buf_ptr.add(*curr + 0), 2); + ptr::copy_nonoverlapping(lut_ptr.add(d2), buf_ptr.add(*curr + 2), 2); } // `n` < 1e4 < (1 << 16) let mut n = n as u16; if n >= 100 { - let d1 = (n % 100) << 1; + let d1 = ((n % 100) << 1) as usize; n /= 100; *curr -= 2; - ptr::copy_nonoverlapping(lut_ptr.offset(d1 as isize), buf_ptr.offset(*curr), 2); + ptr::copy_nonoverlapping(lut_ptr.add(d1), buf_ptr.add(*curr), 2); } // decode last 1 or 2 chars if n < 10 { *curr -= 1; - *buf_ptr.offset(*curr) = (n as u8) + b'0'; + *buf_ptr.add(*curr) = (n as u8) + b'0'; } else { - let d1 = n << 1; + let d1 = (n << 1) as usize; *curr -= 2; - ptr::copy_nonoverlapping(lut_ptr.offset(d1 as isize), buf_ptr.offset(*curr), 2); + ptr::copy_nonoverlapping(lut_ptr.add(d1), buf_ptr.add(*curr), 2); } } } @@ -593,21 +593,21 @@ impl fmt::Display for i128 { fn fmt_u128(n: u128, is_nonnegative: bool, f: &mut fmt::Formatter<'_>) -> fmt::Result { // 2^128 is about 3*10^38, so 39 gives an extra byte of space let mut buf = [MaybeUninit::::uninit(); 39]; - let mut curr = buf.len() as isize; + let mut curr = buf.len(); let (n, rem) = udiv_1e19(n); parse_u64_into(rem, &mut buf, &mut curr); if n != 0 { // 0 pad up to point - let target = (buf.len() - 19) as isize; + let target = buf.len() - 19; // SAFETY: Guaranteed that we wrote at most 19 bytes, and there must be space // remaining since it has length 39 unsafe { ptr::write_bytes( - MaybeUninit::slice_as_mut_ptr(&mut buf).offset(target), + MaybeUninit::slice_as_mut_ptr(&mut buf).add(target), b'0', - (curr - target) as usize, + curr - target, ); } curr = target; @@ -616,16 +616,16 @@ fn fmt_u128(n: u128, is_nonnegative: bool, f: &mut fmt::Formatter<'_>) -> fmt::R parse_u64_into(rem, &mut buf, &mut curr); // Should this following branch be annotated with unlikely? if n != 0 { - let target = (buf.len() - 38) as isize; + let target = buf.len() - 38; // The raw `buf_ptr` pointer is only valid until `buf` is used the next time, // buf `buf` is not used in this scope so we are good. let buf_ptr = MaybeUninit::slice_as_mut_ptr(&mut buf); // SAFETY: At this point we wrote at most 38 bytes, pad up to that point, // There can only be at most 1 digit remaining. unsafe { - ptr::write_bytes(buf_ptr.offset(target), b'0', (curr - target) as usize); + ptr::write_bytes(buf_ptr.add(target), b'0', curr - target); curr = target - 1; - *buf_ptr.offset(curr) = (n as u8) + b'0'; + *buf_ptr.add(curr) = (n as u8) + b'0'; } } } @@ -634,8 +634,8 @@ fn fmt_u128(n: u128, is_nonnegative: bool, f: &mut fmt::Formatter<'_>) -> fmt::R // UTF-8 since `DEC_DIGITS_LUT` is let buf_slice = unsafe { str::from_utf8_unchecked(slice::from_raw_parts( - MaybeUninit::slice_as_mut_ptr(&mut buf).offset(curr), - buf.len() - curr as usize, + MaybeUninit::slice_as_mut_ptr(&mut buf).add(curr), + buf.len() - curr, )) }; f.pad_integral(is_nonnegative, "", buf_slice) From 7e226e6d3f5dc5c39a222091f7a234c1480e1cbd Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 5 Sep 2022 05:00:26 +0000 Subject: [PATCH 040/586] Look at move place's type when suggesting mutable reborrow --- .../src/diagnostics/conflict_errors.rs | 1 - .../rustc_borrowck/src/diagnostics/mod.rs | 9 ++++--- .../src/diagnostics/move_errors.rs | 2 +- .../reborrow-sugg-move-then-borrow.rs | 26 +++++++++++++++++++ .../reborrow-sugg-move-then-borrow.stderr | 24 +++++++++++++++++ 5 files changed, 56 insertions(+), 6 deletions(-) create mode 100644 src/test/ui/borrowck/reborrow-sugg-move-then-borrow.rs create mode 100644 src/test/ui/borrowck/reborrow-sugg-move-then-borrow.stderr diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 5971f7623f215..a2e4641f66d5c 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -198,7 +198,6 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { move_span, move_spans, *moved_place, - Some(used_place), partially_str, loop_message, move_msg, diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs index 683084cf09d44..2d849316f9294 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mod.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs @@ -970,7 +970,6 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { move_span: Span, move_spans: UseSpans<'tcx>, moved_place: Place<'tcx>, - used_place: Option>, partially_str: &str, loop_message: &str, move_msg: &str, @@ -1058,9 +1057,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { place_name, partially_str, loop_message ), ); - // If we have a `&mut` ref, we need to reborrow. - if let Some(ty::Ref(_, _, hir::Mutability::Mut)) = used_place - .map(|used_place| used_place.ty(self.body, self.infcx.tcx).ty.kind()) + // If the moved place was a `&mut` ref, then we can + // suggest to reborrow it where it was moved, so it + // will still be valid by the time we get to the usage. + if let ty::Ref(_, _, hir::Mutability::Mut) = + moved_place.ty(self.body, self.infcx.tcx).ty.kind() { // If we are in a loop this will be suggested later. if !is_loop_move { diff --git a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs index 16c2f9ccc6aa4..bb06a94635c46 100644 --- a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs @@ -401,7 +401,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { }; if let Some(use_spans) = use_spans { self.explain_captures( - &mut err, span, span, use_spans, move_place, None, "", "", "", false, true, + &mut err, span, span, use_spans, move_place, "", "", "", false, true, ); } err diff --git a/src/test/ui/borrowck/reborrow-sugg-move-then-borrow.rs b/src/test/ui/borrowck/reborrow-sugg-move-then-borrow.rs new file mode 100644 index 0000000000000..31eba07400846 --- /dev/null +++ b/src/test/ui/borrowck/reborrow-sugg-move-then-borrow.rs @@ -0,0 +1,26 @@ +// Tests the suggestion to reborrow the first move site +// when we move then borrow a `&mut` ref. + +struct State; + +impl IntoIterator for &mut State { + type IntoIter = std::vec::IntoIter<()>; + type Item = (); + + fn into_iter(self) -> Self::IntoIter { + vec![].into_iter() + } +} + +fn once(f: impl FnOnce()) {} + +fn fill_memory_blocks_mt(state: &mut State) { + for _ in state {} + //~^ HELP consider creating a fresh reborrow of `state` here + fill_segment(state); + //~^ ERROR borrow of moved value: `state` +} + +fn fill_segment(state: &mut State) {} + +fn main() {} diff --git a/src/test/ui/borrowck/reborrow-sugg-move-then-borrow.stderr b/src/test/ui/borrowck/reborrow-sugg-move-then-borrow.stderr new file mode 100644 index 0000000000000..13a2005e2ef4c --- /dev/null +++ b/src/test/ui/borrowck/reborrow-sugg-move-then-borrow.stderr @@ -0,0 +1,24 @@ +error[E0382]: borrow of moved value: `state` + --> $DIR/reborrow-sugg-move-then-borrow.rs:20:18 + | +LL | fn fill_memory_blocks_mt(state: &mut State) { + | ----- move occurs because `state` has type `&mut State`, which does not implement the `Copy` trait +LL | for _ in state {} + | ----- `state` moved due to this implicit call to `.into_iter()` +LL | +LL | fill_segment(state); + | ^^^^^ value borrowed here after move + | +note: this function takes ownership of the receiver `self`, which moves `state` + --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL + | +LL | fn into_iter(self) -> Self::IntoIter; + | ^^^^ +help: consider creating a fresh reborrow of `state` here + | +LL | for _ in &mut *state {} + | ++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`. From cb86c38cdbf29a400dd48ec8450ce71b81c8dd45 Mon Sep 17 00:00:00 2001 From: Daniel Henry-Mantilla Date: Fri, 26 Aug 2022 14:59:12 +0200 Subject: [PATCH 041/586] Fix `#[derive(Default)]` on a generic `#[default]` enum adding unnecessary `Default` bounds --- .../src/deriving/bounds.rs | 1 + .../src/deriving/clone.rs | 1 + .../src/deriving/cmp/eq.rs | 1 + .../src/deriving/cmp/ord.rs | 1 + .../src/deriving/cmp/partial_eq.rs | 1 + .../src/deriving/cmp/partial_ord.rs | 1 + .../src/deriving/debug.rs | 1 + .../src/deriving/decodable.rs | 1 + .../src/deriving/default.rs | 20 +++++++++++++++++++ .../src/deriving/encodable.rs | 1 + .../src/deriving/generic/mod.rs | 6 +++++- .../rustc_builtin_macros/src/deriving/hash.rs | 1 + 12 files changed, 35 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_builtin_macros/src/deriving/bounds.rs b/compiler/rustc_builtin_macros/src/deriving/bounds.rs index 77e0b6c55a80e..7bd344467d032 100644 --- a/compiler/rustc_builtin_macros/src/deriving/bounds.rs +++ b/compiler/rustc_builtin_macros/src/deriving/bounds.rs @@ -16,6 +16,7 @@ pub fn expand_deriving_copy( let trait_def = TraitDef { span, path: path_std!(marker::Copy), + skip_path_as_bound: false, additional_bounds: Vec::new(), generics: Bounds::empty(), supports_unions: true, diff --git a/compiler/rustc_builtin_macros/src/deriving/clone.rs b/compiler/rustc_builtin_macros/src/deriving/clone.rs index c7f2d95e72f0c..fa8685f5f4e56 100644 --- a/compiler/rustc_builtin_macros/src/deriving/clone.rs +++ b/compiler/rustc_builtin_macros/src/deriving/clone.rs @@ -72,6 +72,7 @@ pub fn expand_deriving_clone( let trait_def = TraitDef { span, path: path_std!(clone::Clone), + skip_path_as_bound: false, additional_bounds: bounds, generics: Bounds::empty(), supports_unions: true, diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs index 5b556c5c9b9d1..eab67b0d354cf 100644 --- a/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs +++ b/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs @@ -25,6 +25,7 @@ pub fn expand_deriving_eq( let trait_def = TraitDef { span, path: path_std!(cmp::Eq), + skip_path_as_bound: false, additional_bounds: Vec::new(), generics: Bounds::empty(), supports_unions: true, diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs index 7262586955811..7f117981a9a2f 100644 --- a/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs +++ b/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs @@ -19,6 +19,7 @@ pub fn expand_deriving_ord( let trait_def = TraitDef { span, path: path_std!(cmp::Ord), + skip_path_as_bound: false, additional_bounds: Vec::new(), generics: Bounds::empty(), supports_unions: false, diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs index 42ee65b570a2a..236cbccaf9fee 100644 --- a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs +++ b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs @@ -83,6 +83,7 @@ pub fn expand_deriving_partial_eq( let trait_def = TraitDef { span, path: path_std!(cmp::PartialEq), + skip_path_as_bound: false, additional_bounds: Vec::new(), generics: Bounds::empty(), supports_unions: false, diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs index 516892aeda96f..4173403a1b84a 100644 --- a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs +++ b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs @@ -37,6 +37,7 @@ pub fn expand_deriving_partial_ord( let trait_def = TraitDef { span, path: path_std!(cmp::PartialOrd), + skip_path_as_bound: false, additional_bounds: vec![], generics: Bounds::empty(), supports_unions: false, diff --git a/compiler/rustc_builtin_macros/src/deriving/debug.rs b/compiler/rustc_builtin_macros/src/deriving/debug.rs index 4af7fd8165388..2cf614ed9476c 100644 --- a/compiler/rustc_builtin_macros/src/deriving/debug.rs +++ b/compiler/rustc_builtin_macros/src/deriving/debug.rs @@ -20,6 +20,7 @@ pub fn expand_deriving_debug( let trait_def = TraitDef { span, path: path_std!(fmt::Debug), + skip_path_as_bound: false, additional_bounds: Vec::new(), generics: Bounds::empty(), supports_unions: false, diff --git a/compiler/rustc_builtin_macros/src/deriving/decodable.rs b/compiler/rustc_builtin_macros/src/deriving/decodable.rs index 7174dbbe7ea8b..d669f616802fe 100644 --- a/compiler/rustc_builtin_macros/src/deriving/decodable.rs +++ b/compiler/rustc_builtin_macros/src/deriving/decodable.rs @@ -23,6 +23,7 @@ pub fn expand_deriving_rustc_decodable( let trait_def = TraitDef { span, path: Path::new_(vec![krate, sym::Decodable], vec![], PathKind::Global), + skip_path_as_bound: false, additional_bounds: Vec::new(), generics: Bounds::empty(), supports_unions: false, diff --git a/compiler/rustc_builtin_macros/src/deriving/default.rs b/compiler/rustc_builtin_macros/src/deriving/default.rs index a94c8a996e642..17df9fb279ad6 100644 --- a/compiler/rustc_builtin_macros/src/deriving/default.rs +++ b/compiler/rustc_builtin_macros/src/deriving/default.rs @@ -24,6 +24,7 @@ pub fn expand_deriving_default( let trait_def = TraitDef { span, path: Path::new(vec![kw::Default, sym::Default]), + skip_path_as_bound: has_a_default_variant(item), additional_bounds: Vec::new(), generics: Bounds::empty(), supports_unions: false, @@ -262,3 +263,22 @@ impl<'a, 'b> rustc_ast::visit::Visitor<'a> for DetectNonVariantDefaultAttr<'a, ' } } } + +fn has_a_default_variant(item: &Annotatable) -> bool { + struct HasDefaultAttrOnVariant { + found: bool, + } + + impl<'ast> rustc_ast::visit::Visitor<'ast> for HasDefaultAttrOnVariant { + fn visit_variant(&mut self, v: &'ast rustc_ast::Variant) { + if v.attrs.iter().any(|attr| attr.has_name(kw::Default)) { + self.found = true; + } + // no need to subrecurse. + } + } + + let mut visitor = HasDefaultAttrOnVariant { found: false }; + item.visit_with(&mut visitor); + visitor.found +} diff --git a/compiler/rustc_builtin_macros/src/deriving/encodable.rs b/compiler/rustc_builtin_macros/src/deriving/encodable.rs index b220e54238f46..f83f58b97d38f 100644 --- a/compiler/rustc_builtin_macros/src/deriving/encodable.rs +++ b/compiler/rustc_builtin_macros/src/deriving/encodable.rs @@ -107,6 +107,7 @@ pub fn expand_deriving_rustc_encodable( let trait_def = TraitDef { span, path: Path::new_(vec![krate, sym::Encodable], vec![], PathKind::Global), + skip_path_as_bound: false, additional_bounds: Vec::new(), generics: Bounds::empty(), supports_unions: false, diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs index adffebd3fd285..cd53050c61e68 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs @@ -172,6 +172,7 @@ use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::Span; use std::cell::RefCell; use std::iter; +use std::ops::Not; use std::vec; use thin_vec::thin_vec; use ty::{Bounds, Path, Ref, Self_, Ty}; @@ -185,6 +186,9 @@ pub struct TraitDef<'a> { /// Path of the trait, including any type parameters pub path: Path, + /// Whether to skip adding the current trait as a bound to the type parameters of the type. + pub skip_path_as_bound: bool, + /// Additional bounds required of any type parameters of the type, /// other than the current trait pub additional_bounds: Vec, @@ -594,7 +598,7 @@ impl<'a> TraitDef<'a> { cx.trait_bound(p.to_path(cx, self.span, type_ident, generics)) }).chain( // require the current trait - iter::once(cx.trait_bound(trait_path.clone())) + self.skip_path_as_bound.not().then(|| cx.trait_bound(trait_path.clone())) ).chain( // also add in any bounds from the declaration param.bounds.iter().cloned() diff --git a/compiler/rustc_builtin_macros/src/deriving/hash.rs b/compiler/rustc_builtin_macros/src/deriving/hash.rs index f1f02e7ce7787..6e9d5f08b9443 100644 --- a/compiler/rustc_builtin_macros/src/deriving/hash.rs +++ b/compiler/rustc_builtin_macros/src/deriving/hash.rs @@ -22,6 +22,7 @@ pub fn expand_deriving_hash( let hash_trait_def = TraitDef { span, path, + skip_path_as_bound: false, additional_bounds: Vec::new(), generics: Bounds::empty(), supports_unions: false, From 975e72fc0f122e2c2b57d8d61a9c6553d29fb366 Mon Sep 17 00:00:00 2001 From: Daniel Henry-Mantilla Date: Fri, 26 Aug 2022 15:00:38 +0200 Subject: [PATCH 042/586] Add corresponding regression test --- src/test/ui/deriving/deriving-default-enum.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/test/ui/deriving/deriving-default-enum.rs b/src/test/ui/deriving/deriving-default-enum.rs index d1a81c72c2fdc..1c7a501edc705 100644 --- a/src/test/ui/deriving/deriving-default-enum.rs +++ b/src/test/ui/deriving/deriving-default-enum.rs @@ -12,6 +12,16 @@ enum Foo { Beta(NotDefault), } +// #[default] on a generic enum does not add `Default` bounds to the type params. +#[derive(Default)] +enum MyOption { + #[default] + None, + #[allow(dead_code)] + Some(T), +} + fn main() { assert_eq!(Foo::default(), Foo::Alpha); + assert!(matches!(MyOption::::default(), MyOption::None)); } From 5510a699813bfc8f84cffaa6a4ba0cc0a0d8accd Mon Sep 17 00:00:00 2001 From: Jacob Pratt Date: Wed, 7 Sep 2022 21:59:09 -0400 Subject: [PATCH 043/586] Stabilize `#![feature(mixed_integer_ops)]` --- library/core/src/lib.rs | 1 - library/core/src/num/int_macros.rs | 40 ++++++++++++----------------- library/core/src/num/uint_macros.rs | 20 ++++++--------- library/std/src/lib.rs | 1 - 4 files changed, 24 insertions(+), 38 deletions(-) diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 5b1e2045fff63..bfe56b733b3f7 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -190,7 +190,6 @@ #![feature(link_llvm_intrinsics)] #![feature(macro_metavar_expr)] #![feature(min_specialization)] -#![feature(mixed_integer_ops)] #![feature(must_not_suspend)] #![feature(negative_impls)] #![feature(never_type)] diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs index 92b12ed33528d..7d0f6266bbb04 100644 --- a/library/core/src/num/int_macros.rs +++ b/library/core/src/num/int_macros.rs @@ -464,12 +464,11 @@ macro_rules! int_impl { /// Basic usage: /// /// ``` - /// # #![feature(mixed_integer_ops)] #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".checked_add_unsigned(2), Some(3));")] #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MAX - 2).checked_add_unsigned(3), None);")] /// ``` - #[unstable(feature = "mixed_integer_ops", issue = "87840")] - #[rustc_const_unstable(feature = "mixed_integer_ops", issue = "87840")] + #[stable(feature = "mixed_integer_ops", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "mixed_integer_ops", since = "CURRENT_RUSTC_VERSION")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -533,12 +532,11 @@ macro_rules! int_impl { /// Basic usage: /// /// ``` - /// # #![feature(mixed_integer_ops)] #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".checked_sub_unsigned(2), Some(-1));")] #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MIN + 2).checked_sub_unsigned(3), None);")] /// ``` - #[unstable(feature = "mixed_integer_ops", issue = "87840")] - #[rustc_const_unstable(feature = "mixed_integer_ops", issue = "87840")] + #[stable(feature = "mixed_integer_ops", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "mixed_integer_ops", since = "CURRENT_RUSTC_VERSION")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -907,12 +905,11 @@ macro_rules! int_impl { /// Basic usage: /// /// ``` - /// # #![feature(mixed_integer_ops)] #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".saturating_add_unsigned(2), 3);")] #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.saturating_add_unsigned(100), ", stringify!($SelfT), "::MAX);")] /// ``` - #[unstable(feature = "mixed_integer_ops", issue = "87840")] - #[rustc_const_unstable(feature = "mixed_integer_ops", issue = "87840")] + #[stable(feature = "mixed_integer_ops", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "mixed_integer_ops", since = "CURRENT_RUSTC_VERSION")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -954,12 +951,11 @@ macro_rules! int_impl { /// Basic usage: /// /// ``` - /// # #![feature(mixed_integer_ops)] #[doc = concat!("assert_eq!(100", stringify!($SelfT), ".saturating_sub_unsigned(127), -27);")] #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.saturating_sub_unsigned(100), ", stringify!($SelfT), "::MIN);")] /// ``` - #[unstable(feature = "mixed_integer_ops", issue = "87840")] - #[rustc_const_unstable(feature = "mixed_integer_ops", issue = "87840")] + #[stable(feature = "mixed_integer_ops", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "mixed_integer_ops", since = "CURRENT_RUSTC_VERSION")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -1135,12 +1131,11 @@ macro_rules! int_impl { /// Basic usage: /// /// ``` - /// # #![feature(mixed_integer_ops)] #[doc = concat!("assert_eq!(100", stringify!($SelfT), ".wrapping_add_unsigned(27), 127);")] #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.wrapping_add_unsigned(2), ", stringify!($SelfT), "::MIN + 1);")] /// ``` - #[unstable(feature = "mixed_integer_ops", issue = "87840")] - #[rustc_const_unstable(feature = "mixed_integer_ops", issue = "87840")] + #[stable(feature = "mixed_integer_ops", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "mixed_integer_ops", since = "CURRENT_RUSTC_VERSION")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline(always)] @@ -1176,12 +1171,11 @@ macro_rules! int_impl { /// Basic usage: /// /// ``` - /// # #![feature(mixed_integer_ops)] #[doc = concat!("assert_eq!(0", stringify!($SelfT), ".wrapping_sub_unsigned(127), -127);")] #[doc = concat!("assert_eq!((-2", stringify!($SelfT), ").wrapping_sub_unsigned(", stringify!($UnsignedT), "::MAX), -1);")] /// ``` - #[unstable(feature = "mixed_integer_ops", issue = "87840")] - #[rustc_const_unstable(feature = "mixed_integer_ops", issue = "87840")] + #[stable(feature = "mixed_integer_ops", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "mixed_integer_ops", since = "CURRENT_RUSTC_VERSION")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline(always)] @@ -1529,13 +1523,12 @@ macro_rules! int_impl { /// Basic usage: /// /// ``` - /// # #![feature(mixed_integer_ops)] #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".overflowing_add_unsigned(2), (3, false));")] #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MIN).overflowing_add_unsigned(", stringify!($UnsignedT), "::MAX), (", stringify!($SelfT), "::MAX, false));")] #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MAX - 2).overflowing_add_unsigned(3), (", stringify!($SelfT), "::MIN, true));")] /// ``` - #[unstable(feature = "mixed_integer_ops", issue = "87840")] - #[rustc_const_unstable(feature = "mixed_integer_ops", issue = "87840")] + #[stable(feature = "mixed_integer_ops", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "mixed_integer_ops", since = "CURRENT_RUSTC_VERSION")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -1580,13 +1573,12 @@ macro_rules! int_impl { /// Basic usage: /// /// ``` - /// # #![feature(mixed_integer_ops)] #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".overflowing_sub_unsigned(2), (-1, false));")] #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MAX).overflowing_sub_unsigned(", stringify!($UnsignedT), "::MAX), (", stringify!($SelfT), "::MIN, false));")] #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MIN + 2).overflowing_sub_unsigned(3), (", stringify!($SelfT), "::MAX, true));")] /// ``` - #[unstable(feature = "mixed_integer_ops", issue = "87840")] - #[rustc_const_unstable(feature = "mixed_integer_ops", issue = "87840")] + #[stable(feature = "mixed_integer_ops", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "mixed_integer_ops", since = "CURRENT_RUSTC_VERSION")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index aa3e8b9974ecb..1b60ec67e3193 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -474,13 +474,12 @@ macro_rules! uint_impl { /// Basic usage: /// /// ``` - /// # #![feature(mixed_integer_ops)] #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".checked_add_signed(2), Some(3));")] #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".checked_add_signed(-2), None);")] #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MAX - 2).checked_add_signed(3), None);")] /// ``` - #[unstable(feature = "mixed_integer_ops", issue = "87840")] - #[rustc_const_unstable(feature = "mixed_integer_ops", issue = "87840")] + #[stable(feature = "mixed_integer_ops", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "mixed_integer_ops", since = "CURRENT_RUSTC_VERSION")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -1057,13 +1056,12 @@ macro_rules! uint_impl { /// Basic usage: /// /// ``` - /// # #![feature(mixed_integer_ops)] #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".saturating_add_signed(2), 3);")] #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".saturating_add_signed(-2), 0);")] #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MAX - 2).saturating_add_signed(4), ", stringify!($SelfT), "::MAX);")] /// ``` - #[unstable(feature = "mixed_integer_ops", issue = "87840")] - #[rustc_const_unstable(feature = "mixed_integer_ops", issue = "87840")] + #[stable(feature = "mixed_integer_ops", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "mixed_integer_ops", since = "CURRENT_RUSTC_VERSION")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -1198,13 +1196,12 @@ macro_rules! uint_impl { /// Basic usage: /// /// ``` - /// # #![feature(mixed_integer_ops)] #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".wrapping_add_signed(2), 3);")] #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".wrapping_add_signed(-2), ", stringify!($SelfT), "::MAX);")] #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MAX - 2).wrapping_add_signed(4), 1);")] /// ``` - #[unstable(feature = "mixed_integer_ops", issue = "87840")] - #[rustc_const_unstable(feature = "mixed_integer_ops", issue = "87840")] + #[stable(feature = "mixed_integer_ops", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "mixed_integer_ops", since = "CURRENT_RUSTC_VERSION")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -1564,13 +1561,12 @@ macro_rules! uint_impl { /// Basic usage: /// /// ``` - /// # #![feature(mixed_integer_ops)] #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".overflowing_add_signed(2), (3, false));")] #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".overflowing_add_signed(-2), (", stringify!($SelfT), "::MAX, true));")] #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MAX - 2).overflowing_add_signed(4), (1, true));")] /// ``` - #[unstable(feature = "mixed_integer_ops", issue = "87840")] - #[rustc_const_unstable(feature = "mixed_integer_ops", issue = "87840")] + #[stable(feature = "mixed_integer_ops", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "mixed_integer_ops", since = "CURRENT_RUSTC_VERSION")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index f13500de01431..8d89ed51419a7 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -296,7 +296,6 @@ #![feature(is_some_with)] #![feature(maybe_uninit_slice)] #![feature(maybe_uninit_write_slice)] -#![feature(mixed_integer_ops)] #![feature(nonnull_slice_from_raw_parts)] #![feature(panic_can_unwind)] #![feature(panic_info_message)] From fa61678a7d471cfc8bf166979674d4574a5d3bec Mon Sep 17 00:00:00 2001 From: Giacomo Stevanato Date: Sat, 10 Sep 2022 11:26:24 +0200 Subject: [PATCH 044/586] Fix leaking in inplace collection when destructor panics --- library/alloc/src/vec/in_place_collect.rs | 8 ++++++-- library/alloc/src/vec/in_place_drop.rs | 15 +++++++++++++++ library/alloc/src/vec/mod.rs | 2 +- 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/library/alloc/src/vec/in_place_collect.rs b/library/alloc/src/vec/in_place_collect.rs index 55dcb84ad16f9..359f1a9cec251 100644 --- a/library/alloc/src/vec/in_place_collect.rs +++ b/library/alloc/src/vec/in_place_collect.rs @@ -138,7 +138,7 @@ use core::iter::{InPlaceIterable, SourceIter, TrustedRandomAccessNoCoerce}; use core::mem::{self, ManuallyDrop}; use core::ptr::{self}; -use super::{InPlaceDrop, SpecFromIter, SpecFromIterNested, Vec}; +use super::{InPlaceDrop, InPlaceDstBufDrop, SpecFromIter, SpecFromIterNested, Vec}; /// Specialization marker for collecting an iterator pipeline into a Vec while reusing the /// source allocation, i.e. executing the pipeline in place. @@ -193,12 +193,16 @@ where // Drop any remaining values at the tail of the source but prevent drop of the allocation // itself once IntoIter goes out of scope. - // If the drop panics then we also leak any elements collected into dst_buf. + // If the drop panics then we also try to drop the destination buffer and its elements. + // This is safe because `forget_allocation_drop_remaining` forgets the allocation *before* + // trying to drop the remaining elements. // // Note: This access to the source wouldn't be allowed by the TrustedRandomIteratorNoCoerce // contract (used by SpecInPlaceCollect below). But see the "O(1) collect" section in the // module documenttation why this is ok anyway. + let dst_guard = InPlaceDstBufDrop { ptr: dst_buf, len, cap }; src.forget_allocation_drop_remaining(); + mem::forget(dst_guard); let vec = unsafe { Vec::from_raw_parts(dst_buf, len, cap) }; diff --git a/library/alloc/src/vec/in_place_drop.rs b/library/alloc/src/vec/in_place_drop.rs index 1b1ef9130face..25ca33c6a7bf0 100644 --- a/library/alloc/src/vec/in_place_drop.rs +++ b/library/alloc/src/vec/in_place_drop.rs @@ -22,3 +22,18 @@ impl Drop for InPlaceDrop { } } } + +// A helper struct for in-place collection that drops the destination allocation and elements, +// to avoid leaking them if some other destructor panics. +pub(super) struct InPlaceDstBufDrop { + pub(super) ptr: *mut T, + pub(super) len: usize, + pub(super) cap: usize, +} + +impl Drop for InPlaceDstBufDrop { + #[inline] + fn drop(&mut self) { + unsafe { super::Vec::from_raw_parts(self.ptr, self.len, self.cap) }; + } +} diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index fa9f2131c0c1d..acfbb98272dd5 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -125,7 +125,7 @@ use self::set_len_on_drop::SetLenOnDrop; mod set_len_on_drop; #[cfg(not(no_global_oom_handling))] -use self::in_place_drop::InPlaceDrop; +use self::in_place_drop::{InPlaceDrop, InPlaceDstBufDrop}; #[cfg(not(no_global_oom_handling))] mod in_place_drop; From f81b07e9470728a311a5d816616762e37b00f29f Mon Sep 17 00:00:00 2001 From: Giacomo Stevanato Date: Sat, 10 Sep 2022 11:27:21 +0200 Subject: [PATCH 045/586] Adapt inplace collection leak test to check for no leaks --- library/alloc/tests/vec.rs | 36 ++++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/library/alloc/tests/vec.rs b/library/alloc/tests/vec.rs index d94da8f5f5a0e..ebf5cbd0e60e0 100644 --- a/library/alloc/tests/vec.rs +++ b/library/alloc/tests/vec.rs @@ -1110,11 +1110,13 @@ fn test_from_iter_specialization_panic_during_iteration_drops() { } #[test] -fn test_from_iter_specialization_panic_during_drop_leaks() { - static mut DROP_COUNTER: usize = 0; +fn test_from_iter_specialization_panic_during_drop_doesnt_leak() { + static mut DROP_COUNTER_SHOULD_BE_DROPPED: usize = 0; + static mut DROP_COUNTER_DROPPED_TWICE: usize = 0; #[derive(Debug)] enum Droppable { + ShouldBeDropped, DroppedTwice(Box), PanicOnDrop, } @@ -1122,11 +1124,17 @@ fn test_from_iter_specialization_panic_during_drop_leaks() { impl Drop for Droppable { fn drop(&mut self) { match self { + Droppable::ShouldBeDropped => { + unsafe { + DROP_COUNTER_SHOULD_BE_DROPPED += 1; + } + println!("Dropping ShouldBeDropped!") + } Droppable::DroppedTwice(_) => { unsafe { - DROP_COUNTER += 1; + DROP_COUNTER_DROPPED_TWICE += 1; } - println!("Dropping!") + println!("Dropping DroppedTwice!") } Droppable::PanicOnDrop => { if !std::thread::panicking() { @@ -1137,21 +1145,17 @@ fn test_from_iter_specialization_panic_during_drop_leaks() { } } - let mut to_free: *mut Droppable = core::ptr::null_mut(); - let mut cap = 0; - let _ = std::panic::catch_unwind(AssertUnwindSafe(|| { - let mut v = vec![Droppable::DroppedTwice(Box::new(123)), Droppable::PanicOnDrop]; - to_free = v.as_mut_ptr(); - cap = v.capacity(); - let _ = v.into_iter().take(0).collect::>(); + let v = vec![ + Droppable::ShouldBeDropped, + Droppable::DroppedTwice(Box::new(123)), + Droppable::PanicOnDrop, + ]; + let _ = v.into_iter().take(1).collect::>(); })); - assert_eq!(unsafe { DROP_COUNTER }, 1); - // clean up the leak to keep miri happy - unsafe { - drop(Vec::from_raw_parts(to_free, 0, cap)); - } + assert_eq!(unsafe { DROP_COUNTER_SHOULD_BE_DROPPED }, 1); + assert_eq!(unsafe { DROP_COUNTER_DROPPED_TWICE }, 1); } // regression test for issue #85322. Peekable previously implemented InPlaceIterable, From f52082f54321e56fa4dbd9194c1cfd61089e2729 Mon Sep 17 00:00:00 2001 From: Giacomo Stevanato Date: Sat, 10 Sep 2022 12:29:16 +0200 Subject: [PATCH 046/586] Update documentation --- library/alloc/src/vec/in_place_collect.rs | 7 +++++-- library/alloc/src/vec/into_iter.rs | 7 ++++++- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/library/alloc/src/vec/in_place_collect.rs b/library/alloc/src/vec/in_place_collect.rs index 359f1a9cec251..83ed3d915a291 100644 --- a/library/alloc/src/vec/in_place_collect.rs +++ b/library/alloc/src/vec/in_place_collect.rs @@ -55,6 +55,9 @@ //! This is handled by the [`InPlaceDrop`] guard for sink items (`U`) and by //! [`vec::IntoIter::forget_allocation_drop_remaining()`] for remaining source items (`T`). //! +//! If dropping any remaining source item (`T`) panics then [`InPlaceDstBufDrop`] will handle dropping +//! the already collected sink items (`U`) and freeing the allocation. +//! //! [`vec::IntoIter::forget_allocation_drop_remaining()`]: super::IntoIter::forget_allocation_drop_remaining() //! //! # O(1) collect @@ -194,8 +197,8 @@ where // Drop any remaining values at the tail of the source but prevent drop of the allocation // itself once IntoIter goes out of scope. // If the drop panics then we also try to drop the destination buffer and its elements. - // This is safe because `forget_allocation_drop_remaining` forgets the allocation *before* - // trying to drop the remaining elements. + // This is safe because `forget_allocation_drop_remaining` immediately forgets the allocation + // and won't panic before that. // // Note: This access to the source wouldn't be allowed by the TrustedRandomIteratorNoCoerce // contract (used by SpecInPlaceCollect below). But see the "O(1) collect" section in the diff --git a/library/alloc/src/vec/into_iter.rs b/library/alloc/src/vec/into_iter.rs index 1b483e3fc7793..b5a03392a1797 100644 --- a/library/alloc/src/vec/into_iter.rs +++ b/library/alloc/src/vec/into_iter.rs @@ -96,13 +96,16 @@ impl IntoIter { } /// Drops remaining elements and relinquishes the backing allocation. + /// This method guarantees it won't panic before relinquishing + /// the backing allocation. /// /// This is roughly equivalent to the following, but more efficient /// /// ``` /// # let mut into_iter = Vec::::with_capacity(10).into_iter(); + /// let mut into_iter = std::mem::replace(&mut into_iter, Vec::new().into_iter()); /// (&mut into_iter).for_each(core::mem::drop); - /// unsafe { core::ptr::write(&mut into_iter, Vec::new().into_iter()); } + /// std::mem::forget(into_iter); /// ``` /// /// This method is used by in-place iteration, refer to the vec::in_place_collect @@ -119,6 +122,8 @@ impl IntoIter { self.ptr = self.buf.as_ptr(); self.end = self.buf.as_ptr(); + // Dropping the remaining elements can panic, so this needs to be + // done only after updating the other fields. unsafe { ptr::drop_in_place(remaining); } From dad049cb5cb3d259836cfe6a9160521d9d4809ca Mon Sep 17 00:00:00 2001 From: Giacomo Stevanato Date: Sat, 10 Sep 2022 12:29:25 +0200 Subject: [PATCH 047/586] Update test --- library/alloc/tests/vec.rs | 67 +++++++++++++++++++------------------- 1 file changed, 34 insertions(+), 33 deletions(-) diff --git a/library/alloc/tests/vec.rs b/library/alloc/tests/vec.rs index ebf5cbd0e60e0..990ce38e22edd 100644 --- a/library/alloc/tests/vec.rs +++ b/library/alloc/tests/vec.rs @@ -1111,51 +1111,52 @@ fn test_from_iter_specialization_panic_during_iteration_drops() { #[test] fn test_from_iter_specialization_panic_during_drop_doesnt_leak() { - static mut DROP_COUNTER_SHOULD_BE_DROPPED: usize = 0; - static mut DROP_COUNTER_DROPPED_TWICE: usize = 0; + static mut DROP_COUNTER_OLD: [usize; 5] = [0; 5]; + static mut DROP_COUNTER_NEW: [usize; 2] = [0; 2]; #[derive(Debug)] - enum Droppable { - ShouldBeDropped, - DroppedTwice(Box), - PanicOnDrop, + struct Old(usize); + + impl Drop for Old { + fn drop(&mut self) { + unsafe { + DROP_COUNTER_OLD[self.0] += 1; + } + + if self.0 == 3 { + panic!(); + } + + println!("Dropped Old: {}", self.0); + } } - impl Drop for Droppable { + #[derive(Debug)] + struct New(usize); + + impl Drop for New { fn drop(&mut self) { - match self { - Droppable::ShouldBeDropped => { - unsafe { - DROP_COUNTER_SHOULD_BE_DROPPED += 1; - } - println!("Dropping ShouldBeDropped!") - } - Droppable::DroppedTwice(_) => { - unsafe { - DROP_COUNTER_DROPPED_TWICE += 1; - } - println!("Dropping DroppedTwice!") - } - Droppable::PanicOnDrop => { - if !std::thread::panicking() { - panic!(); - } - } + unsafe { + DROP_COUNTER_NEW[self.0] += 1; } + + println!("Dropped New: {}", self.0); } } let _ = std::panic::catch_unwind(AssertUnwindSafe(|| { - let v = vec![ - Droppable::ShouldBeDropped, - Droppable::DroppedTwice(Box::new(123)), - Droppable::PanicOnDrop, - ]; - let _ = v.into_iter().take(1).collect::>(); + let v = vec![Old(0), Old(1), Old(2), Old(3), Old(4)]; + let _ = v.into_iter().map(|x| New(x.0)).take(2).collect::>(); })); - assert_eq!(unsafe { DROP_COUNTER_SHOULD_BE_DROPPED }, 1); - assert_eq!(unsafe { DROP_COUNTER_DROPPED_TWICE }, 1); + assert_eq!(unsafe { DROP_COUNTER_OLD[0] }, 1); + assert_eq!(unsafe { DROP_COUNTER_OLD[1] }, 1); + assert_eq!(unsafe { DROP_COUNTER_OLD[2] }, 1); + assert_eq!(unsafe { DROP_COUNTER_OLD[3] }, 1); + assert_eq!(unsafe { DROP_COUNTER_OLD[4] }, 1); + + assert_eq!(unsafe { DROP_COUNTER_NEW[0] }, 1); + assert_eq!(unsafe { DROP_COUNTER_NEW[1] }, 1); } // regression test for issue #85322. Peekable previously implemented InPlaceIterable, From 2db0492e6264d22629ed75b60f8c0dcebc451966 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 12 Sep 2022 04:20:26 +0000 Subject: [PATCH 048/586] Normalize closure signature after construction --- compiler/rustc_typeck/src/check/closure.rs | 3 ++ src/test/ui/closures/issue-101696.rs | 36 ++++++++++++++++++++++ 2 files changed, 39 insertions(+) create mode 100644 src/test/ui/closures/issue-101696.rs diff --git a/compiler/rustc_typeck/src/check/closure.rs b/compiler/rustc_typeck/src/check/closure.rs index 55cbaf71e7cfd..893227d3e7df2 100644 --- a/compiler/rustc_typeck/src/check/closure.rs +++ b/compiler/rustc_typeck/src/check/closure.rs @@ -624,6 +624,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ), bound_vars, ); + // Astconv can't normalize inputs or outputs with escaping bound vars, + // so normalize them here, after we've wrapped them in a binder. + let result = self.normalize_associated_types_in(self.tcx.hir().span(hir_id), result); let c_result = self.inh.infcx.canonicalize_response(result); self.typeck_results.borrow_mut().user_provided_sigs.insert(expr_def_id, c_result); diff --git a/src/test/ui/closures/issue-101696.rs b/src/test/ui/closures/issue-101696.rs new file mode 100644 index 0000000000000..0a358bd164387 --- /dev/null +++ b/src/test/ui/closures/issue-101696.rs @@ -0,0 +1,36 @@ +// check-pass + +use std::marker::PhantomData; + +#[derive(Default)] +struct MyType<'a> { + field: usize, + _phantom: PhantomData<&'a ()>, +} + +#[derive(Default)] +struct MyTypeVariant<'a> { + field: usize, + _phantom: PhantomData<&'a ()>, +} + +trait AsVariantTrait { + type Type; +} + +impl<'a> AsVariantTrait for MyType<'a> { + type Type = MyTypeVariant<'a>; +} + +type Variant = ::Type; + +fn foo(f: F) { + let input = T::default(); + f(input); +} + +fn main() { + foo(|a: ::Type| { + a.field; + }); +} From 8d6edac7639bdd4854ab026fbdac0c4d1a22f64d Mon Sep 17 00:00:00 2001 From: onestacked Date: Wed, 14 Sep 2022 16:54:49 +0200 Subject: [PATCH 049/586] Add const_slice_split_at_mut Feature gate. --- library/core/src/lib.rs | 1 + library/core/src/slice/mod.rs | 6 ++++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 5621d15c1cd6f..79dfc9cb1b1fd 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -137,6 +137,7 @@ #![feature(const_size_of_val)] #![feature(const_slice_from_raw_parts_mut)] #![feature(const_slice_ptr_len)] +#![feature(const_slice_split_at_mut)] #![feature(const_str_from_utf8_unchecked_mut)] #![feature(const_swap)] #![feature(const_trait_impl)] diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index 6a7150d2986ed..03c8051c5b4c1 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -1580,7 +1580,8 @@ impl [T] { #[inline] #[track_caller] #[must_use] - pub fn split_at_mut(&mut self, mid: usize) -> (&mut [T], &mut [T]) { + #[rustc_const_unstable(feature = "const_slice_split_at_mut", issue = "101804")] + pub const fn split_at_mut(&mut self, mid: usize) -> (&mut [T], &mut [T]) { assert!(mid <= self.len()); // SAFETY: `[ptr; mid]` and `[mid; len]` are inside `self`, which // fulfills the requirements of `from_raw_parts_mut`. @@ -1679,9 +1680,10 @@ impl [T] { /// assert_eq!(v, [1, 2, 3, 4, 5, 6]); /// ``` #[unstable(feature = "slice_split_at_unchecked", reason = "new API", issue = "76014")] + #[rustc_const_unstable(feature = "const_slice_split_at_mut", issue = "101804")] #[inline] #[must_use] - pub unsafe fn split_at_mut_unchecked(&mut self, mid: usize) -> (&mut [T], &mut [T]) { + pub const unsafe fn split_at_mut_unchecked(&mut self, mid: usize) -> (&mut [T], &mut [T]) { let len = self.len(); let ptr = self.as_mut_ptr(); From 282b1e476883fbfd8924535185512199b4eaff3c Mon Sep 17 00:00:00 2001 From: Tuna Date: Wed, 14 Sep 2022 18:17:05 -0500 Subject: [PATCH 050/586] Distribute bootstrap in CI artifacts - Add a new `bootstrap` component Originally, we planned to combine this with the `rust-dev` component. However, I realized that would force LLVM to be redownloaded whenever bootstrap is modified. LLVM is a much larger download, so split this to get better caching. - Build bootstrap for all tier 1 and 2 targets --- .github/workflows/ci.yml | 20 +++++------ src/bootstrap/builder.rs | 1 + src/bootstrap/dist.rs | 35 +++++++++++++++++++ .../host-x86_64/dist-x86_64-linux/Dockerfile | 2 +- src/ci/github-actions/ci.yml | 20 +++++------ 5 files changed, 57 insertions(+), 21 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ec1ef041b2068..5e458c5a98769 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -291,7 +291,7 @@ jobs: os: ubuntu-20.04-xl - name: dist-x86_64-apple env: - SCRIPT: "./x.py dist --host=x86_64-apple-darwin --target=x86_64-apple-darwin" + SCRIPT: "./x.py dist bootstrap --include-default-paths --host=x86_64-apple-darwin --target=x86_64-apple-darwin" RUST_CONFIGURE_ARGS: "--enable-full-tools --enable-sanitizers --enable-profiler --set rust.jemalloc --set llvm.ninja=false" RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 MACOSX_DEPLOYMENT_TARGET: 10.7 @@ -302,7 +302,7 @@ jobs: os: macos-latest - name: dist-apple-various env: - SCRIPT: "./x.py dist --host='' --target=aarch64-apple-ios,x86_64-apple-ios,aarch64-apple-ios-sim" + SCRIPT: "./x.py dist bootstrap --include-default-paths --host='' --target=aarch64-apple-ios,x86_64-apple-ios,aarch64-apple-ios-sim" RUST_CONFIGURE_ARGS: "--enable-sanitizers --enable-profiler --set rust.jemalloc --set llvm.ninja=false" RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 MACOSX_DEPLOYMENT_TARGET: 10.7 @@ -312,7 +312,7 @@ jobs: os: macos-latest - name: dist-x86_64-apple-alt env: - SCRIPT: "./x.py dist" + SCRIPT: "./x.py dist bootstrap --include-default-paths" RUST_CONFIGURE_ARGS: "--enable-extended --enable-profiler --set rust.jemalloc --set llvm.ninja=false" RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 MACOSX_DEPLOYMENT_TARGET: 10.7 @@ -344,7 +344,7 @@ jobs: os: macos-latest - name: dist-aarch64-apple env: - SCRIPT: "./x.py dist --stage 2" + SCRIPT: "./x.py dist bootstrap --include-default-paths --stage 2" RUST_CONFIGURE_ARGS: "--build=x86_64-apple-darwin --host=aarch64-apple-darwin --target=aarch64-apple-darwin --enable-full-tools --enable-sanitizers --enable-profiler --disable-docs --set rust.jemalloc --set llvm.ninja=false" RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 USE_XCODE_CLANG: 1 @@ -418,19 +418,19 @@ jobs: - name: dist-x86_64-msvc env: RUST_CONFIGURE_ARGS: "--build=x86_64-pc-windows-msvc --host=x86_64-pc-windows-msvc --target=x86_64-pc-windows-msvc --enable-full-tools --enable-profiler" - SCRIPT: PGO_HOST=x86_64-pc-windows-msvc src/ci/pgo.sh python x.py dist + SCRIPT: PGO_HOST=x86_64-pc-windows-msvc src/ci/pgo.sh python x.py dist bootstrap --include-default-paths DIST_REQUIRE_ALL_TOOLS: 1 os: windows-latest-xl - name: dist-i686-msvc env: RUST_CONFIGURE_ARGS: "--build=i686-pc-windows-msvc --host=i686-pc-windows-msvc --target=i686-pc-windows-msvc,i586-pc-windows-msvc --enable-full-tools --enable-profiler" - SCRIPT: python x.py dist + SCRIPT: python x.py dist bootstrap --include-default-paths DIST_REQUIRE_ALL_TOOLS: 1 os: windows-latest-xl - name: dist-aarch64-msvc env: RUST_CONFIGURE_ARGS: "--build=x86_64-pc-windows-msvc --host=aarch64-pc-windows-msvc --enable-full-tools --enable-profiler" - SCRIPT: python x.py dist + SCRIPT: python x.py dist bootstrap --include-default-paths DIST_REQUIRE_ALL_TOOLS: 1 WINDOWS_SDK_20348_HACK: 1 os: windows-latest-xl @@ -438,13 +438,13 @@ jobs: env: RUST_CONFIGURE_ARGS: "--build=i686-pc-windows-gnu --enable-full-tools --enable-profiler --set llvm.allow-old-toolchain" NO_DOWNLOAD_CI_LLVM: 1 - SCRIPT: python x.py dist + SCRIPT: python x.py dist bootstrap --include-default-paths CUSTOM_MINGW: 1 DIST_REQUIRE_ALL_TOOLS: 1 os: windows-latest-xl - name: dist-x86_64-mingw env: - SCRIPT: python x.py dist + SCRIPT: python x.py dist bootstrap --include-default-paths RUST_CONFIGURE_ARGS: "--build=x86_64-pc-windows-gnu --enable-full-tools --enable-profiler --set llvm.allow-old-toolchain" NO_DOWNLOAD_CI_LLVM: 1 CUSTOM_MINGW: 1 @@ -453,7 +453,7 @@ jobs: - name: dist-x86_64-msvc-alt env: RUST_CONFIGURE_ARGS: "--build=x86_64-pc-windows-msvc --enable-extended --enable-profiler" - SCRIPT: python x.py dist + SCRIPT: python x.py dist bootstrap --include-default-paths os: windows-latest-xl timeout-minutes: 600 runs-on: "${{ matrix.os }}" diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 14e8ebd6876b4..8ec64657f47dd 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -723,6 +723,7 @@ impl<'a> Builder<'a> { dist::Miri, dist::LlvmTools, dist::RustDev, + dist::Bootstrap, dist::Extended, // It seems that PlainSourceTarball somehow changes how some of the tools // perceive their dependencies (see #93033) which would invalidate fingerprints diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index 1a59b3958f106..679f017c77062 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -2050,6 +2050,41 @@ impl Step for RustDev { } } +// Tarball intended for internal consumption to ease rustc/std development. +// +// Should not be considered stable by end users. +#[derive(Clone, Debug, Eq, Hash, PartialEq)] +pub struct Bootstrap { + pub target: TargetSelection, +} + +impl Step for Bootstrap { + type Output = Option; + const DEFAULT: bool = false; + const ONLY_HOSTS: bool = true; + + fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { + run.alias("bootstrap") + } + + fn make_run(run: RunConfig<'_>) { + run.builder.ensure(Bootstrap { target: run.target }); + } + + fn run(self, builder: &Builder<'_>) -> Option { + let target = self.target; + + let tarball = Tarball::new(builder, "bootstrap", &target.triple); + + let bootstrap_outdir = &builder.bootstrap_out; + for file in &["bootstrap", "llvm-config-wrapper", "rustc", "rustdoc", "sccache-plus-cl"] { + tarball.add_file(bootstrap_outdir.join(file), "bootstrap/bin", 0o755); + } + + Some(tarball.generate()) + } +} + /// Tarball containing a prebuilt version of the build-manifest tool, intended to be used by the /// release process to avoid cloning the monorepo and building stuff. /// diff --git a/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile b/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile index 973c43072bf40..b960239807af8 100644 --- a/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile @@ -82,7 +82,7 @@ ENV RUST_CONFIGURE_ARGS \ ENV SCRIPT ../src/ci/pgo.sh python3 ../x.py dist \ --host $HOSTS --target $HOSTS \ --include-default-paths \ - build-manifest + build-manifest bootstrap ENV CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_LINKER=clang # This is the only builder which will create source tarballs diff --git a/src/ci/github-actions/ci.yml b/src/ci/github-actions/ci.yml index 6e4b0b0c2c3f1..6056e722362a3 100644 --- a/src/ci/github-actions/ci.yml +++ b/src/ci/github-actions/ci.yml @@ -455,7 +455,7 @@ jobs: - name: dist-x86_64-apple env: - SCRIPT: ./x.py dist --host=x86_64-apple-darwin --target=x86_64-apple-darwin + SCRIPT: ./x.py dist bootstrap --include-default-paths --host=x86_64-apple-darwin --target=x86_64-apple-darwin RUST_CONFIGURE_ARGS: --enable-full-tools --enable-sanitizers --enable-profiler --set rust.jemalloc --set llvm.ninja=false RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 MACOSX_DEPLOYMENT_TARGET: 10.7 @@ -467,7 +467,7 @@ jobs: - name: dist-apple-various env: - SCRIPT: ./x.py dist --host='' --target=aarch64-apple-ios,x86_64-apple-ios,aarch64-apple-ios-sim + SCRIPT: ./x.py dist bootstrap --include-default-paths --host='' --target=aarch64-apple-ios,x86_64-apple-ios,aarch64-apple-ios-sim RUST_CONFIGURE_ARGS: --enable-sanitizers --enable-profiler --set rust.jemalloc --set llvm.ninja=false RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 MACOSX_DEPLOYMENT_TARGET: 10.7 @@ -478,7 +478,7 @@ jobs: - name: dist-x86_64-apple-alt env: - SCRIPT: ./x.py dist + SCRIPT: ./x.py dist bootstrap --include-default-paths RUST_CONFIGURE_ARGS: --enable-extended --enable-profiler --set rust.jemalloc --set llvm.ninja=false RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 MACOSX_DEPLOYMENT_TARGET: 10.7 @@ -508,7 +508,7 @@ jobs: # This target only needs to support 11.0 and up as nothing else supports the hardware - name: dist-aarch64-apple env: - SCRIPT: ./x.py dist --stage 2 + SCRIPT: ./x.py dist bootstrap --include-default-paths --stage 2 RUST_CONFIGURE_ARGS: >- --build=x86_64-apple-darwin --host=aarch64-apple-darwin @@ -652,7 +652,7 @@ jobs: --target=x86_64-pc-windows-msvc --enable-full-tools --enable-profiler - SCRIPT: PGO_HOST=x86_64-pc-windows-msvc src/ci/pgo.sh python x.py dist + SCRIPT: PGO_HOST=x86_64-pc-windows-msvc src/ci/pgo.sh python x.py dist bootstrap --include-default-paths DIST_REQUIRE_ALL_TOOLS: 1 <<: *job-windows-xl @@ -664,7 +664,7 @@ jobs: --target=i686-pc-windows-msvc,i586-pc-windows-msvc --enable-full-tools --enable-profiler - SCRIPT: python x.py dist + SCRIPT: python x.py dist bootstrap --include-default-paths DIST_REQUIRE_ALL_TOOLS: 1 <<: *job-windows-xl @@ -675,7 +675,7 @@ jobs: --host=aarch64-pc-windows-msvc --enable-full-tools --enable-profiler - SCRIPT: python x.py dist + SCRIPT: python x.py dist bootstrap --include-default-paths DIST_REQUIRE_ALL_TOOLS: 1 # Hack around this SDK version, because it doesn't work with clang. # See https://github.com/rust-lang/rust/issues/88796 @@ -692,14 +692,14 @@ jobs: # We are intentionally allowing an old toolchain on this builder (and that's # incompatible with LLVM downloads today). NO_DOWNLOAD_CI_LLVM: 1 - SCRIPT: python x.py dist + SCRIPT: python x.py dist bootstrap --include-default-paths CUSTOM_MINGW: 1 DIST_REQUIRE_ALL_TOOLS: 1 <<: *job-windows-xl - name: dist-x86_64-mingw env: - SCRIPT: python x.py dist + SCRIPT: python x.py dist bootstrap --include-default-paths RUST_CONFIGURE_ARGS: >- --build=x86_64-pc-windows-gnu --enable-full-tools @@ -715,7 +715,7 @@ jobs: - name: dist-x86_64-msvc-alt env: RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-extended --enable-profiler - SCRIPT: python x.py dist + SCRIPT: python x.py dist bootstrap --include-default-paths <<: *job-windows-xl try: From 63f6289db2d90be05acdf615f8039383c52c4ddc Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Wed, 14 Sep 2022 18:18:57 -0500 Subject: [PATCH 051/586] Fix `--dry-run` for `dist::RustDev` --- src/bootstrap/dist.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index 679f017c77062..3d03a056c1540 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -1873,7 +1873,7 @@ fn maybe_install_llvm(builder: &Builder<'_>, target: TargetSelection, dst_libdir let mut cmd = Command::new(llvm_config); cmd.arg("--libfiles"); builder.verbose(&format!("running {:?}", cmd)); - let files = output(&mut cmd); + let files = if builder.config.dry_run { "".into() } else { output(&mut cmd) }; let build_llvm_out = &builder.llvm_out(builder.config.build); let target_llvm_out = &builder.llvm_out(target); for file in files.trim_end().split(' ') { From 55c040e52964e4ad81b4b2af3c91068a80b92f11 Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Wed, 14 Sep 2022 18:19:28 -0500 Subject: [PATCH 052/586] Make it possible to run bootstrap on a different machine than the one it was built - Default to trying git rev-parse for the root directory CARGO_MANIFEST_DIR is a path on the build machine, not the running machine. Don't require this to succeed, to allow building from a tarball; in that case fall back to CARGO_MANIFEST_DIR. - Set `initial_rustc` to a path based on the path of the running executable, not CARGO_MANIFEST_DIR. We only reset `initial_rustc` if we're sure this isn't the working tree bootstrap was originally built in, since I'm paranoid that setting this in other cases will cause things to break; it's not clear to me when $RUSTC differs from `build/$TARGET/stage0/bin/rustc` (maybe never? but better to be sure). Instead, only set this when a) We are not using a custom rustc. If someone has specified a custom rustc we should respect their wishes. b) We are in a checkout of rust-lang/rust other than the one bootstrap was built in. --- src/bootstrap/config.rs | 48 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 44 insertions(+), 4 deletions(-) diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index 7c062460c4f16..b8e776485e673 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -772,21 +772,20 @@ impl Config { // set by build.rs config.build = TargetSelection::from_user(&env!("BUILD_TRIPLE")); + let manifest_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR")); // Undo `src/bootstrap` config.src = manifest_dir.parent().unwrap().parent().unwrap().to_owned(); config.out = PathBuf::from("build"); - config.initial_cargo = PathBuf::from(env!("CARGO")); - config.initial_rustc = PathBuf::from(env!("RUSTC")); - config } pub fn parse(args: &[String]) -> Config { let flags = Flags::parse(&args); - let mut config = Config::default_opts(); + + // Set flags. config.exclude = flags.exclude.into_iter().map(|path| TaskPath::parse(path)).collect(); config.include_default_paths = flags.include_default_paths; config.rustc_error_format = flags.rustc_error_format; @@ -805,7 +804,41 @@ impl Config { config.llvm_profile_use = flags.llvm_profile_use; config.llvm_profile_generate = flags.llvm_profile_generate; + // Infer the rest of the configuration. + + // Infer the source directory. This is non-trivial because we want to support a downloaded bootstrap binary, + // running on a completely machine from where it was compiled. + let mut cmd = Command::new("git"); + // NOTE: we cannot support running from outside the repository because the only path we have available + // is set at compile time, which can be wrong if bootstrap was downloaded from source. + // We still support running outside the repository if we find we aren't in a git directory. + cmd.arg("rev-parse").arg("--show-toplevel"); + // Discard stderr because we expect this to fail when building from a tarball. + let output = cmd + .stderr(std::process::Stdio::null()) + .output() + .ok() + .and_then(|output| if output.status.success() { Some(output) } else { None }); + if let Some(output) = output { + let git_root = String::from_utf8(output.stdout).unwrap(); + config.src = PathBuf::from(git_root.trim().to_owned()) + } else { + // We're building from a tarball, not git sources. + // We don't support pre-downloaded bootstrap in this case. + } + + if cfg!(test) { + // Use the build directory of the original x.py invocation, so that we can set `initial_rustc` properly. + config.out = Path::new( + &env::var_os("CARGO_TARGET_DIR").expect("cargo test directly is not supported"), + ) + .parent() + .unwrap() + .to_path_buf(); + } + let stage0_json = t!(std::fs::read(&config.src.join("src").join("stage0.json"))); + config.stage0_metadata = t!(serde_json::from_slice::(&stage0_json)); #[cfg(test)] @@ -860,6 +893,7 @@ impl Config { config.config = toml_path; let build = toml.build.unwrap_or_default(); + let has_custom_rustc = build.rustc.is_some(); set(&mut config.initial_rustc, build.rustc.map(PathBuf::from)); set(&mut config.out, flags.build_dir.or_else(|| build.build_dir.map(PathBuf::from))); @@ -870,6 +904,12 @@ impl Config { config.out = crate::util::absolute(&config.out); } + if !has_custom_rustc && !config.initial_rustc.starts_with(&config.out) { + config.initial_rustc = config.out.join(config.build.triple).join("stage0/bin/rustc"); + config.initial_cargo = config.out.join(config.build.triple).join("stage0/bin/cargo"); + } + + // NOTE: it's important this comes *after* we set `initial_rustc` just above. if config.dry_run { let dir = config.out.join("tmp-dry-run"); t!(fs::create_dir_all(&dir)); From b31628ddacda76253b707e230293f13d95b88369 Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Wed, 14 Sep 2022 18:09:33 -0500 Subject: [PATCH 053/586] Don't hardcode the path to `bootstrap_out` The `rust-dev` dist component puts binaries in `bootstrap/bin`, but we expected them to be in `bootstrap/debug` to match cargo's behavior. Rather than making the dist component inconsistent with other components, make bootstrap slightly smarter and allow using any path as long as all the binaries are in the same directory. As a bonus, this greatly simplifies the logic, and makes it possible for the shell scripts to start avoiding python. Co-authored-by: Joshua Nelson --- src/bootstrap/lib.rs | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index cc0cf12bd187a..2f2b3aed98ef1 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -456,19 +456,15 @@ impl Build { .expect("failed to read src/version"); let version = version.trim(); - let bootstrap_out = if std::env::var("BOOTSTRAP_PYTHON").is_ok() { - out.join("bootstrap").join("debug") - } else { - let workspace_target_dir = std::env::var("CARGO_TARGET_DIR") - .map(PathBuf::from) - .unwrap_or_else(|_| src.join("target")); - let bootstrap_out = workspace_target_dir.join("debug"); - if !bootstrap_out.join("rustc").exists() && !cfg!(test) { - // this restriction can be lifted whenever https://github.com/rust-lang/rfcs/pull/3028 is implemented - panic!("run `cargo build --bins` before `cargo run`") - } - bootstrap_out - }; + let bootstrap_out = std::env::current_exe() + .expect("could not determine path to running process") + .parent() + .unwrap() + .to_path_buf(); + if !bootstrap_out.join("rustc").exists() && !cfg!(test) { + // this restriction can be lifted whenever https://github.com/rust-lang/rfcs/pull/3028 is implemented + panic!("run `cargo build --bins` before `cargo run`") + } let mut build = Build { initial_rustc: config.initial_rustc.clone(), From 0a1fde953319bee0060268aec946afd64d7845da Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Wed, 14 Sep 2022 18:01:18 -0500 Subject: [PATCH 054/586] Fix pre-existing bug in exe check --- src/bootstrap/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 2f2b3aed98ef1..4795ae2f95632 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -461,7 +461,7 @@ impl Build { .parent() .unwrap() .to_path_buf(); - if !bootstrap_out.join("rustc").exists() && !cfg!(test) { + if !bootstrap_out.join(exe("rustc", config.build)).exists() && !cfg!(test) { // this restriction can be lifted whenever https://github.com/rust-lang/rfcs/pull/3028 is implemented panic!("run `cargo build --bins` before `cargo run`") } From 0bb4e25ec432beb3629280ea65d1d5475b4f3ee1 Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Sun, 11 Sep 2022 15:14:03 -0500 Subject: [PATCH 055/586] Give a better error messages when the rustc shim is missing --- src/bootstrap/lib.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 4795ae2f95632..dc53e4b545b36 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -463,7 +463,10 @@ impl Build { .to_path_buf(); if !bootstrap_out.join(exe("rustc", config.build)).exists() && !cfg!(test) { // this restriction can be lifted whenever https://github.com/rust-lang/rfcs/pull/3028 is implemented - panic!("run `cargo build --bins` before `cargo run`") + panic!( + "`rustc` not found in {}, run `cargo build --bins` before `cargo run`", + bootstrap_out.display() + ) } let mut build = Build { From 3d4980bc8d8a58df217a6b659b9353a11ce4cd29 Mon Sep 17 00:00:00 2001 From: Daniel Henry-Mantilla Date: Thu, 15 Sep 2022 18:56:12 +0200 Subject: [PATCH 056/586] Future-proof against loose bounds if default variant is non-exhaustive. Co-Authored-By: Mark Rousskov --- src/test/ui/macros/macros-nonfatal-errors.rs | 21 +++++++++++++++++++ .../ui/macros/macros-nonfatal-errors.stderr | 12 ++++++++++- 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/src/test/ui/macros/macros-nonfatal-errors.rs b/src/test/ui/macros/macros-nonfatal-errors.rs index e7a01f105de0b..140cc5b0fd808 100644 --- a/src/test/ui/macros/macros-nonfatal-errors.rs +++ b/src/test/ui/macros/macros-nonfatal-errors.rs @@ -116,3 +116,24 @@ fn main() { trace_macros!(invalid); //~ ERROR } + +/// Check that `#[derive(Default)]` does use a `T : Default` bound when the +/// `#[default]` variant is `#[non_exhaustive]` (should this end up allowed). +const _: () = { + #[derive(Default)] + enum NonExhaustiveDefaultGeneric { + #[default] + #[non_exhaustive] + Foo, //~ ERROR default variant must be exhaustive + Bar(T), + } + + fn assert_impls_default() {} + + enum NotDefault {} + + // Note: the `derive(Default)` currently bails early enough for trait-checking + // not to happen. Should it bail late enough, or even pass, make sure to + // assert that the following line fails. + let _ = assert_impls_default::>; +}; diff --git a/src/test/ui/macros/macros-nonfatal-errors.stderr b/src/test/ui/macros/macros-nonfatal-errors.stderr index b3c6d07f96763..d42f6c179b7ef 100644 --- a/src/test/ui/macros/macros-nonfatal-errors.stderr +++ b/src/test/ui/macros/macros-nonfatal-errors.stderr @@ -215,11 +215,21 @@ error: trace_macros! accepts only `true` or `false` LL | trace_macros!(invalid); | ^^^^^^^^^^^^^^^^^^^^^^ +error: default variant must be exhaustive + --> $DIR/macros-nonfatal-errors.rs:127:9 + | +LL | #[non_exhaustive] + | ----------------- declared `#[non_exhaustive]` here +LL | Foo, + | ^^^ + | + = help: consider a manual implementation of `Default` + error: cannot find macro `llvm_asm` in this scope --> $DIR/macros-nonfatal-errors.rs:99:5 | LL | llvm_asm!(invalid); | ^^^^^^^^ -error: aborting due to 27 previous errors +error: aborting due to 28 previous errors From cf6366babafb3b08c3944ee0a25e398af2657ed5 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 16 Sep 2022 11:02:11 +0000 Subject: [PATCH 057/586] Revert TypeVisitor changes --- compiler/rustc_middle/src/infer/canonical.rs | 15 ++++++-------- .../rustc_middle/src/mir/type_visitable.rs | 6 ++++++ .../rustc_middle/src/ty/structural_impls.rs | 20 +++++++++++++++++++ compiler/rustc_middle/src/ty/subst.rs | 8 +++++++- 4 files changed, 39 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_middle/src/infer/canonical.rs b/compiler/rustc_middle/src/infer/canonical.rs index d3cf519b633c7..4bad0950451ac 100644 --- a/compiler/rustc_middle/src/infer/canonical.rs +++ b/compiler/rustc_middle/src/infer/canonical.rs @@ -44,15 +44,6 @@ pub struct Canonical<'tcx, V> { pub type CanonicalVarInfos<'tcx> = &'tcx List>; -impl<'tcx> ty::TypeFoldable<'tcx> for CanonicalVarInfos<'tcx> { - fn try_fold_with>( - self, - folder: &mut F, - ) -> Result { - ty::util::fold_list(self, folder, |tcx, v| tcx.intern_canonical_var_infos(v)) - } -} - /// A set of values corresponding to the canonical variables from some /// `Canonical`. You can give these values to /// `canonical_value.substitute` to substitute them into the canonical @@ -314,6 +305,12 @@ TrivialTypeTraversalAndLiftImpls! { } } +TrivialTypeTraversalImpls! { + for <'tcx> { + crate::infer::canonical::CanonicalVarInfos<'tcx>, + } +} + impl<'tcx> CanonicalVarValues<'tcx> { #[inline] pub fn len(&self) -> usize { diff --git a/compiler/rustc_middle/src/mir/type_visitable.rs b/compiler/rustc_middle/src/mir/type_visitable.rs index 27a251f2f56f8..56fa7f1ede3d4 100644 --- a/compiler/rustc_middle/src/mir/type_visitable.rs +++ b/compiler/rustc_middle/src/mir/type_visitable.rs @@ -8,6 +8,12 @@ impl<'tcx, R: Idx, C: Idx> TypeVisitable<'tcx> for BitMatrix { } } +impl<'tcx> TypeVisitable<'tcx> for &'tcx ty::List> { + fn visit_with>(&self, visitor: &mut V) -> ControlFlow { + self.iter().try_for_each(|t| t.visit_with(visitor)) + } +} + impl<'tcx> TypeVisitable<'tcx> for ConstantKind<'tcx> { fn visit_with>(&self, visitor: &mut V) -> ControlFlow { visitor.visit_mir_const(*self) diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index f5fd1f6ffafce..ecbb2a16b69df 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -602,12 +602,26 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List TypeVisitable<'tcx> + for &'tcx ty::List>> +{ + fn visit_with>(&self, visitor: &mut V) -> ControlFlow { + self.iter().try_for_each(|p| p.visit_with(visitor)) + } +} + impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List { fn try_fold_with>(self, folder: &mut F) -> Result { ty::util::fold_list(self, folder, |tcx, v| tcx.intern_projs(v)) } } +impl<'tcx> TypeVisitable<'tcx> for &'tcx ty::List { + fn visit_with>(&self, visitor: &mut V) -> ControlFlow { + self.iter().try_for_each(|t| t.visit_with(visitor)) + } +} + impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> { fn try_fold_with>(self, folder: &mut F) -> Result { folder.try_fold_ty(self) @@ -783,6 +797,12 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List> { } } +impl<'tcx> TypeVisitable<'tcx> for &'tcx ty::List> { + fn visit_with>(&self, visitor: &mut V) -> ControlFlow { + self.iter().try_for_each(|p| p.visit_with(visitor)) + } +} + impl<'tcx, T: TypeFoldable<'tcx>, I: Idx> TypeFoldable<'tcx> for IndexVec { fn try_fold_with>(self, folder: &mut F) -> Result { self.try_map_id(|x| x.try_fold_with(folder)) diff --git a/compiler/rustc_middle/src/ty/subst.rs b/compiler/rustc_middle/src/ty/subst.rs index 8e69bf067d08e..6262aa1807577 100644 --- a/compiler/rustc_middle/src/ty/subst.rs +++ b/compiler/rustc_middle/src/ty/subst.rs @@ -459,6 +459,12 @@ impl<'tcx> TypeFoldable<'tcx> for SubstsRef<'tcx> { } } +impl<'tcx> TypeVisitable<'tcx> for SubstsRef<'tcx> { + fn visit_with>(&self, visitor: &mut V) -> ControlFlow { + self.iter().try_for_each(|t| t.visit_with(visitor)) + } +} + impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List> { fn try_fold_with>(self, folder: &mut F) -> Result { // This code is fairly hot, though not as hot as `SubstsRef`. @@ -491,7 +497,7 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List> { } } -impl<'tcx, T: TypeVisitable<'tcx>> TypeVisitable<'tcx> for &'tcx ty::List { +impl<'tcx> TypeVisitable<'tcx> for &'tcx ty::List> { fn visit_with>(&self, visitor: &mut V) -> ControlFlow { self.iter().try_for_each(|t| t.visit_with(visitor)) } From e19a98cff73cb18e974c145cb6d15c4860092140 Mon Sep 17 00:00:00 2001 From: Bradford Hovinen Date: Thu, 28 Jul 2022 14:45:43 +0000 Subject: [PATCH 058/586] Do not panic when a test function returns Result::Err. Rust's test library allows test functions to return a Result, so that the test is deemed to have failed if the function returns a Result::Err variant. Currently, this works by having Result implement the Termination trait and asserting in assert_test_result that Termination::report() indicates successful completion. This turns a Result::Err into a panic, which is caught and unwound in the test library. This approach is problematic in certain environments where one wishes to save on both binary size and compute resources when running tests by: * Compiling all code with --panic=abort to avoid having to generate unwinding tables, and * Running most tests in-process to avoid the overhead of spawning new processes. This change removes the intermediate panic step and passes a Result::Err directly through to the test runner. To do this, it modifies assert_test_result to return a Result<(), String> where the Err variant holds what was previously the panic message. It changes the types in the TestFn enum to return Result<(), String>. This tries to minimise the changes to benchmark tests, so it calls unwrap() on the Result returned by assert_test_result, effectively keeping the same behaviour as before. --- library/test/src/bench.rs | 21 ++--- library/test/src/lib.rs | 61 +++++++++---- library/test/src/tests.rs | 90 ++++++++++++++----- library/test/src/types.rs | 15 ++-- src/librustdoc/doctest.rs | 1 + .../termination-trait-test-wrong-type.stderr | 2 +- src/tools/compiletest/src/main.rs | 5 +- 7 files changed, 135 insertions(+), 60 deletions(-) diff --git a/library/test/src/bench.rs b/library/test/src/bench.rs index 7869ba2c04178..23925e6ea72ec 100644 --- a/library/test/src/bench.rs +++ b/library/test/src/bench.rs @@ -49,12 +49,12 @@ impl Bencher { self.summary = Some(iter(&mut inner)); } - pub fn bench(&mut self, mut f: F) -> Option + pub fn bench(&mut self, mut f: F) -> Result, String> where - F: FnMut(&mut Bencher), + F: FnMut(&mut Bencher) -> Result<(), String>, { - f(self); - self.summary + let result = f(self); + result.map(|_| self.summary) } } @@ -195,7 +195,7 @@ pub fn benchmark( nocapture: bool, f: F, ) where - F: FnMut(&mut Bencher), + F: FnMut(&mut Bencher) -> Result<(), String>, { let mut bs = Bencher { mode: BenchMode::Auto, summary: None, bytes: 0 }; @@ -211,14 +211,14 @@ pub fn benchmark( let test_result = match result { //bs.bench(f) { - Ok(Some(ns_iter_summ)) => { + Ok(Ok(Some(ns_iter_summ))) => { let ns_iter = cmp::max(ns_iter_summ.median as u64, 1); let mb_s = bs.bytes * 1000 / ns_iter; let bs = BenchSamples { ns_iter_summ, mb_s: mb_s as usize }; TestResult::TrBench(bs) } - Ok(None) => { + Ok(Ok(None)) => { // iter not called, so no data. // FIXME: error in this case? let samples: &mut [f64] = &mut [0.0_f64; 1]; @@ -226,6 +226,7 @@ pub fn benchmark( TestResult::TrBench(bs) } Err(_) => TestResult::TrFailed, + Ok(Err(_)) => TestResult::TrFailed, }; let stdout = data.lock().unwrap().to_vec(); @@ -233,10 +234,10 @@ pub fn benchmark( monitor_ch.send(message).unwrap(); } -pub fn run_once(f: F) +pub fn run_once(f: F) -> Result<(), String> where - F: FnMut(&mut Bencher), + F: FnMut(&mut Bencher) -> Result<(), String>, { let mut bs = Bencher { mode: BenchMode::Single, summary: None, bytes: 0 }; - bs.bench(f); + bs.bench(f).map(|_| ()) } diff --git a/library/test/src/lib.rs b/library/test/src/lib.rs index 3b7193adcc758..d328582c38671 100644 --- a/library/test/src/lib.rs +++ b/library/test/src/lib.rs @@ -6,7 +6,8 @@ //! benchmarks themselves) should be done via the `#[test]` and //! `#[bench]` attributes. //! -//! See the [Testing Chapter](../book/ch11-00-testing.html) of the book for more details. +//! See the [Testing Chapter](../book/ch11-00-testing.html) of the book for more +//! details. // Currently, not much of this is meant for users. It is intended to // support the simplest interface possible for representing and @@ -77,6 +78,7 @@ mod types; #[cfg(test)] mod tests; +use core::any::Any; use event::{CompletedTest, TestEvent}; use helpers::concurrency::get_concurrency; use helpers::exit_code::get_exit_code; @@ -176,17 +178,20 @@ fn make_owned_test(test: &&TestDescAndFn) -> TestDescAndFn { } } -/// Invoked when unit tests terminate. Should panic if the unit -/// Tests is considered a failure. By default, invokes `report()` -/// and checks for a `0` result. -pub fn assert_test_result(result: T) { +/// Invoked when unit tests terminate. Returns `Result::Err` if the test is +/// considered a failure. By default, invokes `report() and checks for a `0` +/// result. +pub fn assert_test_result(result: T) -> Result<(), String> { let code = result.report().to_i32(); - assert_eq!( - code, 0, - "the test returned a termination value with a non-zero status code ({}) \ - which indicates a failure", - code - ); + if code == 0 { + Ok(()) + } else { + Err(format!( + "the test returned a termination value with a non-zero status code \ + ({}) which indicates a failure", + code + )) + } } pub fn run_tests( @@ -479,7 +484,7 @@ pub fn run_test( id: TestId, desc: TestDesc, monitor_ch: Sender, - testfn: Box, + testfn: Box Result<(), String> + Send>, opts: TestRunOpts, ) -> Option> { let concurrency = opts.concurrency; @@ -568,11 +573,11 @@ pub fn run_test( /// Fixed frame used to clean the backtrace with `RUST_BACKTRACE=1`. #[inline(never)] -fn __rust_begin_short_backtrace(f: F) { - f(); +fn __rust_begin_short_backtrace T>(f: F) -> T { + let result = f(); // prevent this frame from being tail-call optimised away - black_box(()); + black_box(result) } fn run_test_in_process( @@ -580,7 +585,7 @@ fn run_test_in_process( desc: TestDesc, nocapture: bool, report_time: bool, - testfn: Box, + testfn: Box Result<(), String> + Send>, monitor_ch: Sender, time_opts: Option, ) { @@ -592,7 +597,7 @@ fn run_test_in_process( } let start = report_time.then(Instant::now); - let result = catch_unwind(AssertUnwindSafe(testfn)); + let result = fold_err(catch_unwind(AssertUnwindSafe(testfn))); let exec_time = start.map(|start| { let duration = start.elapsed(); TestExecTime(duration) @@ -609,6 +614,19 @@ fn run_test_in_process( monitor_ch.send(message).unwrap(); } +fn fold_err( + result: Result, Box>, +) -> Result> +where + E: Send + 'static, +{ + match result { + Ok(Err(e)) => Err(Box::new(e)), + Ok(Ok(v)) => Ok(v), + Err(e) => Err(e), + } +} + fn spawn_test_subprocess( id: TestId, desc: TestDesc, @@ -664,7 +682,10 @@ fn spawn_test_subprocess( monitor_ch.send(message).unwrap(); } -fn run_test_in_spawned_subprocess(desc: TestDesc, testfn: Box) -> ! { +fn run_test_in_spawned_subprocess( + desc: TestDesc, + testfn: Box Result<(), String> + Send>, +) -> ! { let builtin_panic_hook = panic::take_hook(); let record_result = Arc::new(move |panic_info: Option<&'_ PanicInfo<'_>>| { let test_result = match panic_info { @@ -690,7 +711,9 @@ fn run_test_in_spawned_subprocess(desc: TestDesc, testfn: Box Vec { no_run: false, test_type: TestType::Unknown, }, - testfn: DynTestFn(Box::new(move || {})), + testfn: DynTestFn(Box::new(move || Ok(()))), }, TestDescAndFn { desc: TestDesc { @@ -79,14 +79,14 @@ fn one_ignored_one_unignored_test() -> Vec { no_run: false, test_type: TestType::Unknown, }, - testfn: DynTestFn(Box::new(move || {})), + testfn: DynTestFn(Box::new(move || Ok(()))), }, ] } #[test] pub fn do_not_run_ignored_tests() { - fn f() { + fn f() -> Result<(), String> { panic!(); } let desc = TestDescAndFn { @@ -109,7 +109,9 @@ pub fn do_not_run_ignored_tests() { #[test] pub fn ignored_tests_result_in_ignored() { - fn f() {} + fn f() -> Result<(), String> { + Ok(()) + } let desc = TestDescAndFn { desc: TestDesc { name: StaticTestName("whatever"), @@ -132,7 +134,7 @@ pub fn ignored_tests_result_in_ignored() { #[test] #[cfg(not(target_os = "emscripten"))] fn test_should_panic() { - fn f() { + fn f() -> Result<(), String> { panic!(); } let desc = TestDescAndFn { @@ -157,7 +159,7 @@ fn test_should_panic() { #[test] #[cfg(not(target_os = "emscripten"))] fn test_should_panic_good_message() { - fn f() { + fn f() -> Result<(), String> { panic!("an error message"); } let desc = TestDescAndFn { @@ -183,7 +185,7 @@ fn test_should_panic_good_message() { #[cfg(not(target_os = "emscripten"))] fn test_should_panic_bad_message() { use crate::tests::TrFailedMsg; - fn f() { + fn f() -> Result<(), String> { panic!("an error message"); } let expected = "foobar"; @@ -214,7 +216,7 @@ fn test_should_panic_bad_message() { fn test_should_panic_non_string_message_type() { use crate::tests::TrFailedMsg; use std::any::TypeId; - fn f() { + fn f() -> Result<(), String> { std::panic::panic_any(1i32); } let expected = "foobar"; @@ -249,7 +251,9 @@ fn test_should_panic_but_succeeds() { let should_panic_variants = [ShouldPanic::Yes, ShouldPanic::YesWithMessage("error message")]; for &should_panic in should_panic_variants.iter() { - fn f() {} + fn f() -> Result<(), String> { + Ok(()) + } let desc = TestDescAndFn { desc: TestDesc { name: StaticTestName("whatever"), @@ -283,7 +287,9 @@ fn test_should_panic_but_succeeds() { } fn report_time_test_template(report_time: bool) -> Option { - fn f() {} + fn f() -> Result<(), String> { + Ok(()) + } let desc = TestDescAndFn { desc: TestDesc { name: StaticTestName("whatever"), @@ -318,7 +324,9 @@ fn test_should_report_time() { } fn time_test_failure_template(test_type: TestType) -> TestResult { - fn f() {} + fn f() -> Result<(), String> { + Ok(()) + } let desc = TestDescAndFn { desc: TestDesc { name: StaticTestName("whatever"), @@ -480,7 +488,7 @@ pub fn exclude_should_panic_option() { no_run: false, test_type: TestType::Unknown, }, - testfn: DynTestFn(Box::new(move || {})), + testfn: DynTestFn(Box::new(move || Ok(()))), }); let filtered = filter_tests(&opts, tests); @@ -504,7 +512,7 @@ pub fn exact_filter_match() { no_run: false, test_type: TestType::Unknown, }, - testfn: DynTestFn(Box::new(move || {})), + testfn: DynTestFn(Box::new(move || Ok(()))), }) .collect() } @@ -580,7 +588,9 @@ fn sample_tests() -> Vec { "test::run_include_ignored_option".to_string(), "test::sort_tests".to_string(), ]; - fn testfn() {} + fn testfn() -> Result<(), String> { + Ok(()) + } let mut tests = Vec::new(); for name in &names { let test = TestDescAndFn { @@ -717,21 +727,26 @@ pub fn test_metricmap_compare() { #[test] pub fn test_bench_once_no_iter() { - fn f(_: &mut Bencher) {} - bench::run_once(f); + fn f(_: &mut Bencher) -> Result<(), String> { + Ok(()) + } + bench::run_once(f).unwrap(); } #[test] pub fn test_bench_once_iter() { - fn f(b: &mut Bencher) { - b.iter(|| {}) + fn f(b: &mut Bencher) -> Result<(), String> { + b.iter(|| {}); + Ok(()) } - bench::run_once(f); + bench::run_once(f).unwrap(); } #[test] pub fn test_bench_no_iter() { - fn f(_: &mut Bencher) {} + fn f(_: &mut Bencher) -> Result<(), String> { + Ok(()) + } let (tx, rx) = channel(); @@ -751,8 +766,9 @@ pub fn test_bench_no_iter() { #[test] pub fn test_bench_iter() { - fn f(b: &mut Bencher) { - b.iter(|| {}) + fn f(b: &mut Bencher) -> Result<(), String> { + b.iter(|| {}); + Ok(()) } let (tx, rx) = channel(); @@ -821,3 +837,33 @@ fn should_sort_failures_before_printing_them() { let bpos = s.find("b").unwrap(); assert!(apos < bpos); } + +#[test] +#[cfg(not(target_os = "emscripten"))] +fn test_dyn_bench_returning_err_fails_when_run_as_test() { + fn f(_: &mut Bencher) -> Result<(), String> { + Result::Err("An error".into()) + } + let desc = TestDescAndFn { + desc: TestDesc { + name: StaticTestName("whatever"), + ignore: false, + ignore_message: None, + should_panic: ShouldPanic::No, + compile_fail: false, + no_run: false, + test_type: TestType::Unknown, + }, + testfn: DynBenchFn(Box::new(f)), + }; + let (tx, rx) = channel(); + let notify = move |event: TestEvent| { + if let TestEvent::TeResult(result) = event { + tx.send(result).unwrap(); + } + Ok(()) + }; + run_tests(&TestOpts { run_tests: true, ..TestOpts::new() }, vec![desc], notify).unwrap(); + let result = rx.recv().unwrap().result; + assert_eq!(result, TrFailed); +} diff --git a/library/test/src/types.rs b/library/test/src/types.rs index ffb1efe18cca1..888afff7921d9 100644 --- a/library/test/src/types.rs +++ b/library/test/src/types.rs @@ -75,14 +75,15 @@ impl fmt::Display for TestName { } // A function that runs a test. If the function returns successfully, -// the test succeeds; if the function panics then the test fails. We -// may need to come up with a more clever definition of test in order -// to support isolation of tests into threads. +// the test succeeds; if the function panics or returns Result::Err +// then the test fails. We may need to come up with a more clever +// definition of test in order to support isolation of tests into +// threads. pub enum TestFn { - StaticTestFn(fn()), - StaticBenchFn(fn(&mut Bencher)), - DynTestFn(Box), - DynBenchFn(Box), + StaticTestFn(fn() -> Result<(), String>), + StaticBenchFn(fn(&mut Bencher) -> Result<(), String>), + DynTestFn(Box Result<(), String> + Send>), + DynBenchFn(Box Result<(), String> + Send>), } impl TestFn { diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs index 20ae102bc27d3..f4ec60735a8dd 100644 --- a/src/librustdoc/doctest.rs +++ b/src/librustdoc/doctest.rs @@ -1134,6 +1134,7 @@ impl Tester for Collector { panic::resume_unwind(Box::new(())); } + Ok(()) })), }); } diff --git a/src/test/ui/rfc-1937-termination-trait/termination-trait-test-wrong-type.stderr b/src/test/ui/rfc-1937-termination-trait/termination-trait-test-wrong-type.stderr index 7d81de4385469..7c1390cdc6446 100644 --- a/src/test/ui/rfc-1937-termination-trait/termination-trait-test-wrong-type.stderr +++ b/src/test/ui/rfc-1937-termination-trait/termination-trait-test-wrong-type.stderr @@ -13,7 +13,7 @@ LL | | } note: required by a bound in `assert_test_result` --> $SRC_DIR/test/src/lib.rs:LL:COL | -LL | pub fn assert_test_result(result: T) { +LL | pub fn assert_test_result(result: T) -> Result<(), String> { | ^^^^^^^^^^^ required by this bound in `assert_test_result` = note: this error originates in the attribute macro `test` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs index 38c7b87fc0d9d..c3af71d465a1f 100644 --- a/src/tools/compiletest/src/main.rs +++ b/src/tools/compiletest/src/main.rs @@ -805,7 +805,10 @@ fn make_test_closure( let config = config.clone(); let testpaths = testpaths.clone(); let revision = revision.cloned(); - test::DynTestFn(Box::new(move || runtest::run(config, &testpaths, revision.as_deref()))) + test::DynTestFn(Box::new(move || { + runtest::run(config, &testpaths, revision.as_deref()); + Ok(()) + })) } /// Returns `true` if the given target is an Android target for the From 2860f77a0dd30d7edbb374fff49b39b096e298fd Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Fri, 16 Sep 2022 16:18:27 -0700 Subject: [PATCH 059/586] Remove support for LLVM's legacy pass manager --- Cargo.lock | 1 - compiler/rustc_codegen_llvm/Cargo.toml | 1 - compiler/rustc_codegen_llvm/src/back/lto.rs | 66 +---- compiler/rustc_codegen_llvm/src/back/write.rs | 261 +----------------- compiler/rustc_codegen_llvm/src/lib.rs | 2 +- compiler/rustc_codegen_llvm/src/llvm/ffi.rs | 74 +---- compiler/rustc_codegen_llvm/src/llvm_util.rs | 36 +-- .../rustc_llvm/llvm-wrapper/PassWrapper.cpp | 235 +--------------- 8 files changed, 23 insertions(+), 653 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 12fa14ee81782..90dfaef2a0262 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3263,7 +3263,6 @@ dependencies = [ "bitflags", "cstr", "libc", - "libloading", "measureme", "object 0.29.0", "rustc-demangle", diff --git a/compiler/rustc_codegen_llvm/Cargo.toml b/compiler/rustc_codegen_llvm/Cargo.toml index 74115353aaf76..a068aa2ec6244 100644 --- a/compiler/rustc_codegen_llvm/Cargo.toml +++ b/compiler/rustc_codegen_llvm/Cargo.toml @@ -11,7 +11,6 @@ doctest = false bitflags = "1.0" cstr = "0.2" libc = "0.2" -libloading = "0.7.1" measureme = "10.0.0" object = { version = "0.29.0", default-features = false, features = ["std", "read_core", "archive", "coff", "elf", "macho", "pe"] } tracing = "0.1" diff --git a/compiler/rustc_codegen_llvm/src/back/lto.rs b/compiler/rustc_codegen_llvm/src/back/lto.rs index a89df00e248e3..daf58d7152d60 100644 --- a/compiler/rustc_codegen_llvm/src/back/lto.rs +++ b/compiler/rustc_codegen_llvm/src/back/lto.rs @@ -1,8 +1,6 @@ -use crate::back::write::{ - self, save_temp_bitcode, to_llvm_opt_settings, with_llvm_pmb, DiagnosticHandlers, -}; -use crate::llvm::{self, build_string, False, True}; -use crate::{llvm_util, LlvmCodegenBackend, ModuleLlvm}; +use crate::back::write::{self, save_temp_bitcode, DiagnosticHandlers}; +use crate::llvm::{self, build_string}; +use crate::{LlvmCodegenBackend, ModuleLlvm}; use object::read::archive::ArchiveFile; use rustc_codegen_ssa::back::lto::{LtoModuleCodegen, SerializedModule, ThinModule, ThinShared}; use rustc_codegen_ssa::back::symbol_export; @@ -597,61 +595,9 @@ pub(crate) fn run_pass_manager( 1, ); } - if llvm_util::should_use_new_llvm_pass_manager( - &config.new_llvm_pass_manager, - &cgcx.target_arch, - ) { - let opt_stage = if thin { llvm::OptStage::ThinLTO } else { llvm::OptStage::FatLTO }; - let opt_level = config.opt_level.unwrap_or(config::OptLevel::No); - write::optimize_with_new_llvm_pass_manager( - cgcx, - diag_handler, - module, - config, - opt_level, - opt_stage, - )?; - debug!("lto done"); - return Ok(()); - } - - let pm = llvm::LLVMCreatePassManager(); - llvm::LLVMAddAnalysisPasses(module.module_llvm.tm, pm); - - if config.verify_llvm_ir { - let pass = llvm::LLVMRustFindAndCreatePass("verify\0".as_ptr().cast()); - llvm::LLVMRustAddPass(pm, pass.unwrap()); - } - - let opt_level = config - .opt_level - .map(|x| to_llvm_opt_settings(x).0) - .unwrap_or(llvm::CodeGenOptLevel::None); - with_llvm_pmb(module.module_llvm.llmod(), config, opt_level, false, &mut |b| { - if thin { - llvm::LLVMRustPassManagerBuilderPopulateThinLTOPassManager(b, pm); - } else { - llvm::LLVMRustPassManagerBuilderPopulateLTOPassManager( - b, pm, /* Internalize = */ False, /* RunInliner = */ True, - ); - } - }); - - // We always generate bitcode through ThinLTOBuffers, - // which do not support anonymous globals - if config.bitcode_needed() { - let pass = llvm::LLVMRustFindAndCreatePass("name-anon-globals\0".as_ptr().cast()); - llvm::LLVMRustAddPass(pm, pass.unwrap()); - } - - if config.verify_llvm_ir { - let pass = llvm::LLVMRustFindAndCreatePass("verify\0".as_ptr().cast()); - llvm::LLVMRustAddPass(pm, pass.unwrap()); - } - - llvm::LLVMRunPassManager(pm, module.module_llvm.llmod()); - - llvm::LLVMDisposePassManager(pm); + let opt_stage = if thin { llvm::OptStage::ThinLTO } else { llvm::OptStage::FatLTO }; + let opt_level = config.opt_level.unwrap_or(config::OptLevel::No); + write::optimize(cgcx, diag_handler, module, config, opt_level, opt_stage)?; } debug!("lto done"); Ok(()) diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs index a695df8409bb4..6280bf6cdc2cf 100644 --- a/compiler/rustc_codegen_llvm/src/back/write.rs +++ b/compiler/rustc_codegen_llvm/src/back/write.rs @@ -21,7 +21,6 @@ use rustc_data_structures::profiling::SelfProfilerRef; use rustc_data_structures::small_c_str::SmallCStr; use rustc_errors::{FatalError, Handler, Level}; use rustc_fs_util::{link_or_copy, path_to_c_string}; -use rustc_middle::bug; use rustc_middle::ty::TyCtxt; use rustc_session::config::{self, Lto, OutputType, Passes, SplitDwarfKind, SwitchWithOptPath}; use rustc_session::Session; @@ -417,7 +416,7 @@ fn get_instr_profile_output_path(config: &ModuleConfig) -> Option { } } -pub(crate) unsafe fn optimize_with_new_llvm_pass_manager( +pub(crate) unsafe fn optimize( cgcx: &CodegenContext, diag_handler: &Handler, module: &ModuleCodegen, @@ -465,7 +464,7 @@ pub(crate) unsafe fn optimize_with_new_llvm_pass_manager( // FIXME: NewPM doesn't provide a facility to pass custom InlineParams. // We would have to add upstream support for this first, before we can support // config.inline_threshold and our more aggressive default thresholds. - let result = llvm::LLVMRustOptimizeWithNewPassManager( + let result = llvm::LLVMRustOptimize( module.module_llvm.llmod(), &*module.module_llvm.tm, to_pass_builder_opt_level(opt_level), @@ -499,7 +498,7 @@ pub(crate) unsafe fn optimize_with_new_llvm_pass_manager( } // Unsafe due to LLVM calls. -pub(crate) unsafe fn optimize( +pub(crate) unsafe fn maybe_optimize( cgcx: &CodegenContext, diag_handler: &Handler, module: &ModuleCodegen, @@ -509,16 +508,13 @@ pub(crate) unsafe fn optimize( let llmod = module.module_llvm.llmod(); let llcx = &*module.module_llvm.llcx; - let tm = &*module.module_llvm.tm; let _handlers = DiagnosticHandlers::new(cgcx, diag_handler, llcx); let module_name = module.name.clone(); let module_name = Some(&module_name[..]); - if let Some(false) = config.new_llvm_pass_manager && llvm_util::get_version() >= (15, 0, 0) { - diag_handler.warn( - "ignoring `-Z new-llvm-pass-manager=no`, which is no longer supported with LLVM 15", - ); + if let Some(false) = config.new_llvm_pass_manager { + diag_handler.warn("ignoring `-Z new-llvm-pass-manager=no`, which is no longer supported"); } if config.emit_no_opt_bc { @@ -528,184 +524,17 @@ pub(crate) unsafe fn optimize( } if let Some(opt_level) = config.opt_level { - if llvm_util::should_use_new_llvm_pass_manager( - &config.new_llvm_pass_manager, - &cgcx.target_arch, - ) { - let opt_stage = match cgcx.lto { - Lto::Fat => llvm::OptStage::PreLinkFatLTO, - Lto::Thin | Lto::ThinLocal => llvm::OptStage::PreLinkThinLTO, - _ if cgcx.opts.cg.linker_plugin_lto.enabled() => llvm::OptStage::PreLinkThinLTO, - _ => llvm::OptStage::PreLinkNoLTO, - }; - return optimize_with_new_llvm_pass_manager( - cgcx, - diag_handler, - module, - config, - opt_level, - opt_stage, - ); - } - - if cgcx.prof.llvm_recording_enabled() { - diag_handler - .warn("`-Z self-profile-events = llvm` requires `-Z new-llvm-pass-manager`"); - } - - // Create the two optimizing pass managers. These mirror what clang - // does, and are by populated by LLVM's default PassManagerBuilder. - // Each manager has a different set of passes, but they also share - // some common passes. - let fpm = llvm::LLVMCreateFunctionPassManagerForModule(llmod); - let mpm = llvm::LLVMCreatePassManager(); - - { - let find_pass = |pass_name: &str| { - let pass_name = SmallCStr::new(pass_name); - llvm::LLVMRustFindAndCreatePass(pass_name.as_ptr()) - }; - - if config.verify_llvm_ir { - // Verification should run as the very first pass. - llvm::LLVMRustAddPass(fpm, find_pass("verify").unwrap()); - } - - let mut extra_passes = Vec::new(); - let mut have_name_anon_globals_pass = false; - - for pass_name in &config.passes { - if pass_name == "lint" { - // Linting should also be performed early, directly on the generated IR. - llvm::LLVMRustAddPass(fpm, find_pass("lint").unwrap()); - continue; - } - - if let Some(pass) = find_pass(pass_name) { - extra_passes.push(pass); - } else { - diag_handler.warn(&format!("unknown pass `{}`, ignoring", pass_name)); - } - - if pass_name == "name-anon-globals" { - have_name_anon_globals_pass = true; - } - } - - // Instrumentation must be inserted before optimization, - // otherwise LLVM may optimize some functions away which - // breaks llvm-cov. - // - // This mirrors what Clang does in lib/CodeGen/BackendUtil.cpp. - if config.instrument_gcov { - llvm::LLVMRustAddPass(mpm, find_pass("insert-gcov-profiling").unwrap()); - } - if config.instrument_coverage { - llvm::LLVMRustAddPass(mpm, find_pass("instrprof").unwrap()); - } - if config.debug_info_for_profiling { - llvm::LLVMRustAddPass(mpm, find_pass("add-discriminators").unwrap()); - } - - add_sanitizer_passes(config, &mut extra_passes); - - // Some options cause LLVM bitcode to be emitted, which uses ThinLTOBuffers, so we need - // to make sure we run LLVM's NameAnonGlobals pass when emitting bitcode; otherwise - // we'll get errors in LLVM. - let using_thin_buffers = config.bitcode_needed(); - if !config.no_prepopulate_passes { - llvm::LLVMAddAnalysisPasses(tm, fpm); - llvm::LLVMAddAnalysisPasses(tm, mpm); - let opt_level = to_llvm_opt_settings(opt_level).0; - let prepare_for_thin_lto = cgcx.lto == Lto::Thin - || cgcx.lto == Lto::ThinLocal - || (cgcx.lto != Lto::Fat && cgcx.opts.cg.linker_plugin_lto.enabled()); - with_llvm_pmb(llmod, config, opt_level, prepare_for_thin_lto, &mut |b| { - llvm::LLVMRustAddLastExtensionPasses( - b, - extra_passes.as_ptr(), - extra_passes.len() as size_t, - ); - llvm::LLVMRustPassManagerBuilderPopulateFunctionPassManager(b, fpm); - llvm::LLVMRustPassManagerBuilderPopulateModulePassManager(b, mpm); - }); - - have_name_anon_globals_pass = have_name_anon_globals_pass || prepare_for_thin_lto; - if using_thin_buffers && !prepare_for_thin_lto { - llvm::LLVMRustAddPass(mpm, find_pass("name-anon-globals").unwrap()); - have_name_anon_globals_pass = true; - } - } else { - // If we don't use the standard pipeline, directly populate the MPM - // with the extra passes. - for pass in extra_passes { - llvm::LLVMRustAddPass(mpm, pass); - } - } - - if using_thin_buffers && !have_name_anon_globals_pass { - // As described above, this will probably cause an error in LLVM - if config.no_prepopulate_passes { - diag_handler.err( - "The current compilation is going to use thin LTO buffers \ - without running LLVM's NameAnonGlobals pass. \ - This will likely cause errors in LLVM. Consider adding \ - -C passes=name-anon-globals to the compiler command line.", - ); - } else { - bug!( - "We are using thin LTO buffers without running the NameAnonGlobals pass. \ - This will likely cause errors in LLVM and should never happen." - ); - } - } - } - - diag_handler.abort_if_errors(); - - // Finally, run the actual optimization passes - { - let _timer = cgcx.prof.extra_verbose_generic_activity( - "LLVM_module_optimize_function_passes", - &*module.name, - ); - llvm::LLVMRustRunFunctionPassManager(fpm, llmod); - } - { - let _timer = cgcx.prof.extra_verbose_generic_activity( - "LLVM_module_optimize_module_passes", - &*module.name, - ); - llvm::LLVMRunPassManager(mpm, llmod); - } - - // Deallocate managers that we're now done with - llvm::LLVMDisposePassManager(fpm); - llvm::LLVMDisposePassManager(mpm); + let opt_stage = match cgcx.lto { + Lto::Fat => llvm::OptStage::PreLinkFatLTO, + Lto::Thin | Lto::ThinLocal => llvm::OptStage::PreLinkThinLTO, + _ if cgcx.opts.cg.linker_plugin_lto.enabled() => llvm::OptStage::PreLinkThinLTO, + _ => llvm::OptStage::PreLinkNoLTO, + }; + return optimize(cgcx, diag_handler, module, config, opt_level, opt_stage); } Ok(()) } -unsafe fn add_sanitizer_passes(config: &ModuleConfig, passes: &mut Vec<&'static mut llvm::Pass>) { - if config.sanitizer.contains(SanitizerSet::ADDRESS) { - let recover = config.sanitizer_recover.contains(SanitizerSet::ADDRESS); - passes.push(llvm::LLVMRustCreateAddressSanitizerFunctionPass(recover)); - passes.push(llvm::LLVMRustCreateModuleAddressSanitizerPass(recover)); - } - if config.sanitizer.contains(SanitizerSet::MEMORY) { - let track_origins = config.sanitizer_memory_track_origins as c_int; - let recover = config.sanitizer_recover.contains(SanitizerSet::MEMORY); - passes.push(llvm::LLVMRustCreateMemorySanitizerPass(track_origins, recover)); - } - if config.sanitizer.contains(SanitizerSet::THREAD) { - passes.push(llvm::LLVMRustCreateThreadSanitizerPass()); - } - if config.sanitizer.contains(SanitizerSet::HWADDRESS) { - let recover = config.sanitizer_recover.contains(SanitizerSet::HWADDRESS); - passes.push(llvm::LLVMRustCreateHWAddressSanitizerPass(recover)); - } -} - pub(crate) fn link( cgcx: &CodegenContext, diag_handler: &Handler, @@ -1072,72 +901,6 @@ unsafe fn embed_bitcode( } } -pub unsafe fn with_llvm_pmb( - llmod: &llvm::Module, - config: &ModuleConfig, - opt_level: llvm::CodeGenOptLevel, - prepare_for_thin_lto: bool, - f: &mut dyn FnMut(&llvm::PassManagerBuilder), -) { - use std::ptr; - - // Create the PassManagerBuilder for LLVM. We configure it with - // reasonable defaults and prepare it to actually populate the pass - // manager. - let builder = llvm::LLVMRustPassManagerBuilderCreate(); - let opt_size = config.opt_size.map_or(llvm::CodeGenOptSizeNone, |x| to_llvm_opt_settings(x).1); - let inline_threshold = config.inline_threshold; - let pgo_gen_path = get_pgo_gen_path(config); - let pgo_use_path = get_pgo_use_path(config); - let pgo_sample_use_path = get_pgo_sample_use_path(config); - - llvm::LLVMRustConfigurePassManagerBuilder( - builder, - opt_level, - config.merge_functions, - config.vectorize_slp, - config.vectorize_loop, - prepare_for_thin_lto, - pgo_gen_path.as_ref().map_or(ptr::null(), |s| s.as_ptr()), - pgo_use_path.as_ref().map_or(ptr::null(), |s| s.as_ptr()), - pgo_sample_use_path.as_ref().map_or(ptr::null(), |s| s.as_ptr()), - opt_size as c_int, - ); - - llvm::LLVMRustAddBuilderLibraryInfo(builder, llmod, config.no_builtins); - - // Here we match what clang does (kinda). For O0 we only inline - // always-inline functions (but don't add lifetime intrinsics), at O1 we - // inline with lifetime intrinsics, and O2+ we add an inliner with a - // thresholds copied from clang. - match (opt_level, opt_size, inline_threshold) { - (.., Some(t)) => { - llvm::LLVMRustPassManagerBuilderUseInlinerWithThreshold(builder, t); - } - (llvm::CodeGenOptLevel::Aggressive, ..) => { - llvm::LLVMRustPassManagerBuilderUseInlinerWithThreshold(builder, 275); - } - (_, llvm::CodeGenOptSizeDefault, _) => { - llvm::LLVMRustPassManagerBuilderUseInlinerWithThreshold(builder, 75); - } - (_, llvm::CodeGenOptSizeAggressive, _) => { - llvm::LLVMRustPassManagerBuilderUseInlinerWithThreshold(builder, 25); - } - (llvm::CodeGenOptLevel::None, ..) => { - llvm::LLVMRustAddAlwaysInlinePass(builder, config.emit_lifetime_markers); - } - (llvm::CodeGenOptLevel::Less, ..) => { - llvm::LLVMRustAddAlwaysInlinePass(builder, config.emit_lifetime_markers); - } - (llvm::CodeGenOptLevel::Default, ..) => { - llvm::LLVMRustPassManagerBuilderUseInlinerWithThreshold(builder, 225); - } - } - - f(builder); - llvm::LLVMRustPassManagerBuilderDispose(builder); -} - // Create a `__imp_ = &symbol` global for every public static `symbol`. // This is required to satisfy `dllimport` references to static data in .rlibs // when using MSVC linker. We do this only for data, as linker can fix up diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs index 42c65e04e3b6b..518f9a45733c1 100644 --- a/compiler/rustc_codegen_llvm/src/lib.rs +++ b/compiler/rustc_codegen_llvm/src/lib.rs @@ -207,7 +207,7 @@ impl WriteBackendMethods for LlvmCodegenBackend { module: &ModuleCodegen, config: &ModuleConfig, ) -> Result<(), FatalError> { - back::write::optimize(cgcx, diag_handler, module, config) + back::write::maybe_optimize(cgcx, diag_handler, module, config) } fn optimize_fat( cgcx: &CodegenContext, diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index ce27dc5a5d1ea..801650c3fb13d 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -1810,18 +1810,9 @@ extern "C" { /// Writes a module to the specified path. Returns 0 on success. pub fn LLVMWriteBitcodeToFile(M: &Module, Path: *const c_char) -> c_int; - /// Creates a pass manager. + /// Creates a legacy pass manager -- only used for final codegen. pub fn LLVMCreatePassManager<'a>() -> &'a mut PassManager<'a>; - /// Creates a function-by-function pass manager - pub fn LLVMCreateFunctionPassManagerForModule(M: &Module) -> &mut PassManager<'_>; - - /// Disposes a pass manager. - pub fn LLVMDisposePassManager<'a>(PM: &'a mut PassManager<'a>); - - /// Runs a pass manager on a module. - pub fn LLVMRunPassManager<'a>(PM: &PassManager<'a>, M: &'a Module) -> Bool; - pub fn LLVMInitializePasses(); pub fn LLVMTimeTraceProfilerInitialize(); @@ -1832,32 +1823,6 @@ extern "C" { pub fn LLVMAddAnalysisPasses<'a>(T: &'a TargetMachine, PM: &PassManager<'a>); - pub fn LLVMRustPassManagerBuilderCreate() -> &'static mut PassManagerBuilder; - pub fn LLVMRustPassManagerBuilderDispose(PMB: &'static mut PassManagerBuilder); - pub fn LLVMRustPassManagerBuilderUseInlinerWithThreshold( - PMB: &PassManagerBuilder, - threshold: c_uint, - ); - pub fn LLVMRustPassManagerBuilderPopulateModulePassManager( - PMB: &PassManagerBuilder, - PM: &PassManager<'_>, - ); - - pub fn LLVMRustPassManagerBuilderPopulateFunctionPassManager( - PMB: &PassManagerBuilder, - PM: &PassManager<'_>, - ); - pub fn LLVMRustPassManagerBuilderPopulateLTOPassManager( - PMB: &PassManagerBuilder, - PM: &PassManager<'_>, - Internalize: Bool, - RunInliner: Bool, - ); - pub fn LLVMRustPassManagerBuilderPopulateThinLTOPassManager( - PMB: &PassManagerBuilder, - PM: &PassManager<'_>, - ); - pub fn LLVMGetHostCPUFeatures() -> *mut c_char; pub fn LLVMDisposeMessage(message: *mut c_char); @@ -2262,22 +2227,6 @@ extern "C" { pub fn LLVMIsAConstantInt(value_ref: &Value) -> Option<&ConstantInt>; - pub fn LLVMRustFindAndCreatePass(Pass: *const c_char) -> Option<&'static mut Pass>; - pub fn LLVMRustCreateAddressSanitizerFunctionPass(Recover: bool) -> &'static mut Pass; - pub fn LLVMRustCreateModuleAddressSanitizerPass(Recover: bool) -> &'static mut Pass; - pub fn LLVMRustCreateMemorySanitizerPass( - TrackOrigins: c_int, - Recover: bool, - ) -> &'static mut Pass; - pub fn LLVMRustCreateThreadSanitizerPass() -> &'static mut Pass; - pub fn LLVMRustCreateHWAddressSanitizerPass(Recover: bool) -> &'static mut Pass; - pub fn LLVMRustAddPass(PM: &PassManager<'_>, Pass: &'static mut Pass); - pub fn LLVMRustAddLastExtensionPasses( - PMB: &PassManagerBuilder, - Passes: *const &'static mut Pass, - NumPasses: size_t, - ); - pub fn LLVMRustHasFeature(T: &TargetMachine, s: *const c_char) -> bool; pub fn LLVMRustPrintTargetCPUs(T: &TargetMachine); @@ -2311,29 +2260,11 @@ extern "C" { SplitDwarfFile: *const c_char, ) -> Option<&'static mut TargetMachine>; pub fn LLVMRustDisposeTargetMachine(T: &'static mut TargetMachine); - pub fn LLVMRustAddBuilderLibraryInfo<'a>( - PMB: &'a PassManagerBuilder, - M: &'a Module, - DisableSimplifyLibCalls: bool, - ); - pub fn LLVMRustConfigurePassManagerBuilder( - PMB: &PassManagerBuilder, - OptLevel: CodeGenOptLevel, - MergeFunctions: bool, - SLPVectorize: bool, - LoopVectorize: bool, - PrepareForThinLTO: bool, - PGOGenPath: *const c_char, - PGOUsePath: *const c_char, - PGOSampleUsePath: *const c_char, - SizeLevel: c_int, - ); pub fn LLVMRustAddLibraryInfo<'a>( PM: &PassManager<'a>, M: &'a Module, DisableSimplifyLibCalls: bool, ); - pub fn LLVMRustRunFunctionPassManager<'a>(PM: &PassManager<'a>, M: &'a Module); pub fn LLVMRustWriteOutputFile<'a>( T: &'a TargetMachine, PM: &PassManager<'a>, @@ -2342,7 +2273,7 @@ extern "C" { DwoOutput: *const c_char, FileType: FileType, ) -> LLVMRustResult; - pub fn LLVMRustOptimizeWithNewPassManager<'a>( + pub fn LLVMRustOptimize<'a>( M: &'a Module, TM: &'a TargetMachine, OptLevel: PassBuilderOptLevel, @@ -2380,7 +2311,6 @@ extern "C" { pub fn LLVMRustSetLLVMOptions(Argc: c_int, Argv: *const *const c_char); pub fn LLVMRustPrintPasses(); pub fn LLVMRustSetNormalizedTarget(M: &Module, triple: *const c_char); - pub fn LLVMRustAddAlwaysInlinePass(P: &PassManagerBuilder, AddLifetimes: bool); pub fn LLVMRustRunRestrictionPass(M: &Module, syms: *const *const c_char, len: size_t); pub fn LLVMRustOpenArchive(path: *const c_char) -> Option<&'static mut Archive>; diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index 60707a1c34e85..2fd58567c4874 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -1,7 +1,6 @@ use crate::back::write::create_informational_target_machine; -use crate::{llvm, llvm_util}; +use crate::llvm; use libc::c_int; -use libloading::Library; use rustc_codegen_ssa::target_features::{ supported_target_features, tied_target_features, RUSTC_SPECIFIC_FEATURES, }; @@ -16,7 +15,6 @@ use rustc_target::spec::{MergeFunctions, PanicStrategy}; use smallvec::{smallvec, SmallVec}; use std::ffi::{CStr, CString}; -use std::mem; use std::path::Path; use std::ptr; use std::slice; @@ -120,22 +118,6 @@ unsafe fn configure_llvm(sess: &Session) { llvm::LLVMInitializePasses(); - // Use the legacy plugin registration if we don't use the new pass manager - if !should_use_new_llvm_pass_manager( - &sess.opts.unstable_opts.new_llvm_pass_manager, - &sess.target.arch, - ) { - // Register LLVM plugins by loading them into the compiler process. - for plugin in &sess.opts.unstable_opts.llvm_plugins { - let lib = Library::new(plugin).unwrap_or_else(|e| bug!("couldn't load plugin: {}", e)); - debug!("LLVM plugin loaded successfully {:?} ({})", lib, plugin); - - // Intentionally leak the dynamic library. We can't ever unload it - // since the library can make things that will live arbitrarily long. - mem::forget(lib); - } - } - rustc_llvm::initialize_available_targets(); llvm::LLVMRustSetLLVMOptions(llvm_args.len() as c_int, llvm_args.as_ptr()); @@ -539,19 +521,3 @@ pub fn tune_cpu(sess: &Session) -> Option<&str> { let name = sess.opts.unstable_opts.tune_cpu.as_ref()?; Some(handle_native(name)) } - -pub(crate) fn should_use_new_llvm_pass_manager(user_opt: &Option, target_arch: &str) -> bool { - // The new pass manager is enabled by default for LLVM >= 13. - // This matches Clang, which also enables it since Clang 13. - - // Since LLVM 15, the legacy pass manager is no longer supported. - if llvm_util::get_version() >= (15, 0, 0) { - return true; - } - - // There are some perf issues with the new pass manager when targeting - // s390x with LLVM 13, so enable the new pass manager only with LLVM 14. - // See https://github.com/rust-lang/rust/issues/89609. - let min_version = if target_arch == "s390x" { 14 } else { 13 }; - user_opt.unwrap_or_else(|| llvm_util::get_version() >= (min_version, 0, 0)) -} diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp index 24e1882604898..4cfdd31973c58 100644 --- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp @@ -93,172 +93,6 @@ extern "C" void LLVMTimeTraceProfilerFinish(const char* FileName) { timeTraceProfilerCleanup(); } -extern "C" LLVMPassRef LLVMRustFindAndCreatePass(const char *PassName) { -#if LLVM_VERSION_LT(15, 0) - StringRef SR(PassName); - PassRegistry *PR = PassRegistry::getPassRegistry(); - - const PassInfo *PI = PR->getPassInfo(SR); - if (PI) { - return wrap(PI->createPass()); - } - return nullptr; -#else - report_fatal_error("Legacy PM not supported with LLVM 15"); -#endif -} - -extern "C" LLVMPassRef LLVMRustCreateAddressSanitizerFunctionPass(bool Recover) { -#if LLVM_VERSION_LT(15, 0) - const bool CompileKernel = false; - const bool UseAfterScope = true; - - return wrap(createAddressSanitizerFunctionPass(CompileKernel, Recover, UseAfterScope)); -#else - report_fatal_error("Legacy PM not supported with LLVM 15"); -#endif -} - -extern "C" LLVMPassRef LLVMRustCreateModuleAddressSanitizerPass(bool Recover) { -#if LLVM_VERSION_LT(15, 0) - const bool CompileKernel = false; - - return wrap(createModuleAddressSanitizerLegacyPassPass(CompileKernel, Recover)); -#else - report_fatal_error("Legacy PM not supported with LLVM 15"); -#endif -} - -extern "C" LLVMPassRef LLVMRustCreateMemorySanitizerPass(int TrackOrigins, bool Recover) { -#if LLVM_VERSION_LT(15, 0) - const bool CompileKernel = false; - - return wrap(createMemorySanitizerLegacyPassPass( -#if LLVM_VERSION_GE(14, 0) - MemorySanitizerOptions{TrackOrigins, Recover, CompileKernel, /*EagerChecks=*/true} -#else - MemorySanitizerOptions{TrackOrigins, Recover, CompileKernel} -#endif - )); -#else - report_fatal_error("Legacy PM not supported with LLVM 15"); -#endif -} - -extern "C" LLVMPassRef LLVMRustCreateThreadSanitizerPass() { -#if LLVM_VERSION_LT(15, 0) - return wrap(createThreadSanitizerLegacyPassPass()); -#else - report_fatal_error("Legacy PM not supported with LLVM 15"); -#endif -} - -extern "C" LLVMPassRef LLVMRustCreateHWAddressSanitizerPass(bool Recover) { -#if LLVM_VERSION_LT(15, 0) - const bool CompileKernel = false; - - return wrap(createHWAddressSanitizerLegacyPassPass(CompileKernel, Recover)); -#else - report_fatal_error("Legacy PM not supported with LLVM 15"); -#endif -} - -extern "C" void LLVMRustAddPass(LLVMPassManagerRef PMR, LLVMPassRef RustPass) { -#if LLVM_VERSION_LT(15, 0) - assert(RustPass); - Pass *Pass = unwrap(RustPass); - PassManagerBase *PMB = unwrap(PMR); - PMB->add(Pass); -#else - report_fatal_error("Legacy PM not supported with LLVM 15"); -#endif -} - -extern "C" LLVMPassManagerBuilderRef LLVMRustPassManagerBuilderCreate() { -#if LLVM_VERSION_LT(15, 0) - return LLVMPassManagerBuilderCreate(); -#else - report_fatal_error("Legacy PM not supported with LLVM 15"); -#endif -} - -extern "C" void LLVMRustPassManagerBuilderDispose(LLVMPassManagerBuilderRef PMB) { -#if LLVM_VERSION_LT(15, 0) - LLVMPassManagerBuilderDispose(PMB); -#else - report_fatal_error("Legacy PM not supported with LLVM 15"); -#endif -} - -extern "C" void LLVMRustPassManagerBuilderPopulateFunctionPassManager( - LLVMPassManagerBuilderRef PMB, LLVMPassManagerRef PM) { -#if LLVM_VERSION_LT(15, 0) - LLVMPassManagerBuilderPopulateFunctionPassManager(PMB, PM); -#else - report_fatal_error("Legacy PM not supported with LLVM 15"); -#endif -} - -extern "C" void LLVMRustPassManagerBuilderPopulateModulePassManager( - LLVMPassManagerBuilderRef PMB, LLVMPassManagerRef PM) { -#if LLVM_VERSION_LT(15, 0) - LLVMPassManagerBuilderPopulateModulePassManager(PMB, PM); -#else - report_fatal_error("Legacy PM not supported with LLVM 15"); -#endif -} - -extern "C" void LLVMRustPassManagerBuilderPopulateLTOPassManager( - LLVMPassManagerBuilderRef PMB, LLVMPassManagerRef PM, bool Internalize, bool RunInliner) { -#if LLVM_VERSION_LT(15, 0) - LLVMPassManagerBuilderPopulateLTOPassManager(PMB, PM, Internalize, RunInliner); -#else - report_fatal_error("Legacy PM not supported with LLVM 15"); -#endif -} - -extern "C" -void LLVMRustPassManagerBuilderPopulateThinLTOPassManager( - LLVMPassManagerBuilderRef PMBR, - LLVMPassManagerRef PMR -) { -#if LLVM_VERSION_LT(15, 0) - unwrap(PMBR)->populateThinLTOPassManager(*unwrap(PMR)); -#else - report_fatal_error("Legacy PM not supported with LLVM 15"); -#endif -} - -extern "C" void LLVMRustPassManagerBuilderUseInlinerWithThreshold( - LLVMPassManagerBuilderRef PMB, unsigned Threshold) { -#if LLVM_VERSION_LT(15, 0) - LLVMPassManagerBuilderUseInlinerWithThreshold(PMB, Threshold); -#else - report_fatal_error("Legacy PM not supported with LLVM 15"); -#endif -} - -extern "C" -void LLVMRustAddLastExtensionPasses( - LLVMPassManagerBuilderRef PMBR, LLVMPassRef *Passes, size_t NumPasses) { -#if LLVM_VERSION_LT(15, 0) - auto AddExtensionPasses = [Passes, NumPasses]( - const PassManagerBuilder &Builder, PassManagerBase &PM) { - for (size_t I = 0; I < NumPasses; I++) { - PM.add(unwrap(Passes[I])); - } - }; - // Add the passes to both of the pre-finalization extension points, - // so they are run for optimized and non-optimized builds. - unwrap(PMBR)->addExtension(PassManagerBuilder::EP_OptimizerLast, - AddExtensionPasses); - unwrap(PMBR)->addExtension(PassManagerBuilder::EP_EnabledOnOptLevel0, - AddExtensionPasses); -#else - report_fatal_error("Legacy PM not supported with LLVM 15"); -#endif -} - #ifdef LLVM_COMPONENT_X86 #define SUBTARGET_X86 SUBTARGET(X86) #else @@ -604,47 +438,6 @@ extern "C" void LLVMRustDisposeTargetMachine(LLVMTargetMachineRef TM) { delete unwrap(TM); } -extern "C" void LLVMRustConfigurePassManagerBuilder( - LLVMPassManagerBuilderRef PMBR, LLVMRustCodeGenOptLevel OptLevel, - bool MergeFunctions, bool SLPVectorize, bool LoopVectorize, bool PrepareForThinLTO, - const char* PGOGenPath, const char* PGOUsePath, const char* PGOSampleUsePath, - int SizeLevel) { -#if LLVM_VERSION_LT(15, 0) - unwrap(PMBR)->MergeFunctions = MergeFunctions; - unwrap(PMBR)->SLPVectorize = SLPVectorize; - unwrap(PMBR)->OptLevel = fromRust(OptLevel); - unwrap(PMBR)->LoopVectorize = LoopVectorize; - unwrap(PMBR)->PrepareForThinLTO = PrepareForThinLTO; - unwrap(PMBR)->SizeLevel = SizeLevel; - unwrap(PMBR)->DisableUnrollLoops = SizeLevel != 0; - - if (PGOGenPath) { - assert(!PGOUsePath && !PGOSampleUsePath); - unwrap(PMBR)->EnablePGOInstrGen = true; - unwrap(PMBR)->PGOInstrGen = PGOGenPath; - } else if (PGOUsePath) { - assert(!PGOSampleUsePath); - unwrap(PMBR)->PGOInstrUse = PGOUsePath; - } else if (PGOSampleUsePath) { - unwrap(PMBR)->PGOSampleUse = PGOSampleUsePath; - } -#else - report_fatal_error("Legacy PM not supported with LLVM 15"); -#endif -} - -// Unfortunately, the LLVM C API doesn't provide a way to set the `LibraryInfo` -// field of a PassManagerBuilder, we expose our own method of doing so. -extern "C" void LLVMRustAddBuilderLibraryInfo(LLVMPassManagerBuilderRef PMBR, - LLVMModuleRef M, - bool DisableSimplifyLibCalls) { - Triple TargetTriple(unwrap(M)->getTargetTriple()); - TargetLibraryInfoImpl *TLI = new TargetLibraryInfoImpl(TargetTriple); - if (DisableSimplifyLibCalls) - TLI->disableAllFunctions(); - unwrap(PMBR)->LibraryInfo = TLI; -} - // Unfortunately, the LLVM C API doesn't provide a way to create the // TargetLibraryInfo pass, so we use this method to do so. extern "C" void LLVMRustAddLibraryInfo(LLVMPassManagerRef PMR, LLVMModuleRef M, @@ -656,27 +449,6 @@ extern "C" void LLVMRustAddLibraryInfo(LLVMPassManagerRef PMR, LLVMModuleRef M, unwrap(PMR)->add(new TargetLibraryInfoWrapperPass(TLII)); } -// Unfortunately, the LLVM C API doesn't provide an easy way of iterating over -// all the functions in a module, so we do that manually here. You'll find -// similar code in clang's BackendUtil.cpp file. -extern "C" void LLVMRustRunFunctionPassManager(LLVMPassManagerRef PMR, - LLVMModuleRef M) { - llvm::legacy::FunctionPassManager *P = - unwrap(PMR); - P->doInitialization(); - - // Upgrade all calls to old intrinsics first. - for (Module::iterator I = unwrap(M)->begin(), E = unwrap(M)->end(); I != E;) - UpgradeCallsToIntrinsic(&*I++); // must be post-increment, as we remove - - for (Module::iterator I = unwrap(M)->begin(), E = unwrap(M)->end(); I != E; - ++I) - if (!I->isDeclaration()) - P->run(*I); - - P->doFinalization(); -} - extern "C" void LLVMRustSetLLVMOptions(int Argc, char **Argv) { // Initializing the command-line options more than once is not allowed. So, // check if they've already been initialized. (This could happen if we're @@ -820,7 +592,7 @@ struct LLVMRustSanitizerOptions { }; extern "C" LLVMRustResult -LLVMRustOptimizeWithNewPassManager( +LLVMRustOptimize( LLVMModuleRef ModuleRef, LLVMTargetMachineRef TMRef, LLVMRustPassBuilderOptLevel OptLevelRust, @@ -1241,11 +1013,6 @@ extern "C" void LLVMRustPrintPasses() { PR->enumerateWith(&Listener); } -extern "C" void LLVMRustAddAlwaysInlinePass(LLVMPassManagerBuilderRef PMBR, - bool AddLifetimes) { - unwrap(PMBR)->Inliner = llvm::createAlwaysInlinerLegacyPass(AddLifetimes); -} - extern "C" void LLVMRustRunRestrictionPass(LLVMModuleRef M, char **Symbols, size_t Len) { llvm::legacy::PassManager passes; From 38e0e8f7bb5060d6a656d0d17dd119f9e3482e67 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Fri, 16 Sep 2022 16:37:17 -0700 Subject: [PATCH 060/586] Remove -Znew-llvm-pass-manager --- compiler/rustc_codegen_llvm/src/back/write.rs | 4 ---- compiler/rustc_codegen_ssa/src/back/write.rs | 2 -- compiler/rustc_interface/src/tests.rs | 1 - compiler/rustc_session/src/options.rs | 2 -- .../unstable-book/src/compiler-flags/self-profile-events.md | 2 +- src/test/rustdoc-ui/z-help.stdout | 1 - src/test/ui/invalid/invalid-llvm-passes.rs | 2 +- src/test/ui/sanitize/new-llvm-pass-manager-thin-lto.rs | 2 +- 8 files changed, 3 insertions(+), 13 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs index 6280bf6cdc2cf..92a44a9f426c7 100644 --- a/compiler/rustc_codegen_llvm/src/back/write.rs +++ b/compiler/rustc_codegen_llvm/src/back/write.rs @@ -513,10 +513,6 @@ pub(crate) unsafe fn maybe_optimize( let module_name = module.name.clone(); let module_name = Some(&module_name[..]); - if let Some(false) = config.new_llvm_pass_manager { - diag_handler.warn("ignoring `-Z new-llvm-pass-manager=no`, which is no longer supported"); - } - if config.emit_no_opt_bc { let out = cgcx.output_filenames.temp_path_ext("no-opt.bc", module_name); let out = path_to_c_string(&out); diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index 68f3b19b715ad..680b9b642d9b2 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -113,7 +113,6 @@ pub struct ModuleConfig { pub vectorize_slp: bool, pub merge_functions: bool, pub inline_threshold: Option, - pub new_llvm_pass_manager: Option, pub emit_lifetime_markers: bool, pub llvm_plugins: Vec, } @@ -265,7 +264,6 @@ impl ModuleConfig { }, inline_threshold: sess.opts.cg.inline_threshold, - new_llvm_pass_manager: sess.opts.unstable_opts.new_llvm_pass_manager, emit_lifetime_markers: sess.emit_lifetime_markers(), llvm_plugins: if_regular!(sess.opts.unstable_opts.llvm_plugins.clone(), vec![]), } diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index c7615a5775e33..2cd959689e6cf 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -758,7 +758,6 @@ fn test_unstable_options_tracking_hash() { tracked!(mir_opt_level, Some(4)); tracked!(move_size_limit, Some(4096)); tracked!(mutable_noalias, Some(true)); - tracked!(new_llvm_pass_manager, Some(true)); tracked!(no_generate_arange_section, true); tracked!(no_link, true); tracked!(no_unique_section_names, true); diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index d7f1bc0be8415..486c514a4f5c2 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -1409,8 +1409,6 @@ options! { "the size at which the `large_assignments` lint starts to be emitted"), mutable_noalias: Option = (None, parse_opt_bool, [TRACKED], "emit noalias metadata for mutable references (default: yes)"), - new_llvm_pass_manager: Option = (None, parse_opt_bool, [TRACKED], - "use new LLVM pass manager (default: no)"), nll_facts: bool = (false, parse_bool, [UNTRACKED], "dump facts from NLL analysis into side files (default: no)"), nll_facts_dir: String = ("nll-facts".to_string(), parse_string, [UNTRACKED], diff --git a/src/doc/unstable-book/src/compiler-flags/self-profile-events.md b/src/doc/unstable-book/src/compiler-flags/self-profile-events.md index 3ce18743be508..b7d60409e0006 100644 --- a/src/doc/unstable-book/src/compiler-flags/self-profile-events.md +++ b/src/doc/unstable-book/src/compiler-flags/self-profile-events.md @@ -41,7 +41,7 @@ $ rustc -Zself-profile -Zself-profile-events=default,args - `llvm` - Adds tracing information about LLVM passes and codegeneration. - - Disabled by default because this only works when `-Znew-llvm-pass-manager` is enabled. + - Disabled by default for historical reasons. ## Event synonyms diff --git a/src/test/rustdoc-ui/z-help.stdout b/src/test/rustdoc-ui/z-help.stdout index 749abe36419d0..25d5c6e4ad2b9 100644 --- a/src/test/rustdoc-ui/z-help.stdout +++ b/src/test/rustdoc-ui/z-help.stdout @@ -82,7 +82,6 @@ -Z mir-opt-level=val -- MIR optimization level (0-4; default: 1 in non optimized builds and 2 in optimized builds) -Z move-size-limit=val -- the size at which the `large_assignments` lint starts to be emitted -Z mutable-noalias=val -- emit noalias metadata for mutable references (default: yes) - -Z new-llvm-pass-manager=val -- use new LLVM pass manager (default: no) -Z nll-facts=val -- dump facts from NLL analysis into side files (default: no) -Z nll-facts-dir=val -- the directory the NLL facts are dumped into (default: `nll-facts`) -Z no-analysis=val -- parse and expand the source, but run no analysis diff --git a/src/test/ui/invalid/invalid-llvm-passes.rs b/src/test/ui/invalid/invalid-llvm-passes.rs index ca3c6230af04a..ee28f5eb6d665 100644 --- a/src/test/ui/invalid/invalid-llvm-passes.rs +++ b/src/test/ui/invalid/invalid-llvm-passes.rs @@ -1,4 +1,4 @@ // build-fail -// compile-flags: -Cpasses=unknown-pass -Z new-llvm-pass-manager=yes +// compile-flags: -Cpasses=unknown-pass fn main() {} diff --git a/src/test/ui/sanitize/new-llvm-pass-manager-thin-lto.rs b/src/test/ui/sanitize/new-llvm-pass-manager-thin-lto.rs index 1542c7f311848..33e18e35522ec 100644 --- a/src/test/ui/sanitize/new-llvm-pass-manager-thin-lto.rs +++ b/src/test/ui/sanitize/new-llvm-pass-manager-thin-lto.rs @@ -7,7 +7,7 @@ // // no-prefer-dynamic // revisions: opt0 opt1 -// compile-flags: -Znew-llvm-pass-manager=yes -Zsanitizer=address -Clto=thin +// compile-flags: -Zsanitizer=address -Clto=thin //[opt0]compile-flags: -Copt-level=0 //[opt1]compile-flags: -Copt-level=1 // run-fail From d6318de13a470cab542c572e4450866b5307dd8b Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Sun, 18 Sep 2022 11:53:38 -0700 Subject: [PATCH 061/586] Never use legacy PM for writing bitcode --- compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp | 14 ++------------ compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp | 8 ++------ 2 files changed, 4 insertions(+), 18 deletions(-) diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp index 4cfdd31973c58..349c16f074579 100644 --- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp @@ -31,13 +31,11 @@ #include "llvm/Transforms/IPO/PassManagerBuilder.h" #include "llvm/Transforms/IPO/AlwaysInliner.h" #include "llvm/Transforms/IPO/FunctionImport.h" -#if LLVM_VERSION_GE(15, 0) #include "llvm/Transforms/IPO/ThinLTOBitcodeWriter.h" -#endif #include "llvm/Transforms/Utils/AddDiscriminators.h" #include "llvm/Transforms/Utils/FunctionImportUtils.h" #include "llvm/LTO/LTO.h" -#include "llvm/Bitcode/BitcodeWriterPass.h" +#include "llvm/Bitcode/BitcodeWriter.h" #include "llvm-c/Transforms/PassManagerBuilder.h" #include "llvm/Transforms/Instrumentation.h" @@ -1377,11 +1375,6 @@ LLVMRustThinLTOBufferCreate(LLVMModuleRef M, bool is_thin) { raw_string_ostream OS(Ret->data); { if (is_thin) { -#if LLVM_VERSION_LT(15, 0) - legacy::PassManager PM; - PM.add(createWriteThinLTOBitcodePass(OS)); - PM.run(*unwrap(M)); -#else PassBuilder PB; LoopAnalysisManager LAM; FunctionAnalysisManager FAM; @@ -1395,11 +1388,8 @@ LLVMRustThinLTOBufferCreate(LLVMModuleRef M, bool is_thin) { ModulePassManager MPM; MPM.addPass(ThinLTOBitcodeWriterPass(OS, nullptr)); MPM.run(*unwrap(M), MAM); -#endif } else { - legacy::PassManager PM; - PM.add(createBitcodeWriterPass(OS)); - PM.run(*unwrap(M)); + WriteBitcodeToFile(*unwrap(M), OS); } } } diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp index 6ee3c7d68213e..a908e3457386f 100644 --- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp @@ -12,7 +12,7 @@ #include "llvm/Object/COFFImportFile.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Pass.h" -#include "llvm/Bitcode/BitcodeWriterPass.h" +#include "llvm/Bitcode/BitcodeWriter.h" #include "llvm/Support/Signals.h" #include "llvm/ADT/Optional.h" @@ -1709,11 +1709,7 @@ LLVMRustModuleBufferCreate(LLVMModuleRef M) { auto Ret = std::make_unique(); { raw_string_ostream OS(Ret->data); - { - legacy::PassManager PM; - PM.add(createBitcodeWriterPass(OS)); - PM.run(*unwrap(M)); - } + WriteBitcodeToFile(*unwrap(M), OS); } return Ret.release(); } From 04a318e13edf4064aa8500907c355dabeb81b2b7 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Sun, 18 Sep 2022 12:17:53 -0700 Subject: [PATCH 062/586] Use the helper for internalizing with new PM --- compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp index 349c16f074579..09f377d349f45 100644 --- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp @@ -31,6 +31,7 @@ #include "llvm/Transforms/IPO/PassManagerBuilder.h" #include "llvm/Transforms/IPO/AlwaysInliner.h" #include "llvm/Transforms/IPO/FunctionImport.h" +#include "llvm/Transforms/IPO/Internalize.h" #include "llvm/Transforms/IPO/ThinLTOBitcodeWriter.h" #include "llvm/Transforms/Utils/AddDiscriminators.h" #include "llvm/Transforms/Utils/FunctionImportUtils.h" @@ -1013,8 +1014,6 @@ extern "C" void LLVMRustPrintPasses() { extern "C" void LLVMRustRunRestrictionPass(LLVMModuleRef M, char **Symbols, size_t Len) { - llvm::legacy::PassManager passes; - auto PreserveFunctions = [=](const GlobalValue &GV) { for (size_t I = 0; I < Len; I++) { if (GV.getName() == Symbols[I]) { @@ -1024,9 +1023,7 @@ extern "C" void LLVMRustRunRestrictionPass(LLVMModuleRef M, char **Symbols, return false; }; - passes.add(llvm::createInternalizePass(PreserveFunctions)); - - passes.run(*unwrap(M)); + internalizeModule(*unwrap(M), PreserveFunctions); } extern "C" void From 29124c7fd0c24a439de86bb1d9791dc65adc8f47 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Sun, 18 Sep 2022 15:37:21 -0700 Subject: [PATCH 063/586] Update the reason llvm tracing is disabled by default Co-authored-by: Andreas Jonson --- src/doc/unstable-book/src/compiler-flags/self-profile-events.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/unstable-book/src/compiler-flags/self-profile-events.md b/src/doc/unstable-book/src/compiler-flags/self-profile-events.md index b7d60409e0006..3e644f786f678 100644 --- a/src/doc/unstable-book/src/compiler-flags/self-profile-events.md +++ b/src/doc/unstable-book/src/compiler-flags/self-profile-events.md @@ -41,7 +41,7 @@ $ rustc -Zself-profile -Zself-profile-events=default,args - `llvm` - Adds tracing information about LLVM passes and codegeneration. - - Disabled by default for historical reasons. + - Disabled by default because this significantly increases the trace file size. ## Event synonyms From 71f8fd5c5859fa09587486351f849277a910e4d9 Mon Sep 17 00:00:00 2001 From: lcnr Date: Mon, 19 Sep 2022 14:59:52 +0200 Subject: [PATCH 064/586] improve infer var handling for implied bounds --- .../rustc_infer/src/infer/outlives/env.rs | 2 + .../src/traits/outlives_bounds.rs | 3 +- .../src/implied_outlives_bounds.rs | 69 ++++++++++--------- .../rustc_typeck/src/check/compare_method.rs | 1 + 4 files changed, 41 insertions(+), 34 deletions(-) diff --git a/compiler/rustc_infer/src/infer/outlives/env.rs b/compiler/rustc_infer/src/infer/outlives/env.rs index 872886da36261..9922b156ebf96 100644 --- a/compiler/rustc_infer/src/infer/outlives/env.rs +++ b/compiler/rustc_infer/src/infer/outlives/env.rs @@ -53,6 +53,7 @@ pub struct OutlivesEnvironment<'tcx> { } /// Builder of OutlivesEnvironment. +#[derive(Debug)] struct OutlivesEnvironmentBuilder<'tcx> { param_env: ty::ParamEnv<'tcx>, region_relation: TransitiveRelationBuilder>, @@ -109,6 +110,7 @@ impl<'tcx> OutlivesEnvironment<'tcx> { impl<'a, 'tcx> OutlivesEnvironmentBuilder<'tcx> { #[inline] + #[instrument(level = "debug")] fn build(self) -> OutlivesEnvironment<'tcx> { OutlivesEnvironment { param_env: self.param_env, diff --git a/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs b/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs index a4b540182280b..3008dfcadde9e 100644 --- a/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs +++ b/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs @@ -46,7 +46,7 @@ impl<'a, 'cx, 'tcx: 'a> InferCtxtExt<'a, 'tcx> for InferCtxt<'cx, 'tcx> { /// Note that this may cause outlives obligations to be injected /// into the inference context with this body-id. /// - `ty`, the type that we are supposed to assume is WF. - #[instrument(level = "debug", skip(self, param_env, body_id))] + #[instrument(level = "debug", skip(self, param_env, body_id), ret)] fn implied_outlives_bounds( &self, param_env: ty::ParamEnv<'tcx>, @@ -71,6 +71,7 @@ impl<'a, 'cx, 'tcx: 'a> InferCtxtExt<'a, 'tcx> for InferCtxt<'cx, 'tcx> { let TypeOpOutput { output, constraints, .. } = result; if let Some(constraints) = constraints { + debug!(?constraints); // Instantiation may have produced new inference variables and constraints on those // variables. Process these constraints. let mut fulfill_cx = >::new(self.tcx); diff --git a/compiler/rustc_traits/src/implied_outlives_bounds.rs b/compiler/rustc_traits/src/implied_outlives_bounds.rs index e3e78f70b15ef..691b79f10533d 100644 --- a/compiler/rustc_traits/src/implied_outlives_bounds.rs +++ b/compiler/rustc_traits/src/implied_outlives_bounds.rs @@ -49,7 +49,8 @@ fn compute_implied_outlives_bounds<'tcx>( let mut checked_wf_args = rustc_data_structures::fx::FxHashSet::default(); let mut wf_args = vec![ty.into()]; - let mut implied_bounds = vec![]; + let mut outlives_bounds: Vec, ty::Region<'tcx>>> = + vec![]; let mut fulfill_cx = >::new(tcx); @@ -65,30 +66,17 @@ fn compute_implied_outlives_bounds<'tcx>( // than the ultimate set. (Note: normally there won't be // unresolved inference variables here anyway, but there might be // during typeck under some circumstances.) + // + // FIXME(@lcnr): It's not really "always fine", having fewer implied + // bounds can be backward incompatible, e.g. #101951 was caused by + // us not dealing with inference vars in `TypeOutlives` predicates. let obligations = wf::obligations(infcx, param_env, hir::CRATE_HIR_ID, 0, arg, DUMMY_SP) .unwrap_or_default(); - // N.B., all of these predicates *ought* to be easily proven - // true. In fact, their correctness is (mostly) implied by - // other parts of the program. However, in #42552, we had - // an annoying scenario where: - // - // - Some `T::Foo` gets normalized, resulting in a - // variable `_1` and a `T: Trait` constraint - // (not sure why it couldn't immediately get - // solved). This result of `_1` got cached. - // - These obligations were dropped on the floor here, - // rather than being registered. - // - Then later we would get a request to normalize - // `T::Foo` which would result in `_1` being used from - // the cache, but hence without the `T: Trait` - // constraint. As a result, `_1` never gets resolved, - // and we get an ICE (in dropck). - // - // Therefore, we register any predicates involving - // inference variables. We restrict ourselves to those - // involving inference variables both for efficiency and - // to avoids duplicate errors that otherwise show up. + // While these predicates should all be implied by other parts of + // the program, they are still relevant as they may constrain + // inference variables, which is necessary to add the correct + // implied bounds in some cases, mostly when dealing with projections. fulfill_cx.register_predicate_obligations( infcx, obligations.iter().filter(|o| o.predicate.has_infer_types_or_consts()).cloned(), @@ -96,10 +84,10 @@ fn compute_implied_outlives_bounds<'tcx>( // From the full set of obligations, just filter down to the // region relationships. - implied_bounds.extend(obligations.into_iter().flat_map(|obligation| { + outlives_bounds.extend(obligations.into_iter().filter_map(|obligation| { assert!(!obligation.has_escaping_bound_vars()); match obligation.predicate.kind().no_bound_vars() { - None => vec![], + None => None, Some(pred) => match pred { ty::PredicateKind::Trait(..) | ty::PredicateKind::Subtype(..) @@ -109,21 +97,18 @@ fn compute_implied_outlives_bounds<'tcx>( | ty::PredicateKind::ObjectSafe(..) | ty::PredicateKind::ConstEvaluatable(..) | ty::PredicateKind::ConstEquate(..) - | ty::PredicateKind::TypeWellFormedFromEnv(..) => vec![], + | ty::PredicateKind::TypeWellFormedFromEnv(..) => None, ty::PredicateKind::WellFormed(arg) => { wf_args.push(arg); - vec![] + None } ty::PredicateKind::RegionOutlives(ty::OutlivesPredicate(r_a, r_b)) => { - vec![OutlivesBound::RegionSubRegion(r_b, r_a)] + Some(ty::OutlivesPredicate(r_a.into(), r_b)) } ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(ty_a, r_b)) => { - let ty_a = infcx.resolve_vars_if_possible(ty_a); - let mut components = smallvec![]; - push_outlives_components(tcx, ty_a, &mut components); - implied_bounds_from_components(r_b, components) + Some(ty::OutlivesPredicate(ty_a.into(), r_b)) } }, } @@ -133,9 +118,27 @@ fn compute_implied_outlives_bounds<'tcx>( // Ensure that those obligations that we had to solve // get solved *here*. match fulfill_cx.select_all_or_error(infcx).as_slice() { - [] => Ok(implied_bounds), - _ => Err(NoSolution), + [] => (), + _ => return Err(NoSolution), } + + // We lazily compute the outlives components as + // `select_all_or_error` constrains inference variables. + let implied_bounds = outlives_bounds + .into_iter() + .flat_map(|ty::OutlivesPredicate(a, r_b)| match a.unpack() { + ty::GenericArgKind::Lifetime(r_a) => vec![OutlivesBound::RegionSubRegion(r_b, r_a)], + ty::GenericArgKind::Type(ty_a) => { + let ty_a = infcx.resolve_vars_if_possible(ty_a); + let mut components = smallvec![]; + push_outlives_components(tcx, ty_a, &mut components); + implied_bounds_from_components(r_b, components) + } + ty::GenericArgKind::Const(_) => unreachable!(), + }) + .collect(); + + Ok(implied_bounds) } /// When we have an implied bound that `T: 'a`, we can further break diff --git a/compiler/rustc_typeck/src/check/compare_method.rs b/compiler/rustc_typeck/src/check/compare_method.rs index 0c6d8f26f1d63..59d591acdc445 100644 --- a/compiler/rustc_typeck/src/check/compare_method.rs +++ b/compiler/rustc_typeck/src/check/compare_method.rs @@ -140,6 +140,7 @@ pub(crate) fn compare_impl_method<'tcx>( /// /// Finally we register each of these predicates as an obligation and check that /// they hold. +#[instrument(level = "debug", skip(tcx, impl_m_span, impl_trait_ref))] fn compare_predicate_entailment<'tcx>( tcx: TyCtxt<'tcx>, impl_m: &AssocItem, From 72a21027f5bee367bd9ccbeecc2528986f85d90b Mon Sep 17 00:00:00 2001 From: lcnr Date: Mon, 19 Sep 2022 15:07:01 +0200 Subject: [PATCH 065/586] add test --- src/test/ui/implied-bounds/issue-101951.rs | 50 ++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 src/test/ui/implied-bounds/issue-101951.rs diff --git a/src/test/ui/implied-bounds/issue-101951.rs b/src/test/ui/implied-bounds/issue-101951.rs new file mode 100644 index 0000000000000..108fef8a15fb3 --- /dev/null +++ b/src/test/ui/implied-bounds/issue-101951.rs @@ -0,0 +1,50 @@ +// Taken directly from that issue. +// +// This test detected that we didn't correctly resolve +// inference variables when computing implied bounds. +// +// check-pass +pub trait BuilderFn<'a> { + type Output; +} + +impl<'a, F, Out> BuilderFn<'a> for F +where + F: FnOnce(&'a mut ()) -> Out, +{ + type Output = Out; +} + +pub trait ConstructionFirm { + type Builder: for<'a> BuilderFn<'a>; +} + +pub trait Campus +where + T: ConstructionFirm, +{ + fn add_building( + &mut self, + building: &mut <::Builder as BuilderFn<'_>>::Output, + ); +} + +struct ArchitectsInc {} + +impl ConstructionFirm for ArchitectsInc { + type Builder = fn(&mut ()) -> PrettyCondo<'_>; +} + +struct PrettyCondo<'a> { + _marker: &'a mut (), +} + +struct CondoEstate {} + +impl Campus for CondoEstate { + fn add_building(&mut self, _building: &mut PrettyCondo<'_>) { + todo!() + } +} + +fn main() {} From 18ab705073faed3c01aa2f66a9d99d26d047c7bc Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 19 Sep 2022 14:00:34 +0000 Subject: [PATCH 066/586] Actually visit/fold the types inside CanonicalVarInfos --- compiler/rustc_middle/src/infer/canonical.rs | 23 ++++++++++++++------ 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_middle/src/infer/canonical.rs b/compiler/rustc_middle/src/infer/canonical.rs index 4bad0950451ac..e46cf48142f25 100644 --- a/compiler/rustc_middle/src/infer/canonical.rs +++ b/compiler/rustc_middle/src/infer/canonical.rs @@ -29,7 +29,7 @@ use rustc_index::vec::IndexVec; use rustc_macros::HashStable; use smallvec::SmallVec; use std::iter; -use std::ops::Index; +use std::ops::{ControlFlow, Index}; /// A "canonicalized" type `V` is one where all free inference /// variables have been rewritten to "canonical vars". These are @@ -44,6 +44,21 @@ pub struct Canonical<'tcx, V> { pub type CanonicalVarInfos<'tcx> = &'tcx List>; +impl<'tcx> ty::TypeFoldable<'tcx> for CanonicalVarInfos<'tcx> { + fn try_fold_with>( + self, + folder: &mut F, + ) -> Result { + ty::util::fold_list(self, folder, |tcx, v| tcx.intern_canonical_var_infos(v)) + } +} + +impl<'tcx> ty::TypeVisitable<'tcx> for CanonicalVarInfos<'tcx> { + fn visit_with>(&self, visitor: &mut V) -> ControlFlow { + self.iter().try_for_each(|t| t.visit_with(visitor)) + } +} + /// A set of values corresponding to the canonical variables from some /// `Canonical`. You can give these values to /// `canonical_value.substitute` to substitute them into the canonical @@ -305,12 +320,6 @@ TrivialTypeTraversalAndLiftImpls! { } } -TrivialTypeTraversalImpls! { - for <'tcx> { - crate::infer::canonical::CanonicalVarInfos<'tcx>, - } -} - impl<'tcx> CanonicalVarValues<'tcx> { #[inline] pub fn len(&self) -> usize { From 00bb9fc2be81b8beb257fdf220ed3f2386ab0930 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Mon, 19 Sep 2022 11:10:12 -0700 Subject: [PATCH 067/586] Rename LLVM `optimize` functions --- compiler/rustc_codegen_llvm/src/back/lto.rs | 2 +- compiler/rustc_codegen_llvm/src/back/write.rs | 6 +++--- compiler/rustc_codegen_llvm/src/lib.rs | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/back/lto.rs b/compiler/rustc_codegen_llvm/src/back/lto.rs index daf58d7152d60..2049422b79a30 100644 --- a/compiler/rustc_codegen_llvm/src/back/lto.rs +++ b/compiler/rustc_codegen_llvm/src/back/lto.rs @@ -597,7 +597,7 @@ pub(crate) fn run_pass_manager( } let opt_stage = if thin { llvm::OptStage::ThinLTO } else { llvm::OptStage::FatLTO }; let opt_level = config.opt_level.unwrap_or(config::OptLevel::No); - write::optimize(cgcx, diag_handler, module, config, opt_level, opt_stage)?; + write::llvm_optimize(cgcx, diag_handler, module, config, opt_level, opt_stage)?; } debug!("lto done"); Ok(()) diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs index 92a44a9f426c7..db526746fa70a 100644 --- a/compiler/rustc_codegen_llvm/src/back/write.rs +++ b/compiler/rustc_codegen_llvm/src/back/write.rs @@ -416,7 +416,7 @@ fn get_instr_profile_output_path(config: &ModuleConfig) -> Option { } } -pub(crate) unsafe fn optimize( +pub(crate) unsafe fn llvm_optimize( cgcx: &CodegenContext, diag_handler: &Handler, module: &ModuleCodegen, @@ -498,7 +498,7 @@ pub(crate) unsafe fn optimize( } // Unsafe due to LLVM calls. -pub(crate) unsafe fn maybe_optimize( +pub(crate) unsafe fn optimize( cgcx: &CodegenContext, diag_handler: &Handler, module: &ModuleCodegen, @@ -526,7 +526,7 @@ pub(crate) unsafe fn maybe_optimize( _ if cgcx.opts.cg.linker_plugin_lto.enabled() => llvm::OptStage::PreLinkThinLTO, _ => llvm::OptStage::PreLinkNoLTO, }; - return optimize(cgcx, diag_handler, module, config, opt_level, opt_stage); + return llvm_optimize(cgcx, diag_handler, module, config, opt_level, opt_stage); } Ok(()) } diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs index 518f9a45733c1..42c65e04e3b6b 100644 --- a/compiler/rustc_codegen_llvm/src/lib.rs +++ b/compiler/rustc_codegen_llvm/src/lib.rs @@ -207,7 +207,7 @@ impl WriteBackendMethods for LlvmCodegenBackend { module: &ModuleCodegen, config: &ModuleConfig, ) -> Result<(), FatalError> { - back::write::maybe_optimize(cgcx, diag_handler, module, config) + back::write::optimize(cgcx, diag_handler, module, config) } fn optimize_fat( cgcx: &CodegenContext, From e248523d2aaff6c74919baada18934a19e997509 Mon Sep 17 00:00:00 2001 From: Tuna Date: Tue, 20 Sep 2022 06:29:34 +0300 Subject: [PATCH 068/586] Update src/bootstrap/config.rs Co-authored-by: Bruno Kolenbrander <59372212+mejrs@users.noreply.github.com> --- src/bootstrap/config.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index b8e776485e673..8b657788a687f 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -821,7 +821,14 @@ impl Config { .and_then(|output| if output.status.success() { Some(output) } else { None }); if let Some(output) = output { let git_root = String::from_utf8(output.stdout).unwrap(); - config.src = PathBuf::from(git_root.trim().to_owned()) + let git_root = PathBuf::from(git_root.trim()).canonicalize().unwrap(); + let s = git_root.to_str().unwrap(); + + // Bootstrap is quite bad at handling /? in front of paths + config.src = match s.strip_prefix("\\\\?\\") { + Some(p) => PathBuf::from(p), + None => PathBuf::from(git_root), + }; } else { // We're building from a tarball, not git sources. // We don't support pre-downloaded bootstrap in this case. From 790d9d4dd0d13e254631c17b045a7c6a9587a2ca Mon Sep 17 00:00:00 2001 From: Tuna Date: Tue, 20 Sep 2022 06:39:05 +0300 Subject: [PATCH 069/586] Update src/bootstrap/config.rs Co-authored-by: Joshua Nelson --- src/bootstrap/config.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index 8b657788a687f..a6333976f2ac2 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -821,6 +821,7 @@ impl Config { .and_then(|output| if output.status.success() { Some(output) } else { None }); if let Some(output) = output { let git_root = String::from_utf8(output.stdout).unwrap(); + // We need to canonicalize this path to make sure it uses backslashes instead of forward slashes. let git_root = PathBuf::from(git_root.trim()).canonicalize().unwrap(); let s = git_root.to_str().unwrap(); From f841f1b4435694019336373c9c70476306933615 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 20 Sep 2022 09:15:51 +0000 Subject: [PATCH 070/586] Retry with inlining attributes --- compiler/rustc_middle/src/infer/canonical.rs | 8 +------- .../rustc_middle/src/mir/type_visitable.rs | 6 ------ .../rustc_middle/src/ty/structural_impls.rs | 20 ------------------- compiler/rustc_middle/src/ty/subst.rs | 9 ++------- 4 files changed, 3 insertions(+), 40 deletions(-) diff --git a/compiler/rustc_middle/src/infer/canonical.rs b/compiler/rustc_middle/src/infer/canonical.rs index e46cf48142f25..d3cf519b633c7 100644 --- a/compiler/rustc_middle/src/infer/canonical.rs +++ b/compiler/rustc_middle/src/infer/canonical.rs @@ -29,7 +29,7 @@ use rustc_index::vec::IndexVec; use rustc_macros::HashStable; use smallvec::SmallVec; use std::iter; -use std::ops::{ControlFlow, Index}; +use std::ops::Index; /// A "canonicalized" type `V` is one where all free inference /// variables have been rewritten to "canonical vars". These are @@ -53,12 +53,6 @@ impl<'tcx> ty::TypeFoldable<'tcx> for CanonicalVarInfos<'tcx> { } } -impl<'tcx> ty::TypeVisitable<'tcx> for CanonicalVarInfos<'tcx> { - fn visit_with>(&self, visitor: &mut V) -> ControlFlow { - self.iter().try_for_each(|t| t.visit_with(visitor)) - } -} - /// A set of values corresponding to the canonical variables from some /// `Canonical`. You can give these values to /// `canonical_value.substitute` to substitute them into the canonical diff --git a/compiler/rustc_middle/src/mir/type_visitable.rs b/compiler/rustc_middle/src/mir/type_visitable.rs index 56fa7f1ede3d4..27a251f2f56f8 100644 --- a/compiler/rustc_middle/src/mir/type_visitable.rs +++ b/compiler/rustc_middle/src/mir/type_visitable.rs @@ -8,12 +8,6 @@ impl<'tcx, R: Idx, C: Idx> TypeVisitable<'tcx> for BitMatrix { } } -impl<'tcx> TypeVisitable<'tcx> for &'tcx ty::List> { - fn visit_with>(&self, visitor: &mut V) -> ControlFlow { - self.iter().try_for_each(|t| t.visit_with(visitor)) - } -} - impl<'tcx> TypeVisitable<'tcx> for ConstantKind<'tcx> { fn visit_with>(&self, visitor: &mut V) -> ControlFlow { visitor.visit_mir_const(*self) diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index ecbb2a16b69df..f5fd1f6ffafce 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -602,26 +602,12 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List TypeVisitable<'tcx> - for &'tcx ty::List>> -{ - fn visit_with>(&self, visitor: &mut V) -> ControlFlow { - self.iter().try_for_each(|p| p.visit_with(visitor)) - } -} - impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List { fn try_fold_with>(self, folder: &mut F) -> Result { ty::util::fold_list(self, folder, |tcx, v| tcx.intern_projs(v)) } } -impl<'tcx> TypeVisitable<'tcx> for &'tcx ty::List { - fn visit_with>(&self, visitor: &mut V) -> ControlFlow { - self.iter().try_for_each(|t| t.visit_with(visitor)) - } -} - impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> { fn try_fold_with>(self, folder: &mut F) -> Result { folder.try_fold_ty(self) @@ -797,12 +783,6 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List> { } } -impl<'tcx> TypeVisitable<'tcx> for &'tcx ty::List> { - fn visit_with>(&self, visitor: &mut V) -> ControlFlow { - self.iter().try_for_each(|p| p.visit_with(visitor)) - } -} - impl<'tcx, T: TypeFoldable<'tcx>, I: Idx> TypeFoldable<'tcx> for IndexVec { fn try_fold_with>(self, folder: &mut F) -> Result { self.try_map_id(|x| x.try_fold_with(folder)) diff --git a/compiler/rustc_middle/src/ty/subst.rs b/compiler/rustc_middle/src/ty/subst.rs index 6262aa1807577..c7480f6d84d48 100644 --- a/compiler/rustc_middle/src/ty/subst.rs +++ b/compiler/rustc_middle/src/ty/subst.rs @@ -459,12 +459,6 @@ impl<'tcx> TypeFoldable<'tcx> for SubstsRef<'tcx> { } } -impl<'tcx> TypeVisitable<'tcx> for SubstsRef<'tcx> { - fn visit_with>(&self, visitor: &mut V) -> ControlFlow { - self.iter().try_for_each(|t| t.visit_with(visitor)) - } -} - impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List> { fn try_fold_with>(self, folder: &mut F) -> Result { // This code is fairly hot, though not as hot as `SubstsRef`. @@ -497,7 +491,8 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List> { } } -impl<'tcx> TypeVisitable<'tcx> for &'tcx ty::List> { +impl<'tcx, T: TypeVisitable<'tcx>> TypeVisitable<'tcx> for &'tcx ty::List { + #[inline] fn visit_with>(&self, visitor: &mut V) -> ControlFlow { self.iter().try_for_each(|t| t.visit_with(visitor)) } From 8ca6a272bdc12f0b2e1942d325cd1022117514f1 Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Thu, 8 Sep 2022 09:38:14 +0100 Subject: [PATCH 071/586] Remove `RtlGenRandom` (take two) First try to use the system preferred RNG but if that fails (e.g. due to a broken system configuration) then fallback to manually opening an algorithm handle. --- library/std/src/sys/windows/c.rs | 6 +-- library/std/src/sys/windows/rand.rs | 76 +++++++++++------------------ 2 files changed, 29 insertions(+), 53 deletions(-) diff --git a/library/std/src/sys/windows/c.rs b/library/std/src/sys/windows/c.rs index 89d0ab59be89f..c61a7e7d1e4ab 100644 --- a/library/std/src/sys/windows/c.rs +++ b/library/std/src/sys/windows/c.rs @@ -279,7 +279,6 @@ pub const STATUS_INVALID_PARAMETER: NTSTATUS = 0xc000000d_u32 as _; pub const STATUS_PENDING: NTSTATUS = 0x103 as _; pub const STATUS_END_OF_FILE: NTSTATUS = 0xC0000011_u32 as _; pub const STATUS_NOT_IMPLEMENTED: NTSTATUS = 0xC0000002_u32 as _; -pub const STATUS_NOT_SUPPORTED: NTSTATUS = 0xC00000BB_u32 as _; // Equivalent to the `NT_SUCCESS` C preprocessor macro. // See: https://docs.microsoft.com/en-us/windows-hardware/drivers/kernel/using-ntstatus-values @@ -289,6 +288,7 @@ pub fn nt_success(status: NTSTATUS) -> bool { // "RNG\0" pub const BCRYPT_RNG_ALGORITHM: &[u16] = &[b'R' as u16, b'N' as u16, b'G' as u16, 0]; +pub const BCRYPT_USE_SYSTEM_PREFERRED_RNG: DWORD = 0x00000002; #[repr(C)] pub struct UNICODE_STRING { @@ -817,10 +817,6 @@ if #[cfg(not(target_vendor = "uwp"))] { #[link(name = "advapi32")] extern "system" { - // Forbidden when targeting UWP - #[link_name = "SystemFunction036"] - pub fn RtlGenRandom(RandomBuffer: *mut u8, RandomBufferLength: ULONG) -> BOOLEAN; - // Allowed but unused by UWP pub fn OpenProcessToken( ProcessHandle: HANDLE, diff --git a/library/std/src/sys/windows/rand.rs b/library/std/src/sys/windows/rand.rs index d6cd8f8027162..b5a49489d3fb8 100644 --- a/library/std/src/sys/windows/rand.rs +++ b/library/std/src/sys/windows/rand.rs @@ -13,15 +13,12 @@ //! but significant number of users to experience panics caused by a failure of //! this function. See [#94098]. //! -//! The current version changes this to use the `BCRYPT_RNG_ALG_HANDLE` -//! [Pseudo-handle], which gets the default RNG algorithm without querying the -//! system preference thus hopefully avoiding the previous issue. -//! This is only supported on Windows 10+ so a fallback is used for older versions. +//! The current version falls back to using `BCryptOpenAlgorithmProvider` if +//! `BCRYPT_USE_SYSTEM_PREFERRED_RNG` fails for any reason. //! //! [#94098]: https://github.com/rust-lang/rust/issues/94098 //! [`RtlGenRandom`]: https://docs.microsoft.com/en-us/windows/win32/api/ntsecapi/nf-ntsecapi-rtlgenrandom //! [`BCryptGenRandom`]: https://docs.microsoft.com/en-us/windows/win32/api/bcrypt/nf-bcrypt-bcryptgenrandom -//! [Pseudo-handle]: https://docs.microsoft.com/en-us/windows/win32/seccng/cng-algorithm-pseudo-handles use crate::mem; use crate::ptr; use crate::sys::c; @@ -33,37 +30,35 @@ use crate::sys::c; /// [`HashMap`]: crate::collections::HashMap /// [`RandomState`]: crate::collections::hash_map::RandomState pub fn hashmap_random_keys() -> (u64, u64) { - Rng::open().and_then(|rng| rng.gen_random_keys()).unwrap_or_else(fallback_rng) + Rng::SYSTEM.gen_random_keys().unwrap_or_else(fallback_rng) } -struct Rng(c::BCRYPT_ALG_HANDLE); +struct Rng { + algorithm: c::BCRYPT_ALG_HANDLE, + flags: u32, +} impl Rng { - #[cfg(miri)] - fn open() -> Result { - const BCRYPT_RNG_ALG_HANDLE: c::BCRYPT_ALG_HANDLE = ptr::invalid_mut(0x81); - let _ = ( - c::BCryptOpenAlgorithmProvider, - c::BCryptCloseAlgorithmProvider, - c::BCRYPT_RNG_ALGORITHM, - c::STATUS_NOT_SUPPORTED, - ); - Ok(Self(BCRYPT_RNG_ALG_HANDLE)) + const SYSTEM: Self = unsafe { Self::new(ptr::null_mut(), c::BCRYPT_USE_SYSTEM_PREFERRED_RNG) }; + + /// Create the RNG from an existing algorithm handle. + /// + /// # Safety + /// + /// The handle must either be null or a valid algorithm handle. + const unsafe fn new(algorithm: c::BCRYPT_ALG_HANDLE, flags: u32) -> Self { + Self { algorithm, flags } } - #[cfg(not(miri))] - // Open a handle to the RNG algorithm. + + /// Open a handle to the RNG algorithm. fn open() -> Result { use crate::sync::atomic::AtomicPtr; use crate::sync::atomic::Ordering::{Acquire, Release}; - const ERROR_VALUE: c::LPVOID = ptr::invalid_mut(usize::MAX); // An atomic is used so we don't need to reopen the handle every time. static HANDLE: AtomicPtr = AtomicPtr::new(ptr::null_mut()); let mut handle = HANDLE.load(Acquire); - // We use a sentinel value to designate an error occurred last time. - if handle == ERROR_VALUE { - Err(c::STATUS_NOT_SUPPORTED) - } else if handle.is_null() { + if handle.is_null() { let status = unsafe { c::BCryptOpenAlgorithmProvider( &mut handle, @@ -80,13 +75,12 @@ impl Rng { unsafe { c::BCryptCloseAlgorithmProvider(handle, 0) }; handle = previous_handle; } - Ok(Self(handle)) + Ok(unsafe { Self::new(handle, 0) }) } else { - HANDLE.store(ERROR_VALUE, Release); Err(status) } } else { - Ok(Self(handle)) + Ok(unsafe { Self::new(handle, 0) }) } } @@ -94,33 +88,19 @@ impl Rng { let mut v = (0, 0); let status = unsafe { let size = mem::size_of_val(&v).try_into().unwrap(); - c::BCryptGenRandom(self.0, ptr::addr_of_mut!(v).cast(), size, 0) + c::BCryptGenRandom(self.algorithm, ptr::addr_of_mut!(v).cast(), size, self.flags) }; if c::nt_success(status) { Ok(v) } else { Err(status) } } } -/// Generate random numbers using the fallback RNG function (RtlGenRandom) -#[cfg(not(target_vendor = "uwp"))] +/// Generate random numbers using the fallback RNG function #[inline(never)] fn fallback_rng(rng_status: c::NTSTATUS) -> (u64, u64) { - let mut v = (0, 0); - let ret = - unsafe { c::RtlGenRandom(&mut v as *mut _ as *mut u8, mem::size_of_val(&v) as c::ULONG) }; - - if ret != 0 { - v - } else { - panic!( - "RNG broken: {rng_status:#x}, fallback RNG broken: {}", - crate::io::Error::last_os_error() - ) + match Rng::open().and_then(|rng| rng.gen_random_keys()) { + Ok(keys) => keys, + Err(status) => { + panic!("RNG broken: {rng_status:#x}, fallback RNG broken: {status:#x}") + } } } - -/// We can't use RtlGenRandom with UWP, so there is no fallback -#[cfg(target_vendor = "uwp")] -#[inline(never)] -fn fallback_rng(rng_status: c::NTSTATUS) -> (u64, u64) { - panic!("RNG broken: {rng_status:#x} fallback RNG broken: RtlGenRandom() not supported on UWP"); -} From 303a7dceaef0ec5dc7d178e315ca9ee81d0f8f86 Mon Sep 17 00:00:00 2001 From: Chris Wailes Date: Tue, 20 Sep 2022 14:12:49 -0700 Subject: [PATCH 072/586] Add a platform support document for Android --- src/doc/rustc/src/platform-support/android.md | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 src/doc/rustc/src/platform-support/android.md diff --git a/src/doc/rustc/src/platform-support/android.md b/src/doc/rustc/src/platform-support/android.md new file mode 100644 index 0000000000000..752246db8d58f --- /dev/null +++ b/src/doc/rustc/src/platform-support/android.md @@ -0,0 +1,45 @@ +# *-linux-android and *-linux-androideabi + +**Tier: 2** + +[Android] is a mobile operating system built on top of the Linux kernel. + +[Android]: https://source.android.com/ + +## Target maintainers + +- Chris Wailes ([@chriswailes](https://github.com/chriswailes)) +- Matthew Maurer ([@maurer](https://github.com/maurer)) +- Martin Geisler ([@mgeisler](https://github.com/mgeisler)) + +## Requirements + +This target is cross-compiled from a host environment. Development may be done +from the [source tree] or using the Android NDK. + +[source tree]: https://source.android.com/docs/setup/build/downloading + +Android targets support std and generated binaries use the ELF file format. + +## NDK/API Update Policy + +Rust will support the most recent Long Term Support (LTS) Android Native +Development Kit (NDK). By default Rust will support all API levels supported +by the NDK but a higher minimum API level may be required if deemed necessary. + +## Building the target + +To build Rust binaries for Android you'll need a copy of the most recent LTS +edition of the [Android NDK]. Supported Android targets are: + +* aarch64-linux-android +* arm-linux-androideabi +* armv7-linux-androideabi +* i686-linux-android +* thumbv7neon-linux-androideabi +* x86_64-linux-android + +[Android NDK]: https://developer.android.com/ndk/downloads + +A list of all supported targets can be found +[here](https://doc.rust-lang.org/rustc/platform-support.html) From 47411d7e11bcbe770419da48ba1215c437e21feb Mon Sep 17 00:00:00 2001 From: Chris Wailes Date: Tue, 20 Sep 2022 14:13:39 -0700 Subject: [PATCH 073/586] Add links to the Android platform support doc --- src/doc/rustc/src/SUMMARY.md | 1 + src/doc/rustc/src/platform-support.md | 12 ++++++------ 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md index 5037ec21653ad..5b9e913116e50 100644 --- a/src/doc/rustc/src/SUMMARY.md +++ b/src/doc/rustc/src/SUMMARY.md @@ -23,6 +23,7 @@ - [armv6k-nintendo-3ds](platform-support/armv6k-nintendo-3ds.md) - [armv7-unknown-linux-uclibceabi](platform-support/armv7-unknown-linux-uclibceabi.md) - [armv7-unknown-linux-uclibceabihf](platform-support/armv7-unknown-linux-uclibceabihf.md) + - [\*-android(eabi)?](platform-support/android.md) - [\*-fuchsia](platform-support/fuchsia.md) - [\*-kmc-solid_\*](platform-support/kmc-solid.md) - [m68k-unknown-linux-gnu](platform-support/m68k-unknown-linux-gnu.md) diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index 11c3b89d3a7f3..29ad8fe9b4cc3 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -125,17 +125,17 @@ target | std | notes `aarch64-apple-ios` | ✓ | ARM64 iOS [`aarch64-apple-ios-sim`](platform-support/aarch64-apple-ios-sim.md) | ✓ | Apple iOS Simulator on ARM64 `aarch64-fuchsia` | ✓ | ARM64 Fuchsia -`aarch64-linux-android` | ✓ | ARM64 Android +[`aarch64-linux-android`](platform-support/android.md) | ✓ | ARM64 Android `aarch64-unknown-none-softfloat` | * | Bare ARM64, softfloat `aarch64-unknown-none` | * | Bare ARM64, hardfloat -`arm-linux-androideabi` | ✓ | ARMv7 Android +[`arm-linux-androideabi`](platform-support/android.md) | ✓ | ARMv7 Android `arm-unknown-linux-musleabi` | ✓ | ARMv6 Linux with MUSL `arm-unknown-linux-musleabihf` | ✓ | ARMv6 Linux with MUSL, hardfloat `armebv7r-none-eabi` | * | Bare ARMv7-R, Big Endian `armebv7r-none-eabihf` | * | Bare ARMv7-R, Big Endian, hardfloat `armv5te-unknown-linux-gnueabi` | ✓ | ARMv5TE Linux (kernel 4.4, glibc 2.23) `armv5te-unknown-linux-musleabi` | ✓ | ARMv5TE Linux with MUSL -`armv7-linux-androideabi` | ✓ | ARMv7a Android +[`armv7-linux-androideabi`](platform-support/android.md) | ✓ | ARMv7a Android `armv7-unknown-linux-gnueabi` | ✓ |ARMv7 Linux (kernel 4.15, glibc 2.27) `armv7-unknown-linux-musleabi` | ✓ |ARMv7 Linux with MUSL `armv7-unknown-linux-musleabihf` | ✓ | ARMv7 Linux with MUSL, hardfloat @@ -146,7 +146,7 @@ target | std | notes `i586-pc-windows-msvc` | * | 32-bit Windows w/o SSE `i586-unknown-linux-gnu` | ✓ | 32-bit Linux w/o SSE (kernel 4.4, glibc 2.23) `i586-unknown-linux-musl` | ✓ | 32-bit Linux w/o SSE, MUSL -`i686-linux-android` | ✓ | 32-bit x86 Android +[`i686-linux-android`](platform-support/android.md) | ✓ | 32-bit x86 Android `i686-unknown-freebsd` | ✓ | 32-bit FreeBSD `i686-unknown-linux-musl` | ✓ | 32-bit Linux with MUSL `mips-unknown-linux-musl` | ✓ | MIPS Linux with MUSL @@ -165,7 +165,7 @@ target | std | notes `thumbv7em-none-eabi` | * | Bare Cortex-M4, M7 `thumbv7em-none-eabihf` | * | Bare Cortex-M4F, M7F, FPU, hardfloat `thumbv7m-none-eabi` | * | Bare Cortex-M3 -`thumbv7neon-linux-androideabi` | ✓ | Thumb2-mode ARMv7a Android with NEON +[`thumbv7neon-linux-androideabi`](platform-support/android.md) | ✓ | Thumb2-mode ARMv7a Android with NEON `thumbv7neon-unknown-linux-gnueabihf` | ✓ | Thumb2-mode ARMv7a Linux with NEON (kernel 4.4, glibc 2.23) `thumbv8m.base-none-eabi` | * | ARMv8-M Baseline `thumbv8m.main-none-eabi` | * | ARMv8-M Mainline @@ -176,7 +176,7 @@ target | std | notes `x86_64-apple-ios` | ✓ | 64-bit x86 iOS [`x86_64-fortanix-unknown-sgx`](platform-support/x86_64-fortanix-unknown-sgx.md) | ✓ | [Fortanix ABI] for 64-bit Intel SGX `x86_64-fuchsia` | ✓ | 64-bit Fuchsia -`x86_64-linux-android` | ✓ | 64-bit x86 Android +[`x86_64-linux-android`](platform-support/android.md) | ✓ | 64-bit x86 Android `x86_64-pc-solaris` | ✓ | 64-bit Solaris 10/11, illumos `x86_64-unknown-linux-gnux32` | ✓ | 64-bit Linux (x32 ABI) (kernel 4.15, glibc 2.27) [`x86_64-unknown-none`](platform-support/x86_64-unknown-none.md) | * | Freestanding/bare-metal x86_64, softfloat From b3d7e4edf61979007d116e9d2291e2b0ff01cfb4 Mon Sep 17 00:00:00 2001 From: Andrew Pollack Date: Wed, 21 Sep 2022 00:24:24 +0000 Subject: [PATCH 074/586] Adding ignore fuchsia tests for execvp (pre_exec) --- src/test/ui/command/command-pre-exec.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/ui/command/command-pre-exec.rs b/src/test/ui/command/command-pre-exec.rs index 61914e2293070..d366c5ffbfd8c 100644 --- a/src/test/ui/command/command-pre-exec.rs +++ b/src/test/ui/command/command-pre-exec.rs @@ -6,6 +6,7 @@ // ignore-windows - this is a unix-specific test // ignore-emscripten no processes // ignore-sgx no processes +// ignore-fuchsia no execvp syscall #![feature(process_exec, rustc_private)] extern crate libc; From 9808e10d3fa98f22a20db61cd4c947aeee6ccaed Mon Sep 17 00:00:00 2001 From: Andrew Pollack Date: Wed, 21 Sep 2022 00:35:25 +0000 Subject: [PATCH 075/586] Adding ignore fuchsia non-applicable commands --- src/test/ui/command/command-uid-gid.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/ui/command/command-uid-gid.rs b/src/test/ui/command/command-uid-gid.rs index e1eb4b1405b1f..aa4e2f5b89364 100644 --- a/src/test/ui/command/command-uid-gid.rs +++ b/src/test/ui/command/command-uid-gid.rs @@ -2,6 +2,7 @@ // ignore-android // ignore-emscripten // ignore-sgx +// ignore-fuchsia no '/bin/sh', '/bin/ls' #![feature(rustc_private)] From f9ef7e2835b757129b9171c54a6ce948a4a210be Mon Sep 17 00:00:00 2001 From: yukang Date: Wed, 21 Sep 2022 01:40:31 +0800 Subject: [PATCH 076/586] code refactoring smart_resolve_report_errors --- .../rustc_resolve/src/late/diagnostics.rs | 434 +++++++++++------- 1 file changed, 261 insertions(+), 173 deletions(-) diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index c3c9b0b561782..ac1153602572f 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -130,6 +130,15 @@ pub(super) enum LifetimeElisionCandidate { Missing(MissingLifetime), } +struct BaseError<'a> { + msg: String, + fallback_label: String, + span: Span, + span_label: Option<(Span, &'a str)>, + could_be_expr: bool, + suggestion: Option<(Span, &'a str, String)>, +} + impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { fn def_span(&self, def_id: DefId) -> Option { match def_id.krate { @@ -138,35 +147,18 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { } } - /// Handles error reporting for `smart_resolve_path_fragment` function. - /// Creates base error and amends it with one short label and possibly some longer helps/notes. - pub(crate) fn smart_resolve_report_errors( + fn make_base_error( &mut self, path: &[Segment], span: Span, source: PathSource<'_>, res: Option, - ) -> (DiagnosticBuilder<'a, ErrorGuaranteed>, Vec) { - let ident_span = path.last().map_or(span, |ident| ident.ident.span); - let ns = source.namespace(); - let is_expected = &|res| source.is_expected(res); - let is_enum_variant = &|res| matches!(res, Res::Def(DefKind::Variant, _)); - - debug!(?res, ?source); - + ) -> BaseError<'static> { // Make the base error. - struct BaseError<'a> { - msg: String, - fallback_label: String, - span: Span, - span_label: Option<(Span, &'a str)>, - could_be_expr: bool, - suggestion: Option<(Span, &'a str, String)>, - } let mut expected = source.descr_expected(); let path_str = Segment::names_to_string(path); let item_str = path.last().unwrap().ident; - let base_error = if let Some(res) = res { + if let Some(res) = res { BaseError { msg: format!("expected {}, found {} `{}`", expected, res.descr(), path_str), fallback_label: format!("not a {expected}"), @@ -277,53 +269,92 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { could_be_expr: false, suggestion, } - }; + } + } + /// Handles error reporting for `smart_resolve_path_fragment` function. + /// Creates base error and amends it with one short label and possibly some longer helps/notes. + pub(crate) fn smart_resolve_report_errors( + &mut self, + path: &[Segment], + span: Span, + source: PathSource<'_>, + res: Option, + ) -> (DiagnosticBuilder<'a, ErrorGuaranteed>, Vec) { + debug!(?res, ?source); + let base_error = self.make_base_error(path, span, source, res); let code = source.error_code(res.is_some()); let mut err = self.r.session.struct_span_err_with_code(base_error.span, &base_error.msg, code); self.suggest_swapping_misplaced_self_ty_and_trait(&mut err, source, res, base_error.span); - if let Some((span, label)) = base_error.span_label { + if let Some((span, label)) = base_error.span_label.clone() { err.span_label(span, label); } - if let Some(sugg) = base_error.suggestion { - err.span_suggestion_verbose(sugg.0, sugg.1, sugg.2, Applicability::MaybeIncorrect); + if let Some(ref sugg) = base_error.suggestion { + err.span_suggestion_verbose(sugg.0, sugg.1, &sugg.2, Applicability::MaybeIncorrect); } - if let Some(span) = self.diagnostic_metadata.current_block_could_be_bare_struct_literal { - err.multipart_suggestion( - "you might have meant to write a `struct` literal", - vec![ - (span.shrink_to_lo(), "{ SomeStruct ".to_string()), - (span.shrink_to_hi(), "}".to_string()), - ], - Applicability::HasPlaceholders, - ); + self.suggest_bare_struct_literal(&mut err); + self.suggest_pattern_match_with_let(&mut err, source, span); + + self.suggest_self_or_self_ref(&mut err, path, span); + self.detect_assoct_type_constraint_meant_as_path(&mut err, &base_error); + if self.suggest_self_ty_or_self_value(&mut err, source, path, span) { + return (err, Vec::new()); } - match (source, self.diagnostic_metadata.in_if_condition) { - ( - PathSource::Expr(_), - Some(Expr { span: expr_span, kind: ExprKind::Assign(lhs, _, _), .. }), - ) => { - // Icky heuristic so we don't suggest: - // `if (i + 2) = 2` => `if let (i + 2) = 2` (approximately pattern) - // `if 2 = i` => `if let 2 = i` (lhs needs to contain error span) - if lhs.is_approximately_pattern() && lhs.span.contains(span) { - err.span_suggestion_verbose( - expr_span.shrink_to_lo(), - "you might have meant to use pattern matching", - "let ", - Applicability::MaybeIncorrect, - ); + + let (found, candidates) = + self.try_lookup_name_with_relex_fashion(&mut err, source, path, span, res, &base_error); + if found { + return (err, candidates); + } + + self.suggest_type_ascription(&mut err, source, path, res, span, &base_error); + self.add_err_code_cases(&mut err, source, path, span); + + (err, candidates) + } + + fn detect_assoct_type_constraint_meant_as_path( + &self, + err: &mut Diagnostic, + base_error: &BaseError<'static>, + ) { + let Some(ty) = self.diagnostic_metadata.current_type_path else { return; }; + let TyKind::Path(_, path) = &ty.kind else { return; }; + for segment in &path.segments { + let Some(params) = &segment.args else { continue; }; + let ast::GenericArgs::AngleBracketed(ref params) = params.deref() else { continue; }; + for param in ¶ms.args { + let ast::AngleBracketedArg::Constraint(constraint) = param else { continue; }; + let ast::AssocConstraintKind::Bound { bounds } = &constraint.kind else { + continue; + }; + for bound in bounds { + let ast::GenericBound::Trait(trait_ref, ast::TraitBoundModifier::None) + = bound else + { + continue; + }; + if base_error.span == trait_ref.span { + err.span_suggestion_verbose( + constraint.ident.span.between(trait_ref.span), + "you might have meant to write a path instead of an associated type bound", + "::", + Applicability::MachineApplicable, + ); + } } } - _ => {} } + } + fn suggest_self_or_self_ref(&mut self, err: &mut Diagnostic, path: &[Segment], span: Span) { let is_assoc_fn = self.self_type_is_available(); + let item_str = path.last().unwrap().ident; // Emit help message for fake-self from other languages (e.g., `this` in Javascript). if ["this", "my"].contains(&item_str.as_str()) && is_assoc_fn { err.span_suggestion_short( @@ -358,96 +389,25 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { } } } + } - self.detect_assoct_type_constraint_meant_as_path(base_error.span, &mut err); - - // Emit special messages for unresolved `Self` and `self`. - if is_self_type(path, ns) { - err.code(rustc_errors::error_code!(E0411)); - err.span_label( - span, - "`Self` is only available in impls, traits, and type definitions".to_string(), - ); - if let Some(item_kind) = self.diagnostic_metadata.current_item { - err.span_label( - item_kind.ident.span, - format!( - "`Self` not allowed in {} {}", - item_kind.kind.article(), - item_kind.kind.descr() - ), - ); - } - return (err, Vec::new()); - } - if is_self_value(path, ns) { - debug!("smart_resolve_path_fragment: E0424, source={:?}", source); - - err.code(rustc_errors::error_code!(E0424)); - err.span_label(span, match source { - PathSource::Pat => "`self` value is a keyword and may not be bound to variables or shadowed", - _ => "`self` value is a keyword only available in methods with a `self` parameter", - }); - if let Some((fn_kind, span)) = &self.diagnostic_metadata.current_function { - // The current function has a `self' parameter, but we were unable to resolve - // a reference to `self`. This can only happen if the `self` identifier we - // are resolving came from a different hygiene context. - if fn_kind.decl().inputs.get(0).map_or(false, |p| p.is_self()) { - err.span_label(*span, "this function has a `self` parameter, but a macro invocation can only access identifiers it receives from parameters"); - } else { - let doesnt = if is_assoc_fn { - let (span, sugg) = fn_kind - .decl() - .inputs - .get(0) - .map(|p| (p.span.shrink_to_lo(), "&self, ")) - .unwrap_or_else(|| { - // Try to look for the "(" after the function name, if possible. - // This avoids placing the suggestion into the visibility specifier. - let span = fn_kind - .ident() - .map_or(*span, |ident| span.with_lo(ident.span.hi())); - ( - self.r - .session - .source_map() - .span_through_char(span, '(') - .shrink_to_hi(), - "&self", - ) - }); - err.span_suggestion_verbose( - span, - "add a `self` receiver parameter to make the associated `fn` a method", - sugg, - Applicability::MaybeIncorrect, - ); - "doesn't" - } else { - "can't" - }; - if let Some(ident) = fn_kind.ident() { - err.span_label( - ident.span, - &format!("this function {} have a `self` parameter", doesnt), - ); - } - } - } else if let Some(item_kind) = self.diagnostic_metadata.current_item { - err.span_label( - item_kind.ident.span, - format!( - "`self` not allowed in {} {}", - item_kind.kind.article(), - item_kind.kind.descr() - ), - ); - } - return (err, Vec::new()); - } - + fn try_lookup_name_with_relex_fashion( + &mut self, + err: &mut DiagnosticBuilder<'_, ErrorGuaranteed>, + source: PathSource<'_>, + path: &[Segment], + span: Span, + res: Option, + base_error: &BaseError<'static>, + ) -> (bool, Vec) { // Try to lookup name in more relaxed fashion for better error reporting. let ident = path.last().unwrap().ident; + let is_expected = &|res| source.is_expected(res); + let ns = source.namespace(); + let is_enum_variant = &|res| matches!(res, Res::Def(DefKind::Variant, _)); + let path_str = Segment::names_to_string(path); + let ident_span = path.last().map_or(span, |ident| ident.ident.span); + let mut candidates = self .r .lookup_import_candidates(ident, ns, &self.parent_scope, is_expected) @@ -494,7 +454,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { { // Already reported this issue on the lhs of the type ascription. err.delay_as_bug(); - return (err, candidates); + return (true, candidates); } } @@ -522,8 +482,9 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { ); } } + // Try Levenshtein algorithm. - let typo_sugg = self.lookup_typo_candidate(path, ns, is_expected); + let typo_sugg = self.lookup_typo_candidate(path, source.namespace(), is_expected); if path.len() == 1 && self.self_type_is_available() { if let Some(candidate) = self.lookup_assoc_candidate(ident, ns, is_expected) { let self_is_available = self.self_value_is_available(path[0].ident.span); @@ -560,8 +521,8 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { ); } } - self.r.add_typo_suggestion(&mut err, typo_sugg, ident_span); - return (err, candidates); + self.r.add_typo_suggestion(err, typo_sugg, ident_span); + return (true, candidates); } // If the first argument in call is `self` suggest calling a method. @@ -579,14 +540,14 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { format!("self.{path_str}({args_snippet})"), Applicability::MachineApplicable, ); - return (err, candidates); + return (true, candidates); } } // Try context-dependent help if relaxed lookup didn't work. if let Some(res) = res { if self.smart_resolve_context_dependent_help( - &mut err, + err, span, source, res, @@ -594,14 +555,25 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { &base_error.fallback_label, ) { // We do this to avoid losing a secondary span when we override the main error span. - self.r.add_typo_suggestion(&mut err, typo_sugg, ident_span); - return (err, candidates); + self.r.add_typo_suggestion(err, typo_sugg, ident_span); + return (true, candidates); } } + return (false, candidates); + } + fn suggest_type_ascription( + &mut self, + err: &mut DiagnosticBuilder<'_, ErrorGuaranteed>, + source: PathSource<'_>, + path: &[Segment], + res: Option, + span: Span, + base_error: &BaseError<'static>, + ) { let is_macro = base_error.span.from_expansion() && base_error.span.desugaring_kind().is_none(); - if !self.type_ascription_suggestion(&mut err, base_error.span) { + if !self.type_ascription_suggestion(err, base_error.span) { let mut fallback = false; if let ( PathSource::Trait(AliasPossibility::Maybe), @@ -663,9 +635,12 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { } } - fallback |= self.restrict_assoc_type_in_where_clause(span, &mut err); + let is_expected = &|res| source.is_expected(res); + let ident_span = path.last().map_or(span, |ident| ident.ident.span); + fallback |= self.restrict_assoc_type_in_where_clause(span, err); - if !self.r.add_typo_suggestion(&mut err, typo_sugg, ident_span) { + let typo_sugg = self.lookup_typo_candidate(path, source.namespace(), is_expected); + if !self.r.add_typo_suggestion(err, typo_sugg, ident_span) { fallback = true; match self.diagnostic_metadata.current_let_binding { Some((pat_sp, Some(ty_sp), None)) @@ -683,17 +658,27 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { // If the trait has a single item (which wasn't matched by Levenshtein), suggest it let suggestion = self.get_single_associated_item(&path, &source, is_expected); - self.r.add_typo_suggestion(&mut err, suggestion, ident_span); + self.r.add_typo_suggestion(err, suggestion, ident_span); } if fallback { // Fallback label. - err.span_label(base_error.span, base_error.fallback_label); + err.span_label(base_error.span, &base_error.fallback_label); } } + } + + fn add_err_code_cases( + &mut self, + err: &mut DiagnosticBuilder<'_, ErrorGuaranteed>, + source: PathSource<'_>, + path: &[Segment], + span: Span, + ) { if let Some(err_code) = &err.code { if err_code == &rustc_errors::error_code!(E0425) { for label_rib in &self.label_ribs { for (label_ident, node_id) in &label_rib.bindings { + let ident = path.last().unwrap().ident; if format!("'{}", ident) == label_ident.to_string() { err.span_label(label_ident.span, "a label with a similar name exists"); if let PathSource::Expr(Some(Expr { @@ -724,38 +709,106 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { } } } - - (err, candidates) } - fn detect_assoct_type_constraint_meant_as_path(&self, base_span: Span, err: &mut Diagnostic) { - let Some(ty) = self.diagnostic_metadata.current_type_path else { return; }; - let TyKind::Path(_, path) = &ty.kind else { return; }; - for segment in &path.segments { - let Some(params) = &segment.args else { continue; }; - let ast::GenericArgs::AngleBracketed(ref params) = params.deref() else { continue; }; - for param in ¶ms.args { - let ast::AngleBracketedArg::Constraint(constraint) = param else { continue; }; - let ast::AssocConstraintKind::Bound { bounds } = &constraint.kind else { - continue; - }; - for bound in bounds { - let ast::GenericBound::Trait(trait_ref, ast::TraitBoundModifier::None) - = bound else - { - continue; - }; - if base_span == trait_ref.span { + /// Emit special messages for unresolved `Self` and `self`. + fn suggest_self_ty_or_self_value( + &mut self, + err: &mut Diagnostic, + source: PathSource<'_>, + path: &[Segment], + span: Span, + ) -> bool { + if is_self_type(path, source.namespace()) { + err.code(rustc_errors::error_code!(E0411)); + err.span_label( + span, + "`Self` is only available in impls, traits, and type definitions".to_string(), + ); + if let Some(item_kind) = self.diagnostic_metadata.current_item { + err.span_label( + item_kind.ident.span, + format!( + "`Self` not allowed in {} {}", + item_kind.kind.article(), + item_kind.kind.descr() + ), + ); + } + return true; + } + + if is_self_value(path, source.namespace()) { + debug!("smart_resolve_path_fragment: E0424, source={:?}", source); + err.code(rustc_errors::error_code!(E0424)); + err.span_label( + span, + match source { + PathSource::Pat => { + "`self` value is a keyword and may not be bound to variables or shadowed" + } + _ => "`self` value is a keyword only available in methods with a `self` parameter", + }, + ); + let is_assoc_fn = self.self_type_is_available(); + if let Some((fn_kind, span)) = &self.diagnostic_metadata.current_function { + // The current function has a `self' parameter, but we were unable to resolve + // a reference to `self`. This can only happen if the `self` identifier we + // are resolving came from a different hygiene context. + if fn_kind.decl().inputs.get(0).map_or(false, |p| p.is_self()) { + err.span_label(*span, "this function has a `self` parameter, but a macro invocation can only access identifiers it receives from parameters"); + } else { + let doesnt = if is_assoc_fn { + let (span, sugg) = fn_kind + .decl() + .inputs + .get(0) + .map(|p| (p.span.shrink_to_lo(), "&self, ")) + .unwrap_or_else(|| { + // Try to look for the "(" after the function name, if possible. + // This avoids placing the suggestion into the visibility specifier. + let span = fn_kind + .ident() + .map_or(*span, |ident| span.with_lo(ident.span.hi())); + ( + self.r + .session + .source_map() + .span_through_char(span, '(') + .shrink_to_hi(), + "&self", + ) + }); err.span_suggestion_verbose( - constraint.ident.span.between(trait_ref.span), - "you might have meant to write a path instead of an associated type bound", - "::", - Applicability::MachineApplicable, + span, + "add a `self` receiver parameter to make the associated `fn` a method", + sugg, + Applicability::MaybeIncorrect, + ); + "doesn't" + } else { + "can't" + }; + if let Some(ident) = fn_kind.ident() { + err.span_label( + ident.span, + &format!("this function {} have a `self` parameter", doesnt), ); } } + } else if let Some(item_kind) = self.diagnostic_metadata.current_item { + err.span_label( + item_kind.ident.span, + format!( + "`self` not allowed in {} {}", + item_kind.kind.article(), + item_kind.kind.descr() + ), + ); } + return true; } + false } fn suggest_swapping_misplaced_self_ty_and_trait( @@ -787,6 +840,41 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { } } + fn suggest_bare_struct_literal(&mut self, err: &mut Diagnostic) { + if let Some(span) = self.diagnostic_metadata.current_block_could_be_bare_struct_literal { + err.multipart_suggestion( + "you might have meant to write a `struct` literal", + vec![ + (span.shrink_to_lo(), "{ SomeStruct ".to_string()), + (span.shrink_to_hi(), "}".to_string()), + ], + Applicability::HasPlaceholders, + ); + } + } + + fn suggest_pattern_match_with_let( + &mut self, + err: &mut Diagnostic, + source: PathSource<'_>, + span: Span, + ) { + if let PathSource::Expr(_) = source && + let Some(Expr { span: expr_span, kind: ExprKind::Assign(lhs, _, _), .. } ) = self.diagnostic_metadata.in_if_condition { + // Icky heuristic so we don't suggest: + // `if (i + 2) = 2` => `if let (i + 2) = 2` (approximately pattern) + // `if 2 = i` => `if let 2 = i` (lhs needs to contain error span) + if lhs.is_approximately_pattern() && lhs.span.contains(span) { + err.span_suggestion_verbose( + expr_span.shrink_to_lo(), + "you might have meant to use pattern matching", + "let ", + Applicability::MaybeIncorrect, + ); + } + } + } + fn get_single_associated_item( &mut self, path: &[Segment], From 3e6c9e5a194902ec6c8c26586fe6fa72dd624004 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 21 Sep 2022 08:29:19 +0000 Subject: [PATCH 077/586] Fix wrongly refactored Lift impl --- compiler/rustc_middle/src/ty/structural_impls.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index 004fcffdc4074..3304e7e160200 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -272,7 +272,10 @@ impl<'tcx, A: Lift<'tcx>, B: Lift<'tcx>, C: Lift<'tcx>> Lift<'tcx> for (A, B, C) impl<'tcx, T: Lift<'tcx>> Lift<'tcx> for Option { type Lifted = Option; fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option { - tcx.lift(self?).map(Some) + Some(match self { + Some(x) => Some(tcx.lift(x)?), + None => None, + }) } } From 3d69d23a25d6375ff8083bb94cc5b5fbc1f25415 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 18 May 2022 14:57:22 +0000 Subject: [PATCH 078/586] Split match out into a helper function --- .../src/infer/outlives/obligations.rs | 59 +++++++++++-------- 1 file changed, 34 insertions(+), 25 deletions(-) diff --git a/compiler/rustc_infer/src/infer/outlives/obligations.rs b/compiler/rustc_infer/src/infer/outlives/obligations.rs index 5bd1774f6b1ec..e87510954288d 100644 --- a/compiler/rustc_infer/src/infer/outlives/obligations.rs +++ b/compiler/rustc_infer/src/infer/outlives/obligations.rs @@ -71,7 +71,7 @@ use rustc_data_structures::undo_log::UndoLogs; use rustc_hir::def_id::LocalDefId; use rustc_middle::mir::ConstraintCategory; use rustc_middle::ty::subst::GenericArgKind; -use rustc_middle::ty::{self, Region, Ty, TyCtxt, TypeVisitable}; +use rustc_middle::ty::{self, Region, SubstsRef, Ty, TyCtxt, TypeVisitable}; use smallvec::smallvec; impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { @@ -352,7 +352,7 @@ where // may not apply. let mut approx_env_bounds = self.verify_bound.projection_approx_declared_bounds_from_env(projection_ty); - debug!("projection_must_outlive: approx_env_bounds={:?}", approx_env_bounds); + debug!(?approx_env_bounds); // Remove outlives bounds that we get from the environment but // which are also deducible from the trait. This arises (cc @@ -392,27 +392,9 @@ where // edges, which winds up enforcing the same condition. let needs_infer = projection_ty.needs_infer(); if approx_env_bounds.is_empty() && trait_bounds.is_empty() && needs_infer { - debug!("projection_must_outlive: no declared bounds"); - - let constraint = origin.to_constraint_category(); - for k in projection_ty.substs { - match k.unpack() { - GenericArgKind::Lifetime(lt) => { - self.delegate.push_sub_region_constraint( - origin.clone(), - region, - lt, - constraint, - ); - } - GenericArgKind::Type(ty) => { - self.type_must_outlive(origin.clone(), ty, region, constraint); - } - GenericArgKind::Const(_) => { - // Const parameters don't impose constraints. - } - } - } + debug!("no declared bounds"); + + self.substs_must_outlive(projection_ty.substs, origin, region); return; } @@ -442,8 +424,8 @@ where .all(|b| b == Some(trait_bounds[0])) { let unique_bound = trait_bounds[0]; - debug!("projection_must_outlive: unique trait bound = {:?}", unique_bound); - debug!("projection_must_outlive: unique declared bound appears in trait ref"); + debug!(?unique_bound); + debug!("unique declared bound appears in trait ref"); let category = origin.to_constraint_category(); self.delegate.push_sub_region_constraint(origin, region, unique_bound, category); return; @@ -459,6 +441,33 @@ where debug!("projection_must_outlive: pushing {:?}", verify_bound); self.delegate.push_verify(origin, generic, region, verify_bound); } + + fn substs_must_outlive( + &mut self, + substs: SubstsRef<'tcx>, + origin: infer::SubregionOrigin<'tcx>, + region: ty::Region<'tcx>, + ) { + let constraint = origin.to_constraint_category(); + for k in substs { + match k.unpack() { + GenericArgKind::Lifetime(lt) => { + self.delegate.push_sub_region_constraint( + origin.clone(), + region, + lt, + constraint, + ); + } + GenericArgKind::Type(ty) => { + self.type_must_outlive(origin.clone(), ty, region, constraint); + } + GenericArgKind::Const(_) => { + // Const parameters don't impose constraints. + } + } + } + } } impl<'cx, 'tcx> TypeOutlivesDelegate<'tcx> for &'cx InferCtxt<'cx, 'tcx> { From 759c04a00b46d4a86d71ab69b072b956dfacabf9 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 18 May 2022 14:58:47 +0000 Subject: [PATCH 079/586] Some tracing instrumentation cleanups --- compiler/rustc_infer/src/infer/outlives/verify.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_infer/src/infer/outlives/verify.rs b/compiler/rustc_infer/src/infer/outlives/verify.rs index e344e192a768e..bd7b8a3004f53 100644 --- a/compiler/rustc_infer/src/infer/outlives/verify.rs +++ b/compiler/rustc_infer/src/infer/outlives/verify.rs @@ -124,13 +124,12 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> { self.declared_projection_bounds_from_trait(projection_ty) } - pub fn projection_bound( + #[instrument(level = "debug", skip(self, visited))] + fn projection_bound( &self, projection_ty: ty::ProjectionTy<'tcx>, visited: &mut SsoHashSet>, ) -> VerifyBound<'tcx> { - debug!("projection_bound(projection_ty={:?})", projection_ty); - let projection_ty_as_ty = self.tcx.mk_projection(projection_ty.item_def_id, projection_ty.substs); From b4fdc5861d46dc9204a8a4a51fa287360090ec3c Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 21 Sep 2022 14:17:11 +0200 Subject: [PATCH 080/586] Add missing documentation for `bool::from_str` --- library/core/src/str/traits.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/core/src/str/traits.rs b/library/core/src/str/traits.rs index e9649fc91fa09..18f2ce6edc722 100644 --- a/library/core/src/str/traits.rs +++ b/library/core/src/str/traits.rs @@ -573,8 +573,8 @@ impl FromStr for bool { /// Parse a `bool` from a string. /// - /// Yields a `Result`, because `s` may or may not - /// actually be parseable. + /// The only accepted values are `"true"` and `"false"`. Any other input + /// will return an error. /// /// # Examples /// From 96b819a456672e50444dcccbfed2435f6b212225 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 18 May 2022 15:09:14 +0000 Subject: [PATCH 081/586] Inline a trivial function --- .../src/infer/outlives/obligations.rs | 4 +-- .../rustc_infer/src/infer/outlives/verify.rs | 34 ++++++------------- 2 files changed, 13 insertions(+), 25 deletions(-) diff --git a/compiler/rustc_infer/src/infer/outlives/obligations.rs b/compiler/rustc_infer/src/infer/outlives/obligations.rs index e87510954288d..3f98168e2573a 100644 --- a/compiler/rustc_infer/src/infer/outlives/obligations.rs +++ b/compiler/rustc_infer/src/infer/outlives/obligations.rs @@ -343,7 +343,7 @@ where // These are guaranteed to apply, no matter the inference // results. let trait_bounds: Vec<_> = - self.verify_bound.projection_declared_bounds_from_trait(projection_ty).collect(); + self.verify_bound.bounds(projection_ty.item_def_id, projection_ty.substs).collect(); debug!(?trait_bounds); @@ -369,7 +369,7 @@ where match *bound.0.kind() { ty::Projection(projection_ty) => self .verify_bound - .projection_declared_bounds_from_trait(projection_ty) + .bounds(projection_ty.item_def_id, projection_ty.substs) .all(|r| r != bound.1), _ => panic!("expected only projection types from env, not {:?}", bound.0), diff --git a/compiler/rustc_infer/src/infer/outlives/verify.rs b/compiler/rustc_infer/src/infer/outlives/verify.rs index bd7b8a3004f53..30ee1229faec1 100644 --- a/compiler/rustc_infer/src/infer/outlives/verify.rs +++ b/compiler/rustc_infer/src/infer/outlives/verify.rs @@ -6,7 +6,7 @@ use rustc_data_structures::captures::Captures; use rustc_data_structures::sso::SsoHashSet; use rustc_hir::def_id::DefId; use rustc_middle::ty::GenericArg; -use rustc_middle::ty::{self, EarlyBinder, OutlivesPredicate, Ty, TyCtxt}; +use rustc_middle::ty::{self, EarlyBinder, OutlivesPredicate, SubstsRef, Ty, TyCtxt}; use smallvec::smallvec; @@ -114,16 +114,6 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> { self.declared_generic_bounds_from_env_for_erased_ty(erased_projection_ty) } - /// Searches the where-clauses in scope for regions that - /// `projection_ty` is known to outlive. Currently requires an - /// exact match. - pub fn projection_declared_bounds_from_trait( - &self, - projection_ty: ty::ProjectionTy<'tcx>, - ) -> impl Iterator> + 'cx + Captures<'tcx> { - self.declared_projection_bounds_from_trait(projection_ty) - } - #[instrument(level = "debug", skip(self, visited))] fn projection_bound( &self, @@ -151,7 +141,7 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> { // Extend with bounds that we can find from the trait. let trait_bounds = self - .projection_declared_bounds_from_trait(projection_ty) + .bounds(projection_ty.item_def_id, projection_ty.substs) .map(|r| VerifyBound::OutlivedBy(r)); // see the extensive comment in projection_must_outlive @@ -294,15 +284,15 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> { /// /// then this function would return `'x`. This is subject to the /// limitations around higher-ranked bounds described in - /// `region_bounds_declared_on_associated_item`. - fn declared_projection_bounds_from_trait( + /// `declared_region_bounds`. + #[instrument(level = "debug", skip(self))] + pub fn bounds( &self, - projection_ty: ty::ProjectionTy<'tcx>, + def_id: DefId, + substs: SubstsRef<'tcx>, ) -> impl Iterator> + 'cx + Captures<'tcx> { - debug!("projection_bounds(projection_ty={:?})", projection_ty); let tcx = self.tcx; - self.region_bounds_declared_on_associated_item(projection_ty.item_def_id) - .map(move |r| EarlyBinder(r).subst(tcx, projection_ty.substs)) + self.declared_region_bounds(def_id).map(move |r| EarlyBinder(r).subst(tcx, substs)) } /// Given the `DefId` of an associated item, returns any region @@ -335,12 +325,10 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> { /// /// This is for simplicity, and because we are not really smart /// enough to cope with such bounds anywhere. - fn region_bounds_declared_on_associated_item( - &self, - assoc_item_def_id: DefId, - ) -> impl Iterator> { + fn declared_region_bounds(&self, def_id: DefId) -> impl Iterator> { let tcx = self.tcx; - let bounds = tcx.item_bounds(assoc_item_def_id); + let bounds = tcx.item_bounds(def_id); + trace!("{:#?}", bounds); bounds .into_iter() .filter_map(|p| p.to_opt_type_outlives()) From 4d4cc4fe53aec2a7f36535c3458aced2fcd2988d Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 18 May 2022 15:17:58 +0000 Subject: [PATCH 082/586] Generalize a helper to be useful for types other than projections --- compiler/rustc_infer/src/infer/outlives/obligations.rs | 6 +++--- compiler/rustc_infer/src/infer/outlives/verify.rs | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_infer/src/infer/outlives/obligations.rs b/compiler/rustc_infer/src/infer/outlives/obligations.rs index 3f98168e2573a..ec26a10c5362c 100644 --- a/compiler/rustc_infer/src/infer/outlives/obligations.rs +++ b/compiler/rustc_infer/src/infer/outlives/obligations.rs @@ -347,11 +347,12 @@ where debug!(?trait_bounds); + let generic = GenericKind::Projection(projection_ty); + // Compute the bounds we can derive from the environment. This // is an "approximate" match -- in some cases, these bounds // may not apply. - let mut approx_env_bounds = - self.verify_bound.projection_approx_declared_bounds_from_env(projection_ty); + let mut approx_env_bounds = self.verify_bound.approx_declared_bounds_from_env(generic); debug!(?approx_env_bounds); // Remove outlives bounds that we get from the environment but @@ -436,7 +437,6 @@ where // projection outlive; in some cases, this may add insufficient // edges into the inference graph, leading to inference failures // even though a satisfactory solution exists. - let generic = GenericKind::Projection(projection_ty); let verify_bound = self.verify_bound.generic_bound(generic); debug!("projection_must_outlive: pushing {:?}", verify_bound); self.delegate.push_verify(origin, generic, region, verify_bound); diff --git a/compiler/rustc_infer/src/infer/outlives/verify.rs b/compiler/rustc_infer/src/infer/outlives/verify.rs index 30ee1229faec1..5f1671b4807c9 100644 --- a/compiler/rustc_infer/src/infer/outlives/verify.rs +++ b/compiler/rustc_infer/src/infer/outlives/verify.rs @@ -105,11 +105,11 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> { /// the clause from the environment only applies if `'0 = 'a`, /// which we don't know yet. But we would still include `'b` in /// this list. - pub fn projection_approx_declared_bounds_from_env( + pub fn approx_declared_bounds_from_env( &self, - projection_ty: ty::ProjectionTy<'tcx>, + generic: GenericKind<'tcx>, ) -> Vec, ty::Region<'tcx>>>> { - let projection_ty = GenericKind::Projection(projection_ty).to_ty(self.tcx); + let projection_ty = generic.to_ty(self.tcx); let erased_projection_ty = self.tcx.erase_regions(projection_ty); self.declared_generic_bounds_from_env_for_erased_ty(erased_projection_ty) } @@ -125,7 +125,7 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> { // Search the env for where clauses like `P: 'a`. let env_bounds = self - .projection_approx_declared_bounds_from_env(projection_ty) + .approx_declared_bounds_from_env(GenericKind::Projection(projection_ty)) .into_iter() .map(|binder| { if let Some(ty::OutlivesPredicate(ty, r)) = binder.no_bound_vars() && ty == projection_ty_as_ty { From c8ecf09a25720bb87f1da7b1741238eb70aa2762 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 18 May 2022 15:40:16 +0000 Subject: [PATCH 083/586] Generalize projection_must_outlive --- .../src/infer/outlives/obligations.rs | 43 +++++++++++++------ 1 file changed, 29 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_infer/src/infer/outlives/obligations.rs b/compiler/rustc_infer/src/infer/outlives/obligations.rs index ec26a10c5362c..55bb75c8b6da2 100644 --- a/compiler/rustc_infer/src/infer/outlives/obligations.rs +++ b/compiler/rustc_infer/src/infer/outlives/obligations.rs @@ -68,6 +68,7 @@ use crate::infer::{ }; use crate::traits::{ObligationCause, ObligationCauseCode}; use rustc_data_structures::undo_log::UndoLogs; +use rustc_hir::def_id::DefId; use rustc_hir::def_id::LocalDefId; use rustc_middle::mir::ConstraintCategory; use rustc_middle::ty::subst::GenericArgKind; @@ -324,6 +325,29 @@ where origin: infer::SubregionOrigin<'tcx>, region: ty::Region<'tcx>, projection_ty: ty::ProjectionTy<'tcx>, + ) { + self.generic_must_outlive( + origin, + region, + GenericKind::Projection(projection_ty), + projection_ty.item_def_id, + projection_ty.substs, + |ty| match ty.kind() { + ty::Projection(projection_ty) => (projection_ty.item_def_id, projection_ty.substs), + _ => bug!("expected only projection types from env, not {:?}", ty), + }, + ); + } + + #[instrument(level = "debug", skip(self, filter))] + fn generic_must_outlive( + &mut self, + origin: infer::SubregionOrigin<'tcx>, + region: ty::Region<'tcx>, + generic: GenericKind<'tcx>, + def_id: DefId, + substs: SubstsRef<'tcx>, + filter: impl Fn(Ty<'tcx>) -> (DefId, SubstsRef<'tcx>), ) { // This case is thorny for inference. The fundamental problem is // that there are many cases where we have choice, and inference @@ -342,13 +366,10 @@ where // Compute the bounds we can derive from the trait definition. // These are guaranteed to apply, no matter the inference // results. - let trait_bounds: Vec<_> = - self.verify_bound.bounds(projection_ty.item_def_id, projection_ty.substs).collect(); + let trait_bounds: Vec<_> = self.verify_bound.bounds(def_id, substs).collect(); debug!(?trait_bounds); - let generic = GenericKind::Projection(projection_ty); - // Compute the bounds we can derive from the environment. This // is an "approximate" match -- in some cases, these bounds // may not apply. @@ -367,14 +388,8 @@ where // If the declaration is `trait Trait<'b> { type Item: 'b; }`, then `projection_declared_bounds_from_trait` // will be invoked with `['b => ^1]` and so we will get `^1` returned. let bound = bound_outlives.skip_binder(); - match *bound.0.kind() { - ty::Projection(projection_ty) => self - .verify_bound - .bounds(projection_ty.item_def_id, projection_ty.substs) - .all(|r| r != bound.1), - - _ => panic!("expected only projection types from env, not {:?}", bound.0), - } + let (def_id, substs) = filter(bound.0); + self.verify_bound.bounds(def_id, substs).all(|r| r != bound.1) }); // If declared bounds list is empty, the only applicable rule is @@ -391,11 +406,11 @@ where // the problem is to add `T: 'r`, which isn't true. So, if there are no // inference variables, we use a verify constraint instead of adding // edges, which winds up enforcing the same condition. - let needs_infer = projection_ty.needs_infer(); + let needs_infer = substs.needs_infer(); if approx_env_bounds.is_empty() && trait_bounds.is_empty() && needs_infer { debug!("no declared bounds"); - self.substs_must_outlive(projection_ty.substs, origin, region); + self.substs_must_outlive(substs, origin, region); return; } From 37928f59865b5ff53b95fe2f3c02491890a4129d Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 18 May 2022 16:01:10 +0000 Subject: [PATCH 084/586] Neither require nor imply lifetime bounds on opaque type for well formedness --- .../src/type_check/free_region_relations.rs | 5 ++ .../src/infer/error_reporting/mod.rs | 3 ++ .../src/infer/outlives/components.rs | 17 ++++++- .../rustc_infer/src/infer/outlives/env.rs | 4 ++ .../src/infer/outlives/obligations.rs | 24 +++++++++ .../rustc_infer/src/infer/outlives/verify.rs | 16 ++++++ .../src/infer/region_constraints/mod.rs | 10 ++++ compiler/rustc_infer/src/traits/util.rs | 12 ++++- compiler/rustc_middle/src/traits/query.rs | 4 +- .../src/implied_outlives_bounds.rs | 3 ++ .../rustc_typeck/src/mem_categorization.rs | 12 ++--- compiler/rustc_typeck/src/outlives/utils.rs | 35 ++++++++++++- .../bugs/issue-86218.stderr | 23 --------- .../generic-associated-types/issue-86218-2.rs | 24 +++++++++ .../{bugs => }/issue-86218.rs | 8 ++- .../type-alias-impl-trait/implied_bounds.rs | 51 +++++++++++++++++++ .../implied_bounds.stderr | 16 ++++++ .../type-alias-impl-trait/implied_bounds2.rs | 9 ++++ .../implied_bounds2.stderr | 12 +++++ .../implied_bounds_closure.rs | 31 +++++++++++ .../implied_bounds_closure.stderr | 11 ++++ .../implied_bounds_from_types.rs | 51 +++++++++++++++++++ .../implied_bounds_from_types.stderr | 16 ++++++ .../implied_lifetime_wf_check.rs | 18 +++++++ .../implied_lifetime_wf_check.stderr | 9 ++++ .../implied_lifetime_wf_check2.rs | 13 +++++ .../implied_lifetime_wf_check3.rs | 42 +++++++++++++++ .../implied_lifetime_wf_check3.stderr | 38 ++++++++++++++ .../issue-58662-generator-with-lifetime.rs | 2 +- .../issue-58662-simplified.rs | 20 ++++++++ 30 files changed, 497 insertions(+), 42 deletions(-) delete mode 100644 src/test/ui/generic-associated-types/bugs/issue-86218.stderr create mode 100644 src/test/ui/generic-associated-types/issue-86218-2.rs rename src/test/ui/generic-associated-types/{bugs => }/issue-86218.rs (70%) create mode 100644 src/test/ui/type-alias-impl-trait/implied_bounds.rs create mode 100644 src/test/ui/type-alias-impl-trait/implied_bounds.stderr create mode 100644 src/test/ui/type-alias-impl-trait/implied_bounds2.rs create mode 100644 src/test/ui/type-alias-impl-trait/implied_bounds2.stderr create mode 100644 src/test/ui/type-alias-impl-trait/implied_bounds_closure.rs create mode 100644 src/test/ui/type-alias-impl-trait/implied_bounds_closure.stderr create mode 100644 src/test/ui/type-alias-impl-trait/implied_bounds_from_types.rs create mode 100644 src/test/ui/type-alias-impl-trait/implied_bounds_from_types.stderr create mode 100644 src/test/ui/type-alias-impl-trait/implied_lifetime_wf_check.rs create mode 100644 src/test/ui/type-alias-impl-trait/implied_lifetime_wf_check.stderr create mode 100644 src/test/ui/type-alias-impl-trait/implied_lifetime_wf_check2.rs create mode 100644 src/test/ui/type-alias-impl-trait/implied_lifetime_wf_check3.rs create mode 100644 src/test/ui/type-alias-impl-trait/implied_lifetime_wf_check3.stderr create mode 100644 src/test/ui/type-alias-impl-trait/issue-58662-simplified.rs diff --git a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs index f1b1c33a10543..e0140e281ee73 100644 --- a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs +++ b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs @@ -362,6 +362,11 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> { self.region_bound_pairs .insert(ty::OutlivesPredicate(GenericKind::Projection(projection_b), r_a)); } + + OutlivesBound::RegionSubOpaque(r_a, def_id, substs) => { + self.region_bound_pairs + .insert(ty::OutlivesPredicate(GenericKind::Opaque(def_id, substs), r_a)); + } } } } diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index 546ab82bc238a..e33035381e0a9 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -2374,6 +2374,9 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { let labeled_user_string = match bound_kind { GenericKind::Param(ref p) => format!("the parameter type `{}`", p), GenericKind::Projection(ref p) => format!("the associated type `{}`", p), + GenericKind::Opaque(def_id, substs) => { + format!("the opaque type `{}`", self.tcx.def_path_str_with_substs(def_id, substs)) + } }; if let Some(SubregionOrigin::CompareImplItemObligation { diff --git a/compiler/rustc_infer/src/infer/outlives/components.rs b/compiler/rustc_infer/src/infer/outlives/components.rs index b2d7f4a663ae4..14ee9f0519010 100644 --- a/compiler/rustc_infer/src/infer/outlives/components.rs +++ b/compiler/rustc_infer/src/infer/outlives/components.rs @@ -3,8 +3,9 @@ // RFC for reference. use rustc_data_structures::sso::SsoHashSet; +use rustc_hir::def_id::DefId; use rustc_middle::ty::subst::{GenericArg, GenericArgKind}; -use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitable}; +use rustc_middle::ty::{self, SubstsRef, Ty, TyCtxt, TypeVisitable}; use smallvec::{smallvec, SmallVec}; #[derive(Debug)] @@ -45,6 +46,8 @@ pub enum Component<'tcx> { // them. This gives us room to improve the regionck reasoning in // the future without breaking backwards compat. EscapingProjection(Vec>), + + Opaque(DefId, SubstsRef<'tcx>), } /// Push onto `out` all the things that must outlive `'a` for the condition @@ -120,6 +123,17 @@ fn compute_components<'tcx>( out.push(Component::Param(p)); } + // Ignore lifetimes found in opaque types. Opaque types can + // have lifetimes in their substs which their hidden type doesn't + // actually use. If we inferred that an opaque type is outlived by + // its parameter lifetimes, then we could prove that any lifetime + // outlives any other lifetime, which is unsound. + // See https://github.com/rust-lang/rust/issues/84305 for + // more details. + ty::Opaque(def_id, substs) => { + out.push(Component::Opaque(def_id, substs)); + }, + // For projections, we prefer to generate an obligation like // `>::Foo: 'a`, because this gives the // regionck more ways to prove that it holds. However, @@ -168,7 +182,6 @@ fn compute_components<'tcx>( ty::Float(..) | // OutlivesScalar ty::Never | // ... ty::Adt(..) | // OutlivesNominalType - ty::Opaque(..) | // OutlivesNominalType (ish) ty::Foreign(..) | // OutlivesNominalType ty::Str | // OutlivesScalar (ish) ty::Slice(..) | // ... diff --git a/compiler/rustc_infer/src/infer/outlives/env.rs b/compiler/rustc_infer/src/infer/outlives/env.rs index 872886da36261..281c65bda77a7 100644 --- a/compiler/rustc_infer/src/infer/outlives/env.rs +++ b/compiler/rustc_infer/src/infer/outlives/env.rs @@ -140,6 +140,10 @@ impl<'a, 'tcx> OutlivesEnvironmentBuilder<'tcx> { self.region_bound_pairs .insert(ty::OutlivesPredicate(GenericKind::Projection(projection_b), r_a)); } + OutlivesBound::RegionSubOpaque(r_a, def_id, substs) => { + self.region_bound_pairs + .insert(ty::OutlivesPredicate(GenericKind::Opaque(def_id, substs), r_a)); + } OutlivesBound::RegionSubRegion(r_a, r_b) => { if let (ReEarlyBound(_) | ReFree(_), ReVar(vid_b)) = (r_a.kind(), r_b.kind()) { infcx diff --git a/compiler/rustc_infer/src/infer/outlives/obligations.rs b/compiler/rustc_infer/src/infer/outlives/obligations.rs index 55bb75c8b6da2..ad5fbb9a15823 100644 --- a/compiler/rustc_infer/src/infer/outlives/obligations.rs +++ b/compiler/rustc_infer/src/infer/outlives/obligations.rs @@ -284,6 +284,9 @@ where Component::Param(param_ty) => { self.param_ty_must_outlive(origin, region, *param_ty); } + Component::Opaque(def_id, substs) => { + self.opaque_must_outlive(*def_id, substs, origin, region) + } Component::Projection(projection_ty) => { self.projection_must_outlive(origin, region, *projection_ty); } @@ -319,6 +322,27 @@ where self.delegate.push_verify(origin, generic, region, verify_bound); } + #[instrument(level = "debug", skip(self))] + fn opaque_must_outlive( + &mut self, + def_id: DefId, + substs: SubstsRef<'tcx>, + origin: infer::SubregionOrigin<'tcx>, + region: ty::Region<'tcx>, + ) { + self.generic_must_outlive( + origin, + region, + GenericKind::Opaque(def_id, substs), + def_id, + substs, + |ty| match *ty.kind() { + ty::Opaque(def_id, substs) => (def_id, substs), + _ => bug!("expected only projection types from env, not {:?}", ty), + }, + ); + } + #[instrument(level = "debug", skip(self))] fn projection_must_outlive( &mut self, diff --git a/compiler/rustc_infer/src/infer/outlives/verify.rs b/compiler/rustc_infer/src/infer/outlives/verify.rs index 5f1671b4807c9..040843d837070 100644 --- a/compiler/rustc_infer/src/infer/outlives/verify.rs +++ b/compiler/rustc_infer/src/infer/outlives/verify.rs @@ -47,6 +47,7 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> { GenericKind::Projection(projection_ty) => { self.projection_bound(projection_ty, &mut visited) } + GenericKind::Opaque(def_id, substs) => self.opaque_bound(def_id, substs), } } @@ -155,6 +156,20 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> { VerifyBound::AnyBound(env_bounds.chain(trait_bounds).collect()).or(recursive_bound) } + fn opaque_bound(&self, def_id: DefId, substs: SubstsRef<'tcx>) -> VerifyBound<'tcx> { + let bounds: Vec<_> = + self.bounds(def_id, substs).map(|r| VerifyBound::OutlivedBy(r)).collect(); + trace!("{:#?}", bounds); + if bounds.is_empty() { + // No bounds means the value must not have any lifetimes. + // FIXME: should we implicitly add 'static to `tcx.item_bounds` for opaque types, just + // like we add `Sized`? + VerifyBound::OutlivedBy(self.tcx.lifetimes.re_static) + } else { + VerifyBound::AnyBound(bounds) + } + } + fn bound_from_components( &self, components: &[Component<'tcx>], @@ -184,6 +199,7 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> { match *component { Component::Region(lt) => VerifyBound::OutlivedBy(lt), Component::Param(param_ty) => self.param_bound(param_ty), + Component::Opaque(did, substs) => self.opaque_bound(did, substs), Component::Projection(projection_ty) => self.projection_bound(projection_ty, visited), Component::EscapingProjection(ref components) => { self.bound_from_components(components, visited) diff --git a/compiler/rustc_infer/src/infer/region_constraints/mod.rs b/compiler/rustc_infer/src/infer/region_constraints/mod.rs index e43d28ee56e3e..67b3da687200e 100644 --- a/compiler/rustc_infer/src/infer/region_constraints/mod.rs +++ b/compiler/rustc_infer/src/infer/region_constraints/mod.rs @@ -12,8 +12,10 @@ use rustc_data_structures::intern::Interned; use rustc_data_structures::sync::Lrc; use rustc_data_structures::undo_log::UndoLogs; use rustc_data_structures::unify as ut; +use rustc_hir::def_id::DefId; use rustc_index::vec::IndexVec; use rustc_middle::infer::unify_key::{RegionVidKey, UnifiedRegion}; +use rustc_middle::ty::subst::SubstsRef; use rustc_middle::ty::ReStatic; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_middle::ty::{ReLateBound, ReVar}; @@ -168,6 +170,7 @@ pub struct Verify<'tcx> { pub enum GenericKind<'tcx> { Param(ty::ParamTy), Projection(ty::ProjectionTy<'tcx>), + Opaque(DefId, SubstsRef<'tcx>), } /// Describes the things that some `GenericKind` value `G` is known to @@ -747,6 +750,9 @@ impl<'tcx> fmt::Debug for GenericKind<'tcx> { match *self { GenericKind::Param(ref p) => write!(f, "{:?}", p), GenericKind::Projection(ref p) => write!(f, "{:?}", p), + GenericKind::Opaque(def_id, substs) => ty::tls::with(|tcx| { + write!(f, "{}", tcx.def_path_str_with_substs(def_id, tcx.lift(substs).unwrap())) + }), } } } @@ -756,6 +762,9 @@ impl<'tcx> fmt::Display for GenericKind<'tcx> { match *self { GenericKind::Param(ref p) => write!(f, "{}", p), GenericKind::Projection(ref p) => write!(f, "{}", p), + GenericKind::Opaque(def_id, substs) => ty::tls::with(|tcx| { + write!(f, "{}", tcx.def_path_str_with_substs(def_id, tcx.lift(substs).unwrap())) + }), } } } @@ -765,6 +774,7 @@ impl<'tcx> GenericKind<'tcx> { match *self { GenericKind::Param(ref p) => p.to_ty(tcx), GenericKind::Projection(ref p) => tcx.mk_projection(p.item_def_id, p.substs), + GenericKind::Opaque(def_id, substs) => tcx.mk_opaque(def_id, substs), } } } diff --git a/compiler/rustc_infer/src/traits/util.rs b/compiler/rustc_infer/src/traits/util.rs index f5a1edf6d813f..e12c069dcc1d9 100644 --- a/compiler/rustc_infer/src/traits/util.rs +++ b/compiler/rustc_infer/src/traits/util.rs @@ -246,6 +246,13 @@ impl<'tcx> Elaborator<'tcx> { Component::UnresolvedInferenceVariable(_) => None, + Component::Opaque(def_id, substs) => { + let ty = tcx.mk_opaque(def_id, substs); + Some(ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate( + ty, r_min, + ))) + } + Component::Projection(projection) => { // We might end up here if we have `Foo<::Assoc>: 'a`. // With this, we can deduce that `::Assoc: 'a`. @@ -262,8 +269,9 @@ impl<'tcx> Elaborator<'tcx> { None } }) - .map(ty::Binder::dummy) - .map(|predicate_kind| predicate_kind.to_predicate(tcx)) + .map(|predicate_kind| { + bound_predicate.rebind(predicate_kind).to_predicate(tcx) + }) .filter(|&predicate| visited.insert(predicate)) .map(|predicate| { predicate_obligation( diff --git a/compiler/rustc_middle/src/traits/query.rs b/compiler/rustc_middle/src/traits/query.rs index 0e6cacb9fd0f8..fb152b63f6344 100644 --- a/compiler/rustc_middle/src/traits/query.rs +++ b/compiler/rustc_middle/src/traits/query.rs @@ -8,8 +8,9 @@ use crate::error::DropCheckOverflow; use crate::infer::canonical::{Canonical, QueryResponse}; use crate::ty::error::TypeError; -use crate::ty::subst::GenericArg; +use crate::ty::subst::{GenericArg, SubstsRef}; use crate::ty::{self, Ty, TyCtxt}; +use rustc_hir::def_id::DefId; use rustc_span::source_map::Span; use std::iter::FromIterator; @@ -219,4 +220,5 @@ pub enum OutlivesBound<'tcx> { RegionSubRegion(ty::Region<'tcx>, ty::Region<'tcx>), RegionSubParam(ty::Region<'tcx>, ty::ParamTy), RegionSubProjection(ty::Region<'tcx>, ty::ProjectionTy<'tcx>), + RegionSubOpaque(ty::Region<'tcx>, DefId, SubstsRef<'tcx>), } diff --git a/compiler/rustc_traits/src/implied_outlives_bounds.rs b/compiler/rustc_traits/src/implied_outlives_bounds.rs index e3e78f70b15ef..d77ed97c6c8da 100644 --- a/compiler/rustc_traits/src/implied_outlives_bounds.rs +++ b/compiler/rustc_traits/src/implied_outlives_bounds.rs @@ -153,6 +153,9 @@ fn implied_bounds_from_components<'tcx>( Component::Region(r) => Some(OutlivesBound::RegionSubRegion(sub_region, r)), Component::Param(p) => Some(OutlivesBound::RegionSubParam(sub_region, p)), Component::Projection(p) => Some(OutlivesBound::RegionSubProjection(sub_region, p)), + Component::Opaque(def_id, substs) => { + Some(OutlivesBound::RegionSubOpaque(sub_region, def_id, substs)) + } Component::EscapingProjection(_) => // If the projection has escaping regions, don't // try to infer any implied bounds even for its diff --git a/compiler/rustc_typeck/src/mem_categorization.rs b/compiler/rustc_typeck/src/mem_categorization.rs index ced919f66db41..39610e3ae3805 100644 --- a/compiler/rustc_typeck/src/mem_categorization.rs +++ b/compiler/rustc_typeck/src/mem_categorization.rs @@ -265,6 +265,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { self.cat_expr_adjusted_with(expr, || Ok(previous), adjustment) } + #[instrument(level = "debug", skip(self, previous))] fn cat_expr_adjusted_with( &self, expr: &hir::Expr<'_>, @@ -274,7 +275,6 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { where F: FnOnce() -> McResult>, { - debug!("cat_expr_adjusted_with({:?}): {:?}", adjustment, expr); let target = self.resolve_vars_if_possible(adjustment.target); match adjustment.kind { adjustment::Adjust::Deref(overloaded) => { @@ -299,6 +299,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { } } + #[instrument(level = "debug", skip(self))] pub(crate) fn cat_expr_unadjusted( &self, expr: &hir::Expr<'_>, @@ -387,6 +388,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { } } + #[instrument(level = "debug", skip(self, span))] pub(crate) fn cat_res( &self, hir_id: hir::HirId, @@ -394,8 +396,6 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { expr_ty: Ty<'tcx>, res: Res, ) -> McResult> { - debug!("cat_res: id={:?} expr={:?} def={:?}", hir_id, expr_ty, res); - match res { Res::Def( DefKind::Ctor(..) @@ -475,13 +475,12 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { ret } + #[instrument(level = "debug", skip(self))] fn cat_overloaded_place( &self, expr: &hir::Expr<'_>, base: &hir::Expr<'_>, ) -> McResult> { - debug!("cat_overloaded_place(expr={:?}, base={:?})", expr, base); - // Reconstruct the output assuming it's a reference with the // same region and mutability as the receiver. This holds for // `Deref(Mut)::Deref(_mut)` and `Index(Mut)::index(_mut)`. @@ -497,13 +496,12 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { self.cat_deref(expr, base) } + #[instrument(level = "debug", skip(self, node))] fn cat_deref( &self, node: &impl HirNode, base_place: PlaceWithHirId<'tcx>, ) -> McResult> { - debug!("cat_deref: base_place={:?}", base_place); - let base_curr_ty = base_place.place.ty(); let deref_ty = match base_curr_ty.builtin_deref(true) { Some(mt) => mt.ty, diff --git a/compiler/rustc_typeck/src/outlives/utils.rs b/compiler/rustc_typeck/src/outlives/utils.rs index 3e8d023fb551c..4c32a1e81ba54 100644 --- a/compiler/rustc_typeck/src/outlives/utils.rs +++ b/compiler/rustc_typeck/src/outlives/utils.rs @@ -1,6 +1,6 @@ use rustc_infer::infer::outlives::components::{push_outlives_components, Component}; use rustc_middle::ty::subst::{GenericArg, GenericArgKind}; -use rustc_middle::ty::{self, Region, Ty, TyCtxt}; +use rustc_middle::ty::{self, EarlyBinder, Region, Ty, TyCtxt}; use rustc_span::Span; use smallvec::smallvec; use std::collections::BTreeMap; @@ -96,6 +96,39 @@ pub(crate) fn insert_outlives_predicate<'tcx>( .or_insert(span); } + Component::Opaque(def_id, substs) => { + for predicate in tcx.item_bounds(def_id) { + let predicate = EarlyBinder(predicate).subst(tcx, substs); + // FIXME(oli-obk): fishy skip-binder + match predicate.kind().skip_binder() { + ty::PredicateKind::Trait(tp) => { + for subst in tp.trait_ref.substs { + insert_outlives_predicate( + tcx, + subst, + outlived_region, + span, + required_predicates, + ) + } + } + ty::PredicateKind::RegionOutlives(_) + | ty::PredicateKind::TypeOutlives(_) + | ty::PredicateKind::Projection(_) + | ty::PredicateKind::WellFormed(_) + | ty::PredicateKind::ObjectSafe(_) + | ty::PredicateKind::ClosureKind(_, _, _) + | ty::PredicateKind::Subtype(_) + | ty::PredicateKind::Coerce(_) + | ty::PredicateKind::ConstEvaluatable(_) + | ty::PredicateKind::ConstEquate(_, _) + | ty::PredicateKind::TypeWellFormedFromEnv(_) => { + todo!("{:#?}", predicate) + } + } + } + } + Component::EscapingProjection(_) => { // As above, but the projection involves // late-bound regions. Therefore, the WF diff --git a/src/test/ui/generic-associated-types/bugs/issue-86218.stderr b/src/test/ui/generic-associated-types/bugs/issue-86218.stderr deleted file mode 100644 index de1b464a41dbe..0000000000000 --- a/src/test/ui/generic-associated-types/bugs/issue-86218.stderr +++ /dev/null @@ -1,23 +0,0 @@ -error[E0477]: the type `<() as Yay<&'a ()>>::InnerStream<'s>` does not fulfill the required lifetime - --> $DIR/issue-86218.rs:22:28 - | -LL | type InnerStream<'s> = impl Stream + 's; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -note: type must outlive the lifetime `'s` as defined here as required by this binding - --> $DIR/issue-86218.rs:22:22 - | -LL | type InnerStream<'s> = impl Stream + 's; - | ^^ - -error: unconstrained opaque type - --> $DIR/issue-86218.rs:22:28 - | -LL | type InnerStream<'s> = impl Stream + 's; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `InnerStream` must be used in combination with a concrete type within the same module - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0477`. diff --git a/src/test/ui/generic-associated-types/issue-86218-2.rs b/src/test/ui/generic-associated-types/issue-86218-2.rs new file mode 100644 index 0000000000000..897836af6b0b8 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-86218-2.rs @@ -0,0 +1,24 @@ +// check-pass + +#![feature(type_alias_impl_trait)] + +pub trait Stream { + type Item; +} + +impl Stream for () { + type Item = i32; +} + +trait Yay { + type InnerStream<'s>: Stream + 's; + fn foo<'s>() -> Self::InnerStream<'s>; +} + +impl Yay for () { + type InnerStream<'s> = impl Stream + 's; + //^ ERROR does not fulfill the required lifetime + fn foo<'s>() -> Self::InnerStream<'s> { () } +} + +fn main() {} diff --git a/src/test/ui/generic-associated-types/bugs/issue-86218.rs b/src/test/ui/generic-associated-types/issue-86218.rs similarity index 70% rename from src/test/ui/generic-associated-types/bugs/issue-86218.rs rename to src/test/ui/generic-associated-types/issue-86218.rs index 3a2d758e7d6fe..b2c3071f06b10 100644 --- a/src/test/ui/generic-associated-types/bugs/issue-86218.rs +++ b/src/test/ui/generic-associated-types/issue-86218.rs @@ -1,7 +1,4 @@ -// check-fail -// known-bug: #86218 - -// This should pass, but seems to run into a TAIT issue. +// check-pass #![feature(type_alias_impl_trait)] @@ -20,7 +17,8 @@ trait Yay { impl<'a> Yay<&'a ()> for () { type InnerStream<'s> = impl Stream + 's; - fn foo<'s>() -> Self::InnerStream<'s> { todo!() } + //^ ERROR does not fulfill the required lifetime + fn foo<'s>() -> Self::InnerStream<'s> { () } } fn main() {} diff --git a/src/test/ui/type-alias-impl-trait/implied_bounds.rs b/src/test/ui/type-alias-impl-trait/implied_bounds.rs new file mode 100644 index 0000000000000..53cbf8d229006 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/implied_bounds.rs @@ -0,0 +1,51 @@ +#![feature(type_alias_impl_trait)] + +type WithLifetime<'a> = impl Equals; +fn _defining_use<'a>() -> WithLifetime<'a> {} + +trait Convert<'a> { + type Witness; + fn convert<'b, T: ?Sized>(_proof: &'b Self::Witness, x: &'a T) -> &'b T; +} + +impl<'a> Convert<'a> for () { + type Witness = WithLifetime<'a>; + + fn convert<'b, T: ?Sized>(_proof: &'b WithLifetime<'a>, x: &'a T) -> &'b T { + // compiler used to think it gets to assume 'a: 'b here because + // of the `&'b WithLifetime<'a>` argument + x + //~^ ERROR lifetime may not live long enough + } +} + +fn extend_lifetime<'a, 'b, T: ?Sized>(x: &'a T) -> &'b T { + WithLifetime::<'a>::convert_helper::<(), T>(&(), x) +} + +trait Equals { + type SelfType; + fn convert_helper<'a, 'b, W: Convert<'a, Witness = Self>, T: ?Sized>( + proof: &'b Self::SelfType, + x: &'a T, + ) -> &'b T; +} + +impl Equals for S { + type SelfType = Self; + fn convert_helper<'a, 'b, W: Convert<'a, Witness = Self>, T: ?Sized>( + proof: &'b Self, + x: &'a T, + ) -> &'b T { + W::convert(proof, x) + } +} + +fn main() { + let r; + { + let x = String::from("Hello World?"); + r = extend_lifetime(&x); + } + println!("{}", r); +} diff --git a/src/test/ui/type-alias-impl-trait/implied_bounds.stderr b/src/test/ui/type-alias-impl-trait/implied_bounds.stderr new file mode 100644 index 0000000000000..6f11b66634b29 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/implied_bounds.stderr @@ -0,0 +1,16 @@ +error: lifetime may not live long enough + --> $DIR/implied_bounds.rs:17:9 + | +LL | impl<'a> Convert<'a> for () { + | -- lifetime `'a` defined here +... +LL | fn convert<'b, T: ?Sized>(_proof: &'b WithLifetime<'a>, x: &'a T) -> &'b T { + | -- lifetime `'b` defined here +... +LL | x + | ^ associated function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` + | + = help: consider adding the following bound: `'a: 'b` + +error: aborting due to previous error + diff --git a/src/test/ui/type-alias-impl-trait/implied_bounds2.rs b/src/test/ui/type-alias-impl-trait/implied_bounds2.rs new file mode 100644 index 0000000000000..d2ad062e799b0 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/implied_bounds2.rs @@ -0,0 +1,9 @@ +#![feature(type_alias_impl_trait)] + +type Ty<'a, A> = impl Sized + 'a; +fn defining<'a, A>() -> Ty<'a, A> {} +fn assert_static() {} +fn test<'a, A>() where Ty<'a, A>: 'static, { assert_static::>() } +//~^ ERROR: may not live long enough + +fn main() {} diff --git a/src/test/ui/type-alias-impl-trait/implied_bounds2.stderr b/src/test/ui/type-alias-impl-trait/implied_bounds2.stderr new file mode 100644 index 0000000000000..b1c42c2c37fe2 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/implied_bounds2.stderr @@ -0,0 +1,12 @@ +error[E0310]: the opaque type `Ty<'_, A>::{opaque#0}` may not live long enough + --> $DIR/implied_bounds2.rs:6:46 + | +LL | fn test<'a, A>() where Ty<'a, A>: 'static, { assert_static::>() } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider adding an explicit lifetime bound `Ty<'_, A>::{opaque#0}: 'static`... + = note: ...so that the type `Ty<'_, A>` will meet its required lifetime bounds + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0310`. diff --git a/src/test/ui/type-alias-impl-trait/implied_bounds_closure.rs b/src/test/ui/type-alias-impl-trait/implied_bounds_closure.rs new file mode 100644 index 0000000000000..4cf35f951904a --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/implied_bounds_closure.rs @@ -0,0 +1,31 @@ +trait StaticDefaultRef: 'static { + fn default_ref() -> &'static Self; +} + +impl StaticDefaultRef for str { + fn default_ref() -> &'static str { + "" + } +} + +fn into_impl(x: &str) -> &(impl ?Sized + AsRef + StaticDefaultRef + '_) { + x +} + +fn extend_lifetime<'a>(x: &'a str) -> &'static str { + let t = into_impl(x); + helper(|_| t) //~ ERROR lifetime may not live long enough +} + +fn helper + StaticDefaultRef>(f: impl FnOnce(&T) -> &T) -> &'static str { + f(T::default_ref()).as_ref() +} + +fn main() { + let r; + { + let x = String::from("Hello World?"); + r = extend_lifetime(&x); + } + println!("{}", r); +} diff --git a/src/test/ui/type-alias-impl-trait/implied_bounds_closure.stderr b/src/test/ui/type-alias-impl-trait/implied_bounds_closure.stderr new file mode 100644 index 0000000000000..151564c3b45a1 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/implied_bounds_closure.stderr @@ -0,0 +1,11 @@ +error: lifetime may not live long enough + --> $DIR/implied_bounds_closure.rs:17:16 + | +LL | fn extend_lifetime<'a>(x: &'a str) -> &'static str { + | -- lifetime `'a` defined here +LL | let t = into_impl(x); +LL | helper(|_| t) + | ^ returning this value requires that `'a` must outlive `'static` + +error: aborting due to previous error + diff --git a/src/test/ui/type-alias-impl-trait/implied_bounds_from_types.rs b/src/test/ui/type-alias-impl-trait/implied_bounds_from_types.rs new file mode 100644 index 0000000000000..8023cd24f0bf6 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/implied_bounds_from_types.rs @@ -0,0 +1,51 @@ +#![feature(type_alias_impl_trait)] + +type WithLifetime = impl Equals; +fn _defining_use() -> WithLifetime {} + +trait Convert<'a> { + type Witness; + fn convert<'b, T: ?Sized>(_proof: &'b Self::Witness, x: &'a T) -> &'b T; +} + +impl<'a> Convert<'a> for () { + type Witness = WithLifetime<&'a ()>; + + fn convert<'b, T: ?Sized>(_proof: &'b WithLifetime<&'a ()>, x: &'a T) -> &'b T { + // compiler used to think it gets to assume 'a: 'b here because + // of the `&'b WithLifetime<&'a ()>` argument + x + //~^ ERROR lifetime may not live long enough + } +} + +fn extend_lifetime<'a, 'b, T: ?Sized>(x: &'a T) -> &'b T { + WithLifetime::<&'a ()>::convert_helper::<(), T>(&(), x) +} + +trait Equals { + type SelfType; + fn convert_helper<'a, 'b, W: Convert<'a, Witness = Self>, T: ?Sized>( + proof: &'b Self::SelfType, + x: &'a T, + ) -> &'b T; +} + +impl Equals for S { + type SelfType = Self; + fn convert_helper<'a, 'b, W: Convert<'a, Witness = Self>, T: ?Sized>( + proof: &'b Self, + x: &'a T, + ) -> &'b T { + W::convert(proof, x) + } +} + +fn main() { + let r; + { + let x = String::from("Hello World?"); + r = extend_lifetime(&x); + } + println!("{}", r); +} diff --git a/src/test/ui/type-alias-impl-trait/implied_bounds_from_types.stderr b/src/test/ui/type-alias-impl-trait/implied_bounds_from_types.stderr new file mode 100644 index 0000000000000..cbc5e60731815 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/implied_bounds_from_types.stderr @@ -0,0 +1,16 @@ +error: lifetime may not live long enough + --> $DIR/implied_bounds_from_types.rs:17:9 + | +LL | impl<'a> Convert<'a> for () { + | -- lifetime `'a` defined here +... +LL | fn convert<'b, T: ?Sized>(_proof: &'b WithLifetime<&'a ()>, x: &'a T) -> &'b T { + | -- lifetime `'b` defined here +... +LL | x + | ^ associated function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` + | + = help: consider adding the following bound: `'a: 'b` + +error: aborting due to previous error + diff --git a/src/test/ui/type-alias-impl-trait/implied_lifetime_wf_check.rs b/src/test/ui/type-alias-impl-trait/implied_lifetime_wf_check.rs new file mode 100644 index 0000000000000..a2063cf5e3ee5 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/implied_lifetime_wf_check.rs @@ -0,0 +1,18 @@ +trait Mirror<'a> { + type Item; +} + +impl<'a, T> Mirror<'a> for T { + type Item = T; +} + +trait AnotherTrait { + type Blah; +} + +impl<'a> AnotherTrait for >::Item { + //~^ ERROR: the lifetime parameter `'a` is not constrained + type Blah = &'a u32; +} + +fn main() {} diff --git a/src/test/ui/type-alias-impl-trait/implied_lifetime_wf_check.stderr b/src/test/ui/type-alias-impl-trait/implied_lifetime_wf_check.stderr new file mode 100644 index 0000000000000..cadf2ce4a9d5d --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/implied_lifetime_wf_check.stderr @@ -0,0 +1,9 @@ +error[E0207]: the lifetime parameter `'a` is not constrained by the impl trait, self type, or predicates + --> $DIR/implied_lifetime_wf_check.rs:13:6 + | +LL | impl<'a> AnotherTrait for >::Item { + | ^^ unconstrained lifetime parameter + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0207`. diff --git a/src/test/ui/type-alias-impl-trait/implied_lifetime_wf_check2.rs b/src/test/ui/type-alias-impl-trait/implied_lifetime_wf_check2.rs new file mode 100644 index 0000000000000..4f52f7a34af8e --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/implied_lifetime_wf_check2.rs @@ -0,0 +1,13 @@ +#![feature(type_alias_impl_trait)] + +// check-pass + +trait Tr { type Assoc; } +impl<'a> Tr for &'a str { type Assoc = &'a str; } + +type OpaqueTy<'a> = impl Tr; +fn defining(s: &str) -> OpaqueTy<'_> { s } + +// now we must be able to conclude `'a: 'static` from `Opaque<'a>: 'static` + +fn main() {} diff --git a/src/test/ui/type-alias-impl-trait/implied_lifetime_wf_check3.rs b/src/test/ui/type-alias-impl-trait/implied_lifetime_wf_check3.rs new file mode 100644 index 0000000000000..4cbb6b63670ac --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/implied_lifetime_wf_check3.rs @@ -0,0 +1,42 @@ +#![feature(type_alias_impl_trait)] + +mod test_lifetime_param { + type Ty<'a> = impl Sized; + fn defining(a: &str) -> Ty<'_> { a } + fn assert_static<'a: 'static>() {} + //~^ WARN: unnecessary lifetime parameter `'a` + fn test<'a>() where Ty<'a>: 'static { assert_static::<'a>() } +} + +mod test_higher_kinded_lifetime_param { + type Ty<'a> = impl Sized; + fn defining(a: &str) -> Ty<'_> { a } + fn assert_static<'a: 'static>() {} + //~^ WARN: unnecessary lifetime parameter `'a` + fn test<'a>() where for<'b> Ty<'b>: 'a { assert_static::<'a>() } +} + +mod test_higher_kinded_lifetime_param2 { + fn assert_static<'a: 'static>() {} + //~^ WARN: unnecessary lifetime parameter `'a` + fn test<'a>() { assert_static::<'a>() } + // no error because all the other errors happen first and then we abort before + // emitting an error here. +} + +mod test_type_param { + type Ty = impl Sized; + fn defining(s: A) -> Ty { s } + fn assert_static() {} + fn test() where Ty: 'static { assert_static::() } +} + +mod test_type_param_static { + type Ty = impl Sized + 'static; + //~^ ERROR: the parameter type `A` may not live long enough + fn defining(s: A) -> Ty { s } + fn assert_static() {} + fn test() where Ty: 'static { assert_static::() } +} + +fn main() {} diff --git a/src/test/ui/type-alias-impl-trait/implied_lifetime_wf_check3.stderr b/src/test/ui/type-alias-impl-trait/implied_lifetime_wf_check3.stderr new file mode 100644 index 0000000000000..16d529698f4d6 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/implied_lifetime_wf_check3.stderr @@ -0,0 +1,38 @@ +warning: unnecessary lifetime parameter `'a` + --> $DIR/implied_lifetime_wf_check3.rs:6:22 + | +LL | fn assert_static<'a: 'static>() {} + | ^^ + | + = help: you can use the `'static` lifetime directly, in place of `'a` + +warning: unnecessary lifetime parameter `'a` + --> $DIR/implied_lifetime_wf_check3.rs:14:22 + | +LL | fn assert_static<'a: 'static>() {} + | ^^ + | + = help: you can use the `'static` lifetime directly, in place of `'a` + +warning: unnecessary lifetime parameter `'a` + --> $DIR/implied_lifetime_wf_check3.rs:20:22 + | +LL | fn assert_static<'a: 'static>() {} + | ^^ + | + = help: you can use the `'static` lifetime directly, in place of `'a` + +error[E0310]: the parameter type `A` may not live long enough + --> $DIR/implied_lifetime_wf_check3.rs:35:18 + | +LL | type Ty = impl Sized + 'static; + | ^^^^^^^^^^^^^^^^^^^^ ...so that the type `A` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound... + | +LL | type Ty = impl Sized + 'static; + | +++++++++ + +error: aborting due to previous error; 3 warnings emitted + +For more information about this error, try `rustc --explain E0310`. diff --git a/src/test/ui/type-alias-impl-trait/issue-58662-generator-with-lifetime.rs b/src/test/ui/type-alias-impl-trait/issue-58662-generator-with-lifetime.rs index f20ddf020718e..477b61390ed46 100644 --- a/src/test/ui/type-alias-impl-trait/issue-58662-generator-with-lifetime.rs +++ b/src/test/ui/type-alias-impl-trait/issue-58662-generator-with-lifetime.rs @@ -16,7 +16,7 @@ fn rand_generator<'a>(rng: &'a ()) -> RandGenerator<'a> { } } -pub type RandGeneratorWithIndirection<'a> = impl Generator + 'a; +pub type RandGeneratorWithIndirection<'c> = impl Generator + 'c; pub fn rand_generator_with_indirection<'a>(rng: &'a ()) -> RandGeneratorWithIndirection<'a> { fn helper<'b>(rng: &'b ()) -> impl 'b + Generator { move || { diff --git a/src/test/ui/type-alias-impl-trait/issue-58662-simplified.rs b/src/test/ui/type-alias-impl-trait/issue-58662-simplified.rs new file mode 100644 index 0000000000000..27ca7d0fdc9fa --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/issue-58662-simplified.rs @@ -0,0 +1,20 @@ +// check-pass + +#![feature(generators, generator_trait)] +#![feature(type_alias_impl_trait)] + +trait Trait {} + +impl Trait for T {} + +type Foo<'c> = impl Trait + 'c; +fn foo<'a>(rng: &'a ()) -> Foo<'a> { + fn helper<'b>(rng: &'b ()) -> impl 'b + Trait { + rng + } + + helper(rng) +} + +fn main() { +} From 90b6744af7a5c3944ef7d534b315467386e38673 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 19 May 2022 12:18:16 +0000 Subject: [PATCH 085/586] Also collect bounds from the ParamEnv for opaque types --- .../src/infer/outlives/obligations.rs | 9 ++- .../rustc_infer/src/infer/outlives/verify.rs | 69 +++++++------------ .../type-alias-impl-trait/implied_bounds2.rs | 3 +- .../implied_bounds2.stderr | 12 ---- 4 files changed, 34 insertions(+), 59 deletions(-) delete mode 100644 src/test/ui/type-alias-impl-trait/implied_bounds2.stderr diff --git a/compiler/rustc_infer/src/infer/outlives/obligations.rs b/compiler/rustc_infer/src/infer/outlives/obligations.rs index ad5fbb9a15823..ceea02e7817a9 100644 --- a/compiler/rustc_infer/src/infer/outlives/obligations.rs +++ b/compiler/rustc_infer/src/infer/outlives/obligations.rs @@ -318,7 +318,7 @@ where ); let generic = GenericKind::Param(param_ty); - let verify_bound = self.verify_bound.generic_bound(generic); + let verify_bound = self.verify_bound.param_bound(param_ty); self.delegate.push_verify(origin, generic, region, verify_bound); } @@ -476,7 +476,12 @@ where // projection outlive; in some cases, this may add insufficient // edges into the inference graph, leading to inference failures // even though a satisfactory solution exists. - let verify_bound = self.verify_bound.generic_bound(generic); + let verify_bound = self.verify_bound.projection_opaque_bounds( + generic, + def_id, + substs, + &mut Default::default(), + ); debug!("projection_must_outlive: pushing {:?}", verify_bound); self.delegate.push_verify(origin, generic, region, verify_bound); } diff --git a/compiler/rustc_infer/src/infer/outlives/verify.rs b/compiler/rustc_infer/src/infer/outlives/verify.rs index 040843d837070..f5caa8d684e00 100644 --- a/compiler/rustc_infer/src/infer/outlives/verify.rs +++ b/compiler/rustc_infer/src/infer/outlives/verify.rs @@ -38,21 +38,8 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> { Self { tcx, region_bound_pairs, implicit_region_bound, param_env } } - /// Returns a "verify bound" that encodes what we know about - /// `generic` and the regions it outlives. - pub fn generic_bound(&self, generic: GenericKind<'tcx>) -> VerifyBound<'tcx> { - let mut visited = SsoHashSet::new(); - match generic { - GenericKind::Param(param_ty) => self.param_bound(param_ty), - GenericKind::Projection(projection_ty) => { - self.projection_bound(projection_ty, &mut visited) - } - GenericKind::Opaque(def_id, substs) => self.opaque_bound(def_id, substs), - } - } - #[instrument(level = "debug", skip(self))] - fn param_bound(&self, param_ty: ty::ParamTy) -> VerifyBound<'tcx> { + pub fn param_bound(&self, param_ty: ty::ParamTy) -> VerifyBound<'tcx> { // Start with anything like `T: 'a` we can scrape from the // environment. If the environment contains something like // `for<'a> T: 'a`, then we know that `T` outlives everything. @@ -116,20 +103,21 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> { } #[instrument(level = "debug", skip(self, visited))] - fn projection_bound( + pub fn projection_opaque_bounds( &self, - projection_ty: ty::ProjectionTy<'tcx>, + generic: GenericKind<'tcx>, + def_id: DefId, + substs: SubstsRef<'tcx>, visited: &mut SsoHashSet>, ) -> VerifyBound<'tcx> { - let projection_ty_as_ty = - self.tcx.mk_projection(projection_ty.item_def_id, projection_ty.substs); + let generic_ty = generic.to_ty(self.tcx); // Search the env for where clauses like `P: 'a`. - let env_bounds = self - .approx_declared_bounds_from_env(GenericKind::Projection(projection_ty)) + let projection_opaque_bounds = self + .approx_declared_bounds_from_env(generic) .into_iter() .map(|binder| { - if let Some(ty::OutlivesPredicate(ty, r)) = binder.no_bound_vars() && ty == projection_ty_as_ty { + if let Some(ty::OutlivesPredicate(ty, r)) = binder.no_bound_vars() && ty == generic_ty { // Micro-optimize if this is an exact match (this // occurs often when there are no region variables // involved). @@ -139,35 +127,18 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> { VerifyBound::IfEq(verify_if_eq_b) } }); - // Extend with bounds that we can find from the trait. - let trait_bounds = self - .bounds(projection_ty.item_def_id, projection_ty.substs) - .map(|r| VerifyBound::OutlivedBy(r)); + let trait_bounds = self.bounds(def_id, substs).map(|r| VerifyBound::OutlivedBy(r)); // see the extensive comment in projection_must_outlive let recursive_bound = { let mut components = smallvec![]; - let ty = self.tcx.mk_projection(projection_ty.item_def_id, projection_ty.substs); - compute_components_recursive(self.tcx, ty.into(), &mut components, visited); + compute_components_recursive(self.tcx, generic_ty.into(), &mut components, visited); self.bound_from_components(&components, visited) }; - VerifyBound::AnyBound(env_bounds.chain(trait_bounds).collect()).or(recursive_bound) - } - - fn opaque_bound(&self, def_id: DefId, substs: SubstsRef<'tcx>) -> VerifyBound<'tcx> { - let bounds: Vec<_> = - self.bounds(def_id, substs).map(|r| VerifyBound::OutlivedBy(r)).collect(); - trace!("{:#?}", bounds); - if bounds.is_empty() { - // No bounds means the value must not have any lifetimes. - // FIXME: should we implicitly add 'static to `tcx.item_bounds` for opaque types, just - // like we add `Sized`? - VerifyBound::OutlivedBy(self.tcx.lifetimes.re_static) - } else { - VerifyBound::AnyBound(bounds) - } + VerifyBound::AnyBound(projection_opaque_bounds.chain(trait_bounds).collect()) + .or(recursive_bound) } fn bound_from_components( @@ -199,8 +170,18 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> { match *component { Component::Region(lt) => VerifyBound::OutlivedBy(lt), Component::Param(param_ty) => self.param_bound(param_ty), - Component::Opaque(did, substs) => self.opaque_bound(did, substs), - Component::Projection(projection_ty) => self.projection_bound(projection_ty, visited), + Component::Opaque(did, substs) => self.projection_opaque_bounds( + GenericKind::Opaque(did, substs), + did, + substs, + visited, + ), + Component::Projection(projection_ty) => self.projection_opaque_bounds( + GenericKind::Projection(projection_ty), + projection_ty.item_def_id, + projection_ty.substs, + visited, + ), Component::EscapingProjection(ref components) => { self.bound_from_components(components, visited) } diff --git a/src/test/ui/type-alias-impl-trait/implied_bounds2.rs b/src/test/ui/type-alias-impl-trait/implied_bounds2.rs index d2ad062e799b0..b4c4c013cd251 100644 --- a/src/test/ui/type-alias-impl-trait/implied_bounds2.rs +++ b/src/test/ui/type-alias-impl-trait/implied_bounds2.rs @@ -1,9 +1,10 @@ +// check-pass + #![feature(type_alias_impl_trait)] type Ty<'a, A> = impl Sized + 'a; fn defining<'a, A>() -> Ty<'a, A> {} fn assert_static() {} fn test<'a, A>() where Ty<'a, A>: 'static, { assert_static::>() } -//~^ ERROR: may not live long enough fn main() {} diff --git a/src/test/ui/type-alias-impl-trait/implied_bounds2.stderr b/src/test/ui/type-alias-impl-trait/implied_bounds2.stderr deleted file mode 100644 index b1c42c2c37fe2..0000000000000 --- a/src/test/ui/type-alias-impl-trait/implied_bounds2.stderr +++ /dev/null @@ -1,12 +0,0 @@ -error[E0310]: the opaque type `Ty<'_, A>::{opaque#0}` may not live long enough - --> $DIR/implied_bounds2.rs:6:46 - | -LL | fn test<'a, A>() where Ty<'a, A>: 'static, { assert_static::>() } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: consider adding an explicit lifetime bound `Ty<'_, A>::{opaque#0}: 'static`... - = note: ...so that the type `Ty<'_, A>` will meet its required lifetime bounds - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0310`. From a8c9784336591adce8d39a49a1da8fdf700b2410 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 24 May 2022 09:54:46 +0000 Subject: [PATCH 086/586] Add regression test --- .../type-alias-impl-trait/implied_bounds3.rs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 src/test/ui/type-alias-impl-trait/implied_bounds3.rs diff --git a/src/test/ui/type-alias-impl-trait/implied_bounds3.rs b/src/test/ui/type-alias-impl-trait/implied_bounds3.rs new file mode 100644 index 0000000000000..e39c613281dc7 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/implied_bounds3.rs @@ -0,0 +1,18 @@ +// check-pass + +fn foo(_: F) +where + F: 'static, +{ +} + +fn from(f: F) -> impl Send { + f +} + +fn bar() { + foo(from(|| ())) +} + +fn main() { +} From 615c9e8647b0ce46c1b1755201c8e2799a3ca2bc Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 21 Jun 2022 15:18:11 +0000 Subject: [PATCH 087/586] Inline substitution logic into `declared_region_bounds` --- .../src/infer/outlives/obligations.rs | 5 +-- .../rustc_infer/src/infer/outlives/verify.rs | 35 +++++-------------- 2 files changed, 11 insertions(+), 29 deletions(-) diff --git a/compiler/rustc_infer/src/infer/outlives/obligations.rs b/compiler/rustc_infer/src/infer/outlives/obligations.rs index ceea02e7817a9..ec9a165ea308d 100644 --- a/compiler/rustc_infer/src/infer/outlives/obligations.rs +++ b/compiler/rustc_infer/src/infer/outlives/obligations.rs @@ -390,7 +390,8 @@ where // Compute the bounds we can derive from the trait definition. // These are guaranteed to apply, no matter the inference // results. - let trait_bounds: Vec<_> = self.verify_bound.bounds(def_id, substs).collect(); + let trait_bounds: Vec<_> = + self.verify_bound.declared_region_bounds(def_id, substs).collect(); debug!(?trait_bounds); @@ -413,7 +414,7 @@ where // will be invoked with `['b => ^1]` and so we will get `^1` returned. let bound = bound_outlives.skip_binder(); let (def_id, substs) = filter(bound.0); - self.verify_bound.bounds(def_id, substs).all(|r| r != bound.1) + self.verify_bound.declared_region_bounds(def_id, substs).all(|r| r != bound.1) }); // If declared bounds list is empty, the only applicable rule is diff --git a/compiler/rustc_infer/src/infer/outlives/verify.rs b/compiler/rustc_infer/src/infer/outlives/verify.rs index f5caa8d684e00..f470b2eb8c193 100644 --- a/compiler/rustc_infer/src/infer/outlives/verify.rs +++ b/compiler/rustc_infer/src/infer/outlives/verify.rs @@ -2,7 +2,6 @@ use crate::infer::outlives::components::{compute_components_recursive, Component use crate::infer::outlives::env::RegionBoundPairs; use crate::infer::region_constraints::VerifyIfEq; use crate::infer::{GenericKind, VerifyBound}; -use rustc_data_structures::captures::Captures; use rustc_data_structures::sso::SsoHashSet; use rustc_hir::def_id::DefId; use rustc_middle::ty::GenericArg; @@ -128,7 +127,8 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> { } }); // Extend with bounds that we can find from the trait. - let trait_bounds = self.bounds(def_id, substs).map(|r| VerifyBound::OutlivedBy(r)); + let trait_bounds = + self.declared_region_bounds(def_id, substs).map(|r| VerifyBound::OutlivedBy(r)); // see the extensive comment in projection_must_outlive let recursive_bound = { @@ -279,30 +279,6 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> { /// } /// ``` /// - /// then this function would return `'x`. This is subject to the - /// limitations around higher-ranked bounds described in - /// `declared_region_bounds`. - #[instrument(level = "debug", skip(self))] - pub fn bounds( - &self, - def_id: DefId, - substs: SubstsRef<'tcx>, - ) -> impl Iterator> + 'cx + Captures<'tcx> { - let tcx = self.tcx; - self.declared_region_bounds(def_id).map(move |r| EarlyBinder(r).subst(tcx, substs)) - } - - /// Given the `DefId` of an associated item, returns any region - /// bounds attached to that associated item from the trait definition. - /// - /// For example: - /// - /// ```rust - /// trait Foo<'a> { - /// type Bar: 'a; - /// } - /// ``` - /// /// If we were given the `DefId` of `Foo::Bar`, we would return /// `'a`. You could then apply the substitutions from the /// projection to convert this into your namespace. This also @@ -322,7 +298,11 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> { /// /// This is for simplicity, and because we are not really smart /// enough to cope with such bounds anywhere. - fn declared_region_bounds(&self, def_id: DefId) -> impl Iterator> { + pub fn declared_region_bounds( + &self, + def_id: DefId, + substs: SubstsRef<'tcx>, + ) -> impl Iterator> { let tcx = self.tcx; let bounds = tcx.item_bounds(def_id); trace!("{:#?}", bounds); @@ -331,6 +311,7 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> { .filter_map(|p| p.to_opt_type_outlives()) .filter_map(|p| p.no_bound_vars()) .map(|b| b.1) + .map(move |r| EarlyBinder(r).subst(tcx, substs)) } /// Searches through a predicate list for a predicate `T: 'a`. From 20d962cfa5511eece711684ff83cb721eacd60dc Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 21 Jun 2022 15:42:25 +0000 Subject: [PATCH 088/586] Simplify insert_outlives_predicate opaque type logic --- compiler/rustc_typeck/src/outlives/utils.rs | 46 ++++++------------- .../unbounded_opaque_type.rs | 8 ++++ 2 files changed, 23 insertions(+), 31 deletions(-) create mode 100644 src/test/ui/type-alias-impl-trait/unbounded_opaque_type.rs diff --git a/compiler/rustc_typeck/src/outlives/utils.rs b/compiler/rustc_typeck/src/outlives/utils.rs index 4c32a1e81ba54..f582fdf903ddd 100644 --- a/compiler/rustc_typeck/src/outlives/utils.rs +++ b/compiler/rustc_typeck/src/outlives/utils.rs @@ -1,6 +1,6 @@ use rustc_infer::infer::outlives::components::{push_outlives_components, Component}; use rustc_middle::ty::subst::{GenericArg, GenericArgKind}; -use rustc_middle::ty::{self, EarlyBinder, Region, Ty, TyCtxt}; +use rustc_middle::ty::{self, Region, Ty, TyCtxt}; use rustc_span::Span; use smallvec::smallvec; use std::collections::BTreeMap; @@ -97,36 +97,20 @@ pub(crate) fn insert_outlives_predicate<'tcx>( } Component::Opaque(def_id, substs) => { - for predicate in tcx.item_bounds(def_id) { - let predicate = EarlyBinder(predicate).subst(tcx, substs); - // FIXME(oli-obk): fishy skip-binder - match predicate.kind().skip_binder() { - ty::PredicateKind::Trait(tp) => { - for subst in tp.trait_ref.substs { - insert_outlives_predicate( - tcx, - subst, - outlived_region, - span, - required_predicates, - ) - } - } - ty::PredicateKind::RegionOutlives(_) - | ty::PredicateKind::TypeOutlives(_) - | ty::PredicateKind::Projection(_) - | ty::PredicateKind::WellFormed(_) - | ty::PredicateKind::ObjectSafe(_) - | ty::PredicateKind::ClosureKind(_, _, _) - | ty::PredicateKind::Subtype(_) - | ty::PredicateKind::Coerce(_) - | ty::PredicateKind::ConstEvaluatable(_) - | ty::PredicateKind::ConstEquate(_, _) - | ty::PredicateKind::TypeWellFormedFromEnv(_) => { - todo!("{:#?}", predicate) - } - } - } + // This would arise from something like: + // + // ```rust + // type Opaque = impl Sized; + // fn defining() -> Opaque {} + // struct Ss<'a, T>(&'a Opaque); + // ``` + // + // Here we want to require an explicit `where Opaque: 'a` + + let ty = tcx.mk_opaque(def_id, substs); + required_predicates + .entry(ty::OutlivesPredicate(ty.into(), outlived_region)) + .or_insert(span); } Component::EscapingProjection(_) => { diff --git a/src/test/ui/type-alias-impl-trait/unbounded_opaque_type.rs b/src/test/ui/type-alias-impl-trait/unbounded_opaque_type.rs new file mode 100644 index 0000000000000..a5ab3e1acae52 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/unbounded_opaque_type.rs @@ -0,0 +1,8 @@ +// check-pass + +#![feature(type_alias_impl_trait)] +type Opaque = impl Sized; +fn defining() -> Opaque {} +struct Ss<'a, T>(&'a Opaque); + +fn main() {} From 36cb01deb3d874650881b0bc22448020751ff19c Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 15 Jul 2022 15:26:46 +0000 Subject: [PATCH 089/586] Try out a perf optimization --- compiler/rustc_infer/src/infer/outlives/obligations.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/compiler/rustc_infer/src/infer/outlives/obligations.rs b/compiler/rustc_infer/src/infer/outlives/obligations.rs index ec9a165ea308d..5af76b5d610db 100644 --- a/compiler/rustc_infer/src/infer/outlives/obligations.rs +++ b/compiler/rustc_infer/src/infer/outlives/obligations.rs @@ -373,6 +373,11 @@ where substs: SubstsRef<'tcx>, filter: impl Fn(Ty<'tcx>) -> (DefId, SubstsRef<'tcx>), ) { + // An optimization for a common case with opaque types. + if substs.is_empty() { + return; + } + // This case is thorny for inference. The fundamental problem is // that there are many cases where we have choice, and inference // doesn't like choice (the current region inference in From 4b323e62ba785812fbb5d6b77f2564a59dce2171 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 1 Sep 2022 15:41:13 +0000 Subject: [PATCH 090/586] Reproduce sad diagnostic --- .../ui/impl-trait/unactionable_diagnostic.rs | 23 +++++++++++++++++++ .../impl-trait/unactionable_diagnostic.stderr | 12 ++++++++++ 2 files changed, 35 insertions(+) create mode 100644 src/test/ui/impl-trait/unactionable_diagnostic.rs create mode 100644 src/test/ui/impl-trait/unactionable_diagnostic.stderr diff --git a/src/test/ui/impl-trait/unactionable_diagnostic.rs b/src/test/ui/impl-trait/unactionable_diagnostic.rs new file mode 100644 index 0000000000000..de482e0370ca6 --- /dev/null +++ b/src/test/ui/impl-trait/unactionable_diagnostic.rs @@ -0,0 +1,23 @@ +trait Trait {} + +struct Foo; + +impl Trait for Foo {} + +fn foo<'t, P>( + post: P, + x: &'t Foo, +) -> &'t impl Trait { + x +} + +fn bar<'t, T>( + post: T, + x: &'t Foo, +) -> &'t impl Trait { + foo(post, x) + //~^ ERROR: the opaque type `foo::{opaque#0}` may not live long enough + //~| HELP: consider adding an explicit lifetime bound `foo::{opaque#0}: 't` +} + +fn main() {} diff --git a/src/test/ui/impl-trait/unactionable_diagnostic.stderr b/src/test/ui/impl-trait/unactionable_diagnostic.stderr new file mode 100644 index 0000000000000..fe6fef5815d54 --- /dev/null +++ b/src/test/ui/impl-trait/unactionable_diagnostic.stderr @@ -0,0 +1,12 @@ +error[E0309]: the opaque type `foo::{opaque#0}` may not live long enough + --> $DIR/unactionable_diagnostic.rs:18:5 + | +LL | foo(post, x) + | ^^^^^^^^^^^^ + | + = help: consider adding an explicit lifetime bound `foo::{opaque#0}: 't`... + = note: ...so that the type `impl Trait` will meet its required lifetime bounds + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0309`. From 86f1ca812b8704beb20459bd5723d0cc3a0ace62 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 6 Sep 2022 10:16:26 +0000 Subject: [PATCH 091/586] Improve diagnostic for adding more bounds to opaque types --- compiler/rustc_infer/src/infer/error_reporting/mod.rs | 10 +++++++++- src/test/ui/impl-trait/unactionable_diagnostic.rs | 2 +- src/test/ui/impl-trait/unactionable_diagnostic.stderr | 8 +++++--- 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index e33035381e0a9..8b8cff0dbbe64 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -2314,7 +2314,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { &self, generic_param_scope: LocalDefId, span: Span, - origin: Option>, + mut origin: Option>, bound_kind: GenericKind<'tcx>, sub: Region<'tcx>, ) -> DiagnosticBuilder<'a, ErrorGuaranteed> { @@ -2349,6 +2349,14 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { None } } + GenericKind::Opaque(def_id, _substs) => { + // Avoid emitting a `... so that the type` message at the error site. + // It would be out of order for return position impl trait + origin = None; + // Make sure the lifetime suggestion is on the RPIT instead of proposing + // to add a bound for opaque types (which isn't possible) + Some((self.tcx.def_span(def_id).shrink_to_hi(), true)) + } _ => None, }; diff --git a/src/test/ui/impl-trait/unactionable_diagnostic.rs b/src/test/ui/impl-trait/unactionable_diagnostic.rs index de482e0370ca6..9b82332f9b067 100644 --- a/src/test/ui/impl-trait/unactionable_diagnostic.rs +++ b/src/test/ui/impl-trait/unactionable_diagnostic.rs @@ -8,6 +8,7 @@ fn foo<'t, P>( post: P, x: &'t Foo, ) -> &'t impl Trait { + //~^ HELP: consider adding an explicit lifetime bound... x } @@ -17,7 +18,6 @@ fn bar<'t, T>( ) -> &'t impl Trait { foo(post, x) //~^ ERROR: the opaque type `foo::{opaque#0}` may not live long enough - //~| HELP: consider adding an explicit lifetime bound `foo::{opaque#0}: 't` } fn main() {} diff --git a/src/test/ui/impl-trait/unactionable_diagnostic.stderr b/src/test/ui/impl-trait/unactionable_diagnostic.stderr index fe6fef5815d54..a36e89f58b98e 100644 --- a/src/test/ui/impl-trait/unactionable_diagnostic.stderr +++ b/src/test/ui/impl-trait/unactionable_diagnostic.stderr @@ -1,11 +1,13 @@ error[E0309]: the opaque type `foo::{opaque#0}` may not live long enough - --> $DIR/unactionable_diagnostic.rs:18:5 + --> $DIR/unactionable_diagnostic.rs:19:5 | LL | foo(post, x) | ^^^^^^^^^^^^ | - = help: consider adding an explicit lifetime bound `foo::{opaque#0}: 't`... - = note: ...so that the type `impl Trait` will meet its required lifetime bounds +help: consider adding an explicit lifetime bound... + | +LL | ) -> &'t impl Trait + 't { + | ++++ error: aborting due to previous error From 80c8680a0c0d5b174744c2e56667808be21aeade Mon Sep 17 00:00:00 2001 From: Konrad Borowski Date: Wed, 21 Sep 2022 14:03:49 +0000 Subject: [PATCH 092/586] Use fetch_update in sync::Weak::upgrade --- library/alloc/src/sync.rs | 39 ++++++++++++++++----------------------- 1 file changed, 16 insertions(+), 23 deletions(-) diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index 4377edeee8710..fc000cce8f817 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -1980,33 +1980,26 @@ impl Weak { // We use a CAS loop to increment the strong count instead of a // fetch_add as this function should never take the reference count // from zero to one. - let inner = self.inner()?; - - // Relaxed load because any write of 0 that we can observe - // leaves the field in a permanently zero state (so a - // "stale" read of 0 is fine), and any other value is - // confirmed via the CAS below. - let mut n = inner.strong.load(Relaxed); - - loop { - if n == 0 { - return None; - } - - // See comments in `Arc::clone` for why we do this (for `mem::forget`). - if n > MAX_REFCOUNT { - abort(); - } - + self.inner()? + .strong // Relaxed is fine for the failure case because we don't have any expectations about the new state. // Acquire is necessary for the success case to synchronise with `Arc::new_cyclic`, when the inner // value can be initialized after `Weak` references have already been created. In that case, we // expect to observe the fully initialized value. - match inner.strong.compare_exchange_weak(n, n + 1, Acquire, Relaxed) { - Ok(_) => return Some(unsafe { Arc::from_inner(self.ptr) }), // null checked above - Err(old) => n = old, - } - } + .fetch_update(Acquire, Relaxed, |n| { + // Any write of 0 we can observe leaves the field in permanently zero state. + if n == 0 { + return None; + } + // See comments in `Arc::clone` for why we do this (for `mem::forget`). + if n > MAX_REFCOUNT { + abort(); + } + Some(n + 1) + }) + .ok() + // null checked above + .map(|_| unsafe { Arc::from_inner(self.ptr) }) } /// Gets the number of strong (`Arc`) pointers pointing to this allocation. From 7adfb44b95335ce9a565aea1f5f32a3e14119f9c Mon Sep 17 00:00:00 2001 From: yukang Date: Wed, 21 Sep 2022 12:31:29 +0800 Subject: [PATCH 093/586] add trivial comments --- compiler/rustc_resolve/src/late/diagnostics.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index ac1153602572f..7f3dc2085211f 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -130,6 +130,7 @@ pub(super) enum LifetimeElisionCandidate { Missing(MissingLifetime), } +/// Only used for diagnostics. struct BaseError<'a> { msg: String, fallback_label: String, @@ -313,7 +314,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { } self.suggest_type_ascription(&mut err, source, path, res, span, &base_error); - self.add_err_code_cases(&mut err, source, path, span); + self.err_code_special_cases(&mut err, source, path, span); (err, candidates) } @@ -667,7 +668,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { } } - fn add_err_code_cases( + fn err_code_special_cases( &mut self, err: &mut DiagnosticBuilder<'_, ErrorGuaranteed>, source: PathSource<'_>, From 0f4d7b6de8f9a9d13d9a5d479cbfa74064fd689d Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 21 Sep 2022 22:20:40 +0200 Subject: [PATCH 094/586] OpTy: fix a method taking self rather than &self --- compiler/rustc_const_eval/src/interpret/place.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs index b328892906df2..bc1aa43b73a99 100644 --- a/compiler/rustc_const_eval/src/interpret/place.rs +++ b/compiler/rustc_const_eval/src/interpret/place.rs @@ -280,7 +280,7 @@ impl<'tcx, Prov: Provenance> PlaceTy<'tcx, Prov> { #[inline(always)] #[cfg_attr(debug_assertions, track_caller)] // only in debug builds due to perf (see #98980) - pub fn assert_mem_place(self) -> MPlaceTy<'tcx, Prov> { + pub fn assert_mem_place(&self) -> MPlaceTy<'tcx, Prov> { self.try_as_mplace().unwrap() } } From 758ca9dc3aef53218f49ba0429379c66f06c6cbb Mon Sep 17 00:00:00 2001 From: Venus Xeon-Blonde Date: Wed, 21 Sep 2022 17:07:50 -0400 Subject: [PATCH 095/586] Add examples to `bool::then` and `bool::then_some` Added examples to `bool::then` and `bool::then_some` to show the distinction between the eager evaluation of `bool::then_some` and the lazy evaluation of `bool::then`. --- library/core/src/bool.rs | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/library/core/src/bool.rs b/library/core/src/bool.rs index 7667a65083769..bf020bdba76a1 100644 --- a/library/core/src/bool.rs +++ b/library/core/src/bool.rs @@ -18,6 +18,18 @@ impl bool { /// assert_eq!(false.then_some(0), None); /// assert_eq!(true.then_some(0), Some(0)); /// ``` + /// + /// ``` + /// let mut a = 0; + /// let mut function_with_side_effects = || { a += 1; }; + /// + /// true.then_some(function_with_side_effects()); + /// false.then_some(function_with_side_effects()); + /// + /// // `a` is incremented twice because the value passed to `then_some` is + /// // evaluated eagerly. + /// assert_eq!(a, 2); + /// ``` #[stable(feature = "bool_to_option", since = "1.62.0")] #[rustc_const_unstable(feature = "const_bool_to_option", issue = "91917")] #[inline] @@ -37,6 +49,16 @@ impl bool { /// assert_eq!(false.then(|| 0), None); /// assert_eq!(true.then(|| 0), Some(0)); /// ``` + /// + /// ``` + /// let mut a = 0; + /// + /// true.then(|| { a += 1; }); + /// false.then(|| { a += 1; }); + /// + /// // `a` is incremented once because the closure is evaluated lazily by + /// // `then`. + /// ``` #[stable(feature = "lazy_bool_to_option", since = "1.50.0")] #[rustc_const_unstable(feature = "const_bool_to_option", issue = "91917")] #[inline] From 7a718f3be217a17e00de317fba6d1d60facfd613 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Wed, 21 Sep 2022 15:26:15 -0700 Subject: [PATCH 096/586] rustdoc: use block flex for line-number CSS `display: inline-flex` was used as part of e961d397cab900c55f8d8c104648852e2b63664e, the original commit that added these line numbers. Does anyone know why it was done this way? --- src/librustdoc/html/static/css/rustdoc.css | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index e985e6c43ade9..1d37c4f60d013 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -577,13 +577,9 @@ h2.location a { } .rustdoc .example-wrap { - display: inline-flex; + display: flex; margin-bottom: 10px; -} - -.example-wrap { position: relative; - width: 100%; } .example-wrap > pre.line-number { From f66769fe8d71d9d5d15f845e6ef918f2e417598f Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Wed, 21 Sep 2022 15:43:38 -0700 Subject: [PATCH 097/586] rustdoc: dynamically show-hide line numbers on code examples --- src/librustdoc/html/static/js/main.js | 41 ++++++++++++++----- src/librustdoc/html/static/js/settings.js | 7 ++++ .../docblock-code-block-line-number.goml | 17 ++++++++ 3 files changed, 54 insertions(+), 11 deletions(-) diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js index 6e9660ddcc96a..5fbe540c32045 100644 --- a/src/librustdoc/html/static/js/main.js +++ b/src/librustdoc/html/static/js/main.js @@ -697,20 +697,39 @@ function loadCss(cssFileName) { } }()); + window.rustdoc_add_line_numbers_to_examples = () => { + onEachLazy(document.getElementsByClassName("rust-example-rendered"), x => { + const parent = x.parentNode; + const line_numbers = parent.querySelectorAll(".line-number"); + if (line_numbers.length > 0) { + return; + } + const count = x.textContent.split("\n").length; + const elems = []; + for (let i = 0; i < count; ++i) { + elems.push(i + 1); + } + const node = document.createElement("pre"); + addClass(node, "line-number"); + node.innerHTML = elems.join("\n"); + parent.insertBefore(node, x); + }); + }; + + window.rustdoc_remove_line_numbers_from_examples = () => { + onEachLazy(document.getElementsByClassName("rust-example-rendered"), x => { + const parent = x.parentNode; + const line_numbers = parent.querySelectorAll(".line-number"); + for (const node of line_numbers) { + parent.removeChild(node); + } + }); + }; + (function() { // To avoid checking on "rustdoc-line-numbers" value on every loop... if (getSettingValue("line-numbers") === "true") { - onEachLazy(document.getElementsByClassName("rust-example-rendered"), x => { - const count = x.textContent.split("\n").length; - const elems = []; - for (let i = 0; i < count; ++i) { - elems.push(i + 1); - } - const node = document.createElement("pre"); - addClass(node, "line-number"); - node.innerHTML = elems.join("\n"); - x.parentNode.insertBefore(node, x); - }); + window.rustdoc_add_line_numbers_to_examples(); } }()); diff --git a/src/librustdoc/html/static/js/settings.js b/src/librustdoc/html/static/js/settings.js index 797b931afc643..1c5d33e212754 100644 --- a/src/librustdoc/html/static/js/settings.js +++ b/src/librustdoc/html/static/js/settings.js @@ -19,6 +19,13 @@ updateSystemTheme(); updateLightAndDark(); break; + case "line-numbers": + if (value === true) { + window.rustdoc_add_line_numbers_to_examples(); + } else { + window.rustdoc_remove_line_numbers_from_examples(); + } + break; } } diff --git a/src/test/rustdoc-gui/docblock-code-block-line-number.goml b/src/test/rustdoc-gui/docblock-code-block-line-number.goml index baf9651c40de3..ebfffbce71561 100644 --- a/src/test/rustdoc-gui/docblock-code-block-line-number.goml +++ b/src/test/rustdoc-gui/docblock-code-block-line-number.goml @@ -20,3 +20,20 @@ assert-css: ("pre.line-number", { }) // The first code block has two lines so let's check its `
` elements lists both of them.
 assert-text: ("pre.line-number", "1\n2")
+
+// Now, try changing the setting dynamically. We'll turn it off, using the settings menu,
+// and make sure it goes away.
+
+// First, open the settings menu.
+click: "#settings-menu"
+wait-for: "#settings"
+assert-css: ("#settings", {"display": "block"})
+
+// Then, click the toggle button.
+click: "input#line-numbers + .slider"
+wait-for: 100 // wait-for-false does not exist
+assert-false: "pre.line-number"
+
+// Finally, turn it on again.
+click: "input#line-numbers + .slider"
+wait-for: "pre.line-number"

From 8b4c0d90dc403cb9727e80d73c27d4f3de574d60 Mon Sep 17 00:00:00 2001
From: Michael Howell 
Date: Wed, 21 Sep 2022 16:44:33 -0700
Subject: [PATCH 098/586] rustdoc: adjust test to cope with slightly different
 scrolling behaviour

---
 src/test/rustdoc-gui/source-anchor-scroll.goml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/test/rustdoc-gui/source-anchor-scroll.goml b/src/test/rustdoc-gui/source-anchor-scroll.goml
index 4e51c8dcac0af..47e40aa8e3b1c 100644
--- a/src/test/rustdoc-gui/source-anchor-scroll.goml
+++ b/src/test/rustdoc-gui/source-anchor-scroll.goml
@@ -10,7 +10,7 @@ assert-property: ("html", {"scrollTop": "0"})
 click: '//a[text() = "barbar"]'
 assert-property: ("html", {"scrollTop": "125"})
 click: '//a[text() = "bar"]'
-assert-property: ("html", {"scrollTop": "166"})
+assert-property: ("html", {"scrollTop": "156"})
 click: '//a[text() = "sub_fn"]'
 assert-property: ("html", {"scrollTop": "53"})
 

From 51c752a375b280c9d78a8a75987497ee08d16385 Mon Sep 17 00:00:00 2001
From: Steve Heindel 
Date: Wed, 21 Sep 2022 19:45:57 -0400
Subject: [PATCH 099/586] Add note to clippy::non_expressive_names doc

---
 src/tools/clippy/clippy_lints/src/non_expressive_names.rs | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/src/tools/clippy/clippy_lints/src/non_expressive_names.rs b/src/tools/clippy/clippy_lints/src/non_expressive_names.rs
index b96af06b8d7c6..a7cd1f6d0652b 100644
--- a/src/tools/clippy/clippy_lints/src/non_expressive_names.rs
+++ b/src/tools/clippy/clippy_lints/src/non_expressive_names.rs
@@ -15,6 +15,10 @@ declare_clippy_lint! {
     /// ### What it does
     /// Checks for names that are very similar and thus confusing.
     ///
+    /// Note: this lint looks for similar names throughout each
+    /// scope. To allow it, you need to allow it on the scope
+    /// level, not on the name that is reported.
+    ///
     /// ### Why is this bad?
     /// It's hard to distinguish between names that differ only
     /// by a single character.

From 804cd8499b197907ee2c74c5f2c6dab57269d728 Mon Sep 17 00:00:00 2001
From: Venus Xeon-Blonde 
Date: Wed, 21 Sep 2022 23:23:14 -0400
Subject: [PATCH 100/586] Remove trailing whitespace

Trailing whitespace seemed to be causing the CI checks to error out.
---
 library/core/src/bool.rs | 18 +++++++++---------
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/library/core/src/bool.rs b/library/core/src/bool.rs
index bf020bdba76a1..e717d1f3524d1 100644
--- a/library/core/src/bool.rs
+++ b/library/core/src/bool.rs
@@ -18,16 +18,16 @@ impl bool {
     /// assert_eq!(false.then_some(0), None);
     /// assert_eq!(true.then_some(0), Some(0));
     /// ```
-    /// 
+    ///
     /// ```
     /// let mut a = 0;
     /// let mut function_with_side_effects = || { a += 1; };
-    /// 
+    ///
     /// true.then_some(function_with_side_effects());
     /// false.then_some(function_with_side_effects());
-    /// 
-    /// // `a` is incremented twice because the value passed to `then_some` is 
-    /// // evaluated eagerly. 
+    ///
+    /// // `a` is incremented twice because the value passed to `then_some` is
+    /// // evaluated eagerly.
     /// assert_eq!(a, 2);
     /// ```
     #[stable(feature = "bool_to_option", since = "1.62.0")]
@@ -49,14 +49,14 @@ impl bool {
     /// assert_eq!(false.then(|| 0), None);
     /// assert_eq!(true.then(|| 0), Some(0));
     /// ```
-    /// 
+    ///
     /// ```
     /// let mut a = 0;
-    /// 
+    ///
     /// true.then(|| { a += 1; });
     /// false.then(|| { a += 1; });
-    /// 
-    /// // `a` is incremented once because the closure is evaluated lazily by 
+    ///
+    /// // `a` is incremented once because the closure is evaluated lazily by
     /// // `then`.
     /// ```
     #[stable(feature = "lazy_bool_to_option", since = "1.50.0")]

From 876c7076c8592ac2ca7bc243340646321b224c38 Mon Sep 17 00:00:00 2001
From: Michael Howell 
Date: Wed, 21 Sep 2022 20:47:33 -0700
Subject: [PATCH 101/586] rustdoc: remove no-op CSS `.content .item-info {
 position: relative }`

This rule was added to help position the marker line in
110e7270ab7b0700ce714b8b1c7e509195dea2c4, which was a `position: absolute`
pseudo-element that relied on its parent to put it in the right spot.

The arrow was removed in 73d0f7c7b68784f1db0a1f53855c20d118a7e8b0, so the
`relative` position is no longer necessary.
---
 src/librustdoc/html/static/css/rustdoc.css | 1 -
 1 file changed, 1 deletion(-)

diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css
index e985e6c43ade9..a442c09bfb7c3 100644
--- a/src/librustdoc/html/static/css/rustdoc.css
+++ b/src/librustdoc/html/static/css/rustdoc.css
@@ -749,7 +749,6 @@ pre, .rustdoc.source .example-wrap {
 }
 
 .content .item-info {
-	position: relative;
 	margin-left: 24px;
 }
 

From ca26dec15fb35f8e27c517baf2b147edefbb4cd6 Mon Sep 17 00:00:00 2001
From: Venus Xeon-Blonde 
Date: Thu, 22 Sep 2022 02:12:06 -0400
Subject: [PATCH 102/586] Add missing assertion

---
 library/core/src/bool.rs | 1 +
 1 file changed, 1 insertion(+)

diff --git a/library/core/src/bool.rs b/library/core/src/bool.rs
index e717d1f3524d1..db1c505ba3851 100644
--- a/library/core/src/bool.rs
+++ b/library/core/src/bool.rs
@@ -58,6 +58,7 @@ impl bool {
     ///
     /// // `a` is incremented once because the closure is evaluated lazily by
     /// // `then`.
+    /// assert_eq!(a, 1);
     /// ```
     #[stable(feature = "lazy_bool_to_option", since = "1.50.0")]
     #[rustc_const_unstable(feature = "const_bool_to_option", issue = "91917")]

From 2d7f9877153623c841517f8c6578edafd19c4daa Mon Sep 17 00:00:00 2001
From: Takayuki Maeda 
Date: Thu, 22 Sep 2022 16:11:51 +0900
Subject: [PATCH 103/586] use appropriate variable names

---
 compiler/rustc_passes/src/check_attr.rs | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index b3f15ba7cbf25..f112f1274b8c7 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -35,8 +35,8 @@ pub(crate) fn target_from_impl_item<'tcx>(
     match impl_item.kind {
         hir::ImplItemKind::Const(..) => Target::AssocConst,
         hir::ImplItemKind::Fn(..) => {
-            let parent_hir_id = tcx.hir().get_parent_item(impl_item.hir_id());
-            let containing_item = tcx.hir().expect_item(parent_hir_id);
+            let parent_def_id = tcx.hir().get_parent_item(impl_item.hir_id());
+            let containing_item = tcx.hir().expect_item(parent_def_id);
             let containing_impl_is_for_trait = match &containing_item.kind {
                 hir::ItemKind::Impl(impl_) => impl_.of_trait.is_some(),
                 _ => bug!("parent of an ImplItem must be an Impl"),
@@ -640,8 +640,8 @@ impl CheckAttrVisitor<'_> {
         let span = meta.span();
         if let Some(location) = match target {
             Target::AssocTy => {
-                let parent_hir_id = self.tcx.hir().get_parent_item(hir_id);
-                let containing_item = self.tcx.hir().expect_item(parent_hir_id);
+                let parent_def_id = self.tcx.hir().get_parent_item(hir_id);
+                let containing_item = self.tcx.hir().expect_item(parent_def_id);
                 if Target::from_item(containing_item) == Target::Impl {
                     Some("type alias in implementation block")
                 } else {
@@ -649,8 +649,8 @@ impl CheckAttrVisitor<'_> {
                 }
             }
             Target::AssocConst => {
-                let parent_hir_id = self.tcx.hir().get_parent_item(hir_id);
-                let containing_item = self.tcx.hir().expect_item(parent_hir_id);
+                let parent_def_id = self.tcx.hir().get_parent_item(hir_id);
+                let containing_item = self.tcx.hir().expect_item(parent_def_id);
                 // We can't link to trait impl's consts.
                 let err = "associated constant in trait implementation block";
                 match containing_item.kind {

From 13438ee29c7835969765f273df34312586d31731 Mon Sep 17 00:00:00 2001
From: Oli Scherer 
Date: Thu, 22 Sep 2022 08:20:13 +0000
Subject: [PATCH 104/586] Const unification is already infallible, remove the
 error handling logic

---
 compiler/rustc_infer/src/infer/combine.rs    | 37 ++++++--------------
 compiler/rustc_middle/src/infer/unify_key.rs |  2 +-
 2 files changed, 12 insertions(+), 27 deletions(-)

diff --git a/compiler/rustc_infer/src/infer/combine.rs b/compiler/rustc_infer/src/infer/combine.rs
index c406df9e41116..682ad02da8635 100644
--- a/compiler/rustc_infer/src/infer/combine.rs
+++ b/compiler/rustc_infer/src/infer/combine.rs
@@ -147,11 +147,7 @@ impl<'infcx, 'tcx> InferCtxt<'infcx, 'tcx> {
                 ty::ConstKind::Infer(InferConst::Var(a_vid)),
                 ty::ConstKind::Infer(InferConst::Var(b_vid)),
             ) => {
-                self.inner
-                    .borrow_mut()
-                    .const_unification_table()
-                    .unify_var_var(a_vid, b_vid)
-                    .map_err(|e| const_unification_error(a_is_expected, e))?;
+                self.inner.borrow_mut().const_unification_table().union(a_vid, b_vid);
                 return Ok(a);
             }
 
@@ -246,21 +242,17 @@ impl<'infcx, 'tcx> InferCtxt<'infcx, 'tcx> {
         let value = ConstInferUnifier { infcx: self, span, param_env, for_universe, target_vid }
             .relate(ct, ct)?;
 
-        self.inner
-            .borrow_mut()
-            .const_unification_table()
-            .unify_var_value(
-                target_vid,
-                ConstVarValue {
-                    origin: ConstVariableOrigin {
-                        kind: ConstVariableOriginKind::ConstInference,
-                        span: DUMMY_SP,
-                    },
-                    val: ConstVariableValue::Known { value },
+        self.inner.borrow_mut().const_unification_table().union_value(
+            target_vid,
+            ConstVarValue {
+                origin: ConstVariableOrigin {
+                    kind: ConstVariableOriginKind::ConstInference,
+                    span: DUMMY_SP,
                 },
-            )
-            .map(|()| value)
-            .map_err(|e| const_unification_error(vid_is_expected, e))
+                val: ConstVariableValue::Known { value },
+            },
+        );
+        Ok(value)
     }
 
     fn unify_integral_variable(
@@ -768,13 +760,6 @@ pub trait ConstEquateRelation<'tcx>: TypeRelation<'tcx> {
     fn const_equate_obligation(&mut self, a: ty::Const<'tcx>, b: ty::Const<'tcx>);
 }
 
-pub fn const_unification_error<'tcx>(
-    a_is_expected: bool,
-    (a, b): (ty::Const<'tcx>, ty::Const<'tcx>),
-) -> TypeError<'tcx> {
-    TypeError::ConstMismatch(ExpectedFound::new(a_is_expected, a, b))
-}
-
 fn int_unification_error<'tcx>(
     a_is_expected: bool,
     v: (ty::IntVarValue, ty::IntVarValue),
diff --git a/compiler/rustc_middle/src/infer/unify_key.rs b/compiler/rustc_middle/src/infer/unify_key.rs
index f2627885d030d..41d8c7ffdb945 100644
--- a/compiler/rustc_middle/src/infer/unify_key.rs
+++ b/compiler/rustc_middle/src/infer/unify_key.rs
@@ -129,7 +129,7 @@ impl<'tcx> UnifyKey for ty::ConstVid<'tcx> {
 }
 
 impl<'tcx> UnifyValue for ConstVarValue<'tcx> {
-    type Error = (ty::Const<'tcx>, ty::Const<'tcx>);
+    type Error = NoError;
 
     fn unify_values(&value1: &Self, &value2: &Self) -> Result {
         Ok(match (value1.val, value2.val) {

From 9f3784df89e9f19d4b99660434e0b0e226ff2c22 Mon Sep 17 00:00:00 2001
From: b-naber 
Date: Mon, 19 Sep 2022 19:46:53 +0200
Subject: [PATCH 105/586] introduce mir::Unevaluated

---
 .../rustc_codegen_cranelift/src/constant.rs   | 13 ++-----
 .../src/transform/check_consts/qualifs.rs     | 17 +++-------
 .../src/transform/promote_consts.rs           |  3 +-
 compiler/rustc_infer/src/infer/combine.rs     | 12 +++----
 compiler/rustc_infer/src/infer/mod.rs         | 11 +++---
 .../rustc_middle/src/mir/interpret/queries.rs | 10 ++++--
 compiler/rustc_middle/src/mir/mod.rs          | 34 ++++++++++++++++---
 compiler/rustc_middle/src/mir/pretty.rs       |  3 +-
 .../rustc_middle/src/mir/type_foldable.rs     | 20 +++++++++++
 .../rustc_middle/src/mir/type_visitable.rs    | 13 +++++++
 compiler/rustc_middle/src/query/mod.rs        |  2 +-
 .../rustc_middle/src/ty/abstract_const.rs     |  2 +-
 compiler/rustc_middle/src/ty/consts.rs        |  1 -
 compiler/rustc_middle/src/ty/consts/kind.rs   | 30 +++++-----------
 compiler/rustc_middle/src/ty/flags.rs         |  2 +-
 compiler/rustc_middle/src/ty/fold.rs          | 26 +++++++++++---
 compiler/rustc_middle/src/ty/mod.rs           |  2 +-
 compiler/rustc_middle/src/ty/print/pretty.rs  |  4 +--
 compiler/rustc_middle/src/ty/relate.rs        | 12 ++-----
 .../rustc_middle/src/ty/structural_impls.rs   | 22 ++----------
 compiler/rustc_middle/src/ty/visit.rs         | 18 ++++++++--
 .../src/build/expr/as_constant.rs             |  5 +--
 .../src/const_prop_lint.rs                    |  6 ++--
 .../rustc_monomorphize/src/polymorphize.rs    |  7 ++--
 compiler/rustc_query_impl/src/keys.rs         |  2 +-
 .../src/traits/auto_trait.rs                  |  2 +-
 .../src/traits/const_evaluatable.rs           |  4 +--
 .../src/traits/object_safety.rs               |  7 ++--
 compiler/rustc_typeck/src/collect.rs          |  1 -
 src/librustdoc/clean/utils.rs                 |  3 +-
 .../clippy/clippy_lints/src/non_copy_const.rs |  2 +-
 src/tools/clippy/clippy_utils/src/consts.rs   |  2 +-
 32 files changed, 166 insertions(+), 132 deletions(-)

diff --git a/compiler/rustc_codegen_cranelift/src/constant.rs b/compiler/rustc_codegen_cranelift/src/constant.rs
index 6b4ed9b9d4053..aac64d854a6b5 100644
--- a/compiler/rustc_codegen_cranelift/src/constant.rs
+++ b/compiler/rustc_codegen_cranelift/src/constant.rs
@@ -5,7 +5,6 @@ use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use rustc_middle::mir::interpret::{
     read_target_uint, AllocId, ConstAllocation, ConstValue, ErrorHandled, GlobalAlloc, Scalar,
 };
-use rustc_middle::ty::ConstKind;
 use rustc_span::DUMMY_SP;
 
 use cranelift_codegen::ir::GlobalValueData;
@@ -42,15 +41,7 @@ pub(crate) fn check_constants(fx: &mut FunctionCx<'_, '_, '_>) -> bool {
     let mut all_constants_ok = true;
     for constant in &fx.mir.required_consts {
         let unevaluated = match fx.monomorphize(constant.literal) {
-            ConstantKind::Ty(ct) => match ct.kind() {
-                ConstKind::Unevaluated(uv) => uv.expand(),
-                ConstKind::Value(_) => continue,
-                ConstKind::Param(_)
-                | ConstKind::Infer(_)
-                | ConstKind::Bound(_, _)
-                | ConstKind::Placeholder(_)
-                | ConstKind::Error(_) => unreachable!("{:?}", ct),
-            },
+            ConstantKind::Ty(_) => unreachable!(),
             ConstantKind::Unevaluated(uv, _) => uv,
             ConstantKind::Val(..) => continue,
         };
@@ -118,7 +109,7 @@ pub(crate) fn codegen_constant<'tcx>(
 ) -> CValue<'tcx> {
     let (const_val, ty) = match fx.monomorphize(constant.literal) {
         ConstantKind::Ty(const_) => unreachable!("{:?}", const_),
-        ConstantKind::Unevaluated(ty::Unevaluated { def, substs, promoted }, ty)
+        ConstantKind::Unevaluated(mir::Unevaluated { def, substs, promoted }, ty)
             if fx.tcx.is_static(def.did) =>
         {
             assert!(substs.is_empty());
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs
index fb22befd0a4a7..b1d140726d11f 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs
@@ -5,6 +5,7 @@
 use rustc_errors::ErrorGuaranteed;
 use rustc_hir::LangItem;
 use rustc_infer::infer::TyCtxtInferExt;
+use rustc_middle::mir;
 use rustc_middle::mir::*;
 use rustc_middle::ty::{self, subst::SubstsRef, AdtDef, Ty};
 use rustc_span::DUMMY_SP;
@@ -350,17 +351,13 @@ where
     // FIXME(valtrees): check whether const qualifs should behave the same
     // way for type and mir constants.
     let uneval = match constant.literal {
-        ConstantKind::Ty(ct) if matches!(ct.kind(), ty::ConstKind::Unevaluated(_)) => {
-            let ty::ConstKind::Unevaluated(uv) = ct.kind() else { unreachable!() };
-
-            Some(uv.expand())
-        }
-        ConstantKind::Ty(_) => None,
+        ConstantKind::Ty(ct) if matches!(ct.kind(), ty::ConstKind::Param(_)) => None,
+        ConstantKind::Ty(c) => bug!("expected ConstKind::Param here, found {:?}", c),
         ConstantKind::Unevaluated(uv, _) => Some(uv),
         ConstantKind::Val(..) => None,
     };
 
-    if let Some(ty::Unevaluated { def, substs: _, promoted }) = uneval {
+    if let Some(mir::Unevaluated { def, substs: _, promoted }) = uneval {
         // Use qualifs of the type for the promoted. Promoteds in MIR body should be possible
         // only for `NeedsNonConstDrop` with precise drop checking. This is the only const
         // check performed after the promotion. Verify that with an assertion.
@@ -368,11 +365,7 @@ where
 
         // Don't peek inside trait associated constants.
         if promoted.is_none() && cx.tcx.trait_of_item(def.did).is_none() {
-            let qualifs = if let Some((did, param_did)) = def.as_const_arg() {
-                cx.tcx.at(constant.span).mir_const_qualif_const_arg((did, param_did))
-            } else {
-                cx.tcx.at(constant.span).mir_const_qualif(def.did)
-            };
+            let qualifs = cx.tcx.at(constant.span).mir_const_qualif(def.did);
 
             if !Q::in_qualifs(&qualifs) {
                 return false;
diff --git a/compiler/rustc_const_eval/src/transform/promote_consts.rs b/compiler/rustc_const_eval/src/transform/promote_consts.rs
index 461051574e565..733683bf7baa2 100644
--- a/compiler/rustc_const_eval/src/transform/promote_consts.rs
+++ b/compiler/rustc_const_eval/src/transform/promote_consts.rs
@@ -13,6 +13,7 @@
 //! move analysis runs after promotion on broken MIR.
 
 use rustc_hir as hir;
+use rustc_middle::mir;
 use rustc_middle::mir::traversal::ReversePostorderIter;
 use rustc_middle::mir::visit::{MutVisitor, MutatingUseContext, PlaceContext, Visitor};
 use rustc_middle::mir::*;
@@ -840,7 +841,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
                 promoted.span = span;
                 promoted.local_decls[RETURN_PLACE] = LocalDecl::new(ty, span);
                 let substs = tcx.erase_regions(InternalSubsts::identity_for_item(tcx, def.did));
-                let uneval = ty::Unevaluated { def, substs, promoted: Some(promoted_id) };
+                let uneval = mir::Unevaluated { def, substs, promoted: Some(promoted_id) };
 
                 Operand::Constant(Box::new(Constant {
                     span,
diff --git a/compiler/rustc_infer/src/infer/combine.rs b/compiler/rustc_infer/src/infer/combine.rs
index c406df9e41116..18e05fa37f71f 100644
--- a/compiler/rustc_infer/src/infer/combine.rs
+++ b/compiler/rustc_infer/src/infer/combine.rs
@@ -742,9 +742,7 @@ impl<'tcx> TypeRelation<'tcx> for Generalizer<'_, 'tcx> {
                     }
                 }
             }
-            ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }) => {
-                assert_eq!(promoted, ());
-
+            ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs }) => {
                 let substs = self.relate_with_variance(
                     ty::Variance::Invariant,
                     ty::VarianceDiagInfo::default(),
@@ -753,7 +751,7 @@ impl<'tcx> TypeRelation<'tcx> for Generalizer<'_, 'tcx> {
                 )?;
                 Ok(self.tcx().mk_const(ty::ConstS {
                     ty: c.ty(),
-                    kind: ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }),
+                    kind: ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs }),
                 }))
             }
             _ => relate::super_relate_consts(self, c, c),
@@ -964,9 +962,7 @@ impl<'tcx> TypeRelation<'tcx> for ConstInferUnifier<'_, 'tcx> {
                     }
                 }
             }
-            ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }) => {
-                assert_eq!(promoted, ());
-
+            ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs }) => {
                 let substs = self.relate_with_variance(
                     ty::Variance::Invariant,
                     ty::VarianceDiagInfo::default(),
@@ -976,7 +972,7 @@ impl<'tcx> TypeRelation<'tcx> for ConstInferUnifier<'_, 'tcx> {
 
                 Ok(self.tcx().mk_const(ty::ConstS {
                     ty: c.ty(),
-                    kind: ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }),
+                    kind: ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs }),
                 }))
             }
             _ => relate::super_relate_consts(self, c, c),
diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs
index 3abed12217ccd..0a37aa035c2a0 100644
--- a/compiler/rustc_infer/src/infer/mod.rs
+++ b/compiler/rustc_infer/src/infer/mod.rs
@@ -705,8 +705,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
     #[instrument(skip(self), level = "debug")]
     pub fn try_unify_abstract_consts(
         &self,
-        a: ty::Unevaluated<'tcx, ()>,
-        b: ty::Unevaluated<'tcx, ()>,
+        a: ty::Unevaluated<'tcx>,
+        b: ty::Unevaluated<'tcx>,
         param_env: ty::ParamEnv<'tcx>,
     ) -> bool {
         // Reject any attempt to unify two unevaluated constants that contain inference
@@ -1690,7 +1690,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
     pub fn try_const_eval_resolve(
         &self,
         param_env: ty::ParamEnv<'tcx>,
-        unevaluated: ty::Unevaluated<'tcx, ()>,
+        unevaluated: ty::Unevaluated<'tcx>,
         ty: Ty<'tcx>,
         span: Option,
     ) -> Result, ErrorHandled> {
@@ -1725,7 +1725,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
     pub fn const_eval_resolve(
         &self,
         mut param_env: ty::ParamEnv<'tcx>,
-        unevaluated: ty::Unevaluated<'tcx, ()>,
+        unevaluated: ty::Unevaluated<'tcx>,
         span: Option,
     ) -> EvalToValTreeResult<'tcx> {
         let mut substs = self.resolve_vars_if_possible(unevaluated.substs);
@@ -1756,8 +1756,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
         debug!(?param_env_erased);
         debug!(?substs_erased);
 
-        let unevaluated =
-            ty::Unevaluated { def: unevaluated.def, substs: substs_erased, promoted: () };
+        let unevaluated = ty::Unevaluated { def: unevaluated.def, substs: substs_erased };
 
         // The return value is the evaluated value which doesn't contain any reference to inference
         // variables, thus we don't need to substitute back the original values.
diff --git a/compiler/rustc_middle/src/mir/interpret/queries.rs b/compiler/rustc_middle/src/mir/interpret/queries.rs
index a8c7505329cda..5f3124e482d49 100644
--- a/compiler/rustc_middle/src/mir/interpret/queries.rs
+++ b/compiler/rustc_middle/src/mir/interpret/queries.rs
@@ -36,7 +36,7 @@ impl<'tcx> TyCtxt<'tcx> {
     pub fn const_eval_resolve(
         self,
         param_env: ty::ParamEnv<'tcx>,
-        ct: ty::Unevaluated<'tcx>,
+        ct: mir::Unevaluated<'tcx>,
         span: Option,
     ) -> EvalToConstValueResult<'tcx> {
         // Cannot resolve `Unevaluated` constants that contain inference
@@ -49,7 +49,11 @@ impl<'tcx> TyCtxt<'tcx> {
             bug!("did not expect inference variables here");
         }
 
-        match ty::Instance::resolve_opt_const_arg(self, param_env, ct.def, ct.substs) {
+        match ty::Instance::resolve_opt_const_arg(
+            self, param_env,
+            // FIXME: maybe have a seperate version for resolving mir::Unevaluated?
+            ct.def, ct.substs,
+        ) {
             Ok(Some(instance)) => {
                 let cid = GlobalId { instance, promoted: ct.promoted };
                 self.const_eval_global_id(param_env, cid, span)
@@ -63,7 +67,7 @@ impl<'tcx> TyCtxt<'tcx> {
     pub fn const_eval_resolve_for_typeck(
         self,
         param_env: ty::ParamEnv<'tcx>,
-        ct: ty::Unevaluated<'tcx, ()>,
+        ct: ty::Unevaluated<'tcx>,
         span: Option,
     ) -> EvalToValTreeResult<'tcx> {
         // Cannot resolve `Unevaluated` constants that contain inference
diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs
index 86ffce8ceb41a..4b3a3085b71e0 100644
--- a/compiler/rustc_middle/src/mir/mod.rs
+++ b/compiler/rustc_middle/src/mir/mod.rs
@@ -2055,7 +2055,7 @@ pub enum ConstantKind<'tcx> {
     Ty(ty::Const<'tcx>),
 
     /// An unevaluated mir constant which is not part of the type system.
-    Unevaluated(ty::Unevaluated<'tcx, Option>, Ty<'tcx>),
+    Unevaluated(Unevaluated<'tcx, Option>, Ty<'tcx>),
 
     /// This constant cannot go back into the type system, as it represents
     /// something the type system cannot handle (e.g. pointers).
@@ -2315,12 +2315,11 @@ impl<'tcx> ConstantKind<'tcx> {
             ty::InlineConstSubsts::new(tcx, ty::InlineConstSubstsParts { parent_substs, ty })
                 .substs;
 
-        let uneval = ty::Unevaluated {
+        let uneval = Unevaluated {
             def: ty::WithOptConstParam::unknown(def_id).to_global(),
             substs,
             promoted: None,
         };
-
         debug_assert!(!uneval.has_free_regions());
 
         Self::Unevaluated(uneval, ty)
@@ -2404,7 +2403,7 @@ impl<'tcx> ConstantKind<'tcx> {
 
         let hir_id = tcx.hir().local_def_id_to_hir_id(def.did);
         let span = tcx.hir().span(hir_id);
-        let uneval = ty::Unevaluated::new(def.to_global(), substs);
+        let uneval = Unevaluated::new(def.to_global(), substs);
         debug!(?span, ?param_env);
 
         match tcx.const_eval_resolve(param_env, uneval, Some(span)) {
@@ -2417,7 +2416,7 @@ impl<'tcx> ConstantKind<'tcx> {
                 // Error was handled in `const_eval_resolve`. Here we just create a
                 // new unevaluated const and error hard later in codegen
                 Self::Unevaluated(
-                    ty::Unevaluated {
+                    Unevaluated {
                         def: def.to_global(),
                         substs: InternalSubsts::identity_for_item(tcx, def.did.to_def_id()),
                         promoted: None,
@@ -2440,6 +2439,31 @@ impl<'tcx> ConstantKind<'tcx> {
     }
 }
 
+/// An unevaluated (potentially generic) constant used in MIR.
+#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable, Lift)]
+#[derive(Hash, HashStable)]
+pub struct Unevaluated<'tcx, P = Option> {
+    pub def: ty::WithOptConstParam,
+    pub substs: SubstsRef<'tcx>,
+    pub promoted: P,
+}
+
+impl<'tcx> Unevaluated<'tcx> {
+    // FIXME: probably should get rid of this method. It's also wrong to
+    // shrink and then later expand a promoted.
+    #[inline]
+    pub fn shrink(self) -> ty::Unevaluated<'tcx> {
+        ty::Unevaluated { def: self.def, substs: self.substs }
+    }
+}
+
+impl<'tcx, P: Default> Unevaluated<'tcx, P> {
+    #[inline]
+    pub fn new(def: ty::WithOptConstParam, substs: SubstsRef<'tcx>) -> Unevaluated<'tcx, P> {
+        Unevaluated { def, substs, promoted: Default::default() }
+    }
+}
+
 /// A collection of projections into user types.
 ///
 /// They are projections because a binding can occur a part of a
diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs
index 0b42137d4e3cd..05dcfba77b233 100644
--- a/compiler/rustc_middle/src/mir/pretty.rs
+++ b/compiler/rustc_middle/src/mir/pretty.rs
@@ -466,10 +466,9 @@ impl<'tcx> Visitor<'tcx> for ExtraComments<'tcx> {
                     ty::ConstKind::Param(p) => format!("Param({})", p),
                     ty::ConstKind::Unevaluated(uv) => {
                         format!(
-                            "Unevaluated({}, {:?}, {:?})",
+                            "Unevaluated({}, {:?})",
                             self.tcx.def_path_str(uv.def.did),
                             uv.substs,
-                            uv.promoted,
                         )
                     }
                     ty::ConstKind::Value(val) => format!("Value({})", fmt_valtree(&val)),
diff --git a/compiler/rustc_middle/src/mir/type_foldable.rs b/compiler/rustc_middle/src/mir/type_foldable.rs
index 9d098c8083ece..88c07ca17e204 100644
--- a/compiler/rustc_middle/src/mir/type_foldable.rs
+++ b/compiler/rustc_middle/src/mir/type_foldable.rs
@@ -3,6 +3,7 @@
 use rustc_ast::InlineAsmTemplatePiece;
 
 use super::*;
+use crate::mir;
 use crate::ty;
 
 TrivialTypeTraversalAndLiftImpls! {
@@ -50,6 +51,25 @@ impl<'tcx, R: Idx, C: Idx> TypeFoldable<'tcx> for BitMatrix {
     }
 }
 
+impl<'tcx> TypeFoldable<'tcx> for mir::Unevaluated<'tcx> {
+    fn try_fold_with>(self, folder: &mut F) -> Result {
+        folder.try_fold_mir_unevaluated(self)
+    }
+}
+
+impl<'tcx> TypeSuperFoldable<'tcx> for mir::Unevaluated<'tcx> {
+    fn try_super_fold_with>(
+        self,
+        folder: &mut F,
+    ) -> Result {
+        Ok(mir::Unevaluated {
+            def: self.def,
+            substs: self.substs.try_fold_with(folder)?,
+            promoted: self.promoted,
+        })
+    }
+}
+
 impl<'tcx> TypeFoldable<'tcx> for ConstantKind<'tcx> {
     #[inline(always)]
     fn try_fold_with>(self, folder: &mut F) -> Result {
diff --git a/compiler/rustc_middle/src/mir/type_visitable.rs b/compiler/rustc_middle/src/mir/type_visitable.rs
index be19bb486d4b5..3f213697884ae 100644
--- a/compiler/rustc_middle/src/mir/type_visitable.rs
+++ b/compiler/rustc_middle/src/mir/type_visitable.rs
@@ -1,6 +1,7 @@
 //! `TypeVisitable` implementations for MIR types
 
 use super::*;
+use crate::mir;
 
 impl<'tcx, R: Idx, C: Idx> TypeVisitable<'tcx> for BitMatrix {
     fn visit_with>(&self, _: &mut V) -> ControlFlow {
@@ -8,6 +9,18 @@ impl<'tcx, R: Idx, C: Idx> TypeVisitable<'tcx> for BitMatrix {
     }
 }
 
+impl<'tcx> TypeVisitable<'tcx> for mir::Unevaluated<'tcx> {
+    fn visit_with>(&self, visitor: &mut V) -> ControlFlow {
+        visitor.visit_mir_unevaluated(*self)
+    }
+}
+
+impl<'tcx> TypeSuperVisitable<'tcx> for mir::Unevaluated<'tcx> {
+    fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow {
+        self.substs.visit_with(visitor)
+    }
+}
+
 impl<'tcx> TypeVisitable<'tcx> for ConstantKind<'tcx> {
     fn visit_with>(&self, visitor: &mut V) -> ControlFlow {
         visitor.visit_mir_const(*self)
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index 1afea4864b8dd..9b112dcdb1b98 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -381,7 +381,7 @@ rustc_queries! {
     }
 
     query try_unify_abstract_consts(key:
-        ty::ParamEnvAnd<'tcx, (ty::Unevaluated<'tcx, ()>, ty::Unevaluated<'tcx, ()>
+        ty::ParamEnvAnd<'tcx, (ty::Unevaluated<'tcx>, ty::Unevaluated<'tcx>
     )>) -> bool {
         desc {
             |tcx| "trying to unify the generic constants {} and {}",
diff --git a/compiler/rustc_middle/src/ty/abstract_const.rs b/compiler/rustc_middle/src/ty/abstract_const.rs
index 8e0a1f1f9acf0..f6f86540dd061 100644
--- a/compiler/rustc_middle/src/ty/abstract_const.rs
+++ b/compiler/rustc_middle/src/ty/abstract_const.rs
@@ -30,7 +30,7 @@ pub struct AbstractConst<'tcx> {
 impl<'tcx> AbstractConst<'tcx> {
     pub fn new(
         tcx: TyCtxt<'tcx>,
-        uv: ty::Unevaluated<'tcx, ()>,
+        uv: ty::Unevaluated<'tcx>,
     ) -> Result>, ErrorGuaranteed> {
         let inner = tcx.thir_abstract_const_opt_const_arg(uv.def)?;
         debug!("AbstractConst::new({:?}) = {:?}", uv, inner);
diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs
index 4bc821dcfa1fb..c2c6076e12b98 100644
--- a/compiler/rustc_middle/src/ty/consts.rs
+++ b/compiler/rustc_middle/src/ty/consts.rs
@@ -81,7 +81,6 @@ impl<'tcx> Const<'tcx> {
                 kind: ty::ConstKind::Unevaluated(ty::Unevaluated {
                     def: def.to_global(),
                     substs: InternalSubsts::identity_for_item(tcx, def.did.to_def_id()),
-                    promoted: (),
                 }),
                 ty,
             }),
diff --git a/compiler/rustc_middle/src/ty/consts/kind.rs b/compiler/rustc_middle/src/ty/consts/kind.rs
index 4550152804ea8..a04bdb1319ef8 100644
--- a/compiler/rustc_middle/src/ty/consts/kind.rs
+++ b/compiler/rustc_middle/src/ty/consts/kind.rs
@@ -1,7 +1,7 @@
 use std::convert::TryInto;
 
+use crate::mir;
 use crate::mir::interpret::{AllocId, ConstValue, Scalar};
-use crate::mir::Promoted;
 use crate::ty::subst::{InternalSubsts, SubstsRef};
 use crate::ty::ParamEnv;
 use crate::ty::{self, TyCtxt, TypeVisitable};
@@ -12,13 +12,12 @@ use rustc_target::abi::Size;
 
 use super::ScalarInt;
 
-/// An unevaluated, potentially generic, constant.
+/// An unevaluated (potentially generic) constant used in the type-system.
 #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable, Lift)]
 #[derive(Hash, HashStable)]
-pub struct Unevaluated<'tcx, P = Option> {
+pub struct Unevaluated<'tcx> {
     pub def: ty::WithOptConstParam,
     pub substs: SubstsRef<'tcx>,
-    pub promoted: P,
 }
 
 impl rustc_errors::IntoDiagnosticArg for Unevaluated<'_> {
@@ -29,23 +28,15 @@ impl rustc_errors::IntoDiagnosticArg for Unevaluated<'_> {
 
 impl<'tcx> Unevaluated<'tcx> {
     #[inline]
-    pub fn shrink(self) -> Unevaluated<'tcx, ()> {
-        debug_assert_eq!(self.promoted, None);
-        Unevaluated { def: self.def, substs: self.substs, promoted: () }
+    pub fn expand(self) -> mir::Unevaluated<'tcx> {
+        mir::Unevaluated { def: self.def, substs: self.substs, promoted: None }
     }
 }
 
-impl<'tcx> Unevaluated<'tcx, ()> {
-    #[inline]
-    pub fn expand(self) -> Unevaluated<'tcx> {
-        Unevaluated { def: self.def, substs: self.substs, promoted: None }
-    }
-}
-
-impl<'tcx, P: Default> Unevaluated<'tcx, P> {
+impl<'tcx> Unevaluated<'tcx> {
     #[inline]
-    pub fn new(def: ty::WithOptConstParam, substs: SubstsRef<'tcx>) -> Unevaluated<'tcx, P> {
-        Unevaluated { def, substs, promoted: Default::default() }
+    pub fn new(def: ty::WithOptConstParam, substs: SubstsRef<'tcx>) -> Unevaluated<'tcx> {
+        Unevaluated { def, substs }
     }
 }
 
@@ -67,7 +58,7 @@ pub enum ConstKind<'tcx> {
 
     /// Used in the HIR by using `Unevaluated` everywhere and later normalizing to one of the other
     /// variants when the code is monomorphic enough for that.
-    Unevaluated(Unevaluated<'tcx, ()>),
+    Unevaluated(Unevaluated<'tcx>),
 
     /// Used to hold computed value.
     Value(ty::ValTree<'tcx>),
@@ -185,8 +176,6 @@ impl<'tcx> ConstKind<'tcx> {
         if let ConstKind::Unevaluated(unevaluated) = self {
             use crate::mir::interpret::ErrorHandled;
 
-            assert_eq!(unevaluated.promoted, ());
-
             // HACK(eddyb) this erases lifetimes even though `const_eval_resolve`
             // also does later, but we want to do it before checking for
             // inference variables.
@@ -207,7 +196,6 @@ impl<'tcx> ConstKind<'tcx> {
                 tcx.param_env(unevaluated.def.did).and(ty::Unevaluated {
                     def: unevaluated.def,
                     substs: InternalSubsts::identity_for_item(tcx, unevaluated.def.did),
-                    promoted: (),
                 })
             } else {
                 param_env_and
diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs
index 98b8a7386fe6a..2c2acfa0697b7 100644
--- a/compiler/rustc_middle/src/ty/flags.rs
+++ b/compiler/rustc_middle/src/ty/flags.rs
@@ -313,7 +313,7 @@ impl FlagComputation {
         }
     }
 
-    fn add_unevaluated_const

(&mut self, ct: ty::Unevaluated<'_, P>) { + fn add_unevaluated_const(&mut self, ct: ty::Unevaluated<'_>) { self.add_substs(ct.substs); self.add_flags(TypeFlags::HAS_CT_PROJECTION); } diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs index cac95e14a2337..b921ae829e550 100644 --- a/compiler/rustc_middle/src/ty/fold.rs +++ b/compiler/rustc_middle/src/ty/fold.rs @@ -128,7 +128,11 @@ pub trait TypeFolder<'tcx>: FallibleTypeFolder<'tcx, Error = !> { c.super_fold_with(self) } - fn fold_unevaluated(&mut self, uv: ty::Unevaluated<'tcx>) -> ty::Unevaluated<'tcx> { + fn fold_ty_unevaluated(&mut self, uv: ty::Unevaluated<'tcx>) -> ty::Unevaluated<'tcx> { + uv.super_fold_with(self) + } + + fn fold_mir_unevaluated(&mut self, uv: mir::Unevaluated<'tcx>) -> mir::Unevaluated<'tcx> { uv.super_fold_with(self) } @@ -172,13 +176,20 @@ pub trait FallibleTypeFolder<'tcx>: Sized { c.try_super_fold_with(self) } - fn try_fold_unevaluated( + fn try_fold_ty_unevaluated( &mut self, c: ty::Unevaluated<'tcx>, ) -> Result, Self::Error> { c.try_super_fold_with(self) } + fn try_fold_mir_unevaluated( + &mut self, + c: mir::Unevaluated<'tcx>, + ) -> Result, Self::Error> { + c.try_super_fold_with(self) + } + fn try_fold_predicate( &mut self, p: ty::Predicate<'tcx>, @@ -225,11 +236,18 @@ where Ok(self.fold_const(c)) } - fn try_fold_unevaluated( + fn try_fold_ty_unevaluated( &mut self, c: ty::Unevaluated<'tcx>, ) -> Result, !> { - Ok(self.fold_unevaluated(c)) + Ok(self.fold_ty_unevaluated(c)) + } + + fn try_fold_mir_unevaluated( + &mut self, + c: mir::Unevaluated<'tcx>, + ) -> Result, !> { + Ok(self.fold_mir_unevaluated(c)) } fn try_fold_predicate(&mut self, p: ty::Predicate<'tcx>) -> Result, !> { diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 982aacc768696..6cc73f2561fa7 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -682,7 +682,7 @@ pub enum PredicateKind<'tcx> { Coerce(CoercePredicate<'tcx>), /// Constant initializer must evaluate successfully. - ConstEvaluatable(ty::Unevaluated<'tcx, ()>), + ConstEvaluatable(ty::Unevaluated<'tcx>), /// Constants must be equal. The first component is the const that is expected. ConstEquate(Const<'tcx>, Const<'tcx>), diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index b6cd5396b1d23..6318fe679df38 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -1201,9 +1201,7 @@ pub trait PrettyPrinter<'tcx>: } match ct.kind() { - ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }) => { - assert_eq!(promoted, ()); - + ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs }) => { match self.tcx().def_kind(def.did) { DefKind::Static(..) | DefKind::Const | DefKind::AssocConst => { p!(print_value_path(def.did, substs)) diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs index 0d97d4acdfc78..a56010146c09e 100644 --- a/compiler/rustc_middle/src/ty/relate.rs +++ b/compiler/rustc_middle/src/ty/relate.rs @@ -621,11 +621,7 @@ pub fn super_relate_consts<'tcx, R: TypeRelation<'tcx>>( // While this is slightly incorrect, it shouldn't matter for `min_const_generics` // and is the better alternative to waiting until `generic_const_exprs` can // be stabilized. - (ty::ConstKind::Unevaluated(au), ty::ConstKind::Unevaluated(bu)) - if au.def == bu.def && au.promoted == bu.promoted => - { - assert_eq!(au.promoted, ()); - + (ty::ConstKind::Unevaluated(au), ty::ConstKind::Unevaluated(bu)) if au.def == bu.def => { let substs = relation.relate_with_variance( ty::Variance::Invariant, ty::VarianceDiagInfo::default(), @@ -633,11 +629,7 @@ pub fn super_relate_consts<'tcx, R: TypeRelation<'tcx>>( bu.substs, )?; return Ok(tcx.mk_const(ty::ConstS { - kind: ty::ConstKind::Unevaluated(ty::Unevaluated { - def: au.def, - substs, - promoted: (), - }), + kind: ty::ConstKind::Unevaluated(ty::Unevaluated { def: au.def, substs }), ty: a.ty(), })); } diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index 004fcffdc4074..9cabce5f82cc0 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -831,13 +831,13 @@ impl<'tcx> TypeVisitable<'tcx> for InferConst<'tcx> { impl<'tcx> TypeFoldable<'tcx> for ty::Unevaluated<'tcx> { fn try_fold_with>(self, folder: &mut F) -> Result { - folder.try_fold_unevaluated(self) + folder.try_fold_ty_unevaluated(self) } } impl<'tcx> TypeVisitable<'tcx> for ty::Unevaluated<'tcx> { fn visit_with>(&self, visitor: &mut V) -> ControlFlow { - visitor.visit_unevaluated(*self) + visitor.visit_ty_unevaluated(*self) } } @@ -846,11 +846,7 @@ impl<'tcx> TypeSuperFoldable<'tcx> for ty::Unevaluated<'tcx> { self, folder: &mut F, ) -> Result { - Ok(ty::Unevaluated { - def: self.def, - substs: self.substs.try_fold_with(folder)?, - promoted: self.promoted, - }) + Ok(ty::Unevaluated { def: self.def, substs: self.substs.try_fold_with(folder)? }) } } @@ -859,15 +855,3 @@ impl<'tcx> TypeSuperVisitable<'tcx> for ty::Unevaluated<'tcx> { self.substs.visit_with(visitor) } } - -impl<'tcx> TypeFoldable<'tcx> for ty::Unevaluated<'tcx, ()> { - fn try_fold_with>(self, folder: &mut F) -> Result { - Ok(self.expand().try_fold_with(folder)?.shrink()) - } -} - -impl<'tcx> TypeVisitable<'tcx> for ty::Unevaluated<'tcx, ()> { - fn visit_with>(&self, visitor: &mut V) -> ControlFlow { - self.expand().visit_with(visitor) - } -} diff --git a/compiler/rustc_middle/src/ty/visit.rs b/compiler/rustc_middle/src/ty/visit.rs index 5f8cb57820210..7b913de83ac26 100644 --- a/compiler/rustc_middle/src/ty/visit.rs +++ b/compiler/rustc_middle/src/ty/visit.rs @@ -199,7 +199,11 @@ pub trait TypeVisitor<'tcx>: Sized { c.super_visit_with(self) } - fn visit_unevaluated(&mut self, uv: ty::Unevaluated<'tcx>) -> ControlFlow { + fn visit_ty_unevaluated(&mut self, uv: ty::Unevaluated<'tcx>) -> ControlFlow { + uv.super_visit_with(self) + } + + fn visit_mir_unevaluated(&mut self, uv: mir::Unevaluated<'tcx>) -> ControlFlow { uv.super_visit_with(self) } @@ -597,7 +601,7 @@ impl<'tcx> TypeVisitor<'tcx> for HasTypeFlagsVisitor { #[inline] #[instrument(level = "trace", ret)] - fn visit_unevaluated(&mut self, uv: ty::Unevaluated<'tcx>) -> ControlFlow { + fn visit_ty_unevaluated(&mut self, uv: ty::Unevaluated<'tcx>) -> ControlFlow { let flags = FlagComputation::for_unevaluated_const(uv); trace!(r.flags=?flags); if flags.intersects(self.flags) { @@ -607,6 +611,16 @@ impl<'tcx> TypeVisitor<'tcx> for HasTypeFlagsVisitor { } } + fn visit_mir_unevaluated(&mut self, uv: mir::Unevaluated<'tcx>) -> ControlFlow { + let flags = FlagComputation::for_unevaluated_const(uv.shrink()); + trace!(r.flags=?flags); + if flags.intersects(self.flags) { + ControlFlow::Break(FoundFlags) + } else { + ControlFlow::CONTINUE + } + } + #[inline] #[instrument(level = "trace", ret)] fn visit_predicate(&mut self, predicate: ty::Predicate<'tcx>) -> ControlFlow { diff --git a/compiler/rustc_mir_build/src/build/expr/as_constant.rs b/compiler/rustc_mir_build/src/build/expr/as_constant.rs index c9bec130cc8fe..00fbdb42435be 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_constant.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_constant.rs @@ -2,6 +2,7 @@ use crate::build::{parse_float_into_constval, Builder}; use rustc_ast as ast; +use rustc_middle::mir; use rustc_middle::mir::interpret::{ Allocation, ConstValue, LitToConstError, LitToConstInput, Scalar, }; @@ -66,7 +67,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { }) }); - let uneval = ty::Unevaluated::new(ty::WithOptConstParam::unknown(def_id), substs); + let uneval = mir::Unevaluated::new(ty::WithOptConstParam::unknown(def_id), substs); let literal = ConstantKind::Unevaluated(uneval, ty); Constant { user_ty, span, literal } @@ -79,7 +80,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { Constant { user_ty: None, span, literal } } ExprKind::ConstBlock { did: def_id, substs } => { - let uneval = ty::Unevaluated::new(ty::WithOptConstParam::unknown(def_id), substs); + let uneval = mir::Unevaluated::new(ty::WithOptConstParam::unknown(def_id), substs); let literal = ConstantKind::Unevaluated(uneval, ty); Constant { user_ty: None, span, literal } diff --git a/compiler/rustc_mir_transform/src/const_prop_lint.rs b/compiler/rustc_mir_transform/src/const_prop_lint.rs index 2885f06b19cd6..351c86b5d63d5 100644 --- a/compiler/rustc_mir_transform/src/const_prop_lint.rs +++ b/compiler/rustc_mir_transform/src/const_prop_lint.rs @@ -16,8 +16,8 @@ use rustc_index::bit_set::BitSet; use rustc_index::vec::IndexVec; use rustc_middle::mir::visit::Visitor; use rustc_middle::mir::{ - AssertKind, BinOp, Body, Constant, ConstantKind, Local, LocalDecl, Location, Operand, Place, - Rvalue, SourceInfo, SourceScope, SourceScopeData, Statement, StatementKind, Terminator, + self, AssertKind, BinOp, Body, Constant, ConstantKind, Local, LocalDecl, Location, Operand, + Place, Rvalue, SourceInfo, SourceScope, SourceScopeData, Statement, StatementKind, Terminator, TerminatorKind, UnOp, RETURN_PLACE, }; use rustc_middle::ty::layout::{LayoutError, LayoutOf, LayoutOfHelpers, TyAndLayout}; @@ -301,7 +301,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { let lint_only = match c.literal { ConstantKind::Ty(ct) => ct.needs_subst(), ConstantKind::Unevaluated( - ty::Unevaluated { def: _, substs: _, promoted: Some(_) }, + mir::Unevaluated { def: _, substs: _, promoted: Some(_) }, _, ) => { // Promoteds must lint and not error as the user didn't ask for them diff --git a/compiler/rustc_monomorphize/src/polymorphize.rs b/compiler/rustc_monomorphize/src/polymorphize.rs index 71cab023215ec..a054bc6746295 100644 --- a/compiler/rustc_monomorphize/src/polymorphize.rs +++ b/compiler/rustc_monomorphize/src/polymorphize.rs @@ -8,6 +8,7 @@ use rustc_hir::{def::DefKind, def_id::DefId, ConstContext}; use rustc_index::bit_set::FiniteBitSet; use rustc_middle::mir::{ + self, visit::{TyContext, Visitor}, Constant, ConstantKind, Local, LocalDecl, Location, }; @@ -299,11 +300,9 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> { self.unused_parameters.clear(param.index); ControlFlow::CONTINUE } - ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }) + ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs }) if matches!(self.tcx.def_kind(def.did), DefKind::AnonConst) => { - assert_eq!(promoted, ()); - self.visit_child_body(def.did, substs); ControlFlow::CONTINUE } @@ -318,7 +317,7 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> { match constant { ConstantKind::Ty(ct) => ct.visit_with(self), - ConstantKind::Unevaluated(ty::Unevaluated { def, substs: _, promoted: Some(p) }, _) + ConstantKind::Unevaluated(mir::Unevaluated { def, substs: _, promoted: Some(p) }, _) // Avoid considering `T` unused when constants are of the form: // `>::foo::promoted[p]` if self.def_id == def.did && !self.tcx.generics_of(def.did).has_self => diff --git a/compiler/rustc_query_impl/src/keys.rs b/compiler/rustc_query_impl/src/keys.rs index 31de83ee1418d..046b3f405e911 100644 --- a/compiler/rustc_query_impl/src/keys.rs +++ b/compiler/rustc_query_impl/src/keys.rs @@ -276,7 +276,7 @@ impl<'tcx> Key for (DefId, SubstsRef<'tcx>) { } } -impl<'tcx> Key for (ty::Unevaluated<'tcx, ()>, ty::Unevaluated<'tcx, ()>) { +impl<'tcx> Key for (ty::Unevaluated<'tcx>, ty::Unevaluated<'tcx>) { #[inline(always)] fn query_crate_is_local(&self) -> bool { (self.0).def.did.krate == LOCAL_CRATE diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs index bcdfa4f12d353..6ed4f1b8c4988 100644 --- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs +++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs @@ -834,7 +834,7 @@ impl<'tcx> AutoTraitFinder<'tcx> { let reported = tcx.sess.emit_err(UnableToConstructConstantValue { span: tcx.def_span(def_id), - unevaluated: unevaluated.expand(), + unevaluated: unevaluated, }); Err(ErrorHandled::Reported(reported)) } diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs index 5a213987e87b3..37a0278f0b15a 100644 --- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs +++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs @@ -138,7 +138,7 @@ impl<'tcx> ConstUnifyCtxt<'tcx> { #[instrument(skip(tcx), level = "debug")] pub fn try_unify_abstract_consts<'tcx>( tcx: TyCtxt<'tcx>, - (a, b): (ty::Unevaluated<'tcx, ()>, ty::Unevaluated<'tcx, ()>), + (a, b): (ty::Unevaluated<'tcx>, ty::Unevaluated<'tcx>), param_env: ty::ParamEnv<'tcx>, ) -> bool { (|| { @@ -161,7 +161,7 @@ pub fn try_unify_abstract_consts<'tcx>( #[instrument(skip(infcx), level = "debug")] pub fn is_const_evaluatable<'cx, 'tcx>( infcx: &InferCtxt<'cx, 'tcx>, - uv: ty::Unevaluated<'tcx, ()>, + uv: ty::Unevaluated<'tcx>, param_env: ty::ParamEnv<'tcx>, span: Span, ) -> Result<(), NotConstEvaluatable> { diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs index a54b725753c87..163c5f2c0899e 100644 --- a/compiler/rustc_trait_selection/src/traits/object_safety.rs +++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs @@ -838,7 +838,10 @@ fn contains_illegal_self_type_reference<'tcx, T: TypeVisitable<'tcx>>( } } - fn visit_unevaluated(&mut self, uv: ty::Unevaluated<'tcx>) -> ControlFlow { + fn visit_ty_unevaluated( + &mut self, + uv: ty::Unevaluated<'tcx>, + ) -> ControlFlow { // Constants can only influence object safety if they reference `Self`. // This is only possible for unevaluated constants, so we walk these here. // @@ -852,7 +855,7 @@ fn contains_illegal_self_type_reference<'tcx, T: TypeVisitable<'tcx>>( // This shouldn't really matter though as we can't really use any // constants which are not considered const evaluatable. use rustc_middle::ty::abstract_const::Node; - if let Ok(Some(ct)) = AbstractConst::new(self.tcx, uv.shrink()) { + if let Ok(Some(ct)) = AbstractConst::new(self.tcx, uv) { walk_abstract_const(self.tcx, ct, |node| match node.root(self.tcx) { Node::Leaf(leaf) => self.visit_const(leaf), Node::Cast(_, _, ty) => self.visit_ty(ty), diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index afc8a9600ad48..359a79e9979ed 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -2393,7 +2393,6 @@ fn const_evaluatable_predicates_of<'tcx>( let def_id = self.tcx.hir().local_def_id(c.hir_id); let ct = ty::Const::from_anon_const(self.tcx, def_id); if let ty::ConstKind::Unevaluated(uv) = ct.kind() { - assert_eq!(uv.promoted, ()); let span = self.tcx.hir().span(c.hir_id); self.preds.insert(( ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(uv)) diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index 3eaedaf10830a..af0b300e22b88 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -234,8 +234,7 @@ pub(crate) fn name_from_pat(p: &hir::Pat<'_>) -> Symbol { pub(crate) fn print_const(cx: &DocContext<'_>, n: ty::Const<'_>) -> String { match n.kind() { - ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs: _, promoted }) => { - assert_eq!(promoted, ()); + ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs: _ }) => { let s = if let Some(def) = def.as_local() { print_const_expr(cx.tcx, cx.tcx.hir().body_owned_by(def.did)) } else { diff --git a/src/tools/clippy/clippy_lints/src/non_copy_const.rs b/src/tools/clippy/clippy_lints/src/non_copy_const.rs index 72c86f28bbc6c..85024b0b05c8f 100644 --- a/src/tools/clippy/clippy_lints/src/non_copy_const.rs +++ b/src/tools/clippy/clippy_lints/src/non_copy_const.rs @@ -195,7 +195,7 @@ fn is_value_unfrozen_expr<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId, def_id: D let result = cx.tcx.const_eval_resolve( cx.param_env, - ty::Unevaluated::new(ty::WithOptConstParam::unknown(def_id), substs), + mir::Unevaluated::new(ty::WithOptConstParam::unknown(def_id), substs), None, ); is_value_unfrozen_raw(cx, result, ty) diff --git a/src/tools/clippy/clippy_utils/src/consts.rs b/src/tools/clippy/clippy_utils/src/consts.rs index 1b8a9c05559a9..ac5bac3714f0e 100644 --- a/src/tools/clippy/clippy_utils/src/consts.rs +++ b/src/tools/clippy/clippy_utils/src/consts.rs @@ -424,7 +424,7 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> { .tcx .const_eval_resolve( self.param_env, - ty::Unevaluated::new(ty::WithOptConstParam::unknown(def_id), substs), + mir::Unevaluated::new(ty::WithOptConstParam::unknown(def_id), substs), None, ) .ok() From db7df5941890a7f5482b137ddb8ff34e6aec613b Mon Sep 17 00:00:00 2001 From: b-naber Date: Tue, 20 Sep 2022 17:39:05 +0200 Subject: [PATCH 106/586] bless tests --- src/test/mir-opt/issue_99325.main.mir_map.0.mir | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/mir-opt/issue_99325.main.mir_map.0.mir b/src/test/mir-opt/issue_99325.main.mir_map.0.mir index 8659ddfdb00cc..8b1ffe1599b4d 100644 --- a/src/test/mir-opt/issue_99325.main.mir_map.0.mir +++ b/src/test/mir-opt/issue_99325.main.mir_map.0.mir @@ -2,7 +2,7 @@ | User Type Annotations | 0: user_ty: Canonical { max_universe: U0, variables: [], value: TypeOf(DefId(0:3 ~ issue_99325[8f58]::function_with_bytes), UserSubsts { substs: [Const { ty: &'static [u8; 4], kind: Value(Branch([Leaf(0x41), Leaf(0x41), Leaf(0x41), Leaf(0x41)])) }], user_self_ty: None }) }, span: $DIR/issue-99325.rs:10:16: 10:46, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">} -| 1: user_ty: Canonical { max_universe: U0, variables: [], value: TypeOf(DefId(0:3 ~ issue_99325[8f58]::function_with_bytes), UserSubsts { substs: [Const { ty: &'static [u8; 4], kind: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:8 ~ issue_99325[8f58]::main::{constant#1}), const_param_did: Some(DefId(0:4 ~ issue_99325[8f58]::function_with_bytes::BYTES)) }, substs: [], promoted: () }) }], user_self_ty: None }) }, span: $DIR/issue-99325.rs:11:16: 11:68, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">} +| 1: user_ty: Canonical { max_universe: U0, variables: [], value: TypeOf(DefId(0:3 ~ issue_99325[8f58]::function_with_bytes), UserSubsts { substs: [Const { ty: &'static [u8; 4], kind: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:8 ~ issue_99325[8f58]::main::{constant#1}), const_param_did: Some(DefId(0:4 ~ issue_99325[8f58]::function_with_bytes::BYTES)) }, substs: [] }) }], user_self_ty: None }) }, span: $DIR/issue-99325.rs:11:16: 11:68, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">} | fn main() -> () { let mut _0: (); // return place in scope 0 at $DIR/issue-99325.rs:+0:15: +0:15 From efb908991b2c2cd43c40c8e62f563fdd17d84204 Mon Sep 17 00:00:00 2001 From: b-naber Date: Wed, 21 Sep 2022 18:55:32 +0200 Subject: [PATCH 107/586] address review --- compiler/rustc_middle/src/mir/mod.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 4b3a3085b71e0..9ff57502a385e 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -2055,7 +2055,7 @@ pub enum ConstantKind<'tcx> { Ty(ty::Const<'tcx>), /// An unevaluated mir constant which is not part of the type system. - Unevaluated(Unevaluated<'tcx, Option>, Ty<'tcx>), + Unevaluated(Unevaluated<'tcx>, Ty<'tcx>), /// This constant cannot go back into the type system, as it represents /// something the type system cannot handle (e.g. pointers). @@ -2442,10 +2442,10 @@ impl<'tcx> ConstantKind<'tcx> { /// An unevaluated (potentially generic) constant used in MIR. #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable, Lift)] #[derive(Hash, HashStable)] -pub struct Unevaluated<'tcx, P = Option> { +pub struct Unevaluated<'tcx> { pub def: ty::WithOptConstParam, pub substs: SubstsRef<'tcx>, - pub promoted: P, + pub promoted: Option, } impl<'tcx> Unevaluated<'tcx> { @@ -2457,9 +2457,9 @@ impl<'tcx> Unevaluated<'tcx> { } } -impl<'tcx, P: Default> Unevaluated<'tcx, P> { +impl<'tcx> Unevaluated<'tcx> { #[inline] - pub fn new(def: ty::WithOptConstParam, substs: SubstsRef<'tcx>) -> Unevaluated<'tcx, P> { + pub fn new(def: ty::WithOptConstParam, substs: SubstsRef<'tcx>) -> Unevaluated<'tcx> { Unevaluated { def, substs, promoted: Default::default() } } } From d3f97a331c40f3f64b161aed29f7ef04e607764c Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 22 Sep 2022 13:08:44 +0200 Subject: [PATCH 108/586] Improve some AllTypes fields name --- src/librustdoc/html/render/mod.rs | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 7e5e4df43d291..621f83824d966 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -239,8 +239,8 @@ struct AllTypes { opaque_tys: FxHashSet, statics: FxHashSet, constants: FxHashSet, - attributes: FxHashSet, - derives: FxHashSet, + attribute_macros: FxHashSet, + derive_macros: FxHashSet, trait_aliases: FxHashSet, } @@ -259,8 +259,8 @@ impl AllTypes { opaque_tys: new_set(100), statics: new_set(100), constants: new_set(100), - attributes: new_set(100), - derives: new_set(100), + attribute_macros: new_set(100), + derive_macros: new_set(100), trait_aliases: new_set(100), } } @@ -283,8 +283,10 @@ impl AllTypes { ItemType::OpaqueTy => self.opaque_tys.insert(ItemEntry::new(new_url, name)), ItemType::Static => self.statics.insert(ItemEntry::new(new_url, name)), ItemType::Constant => self.constants.insert(ItemEntry::new(new_url, name)), - ItemType::ProcAttribute => self.attributes.insert(ItemEntry::new(new_url, name)), - ItemType::ProcDerive => self.derives.insert(ItemEntry::new(new_url, name)), + ItemType::ProcAttribute => { + self.attribute_macros.insert(ItemEntry::new(new_url, name)) + } + ItemType::ProcDerive => self.derive_macros.insert(ItemEntry::new(new_url, name)), ItemType::TraitAlias => self.trait_aliases.insert(ItemEntry::new(new_url, name)), _ => true, }; @@ -327,10 +329,10 @@ impl AllTypes { if !self.constants.is_empty() { sections.insert(ItemSection::Constants); } - if !self.attributes.is_empty() { + if !self.attribute_macros.is_empty() { sections.insert(ItemSection::AttributeMacros); } - if !self.derives.is_empty() { + if !self.derive_macros.is_empty() { sections.insert(ItemSection::DeriveMacros); } if !self.trait_aliases.is_empty() { @@ -373,8 +375,8 @@ impl AllTypes { print_entries(f, &self.primitives, ItemSection::PrimitiveTypes); print_entries(f, &self.traits, ItemSection::Traits); print_entries(f, &self.macros, ItemSection::Macros); - print_entries(f, &self.attributes, ItemSection::AttributeMacros); - print_entries(f, &self.derives, ItemSection::DeriveMacros); + print_entries(f, &self.attribute_macros, ItemSection::AttributeMacros); + print_entries(f, &self.derive_macros, ItemSection::DeriveMacros); print_entries(f, &self.functions, ItemSection::Functions); print_entries(f, &self.typedefs, ItemSection::TypeDefinitions); print_entries(f, &self.trait_aliases, ItemSection::TraitAliases); From e8594257f691a1e4e960f1dbb5dd92146fe9d978 Mon Sep 17 00:00:00 2001 From: b-naber Date: Thu, 22 Sep 2022 12:49:04 +0200 Subject: [PATCH 109/586] use valtrees for comparison --- compiler/rustc_middle/src/ty/fast_reject.rs | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/compiler/rustc_middle/src/ty/fast_reject.rs b/compiler/rustc_middle/src/ty/fast_reject.rs index 8d019a3bad8cc..41bb3c7140172 100644 --- a/compiler/rustc_middle/src/ty/fast_reject.rs +++ b/compiler/rustc_middle/src/ty/fast_reject.rs @@ -384,14 +384,7 @@ impl DeepRejectCtxt { // they might unify with any value. ty::ConstKind::Unevaluated(_) | ty::ConstKind::Error(_) => true, ty::ConstKind::Value(obl) => match k { - ty::ConstKind::Value(imp) => { - // FIXME(valtrees): Once we have valtrees, we can just - // compare them directly here. - match (obl.try_to_scalar_int(), imp.try_to_scalar_int()) { - (Some(obl), Some(imp)) => obl == imp, - _ => true, - } - } + ty::ConstKind::Value(imp) => obl == imp, _ => true, }, From 5be901abb74c456e13386ad3086e3f60e609e3ae Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Wed, 21 Sep 2022 19:26:24 +0300 Subject: [PATCH 110/586] effective visibility: Add test for a reexport of two names in different namespaces, one public and another private. --- src/test/ui/privacy/access_levels.rs | 15 ++++++++++- src/test/ui/privacy/access_levels.stderr | 32 +++++++++++++++++++++++- 2 files changed, 45 insertions(+), 2 deletions(-) diff --git a/src/test/ui/privacy/access_levels.rs b/src/test/ui/privacy/access_levels.rs index aa718ab9254df..f22ef74610e87 100644 --- a/src/test/ui/privacy/access_levels.rs +++ b/src/test/ui/privacy/access_levels.rs @@ -55,8 +55,21 @@ mod outer { //~ ERROR Public: pub(self), Exported: pub(self), Reachable: pub(sel } } -pub use outer::inner1; +#[rustc_effective_visibility] +pub use outer::inner1; //~ ERROR Public: pub, Exported: pub, Reachable: pub, ReachableFromImplTrait: pub pub fn foo() -> outer::ReachableStruct { outer::ReachableStruct {a: 0} } +mod half_public_import { + #[rustc_effective_visibility] + pub type HalfPublicImport = u8; //~ ERROR Public: pub(self), Exported: pub, Reachable: pub, ReachableFromImplTrait: pub + #[rustc_effective_visibility] + #[allow(non_upper_case_globals)] + pub(crate) const HalfPublicImport: u8 = 0; //~ ERROR Public: pub(self), Exported: pub(self), Reachable: pub(self), ReachableFromImplTrait: pub(self) +} + +#[rustc_effective_visibility] +pub use half_public_import::HalfPublicImport; //~ ERROR Public: pub, Exported: pub, Reachable: pub, ReachableFromImplTrait: pub + //~^ ERROR Public: pub, Exported: pub, Reachable: pub, ReachableFromImplTrait: pub + fn main() {} diff --git a/src/test/ui/privacy/access_levels.stderr b/src/test/ui/privacy/access_levels.stderr index 2ed6c330a2f97..30e152e9b2e3b 100644 --- a/src/test/ui/privacy/access_levels.stderr +++ b/src/test/ui/privacy/access_levels.stderr @@ -88,6 +88,36 @@ error: Public: pub(self), Exported: pub(self), Reachable: pub, ReachableFromImpl LL | pub a: u8, | ^^^^^^^^^ +error: Public: pub, Exported: pub, Reachable: pub, ReachableFromImplTrait: pub + --> $DIR/access_levels.rs:59:9 + | +LL | pub use outer::inner1; + | ^^^^^^^^^^^^^ + +error: Public: pub(self), Exported: pub, Reachable: pub, ReachableFromImplTrait: pub + --> $DIR/access_levels.rs:65:5 + | +LL | pub type HalfPublicImport = u8; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: Public: pub(self), Exported: pub(self), Reachable: pub(self), ReachableFromImplTrait: pub(self) + --> $DIR/access_levels.rs:68:5 + | +LL | pub(crate) const HalfPublicImport: u8 = 0; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: Public: pub, Exported: pub, Reachable: pub, ReachableFromImplTrait: pub + --> $DIR/access_levels.rs:72:9 + | +LL | pub use half_public_import::HalfPublicImport; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: Public: pub, Exported: pub, Reachable: pub, ReachableFromImplTrait: pub + --> $DIR/access_levels.rs:72:9 + | +LL | pub use half_public_import::HalfPublicImport; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + error: Public: pub(self), Exported: pub, Reachable: pub, ReachableFromImplTrait: pub --> $DIR/access_levels.rs:14:13 | @@ -100,5 +130,5 @@ error: Public: pub(self), Exported: pub, Reachable: pub, ReachableFromImplTrait: LL | type B; | ^^^^^^ -error: aborting due to 17 previous errors +error: aborting due to 22 previous errors From 4ddff03917daea2ff42a5b5a42d38bbeaa051680 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Thu, 22 Sep 2022 14:55:22 +0300 Subject: [PATCH 111/586] resolve: Set effective visibilities for imports more precisely Instead of setting them for all primary and additional IDs of the import, only set them for the binding's true ID. --- compiler/rustc_resolve/src/access_levels.rs | 13 +++------- compiler/rustc_resolve/src/imports.rs | 27 ++++++++++++++++++++- src/test/ui/privacy/access_levels.rs | 2 +- src/test/ui/privacy/access_levels.stderr | 2 +- 4 files changed, 32 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_resolve/src/access_levels.rs b/compiler/rustc_resolve/src/access_levels.rs index 9b1111c02c73f..d806441716fda 100644 --- a/compiler/rustc_resolve/src/access_levels.rs +++ b/compiler/rustc_resolve/src/access_levels.rs @@ -1,4 +1,3 @@ -use crate::imports::ImportKind; use crate::NameBinding; use crate::NameBindingKind; use crate::Resolver; @@ -54,15 +53,11 @@ impl<'r, 'a> AccessLevelsVisitor<'r, 'a> { // sets the rest of the `use` chain to `AccessLevel::Exported` until // we hit the actual exported item. let set_import_binding_access_level = - |this: &mut Self, mut binding: &NameBinding<'a>, mut access_level| { + |this: &mut Self, mut binding: &NameBinding<'a>, mut access_level, ns| { while let NameBindingKind::Import { binding: nested_binding, import, .. } = binding.kind { - this.set_access_level(import.id, access_level); - if let ImportKind::Single { additional_ids, .. } = import.kind { - this.set_access_level(additional_ids.0, access_level); - this.set_access_level(additional_ids.1, access_level); - } + this.set_access_level(this.r.import_id_for_ns(import, ns), access_level); access_level = Some(AccessLevel::Exported); binding = nested_binding; @@ -72,11 +67,11 @@ impl<'r, 'a> AccessLevelsVisitor<'r, 'a> { let module = self.r.get_module(module_id.to_def_id()).unwrap(); let resolutions = self.r.resolutions(module); - for (.., name_resolution) in resolutions.borrow().iter() { + for (key, name_resolution) in resolutions.borrow().iter() { if let Some(binding) = name_resolution.borrow().binding() && binding.vis.is_public() && !binding.is_ambiguity() { let access_level = match binding.is_import() { true => { - set_import_binding_access_level(self, binding, module_level); + set_import_binding_access_level(self, binding, module_level, key.ns); Some(AccessLevel::Exported) }, false => module_level, diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index c133c272bac27..5bdb427478199 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -2,7 +2,7 @@ use crate::diagnostics::Suggestion; use crate::Determinacy::{self, *}; -use crate::Namespace::{MacroNS, TypeNS}; +use crate::Namespace::{self, *}; use crate::{module_to_string, names_to_string}; use crate::{AmbiguityKind, BindingKey, ModuleKind, ResolutionError, Resolver, Segment}; use crate::{Finalize, Module, ModuleOrUniformRoot, ParentScope, PerNS, ScopeSet}; @@ -371,6 +371,31 @@ impl<'a> Resolver<'a> { self.used_imports.insert(import.id); } } + + /// Take primary and additional node IDs from an import and select one that corresponds to the + /// given namespace. The logic must match the corresponding logic from `fn lower_use_tree` that + /// assigns resolutons to IDs. + pub(crate) fn import_id_for_ns(&self, import: &Import<'_>, ns: Namespace) -> NodeId { + if let ImportKind::Single { additional_ids: (id1, id2), .. } = import.kind { + if let Some(resolutions) = self.import_res_map.get(&import.id) { + assert!(resolutions[ns].is_some(), "incorrectly finalized import"); + return match ns { + TypeNS => import.id, + ValueNS => match resolutions.type_ns { + Some(_) => id1, + None => import.id, + }, + MacroNS => match (resolutions.type_ns, resolutions.value_ns) { + (Some(_), Some(_)) => id2, + (Some(_), None) | (None, Some(_)) => id1, + (None, None) => import.id, + }, + }; + } + } + + import.id + } } /// An error that may be transformed into a diagnostic later. Used to combine multiple unresolved diff --git a/src/test/ui/privacy/access_levels.rs b/src/test/ui/privacy/access_levels.rs index f22ef74610e87..bf94d980678f5 100644 --- a/src/test/ui/privacy/access_levels.rs +++ b/src/test/ui/privacy/access_levels.rs @@ -70,6 +70,6 @@ mod half_public_import { #[rustc_effective_visibility] pub use half_public_import::HalfPublicImport; //~ ERROR Public: pub, Exported: pub, Reachable: pub, ReachableFromImplTrait: pub - //~^ ERROR Public: pub, Exported: pub, Reachable: pub, ReachableFromImplTrait: pub + //~^ ERROR Public: pub(self), Exported: pub(self), Reachable: pub(self), ReachableFromImplTrait: pub(self) fn main() {} diff --git a/src/test/ui/privacy/access_levels.stderr b/src/test/ui/privacy/access_levels.stderr index 30e152e9b2e3b..81514d1fbab45 100644 --- a/src/test/ui/privacy/access_levels.stderr +++ b/src/test/ui/privacy/access_levels.stderr @@ -112,7 +112,7 @@ error: Public: pub, Exported: pub, Reachable: pub, ReachableFromImplTrait: pub LL | pub use half_public_import::HalfPublicImport; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: Public: pub, Exported: pub, Reachable: pub, ReachableFromImplTrait: pub +error: Public: pub(self), Exported: pub(self), Reachable: pub(self), ReachableFromImplTrait: pub(self) --> $DIR/access_levels.rs:72:9 | LL | pub use half_public_import::HalfPublicImport; From a9e657dbfccd2fb0dbbd53ddc29fcfc000377561 Mon Sep 17 00:00:00 2001 From: b-naber Date: Thu, 22 Sep 2022 14:22:51 +0200 Subject: [PATCH 112/586] don't convert valtree to constvalue during normalization --- .../src/traits/query/normalize.rs | 20 +------------------ 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs index 88000d469786e..a3ac24f27d155 100644 --- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs @@ -351,25 +351,7 @@ impl<'cx, 'tcx> FallibleTypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> { &mut self, constant: mir::ConstantKind<'tcx>, ) -> Result, Self::Error> { - Ok(match constant { - mir::ConstantKind::Ty(c) => { - let const_folded = c.try_super_fold_with(self)?; - match const_folded.kind() { - ty::ConstKind::Value(valtree) => { - let tcx = self.infcx.tcx; - let ty = const_folded.ty(); - let const_val = tcx.valtree_to_const_val((ty, valtree)); - debug!(?ty, ?valtree, ?const_val); - - mir::ConstantKind::Val(const_val, ty) - } - _ => mir::ConstantKind::Ty(const_folded), - } - } - mir::ConstantKind::Val(_, _) | mir::ConstantKind::Unevaluated(..) => { - constant.try_super_fold_with(self)? - } - }) + constant.try_super_fold_with(self) } #[inline] From 98a32305afabb8e31d898e2a74da63268e0a7f5f Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Thu, 22 Sep 2022 17:44:06 +0400 Subject: [PATCH 113/586] Apply changes proposed in the review --- library/core/src/fmt/num.rs | 66 ++++++++++++++++++------------------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/library/core/src/fmt/num.rs b/library/core/src/fmt/num.rs index b11ed6b0b42ab..d8365ae9bf920 100644 --- a/library/core/src/fmt/num.rs +++ b/library/core/src/fmt/num.rs @@ -345,7 +345,7 @@ macro_rules! impl_Exp { // decode 2 chars at a time while n >= 100 { - let d1 = ((n % 100) << 1) as usize; + let d1 = ((n % 100) as usize) << 1; curr -= 2; // SAFETY: `d1 <= 198`, so we can copy from `lut_ptr[d1..d1 + 2]` since // `DEC_DIGITS_LUT` has a length of 200. @@ -494,41 +494,41 @@ fn parse_u64_into(mut n: u64, buf: &mut [MaybeUninit; N], cu n /= 1e16 as u64; // Some of these are nops but it looks more elegant this way. - let d1 = (((to_parse / 1e14 as u64) % 100) << 1) as usize; - let d2 = (((to_parse / 1e12 as u64) % 100) << 1) as usize; - let d3 = (((to_parse / 1e10 as u64) % 100) << 1) as usize; - let d4 = (((to_parse / 1e8 as u64) % 100) << 1) as usize; - let d5 = (((to_parse / 1e6 as u64) % 100) << 1) as usize; - let d6 = (((to_parse / 1e4 as u64) % 100) << 1) as usize; - let d7 = (((to_parse / 1e2 as u64) % 100) << 1) as usize; - let d8 = (((to_parse / 1e0 as u64) % 100) << 1) as usize; + let d1 = ((to_parse / 1e14 as u64) % 100) << 1; + let d2 = ((to_parse / 1e12 as u64) % 100) << 1; + let d3 = ((to_parse / 1e10 as u64) % 100) << 1; + let d4 = ((to_parse / 1e8 as u64) % 100) << 1; + let d5 = ((to_parse / 1e6 as u64) % 100) << 1; + let d6 = ((to_parse / 1e4 as u64) % 100) << 1; + let d7 = ((to_parse / 1e2 as u64) % 100) << 1; + let d8 = ((to_parse / 1e0 as u64) % 100) << 1; *curr -= 16; - ptr::copy_nonoverlapping(lut_ptr.add(d1), buf_ptr.add(*curr + 0), 2); - ptr::copy_nonoverlapping(lut_ptr.add(d2), buf_ptr.add(*curr + 2), 2); - ptr::copy_nonoverlapping(lut_ptr.add(d3), buf_ptr.add(*curr + 4), 2); - ptr::copy_nonoverlapping(lut_ptr.add(d4), buf_ptr.add(*curr + 6), 2); - ptr::copy_nonoverlapping(lut_ptr.add(d5), buf_ptr.add(*curr + 8), 2); - ptr::copy_nonoverlapping(lut_ptr.add(d6), buf_ptr.add(*curr + 10), 2); - ptr::copy_nonoverlapping(lut_ptr.add(d7), buf_ptr.add(*curr + 12), 2); - ptr::copy_nonoverlapping(lut_ptr.add(d8), buf_ptr.add(*curr + 14), 2); + ptr::copy_nonoverlapping(lut_ptr.add(d1 as usize), buf_ptr.add(*curr + 0), 2); + ptr::copy_nonoverlapping(lut_ptr.add(d2 as usize), buf_ptr.add(*curr + 2), 2); + ptr::copy_nonoverlapping(lut_ptr.add(d3 as usize), buf_ptr.add(*curr + 4), 2); + ptr::copy_nonoverlapping(lut_ptr.add(d4 as usize), buf_ptr.add(*curr + 6), 2); + ptr::copy_nonoverlapping(lut_ptr.add(d5 as usize), buf_ptr.add(*curr + 8), 2); + ptr::copy_nonoverlapping(lut_ptr.add(d6 as usize), buf_ptr.add(*curr + 10), 2); + ptr::copy_nonoverlapping(lut_ptr.add(d7 as usize), buf_ptr.add(*curr + 12), 2); + ptr::copy_nonoverlapping(lut_ptr.add(d8 as usize), buf_ptr.add(*curr + 14), 2); } if n >= 1e8 as u64 { let to_parse = n % 1e8 as u64; n /= 1e8 as u64; // Some of these are nops but it looks more elegant this way. - let d1 = (((to_parse / 1e6 as u64) % 100) << 1) as usize; - let d2 = (((to_parse / 1e4 as u64) % 100) << 1) as usize; - let d3 = (((to_parse / 1e2 as u64) % 100) << 1) as usize; - let d4 = (((to_parse / 1e0 as u64) % 100) << 1) as usize; + let d1 = ((to_parse / 1e6 as u64) % 100) << 1; + let d2 = ((to_parse / 1e4 as u64) % 100) << 1; + let d3 = ((to_parse / 1e2 as u64) % 100) << 1; + let d4 = ((to_parse / 1e0 as u64) % 100) << 1; *curr -= 8; - ptr::copy_nonoverlapping(lut_ptr.add(d1), buf_ptr.add(*curr + 0), 2); - ptr::copy_nonoverlapping(lut_ptr.add(d2), buf_ptr.add(*curr + 2), 2); - ptr::copy_nonoverlapping(lut_ptr.add(d3), buf_ptr.add(*curr + 4), 2); - ptr::copy_nonoverlapping(lut_ptr.add(d4), buf_ptr.add(*curr + 6), 2); + ptr::copy_nonoverlapping(lut_ptr.add(d1 as usize), buf_ptr.add(*curr + 0), 2); + ptr::copy_nonoverlapping(lut_ptr.add(d2 as usize), buf_ptr.add(*curr + 2), 2); + ptr::copy_nonoverlapping(lut_ptr.add(d3 as usize), buf_ptr.add(*curr + 4), 2); + ptr::copy_nonoverlapping(lut_ptr.add(d4 as usize), buf_ptr.add(*curr + 6), 2); } // `n` < 1e8 < (1 << 32) let mut n = n as u32; @@ -536,21 +536,21 @@ fn parse_u64_into(mut n: u64, buf: &mut [MaybeUninit; N], cu let to_parse = n % 1e4 as u32; n /= 1e4 as u32; - let d1 = ((to_parse / 100) << 1) as usize; - let d2 = ((to_parse % 100) << 1) as usize; + let d1 = (to_parse / 100) << 1; + let d2 = (to_parse % 100) << 1; *curr -= 4; - ptr::copy_nonoverlapping(lut_ptr.add(d1), buf_ptr.add(*curr + 0), 2); - ptr::copy_nonoverlapping(lut_ptr.add(d2), buf_ptr.add(*curr + 2), 2); + ptr::copy_nonoverlapping(lut_ptr.add(d1 as usize), buf_ptr.add(*curr + 0), 2); + ptr::copy_nonoverlapping(lut_ptr.add(d2 as usize), buf_ptr.add(*curr + 2), 2); } // `n` < 1e4 < (1 << 16) let mut n = n as u16; if n >= 100 { - let d1 = ((n % 100) << 1) as usize; + let d1 = (n % 100) << 1; n /= 100; *curr -= 2; - ptr::copy_nonoverlapping(lut_ptr.add(d1), buf_ptr.add(*curr), 2); + ptr::copy_nonoverlapping(lut_ptr.add(d1 as usize), buf_ptr.add(*curr), 2); } // decode last 1 or 2 chars @@ -558,9 +558,9 @@ fn parse_u64_into(mut n: u64, buf: &mut [MaybeUninit; N], cu *curr -= 1; *buf_ptr.add(*curr) = (n as u8) + b'0'; } else { - let d1 = (n << 1) as usize; + let d1 = n << 1; *curr -= 2; - ptr::copy_nonoverlapping(lut_ptr.add(d1), buf_ptr.add(*curr), 2); + ptr::copy_nonoverlapping(lut_ptr.add(d1 as usize), buf_ptr.add(*curr), 2); } } } From adcc55d622e92b6067deb76c6c1159802ed96fae Mon Sep 17 00:00:00 2001 From: Xiretza Date: Sat, 10 Sep 2022 14:27:42 +0200 Subject: [PATCH 114/586] Cleanups in SessionDiagnostic derive --- .../src/diagnostics/diagnostic_builder.rs | 20 +++++++++---------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs index 32d6ba62a0d3e..2bff12b0059d7 100644 --- a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs +++ b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs @@ -155,7 +155,7 @@ impl DiagnosticDeriveBuilder { } else { Ident::new(name, attr.span()) }; - return Ok(quote! { #diag.#fn_name(rustc_errors::fluent::_subdiag::#fn_name); }); + return Ok(self.add_subdiagnostic(&fn_name, parse_quote! { _subdiag::#fn_name })); } _ => throw_invalid_attr!(attr, &meta), }; @@ -449,20 +449,18 @@ impl DiagnosticDeriveBuilder { let (span_field, mut applicability) = self.span_and_applicability_of_ty(info)?; - let mut msg = None; let mut code = None; let mut nested_iter = nested.into_iter().peekable(); - if let Some(nested_attr) = nested_iter.peek() { - if let NestedMeta::Meta(Meta::Path(path)) = nested_attr { - msg = Some(path.clone()); - } + let msg = if let Some(NestedMeta::Meta(Meta::Path(path))) = nested_iter.peek() { + let path = path.clone(); + // Move the iterator forward if a path was found (don't otherwise so that + // code/applicability can be found or an error emitted). + nested_iter.next(); + Some(path) + } else { + None }; - // Move the iterator forward if a path was found (don't otherwise so that - // code/applicability can be found or an error emitted). - if msg.is_some() { - let _ = nested_iter.next(); - } for nested_attr in nested_iter { let meta = match nested_attr { From 2e72387fd03082cd067a4a56acf4b231b543c7fd Mon Sep 17 00:00:00 2001 From: Xiretza Date: Sat, 10 Sep 2022 14:28:12 +0200 Subject: [PATCH 115/586] Ensure code= in #[suggestion(...)] is only set once --- .../src/diagnostics/diagnostic_builder.rs | 4 ++-- .../session-diagnostic/diagnostic-derive.rs | 8 ++++++++ .../session-diagnostic/diagnostic-derive.stderr | 14 +++++++++++++- 3 files changed, 23 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs index 2bff12b0059d7..11459e181907a 100644 --- a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs +++ b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs @@ -476,7 +476,7 @@ impl DiagnosticDeriveBuilder { match nested_name { "code" => { let formatted_str = self.build_format(&s.value(), s.span()); - code = Some(formatted_str); + code.set_once((formatted_str, span)); } "applicability" => { applicability = match applicability { @@ -524,7 +524,7 @@ impl DiagnosticDeriveBuilder { let msg = msg.unwrap_or_else(|| parse_quote! { _subdiag::suggestion }); let msg = quote! { rustc_errors::fluent::#msg }; - let code = code.unwrap_or_else(|| quote! { String::new() }); + let code = code.value().unwrap_or_else(|| quote! { String::new() }); Ok(quote! { #diag.#method(#span_field, #msg, #code, #applicability); }) } diff --git a/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs b/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs index 80ea908288103..a113f2a034ae9 100644 --- a/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs +++ b/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs @@ -581,3 +581,11 @@ struct LintAttributeOnSessionDiag {} //~| ERROR diagnostic slug not specified //~| ERROR cannot find attribute `lint` in this scope struct LintAttributeOnLintDiag {} + +#[derive(Diagnostic)] +#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")] +struct DuplicatedSuggestionCode { + #[suggestion(typeck::suggestion, code = "...", code = ",,,")] + //~^ ERROR specified multiple times + suggestion: Span, +} diff --git a/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr b/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr index c3972beb51282..aa768e28334fa 100644 --- a/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr +++ b/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr @@ -403,6 +403,18 @@ LL | | struct LintAttributeOnLintDiag {} | = help: specify the slug as the first argument to the attribute, such as `#[diag(typeck::example_error)]` +error: specified multiple times + --> $DIR/diagnostic-derive.rs:588:52 + | +LL | #[suggestion(typeck::suggestion, code = "...", code = ",,,")] + | ^^^^^^^^^^^^ + | +note: previously specified here + --> $DIR/diagnostic-derive.rs:588:38 + | +LL | #[suggestion(typeck::suggestion, code = "...", code = ",,,")] + | ^^^^^^^^^^^^ + error: cannot find attribute `nonsense` in this scope --> $DIR/diagnostic-derive.rs:53:3 | @@ -459,7 +471,7 @@ LL | arg: impl IntoDiagnosticArg, | ^^^^^^^^^^^^^^^^^ required by this bound in `DiagnosticBuilder::<'a, G>::set_arg` = note: this error originates in the derive macro `Diagnostic` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 55 previous errors +error: aborting due to 56 previous errors Some errors have detailed explanations: E0277, E0425. For more information about an error, try `rustc --explain E0277`. From ec85a1b2634edae81c77f5ea5d1d422215ecc457 Mon Sep 17 00:00:00 2001 From: Xiretza Date: Sat, 10 Sep 2022 14:43:07 +0200 Subject: [PATCH 116/586] Ensure #[suggestion] is only applied to correct tuple types --- .../src/diagnostics/diagnostic_builder.rs | 57 ++++++++----------- .../session-diagnostic/diagnostic-derive.rs | 20 ++++++- .../diagnostic-derive.stderr | 50 +++++++++++----- 3 files changed, 79 insertions(+), 48 deletions(-) diff --git a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs index 11459e181907a..6dd2161e0f95b 100644 --- a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs +++ b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs @@ -571,46 +571,37 @@ impl DiagnosticDeriveBuilder { let mut span_idx = None; let mut applicability_idx = None; + fn type_err(span: &Span) -> Result { + span_err(span.unwrap(), "wrong types for suggestion") + .help( + "`#[suggestion(...)]` on a tuple field must be applied to fields \ + of type `(Span, Applicability)`", + ) + .emit(); + Err(DiagnosticDeriveError::ErrorHandled) + } + for (idx, elem) in tup.elems.iter().enumerate() { if type_matches_path(elem, &["rustc_span", "Span"]) { - if span_idx.is_none() { - span_idx = Some(syn::Index::from(idx)); - } else { - throw_span_err!( - info.span.unwrap(), - "type of field annotated with `#[suggestion(...)]` contains more \ - than one `Span`" - ); - } + span_idx.set_once((syn::Index::from(idx), elem.span().unwrap())); } else if type_matches_path(elem, &["rustc_errors", "Applicability"]) { - if applicability_idx.is_none() { - applicability_idx = Some(syn::Index::from(idx)); - } else { - throw_span_err!( - info.span.unwrap(), - "type of field annotated with `#[suggestion(...)]` contains more \ - than one Applicability" - ); - } + applicability_idx.set_once((syn::Index::from(idx), elem.span().unwrap())); + } else { + type_err(&elem.span())?; } } - if let Some(span_idx) = span_idx { - let binding = &info.binding.binding; - let span = quote!(#binding.#span_idx); - let applicability = applicability_idx - .map(|applicability_idx| quote!(#binding.#applicability_idx)) - .unwrap_or_else(|| quote!(rustc_errors::Applicability::Unspecified)); - - return Ok((span, Some(applicability))); - } + let Some((span_idx, _)) = span_idx else { + type_err(&tup.span())?; + }; + let Some((applicability_idx, _applicability_span)) = applicability_idx else { + type_err(&tup.span())?; + }; + let binding = &info.binding.binding; + let span = quote!(#binding.#span_idx); + let applicability = quote!(#binding.#applicability_idx); - throw_span_err!(info.span.unwrap(), "wrong types for suggestion", |diag| { - diag.help( - "`#[suggestion(...)]` on a tuple field must be applied to fields of type \ - `(Span, Applicability)`", - ) - }); + Ok((span, Some(applicability))) } // If `ty` isn't a `Span` or `(Span, Applicability)` then emit an error. _ => throw_span_err!(info.span.unwrap(), "wrong field type for suggestion", |diag| { diff --git a/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs b/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs index a113f2a034ae9..c774484d8bfb4 100644 --- a/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs +++ b/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs @@ -269,16 +269,16 @@ struct SuggestWithSpanOnly { #[diag(typeck::ambiguous_lifetime_bound, code = "E0123")] struct SuggestWithDuplicateSpanAndApplicability { #[suggestion(typeck::suggestion, code = "This is suggested code")] - //~^ ERROR type of field annotated with `#[suggestion(...)]` contains more than one `Span` suggestion: (Span, Span, Applicability), + //~^ ERROR specified multiple times } #[derive(Diagnostic)] #[diag(typeck::ambiguous_lifetime_bound, code = "E0123")] struct SuggestWithDuplicateApplicabilityAndSpan { #[suggestion(typeck::suggestion, code = "This is suggested code")] - //~^ ERROR type of field annotated with `#[suggestion(...)]` contains more than one suggestion: (Applicability, Applicability, Span), + //~^ ERROR specified multiple times } #[derive(Diagnostic)] @@ -589,3 +589,19 @@ struct DuplicatedSuggestionCode { //~^ ERROR specified multiple times suggestion: Span, } + +#[derive(Diagnostic)] +#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")] +struct InvalidTypeInSuggestionTuple { + #[suggestion(typeck::suggestion, code = "...")] + suggestion: (Span, usize), + //~^ ERROR wrong types for suggestion +} + +#[derive(Diagnostic)] +#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")] +struct MissingApplicabilityInSuggestionTuple { + #[suggestion(typeck::suggestion, code = "...")] + suggestion: (Span,), + //~^ ERROR wrong types for suggestion +} diff --git a/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr b/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr index aa768e28334fa..084a021ac208a 100644 --- a/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr +++ b/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr @@ -263,21 +263,29 @@ LL | | suggestion: Applicability, | = help: `#[suggestion(...)]` should be applied to fields of type `Span` or `(Span, Applicability)` -error: type of field annotated with `#[suggestion(...)]` contains more than one `Span` - --> $DIR/diagnostic-derive.rs:271:5 +error: specified multiple times + --> $DIR/diagnostic-derive.rs:272:24 | -LL | / #[suggestion(typeck::suggestion, code = "This is suggested code")] -LL | | -LL | | suggestion: (Span, Span, Applicability), - | |___________________________________________^ +LL | suggestion: (Span, Span, Applicability), + | ^^^^ + | +note: previously specified here + --> $DIR/diagnostic-derive.rs:272:18 + | +LL | suggestion: (Span, Span, Applicability), + | ^^^^ -error: type of field annotated with `#[suggestion(...)]` contains more than one Applicability - --> $DIR/diagnostic-derive.rs:279:5 +error: specified multiple times + --> $DIR/diagnostic-derive.rs:280:33 | -LL | / #[suggestion(typeck::suggestion, code = "This is suggested code")] -LL | | -LL | | suggestion: (Applicability, Applicability, Span), - | |____________________________________________________^ +LL | suggestion: (Applicability, Applicability, Span), + | ^^^^^^^^^^^^^ + | +note: previously specified here + --> $DIR/diagnostic-derive.rs:280:18 + | +LL | suggestion: (Applicability, Applicability, Span), + | ^^^^^^^^^^^^^ error: `#[label = ...]` is not a valid attribute --> $DIR/diagnostic-derive.rs:287:5 @@ -415,6 +423,22 @@ note: previously specified here LL | #[suggestion(typeck::suggestion, code = "...", code = ",,,")] | ^^^^^^^^^^^^ +error: wrong types for suggestion + --> $DIR/diagnostic-derive.rs:597:24 + | +LL | suggestion: (Span, usize), + | ^^^^^ + | + = help: `#[suggestion(...)]` on a tuple field must be applied to fields of type `(Span, Applicability)` + +error: wrong types for suggestion + --> $DIR/diagnostic-derive.rs:605:17 + | +LL | suggestion: (Span,), + | ^^^^^^^ + | + = help: `#[suggestion(...)]` on a tuple field must be applied to fields of type `(Span, Applicability)` + error: cannot find attribute `nonsense` in this scope --> $DIR/diagnostic-derive.rs:53:3 | @@ -471,7 +495,7 @@ LL | arg: impl IntoDiagnosticArg, | ^^^^^^^^^^^^^^^^^ required by this bound in `DiagnosticBuilder::<'a, G>::set_arg` = note: this error originates in the derive macro `Diagnostic` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 56 previous errors +error: aborting due to 58 previous errors Some errors have detailed explanations: E0277, E0425. For more information about an error, try `rustc --explain E0277`. From efb20bc85547b48c2de0950fbca1dd5b2ed2a564 Mon Sep 17 00:00:00 2001 From: Xiretza Date: Sat, 10 Sep 2022 14:48:01 +0200 Subject: [PATCH 117/586] Point to previous applicability when declared multiple times --- .../src/diagnostics/diagnostic_builder.rs | 35 ++++++------------- .../session-diagnostic/diagnostic-derive.rs | 2 +- .../diagnostic-derive.stderr | 8 ++++- 3 files changed, 19 insertions(+), 26 deletions(-) diff --git a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs index 6dd2161e0f95b..1e1bfbb943ecf 100644 --- a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs +++ b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs @@ -478,26 +478,12 @@ impl DiagnosticDeriveBuilder { let formatted_str = self.build_format(&s.value(), s.span()); code.set_once((formatted_str, span)); } - "applicability" => { - applicability = match applicability { - Some(v) => { - span_err( - span, - "applicability cannot be set in both the field and \ - attribute", - ) - .emit(); - Some(v) - } - None => match Applicability::from_str(&s.value()) { - Ok(v) => Some(quote! { #v }), - Err(()) => { - span_err(span, "invalid applicability").emit(); - None - } - }, + "applicability" => match Applicability::from_str(&s.value()) { + Ok(v) => applicability.set_once((quote! { #v }, span)), + Err(()) => { + span_err(span, "invalid applicability").emit(); } - } + }, _ => throw_invalid_nested_attr!(attr, &nested_attr, |diag| { diag.help( "only `message`, `code` and `applicability` are valid field \ @@ -516,8 +502,9 @@ impl DiagnosticDeriveBuilder { } } - let applicability = - applicability.unwrap_or_else(|| quote!(rustc_errors::Applicability::Unspecified)); + let applicability = applicability + .value() + .unwrap_or_else(|| quote!(rustc_errors::Applicability::Unspecified)); let name = path.segments.last().unwrap().ident.to_string(); let method = format_ident!("span_{}", name); @@ -559,7 +546,7 @@ impl DiagnosticDeriveBuilder { fn span_and_applicability_of_ty( &self, info: FieldInfo<'_>, - ) -> Result<(TokenStream, Option), DiagnosticDeriveError> { + ) -> Result<(TokenStream, Option<(TokenStream, proc_macro::Span)>), DiagnosticDeriveError> { match &info.ty { // If `ty` is `Span` w/out applicability, then use `Applicability::Unspecified`. ty @ Type::Path(..) if type_matches_path(ty, &["rustc_span", "Span"]) => { @@ -594,14 +581,14 @@ impl DiagnosticDeriveBuilder { let Some((span_idx, _)) = span_idx else { type_err(&tup.span())?; }; - let Some((applicability_idx, _applicability_span)) = applicability_idx else { + let Some((applicability_idx, applicability_span)) = applicability_idx else { type_err(&tup.span())?; }; let binding = &info.binding.binding; let span = quote!(#binding.#span_idx); let applicability = quote!(#binding.#applicability_idx); - Ok((span, Some(applicability))) + Ok((span, Some((applicability, applicability_span)))) } // If `ty` isn't a `Span` or `(Span, Applicability)` then emit an error. _ => throw_span_err!(info.span.unwrap(), "wrong field type for suggestion", |diag| { diff --git a/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs b/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs index c774484d8bfb4..c3d3c23fe5bad 100644 --- a/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs +++ b/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs @@ -436,7 +436,7 @@ struct ErrorWithNoteCustomWrongOrder { #[diag(typeck::ambiguous_lifetime_bound, code = "E0123")] struct ApplicabilityInBoth { #[suggestion(typeck::suggestion, code = "...", applicability = "maybe-incorrect")] - //~^ ERROR applicability cannot be set in both the field and attribute + //~^ ERROR specified multiple times suggestion: (Span, Applicability), } diff --git a/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr b/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr index 084a021ac208a..f5432b0bf6561 100644 --- a/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr +++ b/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr @@ -293,11 +293,17 @@ error: `#[label = ...]` is not a valid attribute LL | #[label = "bar"] | ^^^^^^^^^^^^^^^^ -error: applicability cannot be set in both the field and attribute +error: specified multiple times --> $DIR/diagnostic-derive.rs:438:52 | LL | #[suggestion(typeck::suggestion, code = "...", applicability = "maybe-incorrect")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: previously specified here + --> $DIR/diagnostic-derive.rs:440:24 + | +LL | suggestion: (Span, Applicability), + | ^^^^^^^^^^^^^ error: invalid applicability --> $DIR/diagnostic-derive.rs:446:52 From d4a1a6f6986fd722506f7019d4ad669e46f15129 Mon Sep 17 00:00:00 2001 From: Xiretza Date: Sun, 11 Sep 2022 18:30:18 +0200 Subject: [PATCH 118/586] Make SetOnce nicer to use --- .../src/diagnostics/diagnostic_builder.rs | 22 +++++++------- .../src/diagnostics/subdiagnostic.rs | 29 ++++++++++--------- .../rustc_macros/src/diagnostics/utils.rs | 14 +++++++-- 3 files changed, 39 insertions(+), 26 deletions(-) diff --git a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs index 1e1bfbb943ecf..72f20efc8346b 100644 --- a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs +++ b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs @@ -18,6 +18,8 @@ use syn::{ }; use synstructure::{BindingInfo, Structure}; +use super::utils::SpannedOption; + /// What kind of diagnostic is being derived - a fatal/error/warning or a lint? #[derive(Copy, Clone, PartialEq, Eq)] pub(crate) enum DiagnosticDeriveKind { @@ -40,10 +42,10 @@ pub(crate) struct DiagnosticDeriveBuilder { pub kind: DiagnosticDeriveKind, /// Slug is a mandatory part of the struct attribute as corresponds to the Fluent message that /// has the actual diagnostic message. - pub slug: Option<(Path, proc_macro::Span)>, + pub slug: SpannedOption, /// Error codes are a optional part of the struct attribute - this is only set to detect /// multiple specifications. - pub code: Option<(String, proc_macro::Span)>, + pub code: SpannedOption, } impl HasFieldMap for DiagnosticDeriveBuilder { @@ -191,7 +193,7 @@ impl DiagnosticDeriveBuilder { match nested_attr { NestedMeta::Meta(Meta::Path(path)) => { if is_diag { - self.slug.set_once((path.clone(), span)); + self.slug.set_once(path.clone(), span); } else { let fn_name = proc_macro2::Ident::new(name, attr.span()); return Ok(quote! { #diag.#fn_name(rustc_errors::fluent::#path); }); @@ -224,8 +226,8 @@ impl DiagnosticDeriveBuilder { let span = s.span().unwrap(); match nested_name.as_str() { "code" => { - self.code.set_once((s.value(), span)); - let code = &self.code.as_ref().map(|(v, _)| v); + self.code.set_once(s.value(), span); + let code = &self.code.value_ref(); tokens.push(quote! { #diag.code(rustc_errors::DiagnosticId::Error(#code.to_string())); }); @@ -476,10 +478,10 @@ impl DiagnosticDeriveBuilder { match nested_name { "code" => { let formatted_str = self.build_format(&s.value(), s.span()); - code.set_once((formatted_str, span)); + code.set_once(formatted_str, span); } "applicability" => match Applicability::from_str(&s.value()) { - Ok(v) => applicability.set_once((quote! { #v }, span)), + Ok(v) => applicability.set_once(quote! { #v }, span), Err(()) => { span_err(span, "invalid applicability").emit(); } @@ -546,7 +548,7 @@ impl DiagnosticDeriveBuilder { fn span_and_applicability_of_ty( &self, info: FieldInfo<'_>, - ) -> Result<(TokenStream, Option<(TokenStream, proc_macro::Span)>), DiagnosticDeriveError> { + ) -> Result<(TokenStream, SpannedOption), DiagnosticDeriveError> { match &info.ty { // If `ty` is `Span` w/out applicability, then use `Applicability::Unspecified`. ty @ Type::Path(..) if type_matches_path(ty, &["rustc_span", "Span"]) => { @@ -570,9 +572,9 @@ impl DiagnosticDeriveBuilder { for (idx, elem) in tup.elems.iter().enumerate() { if type_matches_path(elem, &["rustc_span", "Span"]) { - span_idx.set_once((syn::Index::from(idx), elem.span().unwrap())); + span_idx.set_once(syn::Index::from(idx), elem.span().unwrap()); } else if type_matches_path(elem, &["rustc_errors", "Applicability"]) { - applicability_idx.set_once((syn::Index::from(idx), elem.span().unwrap())); + applicability_idx.set_once(syn::Index::from(idx), elem.span().unwrap()); } else { type_err(&elem.span())?; } diff --git a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs index bdeca3420bcca..9116dd186f96d 100644 --- a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs +++ b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs @@ -15,6 +15,8 @@ use std::str::FromStr; use syn::{spanned::Spanned, Attribute, Meta, MetaList, MetaNameValue, NestedMeta, Path}; use synstructure::{BindingInfo, Structure, VariantInfo}; +use super::utils::SpannedOption; + /// Which kind of suggestion is being created? #[derive(Clone, Copy)] enum SubdiagnosticSuggestionKind { @@ -195,10 +197,10 @@ struct SubdiagnosticDeriveBuilder<'a> { fields: HashMap, /// Identifier for the binding to the `#[primary_span]` field. - span_field: Option<(proc_macro2::Ident, proc_macro::Span)>, + span_field: SpannedOption, /// If a suggestion, the identifier for the binding to the `#[applicability]` field or a /// `rustc_errors::Applicability::*` variant directly. - applicability: Option<(TokenStream, proc_macro::Span)>, + applicability: SpannedOption, /// Set to true when a `#[suggestion_part]` field is encountered, used to generate an error /// during finalization if still `false`. @@ -283,7 +285,7 @@ impl<'a> SubdiagnosticDeriveBuilder<'a> { if let Some(nested_attr) = nested_iter.next() { match nested_attr { NestedMeta::Meta(Meta::Path(path)) => { - slug.set_once((path.clone(), span)); + slug.set_once(path.clone(), span); } NestedMeta::Meta(meta @ Meta::NameValue(_)) if matches!( @@ -326,7 +328,7 @@ impl<'a> SubdiagnosticDeriveBuilder<'a> { "code" => { if matches!(kind, SubdiagnosticKind::Suggestion { .. }) { let formatted_str = self.build_format(&value.value(), value.span()); - code.set_once((formatted_str, span)); + code.set_once(formatted_str, span); } else { span_err( span, @@ -349,7 +351,7 @@ impl<'a> SubdiagnosticDeriveBuilder<'a> { span_err(span, "invalid applicability").emit(); Applicability::Unspecified }); - self.applicability.set_once((quote! { #value }, span)); + self.applicability.set_once(quote! { #value }, span); } else { span_err( span, @@ -485,7 +487,7 @@ impl<'a> SubdiagnosticDeriveBuilder<'a> { report_error_if_not_applied_to_span(attr, &info)?; let binding = info.binding.binding.clone(); - self.span_field.set_once((binding, span)); + self.span_field.set_once(binding, span); Ok(quote! {}) } @@ -509,7 +511,7 @@ impl<'a> SubdiagnosticDeriveBuilder<'a> { report_error_if_not_applied_to_applicability(attr, &info)?; let binding = info.binding.binding.clone(); - self.applicability.set_once((quote! { #binding }, span)); + self.applicability.set_once(quote! { #binding }, span); } else { span_err(span, "`#[applicability]` is only valid on suggestions").emit(); } @@ -577,7 +579,7 @@ impl<'a> SubdiagnosticDeriveBuilder<'a> { match nested_name { "code" => { let formatted_str = self.build_format(&value.value(), value.span()); - code.set_once((formatted_str, span)); + code.set_once(formatted_str, span); } _ => throw_invalid_nested_attr!(attr, &nested_attr, |diag| { diag.help("`code` is the only valid nested attribute") @@ -635,11 +637,12 @@ impl<'a> SubdiagnosticDeriveBuilder<'a> { .map(|binding| self.generate_field_attr_code(binding, kind_stats)) .collect(); - let span_field = self.span_field.as_ref().map(|(span, _)| span); - let applicability = self.applicability.take().map_or_else( - || quote! { rustc_errors::Applicability::Unspecified }, - |(applicability, _)| applicability, - ); + let span_field = self.span_field.value_ref(); + let applicability = self + .applicability + .take() + .value() + .unwrap_or_else(|| quote! { rustc_errors::Applicability::Unspecified }); let diag = &self.diag; let mut calls = TokenStream::new(); diff --git a/compiler/rustc_macros/src/diagnostics/utils.rs b/compiler/rustc_macros/src/diagnostics/utils.rs index ad9ecd39b9e85..3efcd216d1931 100644 --- a/compiler/rustc_macros/src/diagnostics/utils.rs +++ b/compiler/rustc_macros/src/diagnostics/utils.rs @@ -172,13 +172,17 @@ pub(crate) struct FieldInfo<'a> { /// Small helper trait for abstracting over `Option` fields that contain a value and a `Span` /// for error reporting if they are set more than once. pub(crate) trait SetOnce { - fn set_once(&mut self, _: (T, Span)); + fn set_once(&mut self, value: T, span: Span); fn value(self) -> Option; + fn value_ref(&self) -> Option<&T>; } -impl SetOnce for Option<(T, Span)> { - fn set_once(&mut self, (value, span): (T, Span)) { +/// An [`Option`] that keeps track of the span that caused it to be set; used with [`SetOnce`]. +pub(super) type SpannedOption = Option<(T, Span)>; + +impl SetOnce for SpannedOption { + fn set_once(&mut self, value: T, span: Span) { match self { None => { *self = Some((value, span)); @@ -194,6 +198,10 @@ impl SetOnce for Option<(T, Span)> { fn value(self) -> Option { self.map(|(v, _)| v) } + + fn value_ref(&self) -> Option<&T> { + self.as_ref().map(|(v, _)| v) + } } pub(crate) trait HasFieldMap { From e7251cc441f19306e6e71715a9ab36029c543268 Mon Sep 17 00:00:00 2001 From: Xiretza Date: Mon, 12 Sep 2022 20:44:28 +0200 Subject: [PATCH 119/586] Extract subdiagnostic attribute parsing --- .../src/diagnostics/subdiagnostic.rs | 273 +++--------------- .../rustc_macros/src/diagnostics/utils.rs | 256 +++++++++++++++- .../subdiagnostic-derive.rs | 16 +- .../subdiagnostic-derive.stderr | 172 ++++++----- 4 files changed, 402 insertions(+), 315 deletions(-) diff --git a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs index 9116dd186f96d..9ea03e186e72a 100644 --- a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs +++ b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs @@ -4,100 +4,16 @@ use crate::diagnostics::error::{ span_err, throw_invalid_attr, throw_invalid_nested_attr, throw_span_err, DiagnosticDeriveError, }; use crate::diagnostics::utils::{ - report_error_if_not_applied_to_applicability, report_error_if_not_applied_to_span, - Applicability, FieldInfo, FieldInnerTy, HasFieldMap, SetOnce, + report_error_if_not_applied_to_applicability, report_error_if_not_applied_to_span, FieldInfo, + FieldInnerTy, HasFieldMap, SetOnce, }; use proc_macro2::TokenStream; use quote::{format_ident, quote}; use std::collections::HashMap; -use std::fmt; -use std::str::FromStr; use syn::{spanned::Spanned, Attribute, Meta, MetaList, MetaNameValue, NestedMeta, Path}; use synstructure::{BindingInfo, Structure, VariantInfo}; -use super::utils::SpannedOption; - -/// Which kind of suggestion is being created? -#[derive(Clone, Copy)] -enum SubdiagnosticSuggestionKind { - /// `#[suggestion]` - Normal, - /// `#[suggestion_short]` - Short, - /// `#[suggestion_hidden]` - Hidden, - /// `#[suggestion_verbose]` - Verbose, -} - -impl FromStr for SubdiagnosticSuggestionKind { - type Err = (); - - fn from_str(s: &str) -> Result { - match s { - "" => Ok(SubdiagnosticSuggestionKind::Normal), - "_short" => Ok(SubdiagnosticSuggestionKind::Short), - "_hidden" => Ok(SubdiagnosticSuggestionKind::Hidden), - "_verbose" => Ok(SubdiagnosticSuggestionKind::Verbose), - _ => Err(()), - } - } -} - -impl SubdiagnosticSuggestionKind { - pub fn to_suggestion_style(&self) -> TokenStream { - match self { - SubdiagnosticSuggestionKind::Normal => { - quote! { rustc_errors::SuggestionStyle::ShowCode } - } - SubdiagnosticSuggestionKind::Short => { - quote! { rustc_errors::SuggestionStyle::HideCodeInline } - } - SubdiagnosticSuggestionKind::Hidden => { - quote! { rustc_errors::SuggestionStyle::HideCodeAlways } - } - SubdiagnosticSuggestionKind::Verbose => { - quote! { rustc_errors::SuggestionStyle::ShowAlways } - } - } - } -} - -/// Which kind of subdiagnostic is being created from a variant? -#[derive(Clone)] -enum SubdiagnosticKind { - /// `#[label(...)]` - Label, - /// `#[note(...)]` - Note, - /// `#[help(...)]` - Help, - /// `#[warning(...)]` - Warn, - /// `#[suggestion{,_short,_hidden,_verbose}]` - Suggestion { suggestion_kind: SubdiagnosticSuggestionKind, code: TokenStream }, - /// `#[multipart_suggestion{,_short,_hidden,_verbose}]` - MultipartSuggestion { suggestion_kind: SubdiagnosticSuggestionKind }, -} - -impl quote::IdentFragment for SubdiagnosticKind { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - SubdiagnosticKind::Label => write!(f, "label"), - SubdiagnosticKind::Note => write!(f, "note"), - SubdiagnosticKind::Help => write!(f, "help"), - SubdiagnosticKind::Warn => write!(f, "warn"), - SubdiagnosticKind::Suggestion { .. } => write!(f, "suggestion_with_style"), - SubdiagnosticKind::MultipartSuggestion { .. } => { - write!(f, "multipart_suggestion_with_style") - } - } - } - - fn span(&self) -> Option { - None - } -} +use super::utils::{SpannedOption, SubdiagnosticKind}; /// The central struct for constructing the `add_to_diagnostic` method from an annotated struct. pub(crate) struct SubdiagnosticDerive<'a> { @@ -198,8 +114,8 @@ struct SubdiagnosticDeriveBuilder<'a> { /// Identifier for the binding to the `#[primary_span]` field. span_field: SpannedOption, - /// If a suggestion, the identifier for the binding to the `#[applicability]` field or a - /// `rustc_errors::Applicability::*` variant directly. + + /// The binding to the `#[applicability]` field, if present. applicability: SpannedOption, /// Set to true when a `#[suggestion_part]` field is encountered, used to generate an error @@ -219,6 +135,7 @@ struct KindsStatistics { has_multipart_suggestion: bool, all_multipart_suggestions: bool, has_normal_suggestion: bool, + all_applicabilities_static: bool, } impl<'a> FromIterator<&'a SubdiagnosticKind> for KindsStatistics { @@ -227,8 +144,15 @@ impl<'a> FromIterator<&'a SubdiagnosticKind> for KindsStatistics { has_multipart_suggestion: false, all_multipart_suggestions: true, has_normal_suggestion: false, + all_applicabilities_static: true, }; + for kind in kinds { + if let SubdiagnosticKind::MultipartSuggestion { applicability: None, .. } + | SubdiagnosticKind::Suggestion { applicability: None, .. } = kind + { + ret.all_applicabilities_static = false; + } if let SubdiagnosticKind::MultipartSuggestion { .. } = kind { ret.has_multipart_suggestion = true; } else { @@ -248,129 +172,14 @@ impl<'a> SubdiagnosticDeriveBuilder<'a> { let mut kind_slugs = vec![]; for attr in self.variant.ast().attrs { - let span = attr.span().unwrap(); - - let name = attr.path.segments.last().unwrap().ident.to_string(); - let name = name.as_str(); - - let meta = attr.parse_meta()?; - let Meta::List(MetaList { ref nested, .. }) = meta else { - throw_invalid_attr!(attr, &meta); - }; - - let mut kind = match name { - "label" => SubdiagnosticKind::Label, - "note" => SubdiagnosticKind::Note, - "help" => SubdiagnosticKind::Help, - "warning" => SubdiagnosticKind::Warn, - _ => { - if let Some(suggestion_kind) = - name.strip_prefix("suggestion").and_then(|s| s.parse().ok()) - { - SubdiagnosticKind::Suggestion { suggestion_kind, code: TokenStream::new() } - } else if let Some(suggestion_kind) = - name.strip_prefix("multipart_suggestion").and_then(|s| s.parse().ok()) - { - SubdiagnosticKind::MultipartSuggestion { suggestion_kind } - } else { - throw_invalid_attr!(attr, &meta); - } - } - }; - - let mut slug = None; - let mut code = None; - - let mut nested_iter = nested.into_iter(); - if let Some(nested_attr) = nested_iter.next() { - match nested_attr { - NestedMeta::Meta(Meta::Path(path)) => { - slug.set_once(path.clone(), span); - } - NestedMeta::Meta(meta @ Meta::NameValue(_)) - if matches!( - meta.path().segments.last().unwrap().ident.to_string().as_str(), - "code" | "applicability" - ) => - { - // Don't error for valid follow-up attributes. - } - nested_attr => { - throw_invalid_nested_attr!(attr, &nested_attr, |diag| { - diag.help( - "first argument of the attribute should be the diagnostic \ - slug", - ) - }) - } - }; - } + let (kind, slug) = SubdiagnosticKind::from_attr(attr, self)?; - for nested_attr in nested_iter { - let meta = match nested_attr { - NestedMeta::Meta(ref meta) => meta, - _ => throw_invalid_nested_attr!(attr, &nested_attr), - }; - - let span = meta.span().unwrap(); - let nested_name = meta.path().segments.last().unwrap().ident.to_string(); - let nested_name = nested_name.as_str(); - - let value = match meta { - Meta::NameValue(MetaNameValue { lit: syn::Lit::Str(value), .. }) => value, - Meta::Path(_) => throw_invalid_nested_attr!(attr, &nested_attr, |diag| { - diag.help("a diagnostic slug must be the first argument to the attribute") - }), - _ => throw_invalid_nested_attr!(attr, &nested_attr), - }; - - match nested_name { - "code" => { - if matches!(kind, SubdiagnosticKind::Suggestion { .. }) { - let formatted_str = self.build_format(&value.value(), value.span()); - code.set_once(formatted_str, span); - } else { - span_err( - span, - &format!( - "`code` is not a valid nested attribute of a `{}` attribute", - name - ), - ) - .emit(); - } - } - "applicability" => { - if matches!( - kind, - SubdiagnosticKind::Suggestion { .. } - | SubdiagnosticKind::MultipartSuggestion { .. } - ) { - let value = - Applicability::from_str(&value.value()).unwrap_or_else(|()| { - span_err(span, "invalid applicability").emit(); - Applicability::Unspecified - }); - self.applicability.set_once(quote! { #value }, span); - } else { - span_err( - span, - &format!( - "`applicability` is not a valid nested attribute of a `{}` attribute", - name - ) - ).emit(); - } - } - _ => throw_invalid_nested_attr!(attr, &nested_attr, |diag| { - diag.help("only `code` and `applicability` are valid nested attributes") - }), - } - } + let Some(slug) = slug else { + let name = attr.path.segments.last().unwrap().ident.to_string(); + let name = name.as_str(); - let Some((slug, _)) = slug else { throw_span_err!( - span, + attr.span().unwrap(), &format!( "diagnostic slug must be first argument of a `#[{}(...)]` attribute", name @@ -378,21 +187,7 @@ impl<'a> SubdiagnosticDeriveBuilder<'a> { ); }; - match kind { - SubdiagnosticKind::Suggestion { code: ref mut code_field, .. } => { - let Some((code, _)) = code else { - throw_span_err!(span, "suggestion without `code = \"...\"`"); - }; - *code_field = code; - } - SubdiagnosticKind::Label - | SubdiagnosticKind::Note - | SubdiagnosticKind::Help - | SubdiagnosticKind::Warn - | SubdiagnosticKind::MultipartSuggestion { .. } => {} - } - - kind_slugs.push((kind, slug)) + kind_slugs.push((kind, slug)); } Ok(kind_slugs) @@ -510,6 +305,15 @@ impl<'a> SubdiagnosticDeriveBuilder<'a> { if kind_stats.has_multipart_suggestion || kind_stats.has_normal_suggestion { report_error_if_not_applied_to_applicability(attr, &info)?; + if kind_stats.all_applicabilities_static { + span_err( + span, + "`#[applicability]` has no effect if all `#[suggestion]`/\ + `#[multipart_suggestion]` attributes have a static \ + `applicability = \"...\"`", + ) + .emit(); + } let binding = info.binding.binding.clone(); self.applicability.set_once(quote! { #binding }, span); } else { @@ -638,11 +442,6 @@ impl<'a> SubdiagnosticDeriveBuilder<'a> { .collect(); let span_field = self.span_field.value_ref(); - let applicability = self - .applicability - .take() - .value() - .unwrap_or_else(|| quote! { rustc_errors::Applicability::Unspecified }); let diag = &self.diag; let mut calls = TokenStream::new(); @@ -650,7 +449,13 @@ impl<'a> SubdiagnosticDeriveBuilder<'a> { let name = format_ident!("{}{}", if span_field.is_some() { "span_" } else { "" }, kind); let message = quote! { rustc_errors::fluent::#slug }; let call = match kind { - SubdiagnosticKind::Suggestion { suggestion_kind, code } => { + SubdiagnosticKind::Suggestion { suggestion_kind, applicability, code } => { + let applicability = applicability + .value() + .map(|a| quote! { #a }) + .or_else(|| self.applicability.take().value()) + .unwrap_or_else(|| quote! { rustc_errors::Applicability::Unspecified }); + if let Some(span) = span_field { let style = suggestion_kind.to_suggestion_style(); @@ -660,7 +465,13 @@ impl<'a> SubdiagnosticDeriveBuilder<'a> { quote! { unreachable!(); } } } - SubdiagnosticKind::MultipartSuggestion { suggestion_kind } => { + SubdiagnosticKind::MultipartSuggestion { suggestion_kind, applicability } => { + let applicability = applicability + .value() + .map(|a| quote! { #a }) + .or_else(|| self.applicability.take().value()) + .unwrap_or_else(|| quote! { rustc_errors::Applicability::Unspecified }); + if !self.has_suggestion_parts { span_err( self.span, diff --git a/compiler/rustc_macros/src/diagnostics/utils.rs b/compiler/rustc_macros/src/diagnostics/utils.rs index 3efcd216d1931..a31bda9ca0def 100644 --- a/compiler/rustc_macros/src/diagnostics/utils.rs +++ b/compiler/rustc_macros/src/diagnostics/utils.rs @@ -1,12 +1,18 @@ -use crate::diagnostics::error::{span_err, throw_span_err, DiagnosticDeriveError}; +use crate::diagnostics::error::{ + span_err, throw_invalid_attr, throw_invalid_nested_attr, throw_span_err, DiagnosticDeriveError, +}; use proc_macro::Span; use proc_macro2::TokenStream; use quote::{format_ident, quote, ToTokens}; use std::collections::{BTreeSet, HashMap}; +use std::fmt; use std::str::FromStr; use syn::{spanned::Spanned, Attribute, Meta, Type, TypeTuple}; +use syn::{MetaList, MetaNameValue, NestedMeta, Path}; use synstructure::{BindingInfo, Structure}; +use super::error::invalid_nested_attr; + /// Checks whether the type name of `ty` matches `name`. /// /// Given some struct at `a::b::c::Foo`, this will return true for `c::Foo`, `b::c::Foo`, or @@ -311,6 +317,7 @@ pub(crate) trait HasFieldMap { /// `Applicability` of a suggestion - mirrors `rustc_errors::Applicability` - and used to represent /// the user's selection of applicability if specified in an attribute. +#[derive(Clone, Copy)] pub(crate) enum Applicability { MachineApplicable, MaybeIncorrect, @@ -367,3 +374,250 @@ pub(crate) fn build_field_mapping<'a>(structure: &Structure<'a>) -> HashMap Result { + match s { + "" => Ok(SuggestionKind::Normal), + "_short" => Ok(SuggestionKind::Short), + "_hidden" => Ok(SuggestionKind::Hidden), + "_verbose" => Ok(SuggestionKind::Verbose), + _ => Err(()), + } + } +} + +impl SuggestionKind { + pub fn to_suggestion_style(&self) -> TokenStream { + match self { + SuggestionKind::Normal => { + quote! { rustc_errors::SuggestionStyle::ShowCode } + } + SuggestionKind::Short => { + quote! { rustc_errors::SuggestionStyle::HideCodeInline } + } + SuggestionKind::Hidden => { + quote! { rustc_errors::SuggestionStyle::HideCodeAlways } + } + SuggestionKind::Verbose => { + quote! { rustc_errors::SuggestionStyle::ShowAlways } + } + } + } +} + +/// Types of subdiagnostics that can be created using attributes +#[derive(Clone)] +pub(super) enum SubdiagnosticKind { + /// `#[label(...)]` + Label, + /// `#[note(...)]` + Note, + /// `#[help(...)]` + Help, + /// `#[warning(...)]` + Warn, + /// `#[suggestion{,_short,_hidden,_verbose}]` + Suggestion { + suggestion_kind: SuggestionKind, + applicability: SpannedOption, + code: TokenStream, + }, + /// `#[multipart_suggestion{,_short,_hidden,_verbose}]` + MultipartSuggestion { + suggestion_kind: SuggestionKind, + applicability: SpannedOption, + }, +} + +impl SubdiagnosticKind { + /// Constructs a `SubdiagnosticKind` from a field or type attribute such as `#[note]`, + /// `#[error(parser::add_paren)]` or `#[suggestion(code = "...")]`. Returns the + /// `SubdiagnosticKind` and the diagnostic slug, if specified. + pub(super) fn from_attr( + attr: &Attribute, + fields: &impl HasFieldMap, + ) -> Result<(SubdiagnosticKind, Option), DiagnosticDeriveError> { + let span = attr.span().unwrap(); + + let name = attr.path.segments.last().unwrap().ident.to_string(); + let name = name.as_str(); + + let meta = attr.parse_meta()?; + let mut kind = match name { + "label" => SubdiagnosticKind::Label, + "note" => SubdiagnosticKind::Note, + "help" => SubdiagnosticKind::Help, + "warning" => SubdiagnosticKind::Warn, + _ => { + if let Some(suggestion_kind) = + name.strip_prefix("suggestion").and_then(|s| s.parse().ok()) + { + SubdiagnosticKind::Suggestion { + suggestion_kind, + applicability: None, + code: TokenStream::new(), + } + } else if let Some(suggestion_kind) = + name.strip_prefix("multipart_suggestion").and_then(|s| s.parse().ok()) + { + SubdiagnosticKind::MultipartSuggestion { suggestion_kind, applicability: None } + } else { + throw_invalid_attr!(attr, &meta); + } + } + }; + + let nested = match meta { + Meta::List(MetaList { ref nested, .. }) => { + // An attribute with properties, such as `#[suggestion(code = "...")]` or + // `#[error(some::slug)]` + nested + } + Meta::Path(_) => { + // An attribute without a slug or other properties, such as `#[note]` - return + // without further processing. + // + // Only allow this if there are no mandatory properties, such as `code = "..."` in + // `#[suggestion(...)]` + match kind { + SubdiagnosticKind::Label + | SubdiagnosticKind::Note + | SubdiagnosticKind::Help + | SubdiagnosticKind::Warn + | SubdiagnosticKind::MultipartSuggestion { .. } => return Ok((kind, None)), + SubdiagnosticKind::Suggestion { .. } => { + throw_span_err!(span, "suggestion without `code = \"...\"`") + } + } + } + _ => { + throw_invalid_attr!(attr, &meta) + } + }; + + let mut code = None; + + let mut nested_iter = nested.into_iter().peekable(); + + // Peek at the first nested attribute: if it's a slug path, consume it. + let slug = if let Some(NestedMeta::Meta(Meta::Path(path))) = nested_iter.peek() { + let path = path.clone(); + // Advance the iterator. + nested_iter.next(); + Some(path) + } else { + None + }; + + for nested_attr in nested_iter { + let meta = match nested_attr { + NestedMeta::Meta(ref meta) => meta, + NestedMeta::Lit(_) => { + invalid_nested_attr(attr, &nested_attr).emit(); + continue; + } + }; + + let span = meta.span().unwrap(); + let nested_name = meta.path().segments.last().unwrap().ident.to_string(); + let nested_name = nested_name.as_str(); + + let value = match meta { + Meta::NameValue(MetaNameValue { lit: syn::Lit::Str(value), .. }) => value, + Meta::Path(_) => throw_invalid_nested_attr!(attr, &nested_attr, |diag| { + diag.help("a diagnostic slug must be the first argument to the attribute") + }), + _ => { + invalid_nested_attr(attr, &nested_attr).emit(); + continue; + } + }; + + match (nested_name, &mut kind) { + ("code", SubdiagnosticKind::Suggestion { .. }) => { + let formatted_str = fields.build_format(&value.value(), value.span()); + code.set_once(formatted_str, span); + } + ( + "applicability", + SubdiagnosticKind::Suggestion { ref mut applicability, .. } + | SubdiagnosticKind::MultipartSuggestion { ref mut applicability, .. }, + ) => { + let value = Applicability::from_str(&value.value()).unwrap_or_else(|()| { + span_err(span, "invalid applicability").emit(); + Applicability::Unspecified + }); + applicability.set_once(value, span); + } + + // Invalid nested attribute + (_, SubdiagnosticKind::Suggestion { .. }) => { + invalid_nested_attr(attr, &nested_attr) + .help("only `code` and `applicability` are valid nested attributes") + .emit(); + } + (_, SubdiagnosticKind::MultipartSuggestion { .. }) => { + invalid_nested_attr(attr, &nested_attr) + .help("only `applicability` is a valid nested attributes") + .emit() + } + _ => { + invalid_nested_attr(attr, &nested_attr).emit(); + } + } + } + + match kind { + SubdiagnosticKind::Suggestion { code: ref mut code_field, .. } => { + *code_field = if let Some((code, _)) = code { + code + } else { + span_err(span, "suggestion without `code = \"...\"`").emit(); + quote! { "" } + } + } + SubdiagnosticKind::Label + | SubdiagnosticKind::Note + | SubdiagnosticKind::Help + | SubdiagnosticKind::Warn + | SubdiagnosticKind::MultipartSuggestion { .. } => {} + } + + Ok((kind, slug)) + } +} + +impl quote::IdentFragment for SubdiagnosticKind { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + SubdiagnosticKind::Label => write!(f, "label"), + SubdiagnosticKind::Note => write!(f, "note"), + SubdiagnosticKind::Help => write!(f, "help"), + SubdiagnosticKind::Warn => write!(f, "warn"), + SubdiagnosticKind::Suggestion { .. } => write!(f, "suggestion_with_style"), + SubdiagnosticKind::MultipartSuggestion { .. } => { + write!(f, "multipart_suggestion_with_style") + } + } + } + + fn span(&self) -> Option { + None + } +} diff --git a/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs b/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs index 9fbe7b1f4c859..606b3b5e5ebca 100644 --- a/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs +++ b/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs @@ -52,7 +52,7 @@ struct C { #[derive(Subdiagnostic)] #[label] -//~^ ERROR `#[label]` is not a valid attribute +//~^ ERROR diagnostic slug must be first argument struct D { #[primary_span] span: Span, @@ -81,6 +81,7 @@ struct F { #[derive(Subdiagnostic)] #[label(bug = "...")] //~^ ERROR `#[label(bug = ...)]` is not a valid attribute +//~| ERROR diagnostic slug must be first argument struct G { #[primary_span] span: Span, @@ -90,6 +91,7 @@ struct G { #[derive(Subdiagnostic)] #[label("...")] //~^ ERROR `#[label("...")]` is not a valid attribute +//~| ERROR diagnostic slug must be first argument struct H { #[primary_span] span: Span, @@ -99,6 +101,7 @@ struct H { #[derive(Subdiagnostic)] #[label(slug = 4)] //~^ ERROR `#[label(slug = ...)]` is not a valid attribute +//~| ERROR diagnostic slug must be first argument struct J { #[primary_span] span: Span, @@ -108,6 +111,7 @@ struct J { #[derive(Subdiagnostic)] #[label(slug("..."))] //~^ ERROR `#[label(slug(...))]` is not a valid attribute +//~| ERROR diagnostic slug must be first argument struct K { #[primary_span] span: Span, @@ -135,7 +139,7 @@ struct M { #[derive(Subdiagnostic)] #[label(parser::add_paren, code = "...")] -//~^ ERROR `code` is not a valid nested attribute of a `label` attribute +//~^ ERROR `#[label(code = ...)]` is not a valid attribute struct N { #[primary_span] span: Span, @@ -144,7 +148,7 @@ struct N { #[derive(Subdiagnostic)] #[label(parser::add_paren, applicability = "machine-applicable")] -//~^ ERROR `applicability` is not a valid nested attribute of a `label` attribute +//~^ ERROR `#[label(applicability = ...)]` is not a valid attribute struct O { #[primary_span] span: Span, @@ -216,6 +220,7 @@ enum T { enum U { #[label(code = "...")] //~^ ERROR diagnostic slug must be first argument of a `#[label(...)]` attribute + //~| ERROR `#[label(code = ...)]` is not a valid attribute A { #[primary_span] span: Span, @@ -531,7 +536,7 @@ struct BA { #[derive(Subdiagnostic)] #[multipart_suggestion(parser::add_paren, code = "...", applicability = "machine-applicable")] //~^ ERROR multipart suggestion without any `#[suggestion_part(...)]` fields -//~| ERROR `code` is not a valid nested attribute of a `multipart_suggestion` attribute +//~| ERROR `#[multipart_suggestion(code = ...)]` is not a valid attribute struct BBa { var: String, } @@ -612,10 +617,9 @@ struct BG { #[derive(Subdiagnostic)] #[multipart_suggestion(parser::add_paren, applicability = "machine-applicable")] -//~^ NOTE previously specified here struct BH { #[applicability] - //~^ ERROR specified multiple times + //~^ ERROR `#[applicability]` has no effect appl: Applicability, #[suggestion_part(code = "(")] first: Span, diff --git a/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr b/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr index 0a0247e898088..171b89e657d81 100644 --- a/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr +++ b/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr @@ -8,7 +8,7 @@ LL | | var: String, LL | | } | |_^ -error: `#[label]` is not a valid attribute +error: diagnostic slug must be first argument of a `#[label(...)]` attribute --> $DIR/subdiagnostic-derive.rs:54:1 | LL | #[label] @@ -31,101 +31,123 @@ error: `#[label(bug = ...)]` is not a valid attribute | LL | #[label(bug = "...")] | ^^^^^^^^^^^ + +error: diagnostic slug must be first argument of a `#[label(...)]` attribute + --> $DIR/subdiagnostic-derive.rs:82:1 | - = help: first argument of the attribute should be the diagnostic slug +LL | #[label(bug = "...")] + | ^^^^^^^^^^^^^^^^^^^^^ error: `#[label("...")]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:91:9 + --> $DIR/subdiagnostic-derive.rs:92:9 | LL | #[label("...")] | ^^^^^ + +error: diagnostic slug must be first argument of a `#[label(...)]` attribute + --> $DIR/subdiagnostic-derive.rs:92:1 | - = help: first argument of the attribute should be the diagnostic slug +LL | #[label("...")] + | ^^^^^^^^^^^^^^^ error: `#[label(slug = ...)]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:100:9 + --> $DIR/subdiagnostic-derive.rs:102:9 | LL | #[label(slug = 4)] | ^^^^^^^^ + +error: diagnostic slug must be first argument of a `#[label(...)]` attribute + --> $DIR/subdiagnostic-derive.rs:102:1 | - = help: first argument of the attribute should be the diagnostic slug +LL | #[label(slug = 4)] + | ^^^^^^^^^^^^^^^^^^ error: `#[label(slug(...))]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:109:9 + --> $DIR/subdiagnostic-derive.rs:112:9 | LL | #[label(slug("..."))] | ^^^^^^^^^^^ + +error: diagnostic slug must be first argument of a `#[label(...)]` attribute + --> $DIR/subdiagnostic-derive.rs:112:1 | - = help: first argument of the attribute should be the diagnostic slug +LL | #[label(slug("..."))] + | ^^^^^^^^^^^^^^^^^^^^^ error: diagnostic slug must be first argument of a `#[label(...)]` attribute - --> $DIR/subdiagnostic-derive.rs:128:1 + --> $DIR/subdiagnostic-derive.rs:132:1 | LL | #[label()] | ^^^^^^^^^^ -error: `code` is not a valid nested attribute of a `label` attribute - --> $DIR/subdiagnostic-derive.rs:137:28 +error: `#[label(code = ...)]` is not a valid attribute + --> $DIR/subdiagnostic-derive.rs:141:28 | LL | #[label(parser::add_paren, code = "...")] | ^^^^^^^^^^^^ -error: `applicability` is not a valid nested attribute of a `label` attribute - --> $DIR/subdiagnostic-derive.rs:146:28 +error: `#[label(applicability = ...)]` is not a valid attribute + --> $DIR/subdiagnostic-derive.rs:150:28 | LL | #[label(parser::add_paren, applicability = "machine-applicable")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: unsupported type attribute for subdiagnostic enum - --> $DIR/subdiagnostic-derive.rs:155:1 + --> $DIR/subdiagnostic-derive.rs:159:1 | LL | #[foo] | ^^^^^^ error: `#[bar]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:169:5 + --> $DIR/subdiagnostic-derive.rs:173:5 | LL | #[bar] | ^^^^^^ error: `#[bar = ...]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:181:5 + --> $DIR/subdiagnostic-derive.rs:185:5 | LL | #[bar = "..."] | ^^^^^^^^^^^^^^ error: `#[bar = ...]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:193:5 + --> $DIR/subdiagnostic-derive.rs:197:5 | LL | #[bar = 4] | ^^^^^^^^^^ error: `#[bar(...)]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:205:5 + --> $DIR/subdiagnostic-derive.rs:209:5 | LL | #[bar("...")] | ^^^^^^^^^^^^^ +error: `#[label(code = ...)]` is not a valid attribute + --> $DIR/subdiagnostic-derive.rs:221:13 + | +LL | #[label(code = "...")] + | ^^^^^^^^^^^^ + error: diagnostic slug must be first argument of a `#[label(...)]` attribute - --> $DIR/subdiagnostic-derive.rs:217:5 + --> $DIR/subdiagnostic-derive.rs:221:5 | LL | #[label(code = "...")] | ^^^^^^^^^^^^^^^^^^^^^^ error: subdiagnostic kind not specified - --> $DIR/subdiagnostic-derive.rs:234:5 + --> $DIR/subdiagnostic-derive.rs:239:5 | LL | B { | ^ error: the `#[primary_span]` attribute can only be applied to fields of type `Span` or `MultiSpan` - --> $DIR/subdiagnostic-derive.rs:246:5 + --> $DIR/subdiagnostic-derive.rs:251:5 | LL | #[primary_span] | ^^^^^^^^^^^^^^^ error: label without `#[primary_span]` field - --> $DIR/subdiagnostic-derive.rs:243:1 + --> $DIR/subdiagnostic-derive.rs:248:1 | LL | / #[label(parser::add_paren)] LL | | @@ -137,13 +159,13 @@ LL | | } | |_^ error: `#[applicability]` is only valid on suggestions - --> $DIR/subdiagnostic-derive.rs:256:5 + --> $DIR/subdiagnostic-derive.rs:261:5 | LL | #[applicability] | ^^^^^^^^^^^^^^^^ error: `#[bar]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:266:5 + --> $DIR/subdiagnostic-derive.rs:271:5 | LL | #[bar] | ^^^^^^ @@ -151,13 +173,13 @@ LL | #[bar] = help: only `primary_span`, `applicability` and `skip_arg` are valid field attributes error: `#[bar = ...]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:277:5 + --> $DIR/subdiagnostic-derive.rs:282:5 | LL | #[bar = "..."] | ^^^^^^^^^^^^^^ error: `#[bar(...)]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:288:5 + --> $DIR/subdiagnostic-derive.rs:293:5 | LL | #[bar("...")] | ^^^^^^^^^^^^^ @@ -165,7 +187,7 @@ LL | #[bar("...")] = help: only `primary_span`, `applicability` and `skip_arg` are valid field attributes error: unexpected unsupported untagged union - --> $DIR/subdiagnostic-derive.rs:304:1 + --> $DIR/subdiagnostic-derive.rs:309:1 | LL | / union AC { LL | | @@ -175,7 +197,7 @@ LL | | } | |_^ error: `#[label(parser::add_paren)]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:319:28 + --> $DIR/subdiagnostic-derive.rs:324:28 | LL | #[label(parser::add_paren, parser::add_paren)] | ^^^^^^^^^^^^^^^^^ @@ -183,67 +205,67 @@ LL | #[label(parser::add_paren, parser::add_paren)] = help: a diagnostic slug must be the first argument to the attribute error: specified multiple times - --> $DIR/subdiagnostic-derive.rs:332:5 + --> $DIR/subdiagnostic-derive.rs:337:5 | LL | #[primary_span] | ^^^^^^^^^^^^^^^ | note: previously specified here - --> $DIR/subdiagnostic-derive.rs:329:5 + --> $DIR/subdiagnostic-derive.rs:334:5 | LL | #[primary_span] | ^^^^^^^^^^^^^^^ error: subdiagnostic kind not specified - --> $DIR/subdiagnostic-derive.rs:338:8 + --> $DIR/subdiagnostic-derive.rs:343:8 | LL | struct AG { | ^^ error: specified multiple times - --> $DIR/subdiagnostic-derive.rs:375:47 + --> $DIR/subdiagnostic-derive.rs:380:47 | LL | #[suggestion(parser::add_paren, code = "...", code = "...")] | ^^^^^^^^^^^^ | note: previously specified here - --> $DIR/subdiagnostic-derive.rs:375:33 + --> $DIR/subdiagnostic-derive.rs:380:33 | LL | #[suggestion(parser::add_paren, code = "...", code = "...")] | ^^^^^^^^^^^^ error: specified multiple times - --> $DIR/subdiagnostic-derive.rs:393:5 + --> $DIR/subdiagnostic-derive.rs:398:5 | LL | #[applicability] | ^^^^^^^^^^^^^^^^ | note: previously specified here - --> $DIR/subdiagnostic-derive.rs:390:5 + --> $DIR/subdiagnostic-derive.rs:395:5 | LL | #[applicability] | ^^^^^^^^^^^^^^^^ error: the `#[applicability]` attribute can only be applied to fields of type `Applicability` - --> $DIR/subdiagnostic-derive.rs:403:5 + --> $DIR/subdiagnostic-derive.rs:408:5 | LL | #[applicability] | ^^^^^^^^^^^^^^^^ error: suggestion without `code = "..."` - --> $DIR/subdiagnostic-derive.rs:416:1 + --> $DIR/subdiagnostic-derive.rs:421:1 | LL | #[suggestion(parser::add_paren)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: invalid applicability - --> $DIR/subdiagnostic-derive.rs:426:46 + --> $DIR/subdiagnostic-derive.rs:431:46 | LL | #[suggestion(parser::add_paren, code ="...", applicability = "foo")] | ^^^^^^^^^^^^^^^^^^^^^ error: suggestion without `#[primary_span]` field - --> $DIR/subdiagnostic-derive.rs:444:1 + --> $DIR/subdiagnostic-derive.rs:449:1 | LL | / #[suggestion(parser::add_paren, code = "...")] LL | | @@ -253,25 +275,25 @@ LL | | } | |_^ error: unsupported type attribute for subdiagnostic enum - --> $DIR/subdiagnostic-derive.rs:458:1 + --> $DIR/subdiagnostic-derive.rs:463:1 | LL | #[label] | ^^^^^^^^ error: `var` doesn't refer to a field on this type - --> $DIR/subdiagnostic-derive.rs:478:39 + --> $DIR/subdiagnostic-derive.rs:483:39 | LL | #[suggestion(parser::add_paren, code ="{var}", applicability = "machine-applicable")] | ^^^^^^^ error: `var` doesn't refer to a field on this type - --> $DIR/subdiagnostic-derive.rs:497:43 + --> $DIR/subdiagnostic-derive.rs:502:43 | LL | #[suggestion(parser::add_paren, code ="{var}", applicability = "machine-applicable")] | ^^^^^^^ error: `#[suggestion_part]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:520:5 + --> $DIR/subdiagnostic-derive.rs:525:5 | LL | #[suggestion_part] | ^^^^^^^^^^^^^^^^^^ @@ -279,7 +301,7 @@ LL | #[suggestion_part] = help: `#[suggestion_part(...)]` is only valid in multipart suggestions, use `#[primary_span]` instead error: `#[suggestion_part(...)]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:523:5 + --> $DIR/subdiagnostic-derive.rs:528:5 | LL | #[suggestion_part(code = "...")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -287,7 +309,7 @@ LL | #[suggestion_part(code = "...")] = help: `#[suggestion_part(...)]` is only valid in multipart suggestions error: suggestion without `#[primary_span]` field - --> $DIR/subdiagnostic-derive.rs:517:1 + --> $DIR/subdiagnostic-derive.rs:522:1 | LL | / #[suggestion(parser::add_paren, code = "...")] LL | | @@ -298,14 +320,16 @@ LL | | var: String, LL | | } | |_^ -error: `code` is not a valid nested attribute of a `multipart_suggestion` attribute - --> $DIR/subdiagnostic-derive.rs:532:43 +error: `#[multipart_suggestion(code = ...)]` is not a valid attribute + --> $DIR/subdiagnostic-derive.rs:537:43 | LL | #[multipart_suggestion(parser::add_paren, code = "...", applicability = "machine-applicable")] | ^^^^^^^^^^^^ + | + = help: only `applicability` is a valid nested attributes error: multipart suggestion without any `#[suggestion_part(...)]` fields - --> $DIR/subdiagnostic-derive.rs:532:1 + --> $DIR/subdiagnostic-derive.rs:537:1 | LL | / #[multipart_suggestion(parser::add_paren, code = "...", applicability = "machine-applicable")] LL | | @@ -316,19 +340,19 @@ LL | | } | |_^ error: `#[suggestion_part(...)]` attribute without `code = "..."` - --> $DIR/subdiagnostic-derive.rs:542:5 + --> $DIR/subdiagnostic-derive.rs:547:5 | LL | #[suggestion_part] | ^^^^^^^^^^^^^^^^^^ error: `#[suggestion_part(...)]` attribute without `code = "..."` - --> $DIR/subdiagnostic-derive.rs:550:5 + --> $DIR/subdiagnostic-derive.rs:555:5 | LL | #[suggestion_part()] | ^^^^^^^^^^^^^^^^^^^^ error: `#[primary_span]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:559:5 + --> $DIR/subdiagnostic-derive.rs:564:5 | LL | #[primary_span] | ^^^^^^^^^^^^^^^ @@ -336,7 +360,7 @@ LL | #[primary_span] = help: multipart suggestions use one or more `#[suggestion_part]`s rather than one `#[primary_span]` error: multipart suggestion without any `#[suggestion_part(...)]` fields - --> $DIR/subdiagnostic-derive.rs:556:1 + --> $DIR/subdiagnostic-derive.rs:561:1 | LL | / #[multipart_suggestion(parser::add_paren)] LL | | @@ -348,19 +372,19 @@ LL | | } | |_^ error: `#[suggestion_part(...)]` attribute without `code = "..."` - --> $DIR/subdiagnostic-derive.rs:567:5 + --> $DIR/subdiagnostic-derive.rs:572:5 | LL | #[suggestion_part] | ^^^^^^^^^^^^^^^^^^ error: `#[suggestion_part(...)]` attribute without `code = "..."` - --> $DIR/subdiagnostic-derive.rs:570:5 + --> $DIR/subdiagnostic-derive.rs:575:5 | LL | #[suggestion_part()] | ^^^^^^^^^^^^^^^^^^^^ error: `#[suggestion_part(foo = ...)]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:573:23 + --> $DIR/subdiagnostic-derive.rs:578:23 | LL | #[suggestion_part(foo = "bar")] | ^^^^^^^^^^^ @@ -368,40 +392,34 @@ LL | #[suggestion_part(foo = "bar")] = help: `code` is the only valid nested attribute error: the `#[suggestion_part(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan` - --> $DIR/subdiagnostic-derive.rs:576:5 + --> $DIR/subdiagnostic-derive.rs:581:5 | LL | #[suggestion_part(code = "...")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: the `#[suggestion_part(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan` - --> $DIR/subdiagnostic-derive.rs:579:5 + --> $DIR/subdiagnostic-derive.rs:584:5 | LL | #[suggestion_part()] | ^^^^^^^^^^^^^^^^^^^^ error: specified multiple times - --> $DIR/subdiagnostic-derive.rs:587:37 + --> $DIR/subdiagnostic-derive.rs:592:37 | LL | #[suggestion_part(code = "...", code = ",,,")] | ^^^^^^^^^^^^ | note: previously specified here - --> $DIR/subdiagnostic-derive.rs:587:23 + --> $DIR/subdiagnostic-derive.rs:592:23 | LL | #[suggestion_part(code = "...", code = ",,,")] | ^^^^^^^^^^^^ -error: specified multiple times - --> $DIR/subdiagnostic-derive.rs:617:5 +error: `#[applicability]` has no effect if all `#[suggestion]`/`#[multipart_suggestion]` attributes have a static `applicability = "..."` + --> $DIR/subdiagnostic-derive.rs:621:5 | LL | #[applicability] | ^^^^^^^^^^^^^^^^ - | -note: previously specified here - --> $DIR/subdiagnostic-derive.rs:614:43 - | -LL | #[multipart_suggestion(parser::add_paren, applicability = "machine-applicable")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: cannot find attribute `foo` in this scope --> $DIR/subdiagnostic-derive.rs:63:3 @@ -410,59 +428,59 @@ LL | #[foo] | ^^^ error: cannot find attribute `foo` in this scope - --> $DIR/subdiagnostic-derive.rs:155:3 + --> $DIR/subdiagnostic-derive.rs:159:3 | LL | #[foo] | ^^^ error: cannot find attribute `bar` in this scope - --> $DIR/subdiagnostic-derive.rs:169:7 + --> $DIR/subdiagnostic-derive.rs:173:7 | LL | #[bar] | ^^^ error: cannot find attribute `bar` in this scope - --> $DIR/subdiagnostic-derive.rs:181:7 + --> $DIR/subdiagnostic-derive.rs:185:7 | LL | #[bar = "..."] | ^^^ error: cannot find attribute `bar` in this scope - --> $DIR/subdiagnostic-derive.rs:193:7 + --> $DIR/subdiagnostic-derive.rs:197:7 | LL | #[bar = 4] | ^^^ error: cannot find attribute `bar` in this scope - --> $DIR/subdiagnostic-derive.rs:205:7 + --> $DIR/subdiagnostic-derive.rs:209:7 | LL | #[bar("...")] | ^^^ error: cannot find attribute `bar` in this scope - --> $DIR/subdiagnostic-derive.rs:266:7 + --> $DIR/subdiagnostic-derive.rs:271:7 | LL | #[bar] | ^^^ error: cannot find attribute `bar` in this scope - --> $DIR/subdiagnostic-derive.rs:277:7 + --> $DIR/subdiagnostic-derive.rs:282:7 | LL | #[bar = "..."] | ^^^ error: cannot find attribute `bar` in this scope - --> $DIR/subdiagnostic-derive.rs:288:7 + --> $DIR/subdiagnostic-derive.rs:293:7 | LL | #[bar("...")] | ^^^ error[E0425]: cannot find value `slug` in module `rustc_errors::fluent` - --> $DIR/subdiagnostic-derive.rs:118:9 + --> $DIR/subdiagnostic-derive.rs:122:9 | LL | #[label(slug)] | ^^^^ not found in `rustc_errors::fluent` -error: aborting due to 63 previous errors +error: aborting due to 68 previous errors For more information about this error, try `rustc --explain E0425`. From 57679fb1c5daf402b86763a546ffbfe64621fc2f Mon Sep 17 00:00:00 2001 From: Xiretza Date: Mon, 12 Sep 2022 21:11:49 +0200 Subject: [PATCH 120/586] Better error recovery in Subdiagnostic derive --- .../src/diagnostics/subdiagnostic.rs | 48 +++++++++++-------- 1 file changed, 28 insertions(+), 20 deletions(-) diff --git a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs index 9ea03e186e72a..6545ae086b158 100644 --- a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs +++ b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs @@ -13,6 +13,7 @@ use std::collections::HashMap; use syn::{spanned::Spanned, Attribute, Meta, MetaList, MetaNameValue, NestedMeta, Path}; use synstructure::{BindingInfo, Structure, VariantInfo}; +use super::error::invalid_attr; use super::utils::{SpannedOption, SubdiagnosticKind}; /// The central struct for constructing the `add_to_diagnostic` method from an annotated struct. @@ -271,18 +272,18 @@ impl<'a> SubdiagnosticDeriveBuilder<'a> { "skip_arg" => Ok(quote! {}), "primary_span" => { if kind_stats.has_multipart_suggestion { - throw_invalid_attr!(attr, &Meta::Path(path), |diag| { - diag.help( + invalid_attr(attr, &Meta::Path(path)) + .help( "multipart suggestions use one or more `#[suggestion_part]`s rather \ than one `#[primary_span]`", ) - }) - } - - report_error_if_not_applied_to_span(attr, &info)?; + .emit(); + } else { + report_error_if_not_applied_to_span(attr, &info)?; - let binding = info.binding.binding.clone(); - self.span_field.set_once(binding, span); + let binding = info.binding.binding.clone(); + self.span_field.set_once(binding, span); + } Ok(quote! {}) } @@ -292,14 +293,16 @@ impl<'a> SubdiagnosticDeriveBuilder<'a> { if kind_stats.has_multipart_suggestion { span_err(span, "`#[suggestion_part(...)]` attribute without `code = \"...\"`") .emit(); - Ok(quote! {}) } else { - throw_invalid_attr!(attr, &Meta::Path(path), |diag| { - diag.help( - "`#[suggestion_part(...)]` is only valid in multipart suggestions, use `#[primary_span]` instead", - ) - }); + invalid_attr(attr, &Meta::Path(path)) + .help( + "`#[suggestion_part(...)]` is only valid in multipart suggestions, \ + use `#[primary_span]` instead", + ) + .emit(); } + + Ok(quote! {}) } "applicability" => { if kind_stats.has_multipart_suggestion || kind_stats.has_normal_suggestion { @@ -322,7 +325,7 @@ impl<'a> SubdiagnosticDeriveBuilder<'a> { Ok(quote! {}) } - _ => throw_invalid_attr!(attr, &Meta::Path(path), |diag| { + _ => { let mut span_attrs = vec![]; if kind_stats.has_multipart_suggestion { span_attrs.push("suggestion_part"); @@ -330,11 +333,16 @@ impl<'a> SubdiagnosticDeriveBuilder<'a> { if !kind_stats.all_multipart_suggestions { span_attrs.push("primary_span") } - diag.help(format!( - "only `{}`, `applicability` and `skip_arg` are valid field attributes", - span_attrs.join(", ") - )) - }), + + invalid_attr(attr, &Meta::Path(path)) + .help(format!( + "only `{}`, `applicability` and `skip_arg` are valid field attributes", + span_attrs.join(", ") + )) + .emit(); + + Ok(quote! {}) + } } } From ae56d2a118a780d0ad1de606ad659a95c655b1b2 Mon Sep 17 00:00:00 2001 From: Xiretza Date: Wed, 14 Sep 2022 11:38:31 +0200 Subject: [PATCH 121/586] Add missing code="" attributes to suggestion subdiagnostics --- compiler/rustc_parse/src/parser/diagnostics.rs | 8 ++++---- compiler/rustc_passes/src/errors.rs | 4 ++-- .../ui-fulldeps/session-diagnostic/diagnostic-derive.rs | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index dcea11eadcbf1..0a81cde93be9c 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -289,7 +289,7 @@ pub enum BadTypePlusSub { #[diag(parser::maybe_recover_from_bad_qpath_stage_2)] struct BadQPathStage2 { #[primary_span] - #[suggestion(applicability = "maybe-incorrect")] + #[suggestion(code = "", applicability = "maybe-incorrect")] span: Span, ty: String, } @@ -298,7 +298,7 @@ struct BadQPathStage2 { #[diag(parser::incorrect_semicolon)] struct IncorrectSemicolon<'a> { #[primary_span] - #[suggestion_short(applicability = "machine-applicable")] + #[suggestion_short(code = "", applicability = "machine-applicable")] span: Span, #[help] opt_help: Option<()>, @@ -309,7 +309,7 @@ struct IncorrectSemicolon<'a> { #[diag(parser::incorrect_use_of_await)] struct IncorrectUseOfAwait { #[primary_span] - #[suggestion(parser::parentheses_suggestion, applicability = "machine-applicable")] + #[suggestion(parser::parentheses_suggestion, code = "", applicability = "machine-applicable")] span: Span, } @@ -329,7 +329,7 @@ struct IncorrectAwait { struct InInTypo { #[primary_span] span: Span, - #[suggestion(applicability = "machine-applicable")] + #[suggestion(code = "", applicability = "machine-applicable")] sugg_span: Span, } diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index be67c9e3b82d9..de11bb8901013 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -462,7 +462,7 @@ pub struct LinkSection { pub struct NoMangleForeign { #[label] pub span: Span, - #[suggestion(applicability = "machine-applicable")] + #[suggestion(code = "", applicability = "machine-applicable")] pub attr_span: Span, pub foreign_item_kind: &'static str, } @@ -596,7 +596,7 @@ pub enum UnusedNote { #[derive(LintDiagnostic)] #[diag(passes::unused)] pub struct Unused { - #[suggestion(applicability = "machine-applicable")] + #[suggestion(code = "", applicability = "machine-applicable")] pub attr_span: Span, #[subdiagnostic] pub note: UnusedNote, diff --git a/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs b/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs index c3d3c23fe5bad..eb63a7e52e5fd 100644 --- a/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs +++ b/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs @@ -294,7 +294,7 @@ struct WrongKindOfAnnotation { struct OptionsInErrors { #[label(typeck::label)] label: Option, - #[suggestion(typeck::suggestion)] + #[suggestion(typeck::suggestion, code = "...")] opt_sugg: Option<(Span, Applicability)>, } From 336a72a8daea236a89787f16931611310315340c Mon Sep 17 00:00:00 2001 From: Xiretza Date: Wed, 14 Sep 2022 17:19:40 +0200 Subject: [PATCH 122/586] Unify subdiagnostic attribute parsing --- .../src/diagnostics/diagnostic_builder.rs | 414 ++++++------------ .../session-diagnostic/diagnostic-derive.rs | 56 ++- .../diagnostic-derive.stderr | 250 +++++++---- 3 files changed, 360 insertions(+), 360 deletions(-) diff --git a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs index 72f20efc8346b..2aa292bbce2b6 100644 --- a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs +++ b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs @@ -1,25 +1,23 @@ #![deny(unused_must_use)] +use super::error::throw_invalid_nested_attr; +use super::utils::{SpannedOption, SubdiagnosticKind}; use crate::diagnostics::error::{ - invalid_nested_attr, span_err, throw_invalid_attr, throw_invalid_nested_attr, throw_span_err, - DiagnosticDeriveError, + invalid_nested_attr, span_err, throw_invalid_attr, throw_span_err, DiagnosticDeriveError, }; use crate::diagnostics::utils::{ report_error_if_not_applied_to_span, report_type_error, type_is_unit, type_matches_path, - Applicability, FieldInfo, FieldInnerTy, HasFieldMap, SetOnce, + FieldInfo, FieldInnerTy, HasFieldMap, SetOnce, }; use proc_macro2::{Ident, Span, TokenStream}; use quote::{format_ident, quote}; use std::collections::HashMap; -use std::str::FromStr; use syn::{ parse_quote, spanned::Spanned, Attribute, Field, Meta, MetaList, MetaNameValue, NestedMeta, Path, Type, }; use synstructure::{BindingInfo, Structure}; -use super::utils::SpannedOption; - /// What kind of diagnostic is being derived - a fatal/error/warning or a lint? #[derive(Copy, Clone, PartialEq, Eq)] pub(crate) enum DiagnosticDeriveKind { @@ -45,7 +43,7 @@ pub(crate) struct DiagnosticDeriveBuilder { pub slug: SpannedOption, /// Error codes are a optional part of the struct attribute - this is only set to detect /// multiple specifications. - pub code: SpannedOption, + pub code: SpannedOption<()>, } impl HasFieldMap for DiagnosticDeriveBuilder { @@ -129,6 +127,30 @@ impl DiagnosticDeriveBuilder { || is_subdiagnostic } + fn parse_subdiag_attribute( + &self, + attr: &Attribute, + ) -> Result<(SubdiagnosticKind, Path), DiagnosticDeriveError> { + let (subdiag, slug) = SubdiagnosticKind::from_attr(attr, self)?; + + if let SubdiagnosticKind::MultipartSuggestion { .. } = subdiag { + let meta = attr.parse_meta()?; + throw_invalid_attr!(attr, &meta, |diag| diag + .help("consider creating a `Subdiagnostic` instead")); + } + + let slug = slug.unwrap_or_else(|| match subdiag { + SubdiagnosticKind::Label => parse_quote! { _subdiag::label }, + SubdiagnosticKind::Note => parse_quote! { _subdiag::note }, + SubdiagnosticKind::Help => parse_quote! { _subdiag::help }, + SubdiagnosticKind::Warn => parse_quote! { _subdiag::warn }, + SubdiagnosticKind::Suggestion { .. } => parse_quote! { _subdiag::suggestion }, + SubdiagnosticKind::MultipartSuggestion { .. } => unreachable!(), + }); + + Ok((subdiag, slug)) + } + /// Establishes state in the `DiagnosticDeriveBuilder` resulting from the struct /// attributes like `#[diag(..)]`, such as the slug and error code. Generates /// diagnostic builder calls for setting error code and creating note/help messages. @@ -137,98 +159,64 @@ impl DiagnosticDeriveBuilder { attr: &Attribute, ) -> Result { let diag = &self.diag; - let span = attr.span().unwrap(); let name = attr.path.segments.last().unwrap().ident.to_string(); let name = name.as_str(); let meta = attr.parse_meta()?; - let is_diag = name == "diag"; - - let nested = match meta { - // Most attributes are lists, like `#[diag(..)]` for most cases or - // `#[help(..)]`/`#[note(..)]` when the user is specifying a alternative slug. - Meta::List(MetaList { ref nested, .. }) => nested, - // Subdiagnostics without spans can be applied to the type too, and these are just - // paths: `#[help]`, `#[note]` and `#[warning]` - Meta::Path(_) if !is_diag => { - let fn_name = if name == "warning" { - Ident::new("warn", attr.span()) - } else { - Ident::new(name, attr.span()) - }; - return Ok(self.add_subdiagnostic(&fn_name, parse_quote! { _subdiag::#fn_name })); - } - _ => throw_invalid_attr!(attr, &meta), - }; - - // Check the kind before doing any further processing so that there aren't misleading - // "no kind specified" errors if there are failures later. - match name { - "error" | "lint" => throw_invalid_attr!(attr, &meta, |diag| { - diag.help("`error` and `lint` have been replaced by `diag`") - }), - "warn_" => throw_invalid_attr!(attr, &meta, |diag| { - diag.help("`warn_` have been replaced by `warning`") - }), - "diag" | "help" | "note" | "warning" => (), - _ => throw_invalid_attr!(attr, &meta, |diag| { - diag.help("only `diag`, `help`, `note` and `warning` are valid attributes") - }), - } + if name == "diag" { + let Meta::List(MetaList { ref nested, .. }) = meta else { + throw_invalid_attr!( + attr, + &meta + ); + }; - // First nested element should always be the path, e.g. `#[diag(typeck::invalid)]` or - // `#[help(typeck::another_help)]`. - let mut nested_iter = nested.into_iter(); - if let Some(nested_attr) = nested_iter.next() { - // Report an error if there are any other list items after the path. - if !is_diag && nested_iter.next().is_some() { - throw_invalid_nested_attr!(attr, &nested_attr, |diag| { - diag.help( - "`help`, `note` and `warning` struct attributes can only have one argument", - ) - }); - } + let mut nested_iter = nested.into_iter().peekable(); - match nested_attr { - NestedMeta::Meta(Meta::Path(path)) => { - if is_diag { - self.slug.set_once(path.clone(), span); - } else { - let fn_name = proc_macro2::Ident::new(name, attr.span()); - return Ok(quote! { #diag.#fn_name(rustc_errors::fluent::#path); }); - } + match nested_iter.peek() { + Some(NestedMeta::Meta(Meta::Path(slug))) => { + self.slug.set_once(slug.clone(), slug.span().unwrap()); + nested_iter.next(); } - NestedMeta::Meta(meta @ Meta::NameValue(_)) - if is_diag && meta.path().segments.last().unwrap().ident == "code" => - { - // don't error for valid follow-up attributes - } - nested_attr => throw_invalid_nested_attr!(attr, &nested_attr, |diag| { - diag.help("first argument of the attribute should be the diagnostic slug") - }), + Some(NestedMeta::Meta(Meta::NameValue { .. })) => {} + Some(nested_attr) => throw_invalid_nested_attr!(attr, &nested_attr, |diag| diag + .help("a diagnostic slug is required as the first argument")), + None => throw_invalid_attr!(attr, &meta, |diag| diag + .help("a diagnostic slug is required as the first argument")), }; - } - // Remaining attributes are optional, only `code = ".."` at the moment. - let mut tokens = Vec::new(); - for nested_attr in nested_iter { - let meta = match nested_attr { - syn::NestedMeta::Meta(meta) => meta, - _ => throw_invalid_nested_attr!(attr, &nested_attr), - }; + // Remaining attributes are optional, only `code = ".."` at the moment. + let mut tokens = TokenStream::new(); + for nested_attr in nested_iter { + let (value, path) = match nested_attr { + NestedMeta::Meta(Meta::NameValue(MetaNameValue { + lit: syn::Lit::Str(value), + path, + .. + })) => (value, path), + NestedMeta::Meta(Meta::Path(_)) => { + invalid_nested_attr(attr, &nested_attr) + .help("diagnostic slug must be the first argument") + .emit(); + continue; + } + _ => { + invalid_nested_attr(attr, &nested_attr).emit(); + continue; + } + }; - let path = meta.path(); - let nested_name = path.segments.last().unwrap().ident.to_string(); - // Struct attributes are only allowed to be applied once, and the diagnostic - // changes will be set in the initialisation code. - if let Meta::NameValue(MetaNameValue { lit: syn::Lit::Str(s), .. }) = &meta { - let span = s.span().unwrap(); + let nested_name = path.segments.last().unwrap().ident.to_string(); + // Struct attributes are only allowed to be applied once, and the diagnostic + // changes will be set in the initialisation code. + let span = value.span().unwrap(); match nested_name.as_str() { "code" => { - self.code.set_once(s.value(), span); - let code = &self.code.value_ref(); - tokens.push(quote! { + self.code.set_once((), span); + + let code = value.value(); + tokens.extend(quote! { #diag.code(rustc_errors::DiagnosticId::Error(#code.to_string())); }); } @@ -236,12 +224,22 @@ impl DiagnosticDeriveBuilder { .help("only `code` is a valid nested attributes following the slug") .emit(), } - } else { - invalid_nested_attr(attr, &nested_attr).emit() } + return Ok(tokens); } - Ok(tokens.into_iter().collect()) + let (subdiag, slug) = self.parse_subdiag_attribute(attr)?; + let fn_ident = format_ident!("{}", subdiag); + match subdiag { + SubdiagnosticKind::Note | SubdiagnosticKind::Help | SubdiagnosticKind::Warn => { + Ok(self.add_subdiagnostic(&fn_ident, slug)) + } + SubdiagnosticKind::Label | SubdiagnosticKind::Suggestion { .. } => { + throw_invalid_attr!(attr, &meta, |diag| diag + .help("`#[label]` and `#[suggestion]` can only be applied to fields")); + } + SubdiagnosticKind::MultipartSuggestion { .. } => unreachable!(), + } } fn generate_field_attrs_code(&mut self, binding_info: &BindingInfo<'_>) -> TokenStream { @@ -305,217 +303,83 @@ impl DiagnosticDeriveBuilder { info: FieldInfo<'_>, binding: TokenStream, ) -> Result { - let meta = attr.parse_meta()?; - match meta { - Meta::Path(_) => self.generate_inner_field_code_path(attr, info, binding), - Meta::List(MetaList { .. }) => self.generate_inner_field_code_list(attr, info, binding), - _ => throw_invalid_attr!(attr, &meta), - } - } - - fn generate_inner_field_code_path( - &mut self, - attr: &Attribute, - info: FieldInfo<'_>, - binding: TokenStream, - ) -> Result { - assert!(matches!(attr.parse_meta()?, Meta::Path(_))); let diag = &self.diag; - let meta = attr.parse_meta()?; - let ident = &attr.path.segments.last().unwrap().ident; - let name = ident.to_string(); - let name = name.as_str(); - match name { - "skip_arg" => { - // Don't need to do anything - by virtue of the attribute existing, the - // `set_arg` call will not be generated. - Ok(quote! {}) - } - "primary_span" => { - match self.kind { + if let Meta::Path(_) = meta { + let ident = &attr.path.segments.last().unwrap().ident; + let name = ident.to_string(); + let name = name.as_str(); + match name { + "skip_arg" => { + // Don't need to do anything - by virtue of the attribute existing, the + // `set_arg` call will not be generated. + return Ok(quote! {}); + } + "primary_span" => match self.kind { DiagnosticDeriveKind::Diagnostic => { report_error_if_not_applied_to_span(attr, &info)?; - Ok(quote! { + return Ok(quote! { #diag.set_span(#binding); - }) + }); } DiagnosticDeriveKind::LintDiagnostic => { throw_invalid_attr!(attr, &meta, |diag| { diag.help("the `primary_span` field attribute is not valid for lint diagnostics") }) } - } + }, + "subdiagnostic" => return Ok(quote! { #diag.subdiagnostic(#binding); }), + _ => {} } - "label" => { + } + + let (subdiag, slug) = self.parse_subdiag_attribute(attr)?; + + let fn_ident = format_ident!("{}", subdiag); + match subdiag { + SubdiagnosticKind::Label => { report_error_if_not_applied_to_span(attr, &info)?; - Ok(self.add_spanned_subdiagnostic(binding, ident, parse_quote! { _subdiag::label })) + Ok(self.add_spanned_subdiagnostic(binding, &fn_ident, slug)) } - "note" | "help" | "warning" => { - let warn_ident = Ident::new("warn", Span::call_site()); - let (ident, path) = match name { - "note" => (ident, parse_quote! { _subdiag::note }), - "help" => (ident, parse_quote! { _subdiag::help }), - "warning" => (&warn_ident, parse_quote! { _subdiag::warn }), - _ => unreachable!(), - }; + SubdiagnosticKind::Note | SubdiagnosticKind::Help | SubdiagnosticKind::Warn => { if type_matches_path(&info.ty, &["rustc_span", "Span"]) { - Ok(self.add_spanned_subdiagnostic(binding, ident, path)) + Ok(self.add_spanned_subdiagnostic(binding, &fn_ident, slug)) } else if type_is_unit(&info.ty) { - Ok(self.add_subdiagnostic(ident, path)) + Ok(self.add_subdiagnostic(&fn_ident, slug)) } else { report_type_error(attr, "`Span` or `()`")? } } - "subdiagnostic" => Ok(quote! { #diag.subdiagnostic(#binding); }), - _ => throw_invalid_attr!(attr, &meta, |diag| { - diag.help( - "only `skip_arg`, `primary_span`, `label`, `note`, `help` and `subdiagnostic` \ - are valid field attributes", - ) - }), - } - } - - fn generate_inner_field_code_list( - &mut self, - attr: &Attribute, - info: FieldInfo<'_>, - binding: TokenStream, - ) -> Result { - let meta = attr.parse_meta()?; - let Meta::List(MetaList { ref path, ref nested, .. }) = meta else { unreachable!() }; - - let ident = &attr.path.segments.last().unwrap().ident; - let name = path.segments.last().unwrap().ident.to_string(); - let name = name.as_ref(); - match name { - "suggestion" | "suggestion_short" | "suggestion_hidden" | "suggestion_verbose" => { - return self.generate_inner_field_code_suggestion(attr, info); - } - "label" | "help" | "note" | "warning" => (), - _ => throw_invalid_attr!(attr, &meta, |diag| { - diag.help( - "only `label`, `help`, `note`, `warn` or `suggestion{,_short,_hidden,_verbose}` are \ - valid field attributes", - ) - }), - } - - // For `#[label(..)]`, `#[note(..)]` and `#[help(..)]`, the first nested element must be a - // path, e.g. `#[label(typeck::label)]`. - let mut nested_iter = nested.into_iter(); - let msg = match nested_iter.next() { - Some(NestedMeta::Meta(Meta::Path(path))) => path.clone(), - Some(nested_attr) => throw_invalid_nested_attr!(attr, &nested_attr), - None => throw_invalid_attr!(attr, &meta), - }; - - // None of these attributes should have anything following the slug. - if nested_iter.next().is_some() { - throw_invalid_attr!(attr, &meta); - } - - match name { - "label" => { - report_error_if_not_applied_to_span(attr, &info)?; - Ok(self.add_spanned_subdiagnostic(binding, ident, msg)) - } - "note" | "help" if type_matches_path(&info.ty, &["rustc_span", "Span"]) => { - Ok(self.add_spanned_subdiagnostic(binding, ident, msg)) - } - "note" | "help" if type_is_unit(&info.ty) => Ok(self.add_subdiagnostic(ident, msg)), - // `warning` must be special-cased because the attribute `warn` already has meaning and - // so isn't used, despite the diagnostic API being named `warn`. - "warning" if type_matches_path(&info.ty, &["rustc_span", "Span"]) => Ok(self - .add_spanned_subdiagnostic(binding, &Ident::new("warn", Span::call_site()), msg)), - "warning" if type_is_unit(&info.ty) => { - Ok(self.add_subdiagnostic(&Ident::new("warn", Span::call_site()), msg)) - } - "note" | "help" | "warning" => report_type_error(attr, "`Span` or `()`")?, - _ => unreachable!(), - } - } - - fn generate_inner_field_code_suggestion( - &mut self, - attr: &Attribute, - info: FieldInfo<'_>, - ) -> Result { - let diag = &self.diag; - - let mut meta = attr.parse_meta()?; - let Meta::List(MetaList { ref path, ref mut nested, .. }) = meta else { unreachable!() }; - - let (span_field, mut applicability) = self.span_and_applicability_of_ty(info)?; - - let mut code = None; - - let mut nested_iter = nested.into_iter().peekable(); - let msg = if let Some(NestedMeta::Meta(Meta::Path(path))) = nested_iter.peek() { - let path = path.clone(); - // Move the iterator forward if a path was found (don't otherwise so that - // code/applicability can be found or an error emitted). - nested_iter.next(); - Some(path) - } else { - None - }; - - for nested_attr in nested_iter { - let meta = match nested_attr { - syn::NestedMeta::Meta(ref meta) => meta, - syn::NestedMeta::Lit(_) => throw_invalid_nested_attr!(attr, &nested_attr), - }; - - let nested_name = meta.path().segments.last().unwrap().ident.to_string(); - let nested_name = nested_name.as_str(); - match meta { - Meta::NameValue(MetaNameValue { lit: syn::Lit::Str(s), .. }) => { - let span = meta.span().unwrap(); - match nested_name { - "code" => { - let formatted_str = self.build_format(&s.value(), s.span()); - code.set_once(formatted_str, span); - } - "applicability" => match Applicability::from_str(&s.value()) { - Ok(v) => applicability.set_once(quote! { #v }, span), - Err(()) => { - span_err(span, "invalid applicability").emit(); - } - }, - _ => throw_invalid_nested_attr!(attr, &nested_attr, |diag| { - diag.help( - "only `message`, `code` and `applicability` are valid field \ - attributes", - ) - }), - } + SubdiagnosticKind::Suggestion { + suggestion_kind, + applicability: static_applicability, + code, + } => { + let (span_field, mut applicability) = self.span_and_applicability_of_ty(info)?; + + if let Some((static_applicability, span)) = static_applicability { + applicability.set_once(quote! { #static_applicability }, span); } - _ => throw_invalid_nested_attr!(attr, &nested_attr, |diag| { - if matches!(meta, Meta::Path(_)) { - diag.help("a diagnostic slug must be the first argument to the attribute") - } else { - diag - } - }), + + let applicability = applicability + .value() + .unwrap_or_else(|| quote! { rustc_errors::Applicability::Unspecified }); + let style = suggestion_kind.to_suggestion_style(); + + Ok(quote! { + #diag.span_suggestion_with_style( + #span_field, + rustc_errors::fluent::#slug, + #code, + #applicability, + #style + ); + }) } + SubdiagnosticKind::MultipartSuggestion { .. } => unreachable!(), } - - let applicability = applicability - .value() - .unwrap_or_else(|| quote!(rustc_errors::Applicability::Unspecified)); - - let name = path.segments.last().unwrap().ident.to_string(); - let method = format_ident!("span_{}", name); - - let msg = msg.unwrap_or_else(|| parse_quote! { _subdiag::suggestion }); - let msg = quote! { rustc_errors::fluent::#msg }; - let code = code.value().unwrap_or_else(|| quote! { String::new() }); - - Ok(quote! { #diag.#method(#span_field, #msg, #code, #applicability); }) } /// Adds a spanned subdiagnostic by generating a `diag.span_$kind` call with the current slug diff --git a/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs b/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs index eb63a7e52e5fd..ad481c14bab8d 100644 --- a/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs +++ b/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs @@ -76,13 +76,15 @@ struct InvalidNestedStructAttr1 {} #[derive(Diagnostic)] #[diag(nonsense = "...", code = "E0123", slug = "foo")] //~^ ERROR `#[diag(nonsense = ...)]` is not a valid attribute -//~^^ ERROR diagnostic slug not specified +//~| ERROR `#[diag(slug = ...)]` is not a valid attribute +//~| ERROR diagnostic slug not specified struct InvalidNestedStructAttr2 {} #[derive(Diagnostic)] #[diag(nonsense = 4, code = "E0123", slug = "foo")] //~^ ERROR `#[diag(nonsense = ...)]` is not a valid attribute -//~^^ ERROR diagnostic slug not specified +//~| ERROR `#[diag(slug = ...)]` is not a valid attribute +//~| ERROR diagnostic slug not specified struct InvalidNestedStructAttr3 {} #[derive(Diagnostic)] @@ -217,6 +219,7 @@ struct Suggest { #[diag(typeck::ambiguous_lifetime_bound, code = "E0123")] struct SuggestWithoutCode { #[suggestion(typeck::suggestion)] + //~^ ERROR suggestion without `code = "..."` suggestion: (Span, Applicability), } @@ -225,6 +228,7 @@ struct SuggestWithoutCode { struct SuggestWithBadKey { #[suggestion(nonsense = "bar")] //~^ ERROR `#[suggestion(nonsense = ...)]` is not a valid attribute + //~| ERROR suggestion without `code = "..."` suggestion: (Span, Applicability), } @@ -233,6 +237,7 @@ struct SuggestWithBadKey { struct SuggestWithShorthandMsg { #[suggestion(msg = "bar")] //~^ ERROR `#[suggestion(msg = ...)]` is not a valid attribute + //~| ERROR suggestion without `code = "..."` suggestion: (Span, Applicability), } @@ -507,7 +512,7 @@ struct OptUnitField { #[diag(typeck::ambiguous_lifetime_bound, code = "E0123")] struct LabelWithTrailingPath { #[label(typeck::label, foo)] - //~^ ERROR `#[label(...)]` is not a valid attribute + //~^ ERROR `#[label(foo)]` is not a valid attribute span: Span, } @@ -515,7 +520,7 @@ struct LabelWithTrailingPath { #[diag(typeck::ambiguous_lifetime_bound, code = "E0123")] struct LabelWithTrailingNameValue { #[label(typeck::label, foo = "...")] - //~^ ERROR `#[label(...)]` is not a valid attribute + //~^ ERROR `#[label(foo = ...)]` is not a valid attribute span: Span, } @@ -523,7 +528,7 @@ struct LabelWithTrailingNameValue { #[diag(typeck::ambiguous_lifetime_bound, code = "E0123")] struct LabelWithTrailingList { #[label(typeck::label, foo("..."))] - //~^ ERROR `#[label(...)]` is not a valid attribute + //~^ ERROR `#[label(foo(...))]` is not a valid attribute span: Span, } @@ -605,3 +610,44 @@ struct MissingApplicabilityInSuggestionTuple { suggestion: (Span,), //~^ ERROR wrong types for suggestion } + +#[derive(Diagnostic)] +#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")] +struct MissingCodeInSuggestion { + #[suggestion(typeck::suggestion)] + //~^ ERROR suggestion without `code = "..."` + suggestion: Span, +} + +#[derive(Diagnostic)] +#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")] +#[multipart_suggestion(typeck::suggestion)] +//~^ ERROR `#[multipart_suggestion(...)]` is not a valid attribute +//~| ERROR cannot find attribute `multipart_suggestion` in this scope +#[multipart_suggestion()] +//~^ ERROR `#[multipart_suggestion(...)]` is not a valid attribute +//~| ERROR cannot find attribute `multipart_suggestion` in this scope +struct MultipartSuggestion { + #[multipart_suggestion(typeck::suggestion)] + //~^ ERROR `#[multipart_suggestion(...)]` is not a valid attribute + //~| ERROR cannot find attribute `multipart_suggestion` in this scope + suggestion: Span, +} + +#[derive(Diagnostic)] +#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")] +#[suggestion(typeck::suggestion, code = "...")] +//~^ ERROR `#[suggestion(...)]` is not a valid attribute +struct SuggestionOnStruct { + #[primary_span] + suggestion: Span, +} + +#[derive(Diagnostic)] +#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")] +#[label] +//~^ ERROR `#[label]` is not a valid attribute +struct LabelOnStruct { + #[primary_span] + suggestion: Span, +} diff --git a/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr b/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr index f5432b0bf6561..9919b12beaf0a 100644 --- a/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr +++ b/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr @@ -20,8 +20,6 @@ error: `#[nonsense(...)]` is not a valid attribute | LL | #[nonsense(typeck::ambiguous_lifetime_bound, code = "E0123")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: only `diag`, `help`, `note` and `warning` are valid attributes error: diagnostic slug not specified --> $DIR/diagnostic-derive.rs:53:1 @@ -41,7 +39,7 @@ error: `#[diag("...")]` is not a valid attribute LL | #[diag("E0123")] | ^^^^^^^ | - = help: first argument of the attribute should be the diagnostic slug + = help: a diagnostic slug is required as the first argument error: diagnostic slug not specified --> $DIR/diagnostic-derive.rs:60:1 @@ -60,7 +58,7 @@ error: `#[diag(nonsense(...))]` is not a valid attribute LL | #[diag(nonsense("foo"), code = "E0123", slug = "foo")] | ^^^^^^^^^^^^^^^ | - = help: first argument of the attribute should be the diagnostic slug + = help: a diagnostic slug is required as the first argument error: diagnostic slug not specified --> $DIR/diagnostic-derive.rs:71:1 @@ -79,7 +77,15 @@ error: `#[diag(nonsense = ...)]` is not a valid attribute LL | #[diag(nonsense = "...", code = "E0123", slug = "foo")] | ^^^^^^^^^^^^^^^^ | - = help: first argument of the attribute should be the diagnostic slug + = help: only `code` is a valid nested attributes following the slug + +error: `#[diag(slug = ...)]` is not a valid attribute + --> $DIR/diagnostic-derive.rs:77:42 + | +LL | #[diag(nonsense = "...", code = "E0123", slug = "foo")] + | ^^^^^^^^^^^^ + | + = help: only `code` is a valid nested attributes following the slug error: diagnostic slug not specified --> $DIR/diagnostic-derive.rs:77:1 @@ -87,32 +93,40 @@ error: diagnostic slug not specified LL | / #[diag(nonsense = "...", code = "E0123", slug = "foo")] LL | | LL | | +LL | | LL | | struct InvalidNestedStructAttr2 {} | |__________________________________^ | = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(typeck::example_error)]` error: `#[diag(nonsense = ...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:83:8 + --> $DIR/diagnostic-derive.rs:84:8 | LL | #[diag(nonsense = 4, code = "E0123", slug = "foo")] | ^^^^^^^^^^^^ + +error: `#[diag(slug = ...)]` is not a valid attribute + --> $DIR/diagnostic-derive.rs:84:38 | - = help: first argument of the attribute should be the diagnostic slug +LL | #[diag(nonsense = 4, code = "E0123", slug = "foo")] + | ^^^^^^^^^^^^ + | + = help: only `code` is a valid nested attributes following the slug error: diagnostic slug not specified - --> $DIR/diagnostic-derive.rs:83:1 + --> $DIR/diagnostic-derive.rs:84:1 | LL | / #[diag(nonsense = 4, code = "E0123", slug = "foo")] LL | | LL | | +LL | | LL | | struct InvalidNestedStructAttr3 {} | |__________________________________^ | = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(typeck::example_error)]` error: `#[diag(slug = ...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:89:58 + --> $DIR/diagnostic-derive.rs:91:58 | LL | #[diag(typeck::ambiguous_lifetime_bound, code = "E0123", slug = "foo")] | ^^^^^^^^^^^^ @@ -120,55 +134,57 @@ LL | #[diag(typeck::ambiguous_lifetime_bound, code = "E0123", slug = "foo")] = help: only `code` is a valid nested attributes following the slug error: `#[suggestion = ...]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:96:5 + --> $DIR/diagnostic-derive.rs:98:5 | LL | #[suggestion = "bar"] | ^^^^^^^^^^^^^^^^^^^^^ error: specified multiple times - --> $DIR/diagnostic-derive.rs:103:1 + --> $DIR/diagnostic-derive.rs:105:8 | LL | #[diag(typeck::ambiguous_lifetime_bound, code = "E0456")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: previously specified here - --> $DIR/diagnostic-derive.rs:102:1 + --> $DIR/diagnostic-derive.rs:104:8 | LL | #[diag(typeck::ambiguous_lifetime_bound, code = "E0123")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: specified multiple times - --> $DIR/diagnostic-derive.rs:103:49 + --> $DIR/diagnostic-derive.rs:105:49 | LL | #[diag(typeck::ambiguous_lifetime_bound, code = "E0456")] | ^^^^^^^ | note: previously specified here - --> $DIR/diagnostic-derive.rs:102:49 + --> $DIR/diagnostic-derive.rs:104:49 | LL | #[diag(typeck::ambiguous_lifetime_bound, code = "E0123")] | ^^^^^^^ error: specified multiple times - --> $DIR/diagnostic-derive.rs:109:65 + --> $DIR/diagnostic-derive.rs:111:65 | LL | #[diag(typeck::ambiguous_lifetime_bound, code = "E0456", code = "E0457")] | ^^^^^^^ | note: previously specified here - --> $DIR/diagnostic-derive.rs:109:49 + --> $DIR/diagnostic-derive.rs:111:49 | LL | #[diag(typeck::ambiguous_lifetime_bound, code = "E0456", code = "E0457")] | ^^^^^^^ error: `#[diag(typeck::ambiguous_lifetime_bound)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:114:42 + --> $DIR/diagnostic-derive.rs:116:42 | LL | #[diag(typeck::ambiguous_lifetime_bound, typeck::ambiguous_lifetime_bound, code = "E0456")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: diagnostic slug must be the first argument error: diagnostic slug not specified - --> $DIR/diagnostic-derive.rs:119:1 + --> $DIR/diagnostic-derive.rs:121:1 | LL | struct KindNotProvided {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -176,7 +192,7 @@ LL | struct KindNotProvided {} = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(typeck::example_error)]` error: diagnostic slug not specified - --> $DIR/diagnostic-derive.rs:122:1 + --> $DIR/diagnostic-derive.rs:124:1 | LL | / #[diag(code = "E0456")] LL | | @@ -186,33 +202,31 @@ LL | | struct SlugNotProvided {} = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(typeck::example_error)]` error: the `#[primary_span]` attribute can only be applied to fields of type `Span` or `MultiSpan` - --> $DIR/diagnostic-derive.rs:133:5 + --> $DIR/diagnostic-derive.rs:135:5 | LL | #[primary_span] | ^^^^^^^^^^^^^^^ error: `#[nonsense]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:141:5 + --> $DIR/diagnostic-derive.rs:143:5 | LL | #[nonsense] | ^^^^^^^^^^^ - | - = help: only `skip_arg`, `primary_span`, `label`, `note`, `help` and `subdiagnostic` are valid field attributes error: the `#[label(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan` - --> $DIR/diagnostic-derive.rs:158:5 + --> $DIR/diagnostic-derive.rs:160:5 | LL | #[label(typeck::label)] | ^^^^^^^^^^^^^^^^^^^^^^^ error: `name` doesn't refer to a field on this type - --> $DIR/diagnostic-derive.rs:166:45 + --> $DIR/diagnostic-derive.rs:168:45 | LL | #[suggestion(typeck::suggestion, code = "{name}")] | ^^^^^^^^ error: invalid format string: expected `'}'` but string was terminated - --> $DIR/diagnostic-derive.rs:171:16 + --> $DIR/diagnostic-derive.rs:173:16 | LL | #[derive(Diagnostic)] | - ^ expected `'}'` in format string @@ -223,7 +237,7 @@ LL | #[derive(Diagnostic)] = note: this error originates in the derive macro `Diagnostic` (in Nightly builds, run with -Z macro-backtrace for more info) error: invalid format string: unmatched `}` found - --> $DIR/diagnostic-derive.rs:181:15 + --> $DIR/diagnostic-derive.rs:183:15 | LL | #[derive(Diagnostic)] | ^ unmatched `}` in format string @@ -232,29 +246,47 @@ LL | #[derive(Diagnostic)] = note: this error originates in the derive macro `Diagnostic` (in Nightly builds, run with -Z macro-backtrace for more info) error: the `#[label(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan` - --> $DIR/diagnostic-derive.rs:201:5 + --> $DIR/diagnostic-derive.rs:203:5 | LL | #[label(typeck::label)] | ^^^^^^^^^^^^^^^^^^^^^^^ +error: suggestion without `code = "..."` + --> $DIR/diagnostic-derive.rs:221:5 + | +LL | #[suggestion(typeck::suggestion)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + error: `#[suggestion(nonsense = ...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:226:18 + --> $DIR/diagnostic-derive.rs:229:18 | LL | #[suggestion(nonsense = "bar")] | ^^^^^^^^^^^^^^^^ | - = help: only `message`, `code` and `applicability` are valid field attributes + = help: only `code` and `applicability` are valid nested attributes + +error: suggestion without `code = "..."` + --> $DIR/diagnostic-derive.rs:229:5 + | +LL | #[suggestion(nonsense = "bar")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: `#[suggestion(msg = ...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:234:18 + --> $DIR/diagnostic-derive.rs:238:18 | LL | #[suggestion(msg = "bar")] | ^^^^^^^^^^^ | - = help: only `message`, `code` and `applicability` are valid field attributes + = help: only `code` and `applicability` are valid nested attributes + +error: suggestion without `code = "..."` + --> $DIR/diagnostic-derive.rs:238:5 + | +LL | #[suggestion(msg = "bar")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: wrong field type for suggestion - --> $DIR/diagnostic-derive.rs:256:5 + --> $DIR/diagnostic-derive.rs:261:5 | LL | / #[suggestion(typeck::suggestion, code = "This is suggested code")] LL | | @@ -264,73 +296,75 @@ LL | | suggestion: Applicability, = help: `#[suggestion(...)]` should be applied to fields of type `Span` or `(Span, Applicability)` error: specified multiple times - --> $DIR/diagnostic-derive.rs:272:24 + --> $DIR/diagnostic-derive.rs:277:24 | LL | suggestion: (Span, Span, Applicability), | ^^^^ | note: previously specified here - --> $DIR/diagnostic-derive.rs:272:18 + --> $DIR/diagnostic-derive.rs:277:18 | LL | suggestion: (Span, Span, Applicability), | ^^^^ error: specified multiple times - --> $DIR/diagnostic-derive.rs:280:33 + --> $DIR/diagnostic-derive.rs:285:33 | LL | suggestion: (Applicability, Applicability, Span), | ^^^^^^^^^^^^^ | note: previously specified here - --> $DIR/diagnostic-derive.rs:280:18 + --> $DIR/diagnostic-derive.rs:285:18 | LL | suggestion: (Applicability, Applicability, Span), | ^^^^^^^^^^^^^ error: `#[label = ...]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:287:5 + --> $DIR/diagnostic-derive.rs:292:5 | LL | #[label = "bar"] | ^^^^^^^^^^^^^^^^ error: specified multiple times - --> $DIR/diagnostic-derive.rs:438:52 + --> $DIR/diagnostic-derive.rs:443:52 | LL | #[suggestion(typeck::suggestion, code = "...", applicability = "maybe-incorrect")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: previously specified here - --> $DIR/diagnostic-derive.rs:440:24 + --> $DIR/diagnostic-derive.rs:445:24 | LL | suggestion: (Span, Applicability), | ^^^^^^^^^^^^^ error: invalid applicability - --> $DIR/diagnostic-derive.rs:446:52 + --> $DIR/diagnostic-derive.rs:451:52 | LL | #[suggestion(typeck::suggestion, code = "...", applicability = "batman")] | ^^^^^^^^^^^^^^^^^^^^^^^^ -error: `#[label(...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:509:5 +error: `#[label(foo)]` is not a valid attribute + --> $DIR/diagnostic-derive.rs:514:28 | LL | #[label(typeck::label, foo)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^ + | + = help: a diagnostic slug must be the first argument to the attribute -error: `#[label(...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:517:5 +error: `#[label(foo = ...)]` is not a valid attribute + --> $DIR/diagnostic-derive.rs:522:28 | LL | #[label(typeck::label, foo = "...")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^ -error: `#[label(...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:525:5 +error: `#[label(foo(...))]` is not a valid attribute + --> $DIR/diagnostic-derive.rs:530:28 | LL | #[label(typeck::label, foo("..."))] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^ error: `#[primary_span]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:538:5 + --> $DIR/diagnostic-derive.rs:543:5 | LL | #[primary_span] | ^^^^^^^^^^^^^^^ @@ -338,15 +372,13 @@ LL | #[primary_span] = help: the `primary_span` field attribute is not valid for lint diagnostics error: `#[error(...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:558:1 + --> $DIR/diagnostic-derive.rs:563:1 | LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0123")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: `error` and `lint` have been replaced by `diag` error: diagnostic slug not specified - --> $DIR/diagnostic-derive.rs:558:1 + --> $DIR/diagnostic-derive.rs:563:1 | LL | / #[error(typeck::ambiguous_lifetime_bound, code = "E0123")] LL | | @@ -358,15 +390,13 @@ LL | | struct ErrorAttribute {} = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(typeck::example_error)]` error: `#[warn_(...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:565:1 + --> $DIR/diagnostic-derive.rs:570:1 | LL | #[warn_(typeck::ambiguous_lifetime_bound, code = "E0123")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: `warn_` have been replaced by `warning` error: diagnostic slug not specified - --> $DIR/diagnostic-derive.rs:565:1 + --> $DIR/diagnostic-derive.rs:570:1 | LL | / #[warn_(typeck::ambiguous_lifetime_bound, code = "E0123")] LL | | @@ -378,15 +408,13 @@ LL | | struct WarnAttribute {} = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(typeck::example_error)]` error: `#[lint(...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:572:1 + --> $DIR/diagnostic-derive.rs:577:1 | LL | #[lint(typeck::ambiguous_lifetime_bound, code = "E0123")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: `error` and `lint` have been replaced by `diag` error: diagnostic slug not specified - --> $DIR/diagnostic-derive.rs:572:1 + --> $DIR/diagnostic-derive.rs:577:1 | LL | / #[lint(typeck::ambiguous_lifetime_bound, code = "E0123")] LL | | @@ -398,15 +426,13 @@ LL | | struct LintAttributeOnSessionDiag {} = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(typeck::example_error)]` error: `#[lint(...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:579:1 + --> $DIR/diagnostic-derive.rs:584:1 | LL | #[lint(typeck::ambiguous_lifetime_bound, code = "E0123")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: `error` and `lint` have been replaced by `diag` error: diagnostic slug not specified - --> $DIR/diagnostic-derive.rs:579:1 + --> $DIR/diagnostic-derive.rs:584:1 | LL | / #[lint(typeck::ambiguous_lifetime_bound, code = "E0123")] LL | | @@ -418,19 +444,19 @@ LL | | struct LintAttributeOnLintDiag {} = help: specify the slug as the first argument to the attribute, such as `#[diag(typeck::example_error)]` error: specified multiple times - --> $DIR/diagnostic-derive.rs:588:52 + --> $DIR/diagnostic-derive.rs:593:52 | LL | #[suggestion(typeck::suggestion, code = "...", code = ",,,")] | ^^^^^^^^^^^^ | note: previously specified here - --> $DIR/diagnostic-derive.rs:588:38 + --> $DIR/diagnostic-derive.rs:593:38 | LL | #[suggestion(typeck::suggestion, code = "...", code = ",,,")] | ^^^^^^^^^^^^ error: wrong types for suggestion - --> $DIR/diagnostic-derive.rs:597:24 + --> $DIR/diagnostic-derive.rs:602:24 | LL | suggestion: (Span, usize), | ^^^^^ @@ -438,13 +464,59 @@ LL | suggestion: (Span, usize), = help: `#[suggestion(...)]` on a tuple field must be applied to fields of type `(Span, Applicability)` error: wrong types for suggestion - --> $DIR/diagnostic-derive.rs:605:17 + --> $DIR/diagnostic-derive.rs:610:17 | LL | suggestion: (Span,), | ^^^^^^^ | = help: `#[suggestion(...)]` on a tuple field must be applied to fields of type `(Span, Applicability)` +error: suggestion without `code = "..."` + --> $DIR/diagnostic-derive.rs:617:5 + | +LL | #[suggestion(typeck::suggestion)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: `#[multipart_suggestion(...)]` is not a valid attribute + --> $DIR/diagnostic-derive.rs:624:1 + | +LL | #[multipart_suggestion(typeck::suggestion)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider creating a `Subdiagnostic` instead + +error: `#[multipart_suggestion(...)]` is not a valid attribute + --> $DIR/diagnostic-derive.rs:627:1 + | +LL | #[multipart_suggestion()] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider creating a `Subdiagnostic` instead + +error: `#[multipart_suggestion(...)]` is not a valid attribute + --> $DIR/diagnostic-derive.rs:631:5 + | +LL | #[multipart_suggestion(typeck::suggestion)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider creating a `Subdiagnostic` instead + +error: `#[suggestion(...)]` is not a valid attribute + --> $DIR/diagnostic-derive.rs:639:1 + | +LL | #[suggestion(typeck::suggestion, code = "...")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: `#[label]` and `#[suggestion]` can only be applied to fields + +error: `#[label]` is not a valid attribute + --> $DIR/diagnostic-derive.rs:648:1 + | +LL | #[label] + | ^^^^^^^^ + | + = help: `#[label]` and `#[suggestion]` can only be applied to fields + error: cannot find attribute `nonsense` in this scope --> $DIR/diagnostic-derive.rs:53:3 | @@ -452,35 +524,53 @@ LL | #[nonsense(typeck::ambiguous_lifetime_bound, code = "E0123")] | ^^^^^^^^ error: cannot find attribute `nonsense` in this scope - --> $DIR/diagnostic-derive.rs:141:7 + --> $DIR/diagnostic-derive.rs:143:7 | LL | #[nonsense] | ^^^^^^^^ error: cannot find attribute `error` in this scope - --> $DIR/diagnostic-derive.rs:558:3 + --> $DIR/diagnostic-derive.rs:563:3 | LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0123")] | ^^^^^ error: cannot find attribute `warn_` in this scope - --> $DIR/diagnostic-derive.rs:565:3 + --> $DIR/diagnostic-derive.rs:570:3 | LL | #[warn_(typeck::ambiguous_lifetime_bound, code = "E0123")] | ^^^^^ help: a built-in attribute with a similar name exists: `warn` error: cannot find attribute `lint` in this scope - --> $DIR/diagnostic-derive.rs:572:3 + --> $DIR/diagnostic-derive.rs:577:3 | LL | #[lint(typeck::ambiguous_lifetime_bound, code = "E0123")] | ^^^^ help: a built-in attribute with a similar name exists: `link` error: cannot find attribute `lint` in this scope - --> $DIR/diagnostic-derive.rs:579:3 + --> $DIR/diagnostic-derive.rs:584:3 | LL | #[lint(typeck::ambiguous_lifetime_bound, code = "E0123")] | ^^^^ help: a built-in attribute with a similar name exists: `link` +error: cannot find attribute `multipart_suggestion` in this scope + --> $DIR/diagnostic-derive.rs:624:3 + | +LL | #[multipart_suggestion(typeck::suggestion)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: cannot find attribute `multipart_suggestion` in this scope + --> $DIR/diagnostic-derive.rs:627:3 + | +LL | #[multipart_suggestion()] + | ^^^^^^^^^^^^^^^^^^^^ + +error: cannot find attribute `multipart_suggestion` in this scope + --> $DIR/diagnostic-derive.rs:631:7 + | +LL | #[multipart_suggestion(typeck::suggestion)] + | ^^^^^^^^^^^^^^^^^^^^ + error[E0425]: cannot find value `nonsense` in module `rustc_errors::fluent` --> $DIR/diagnostic-derive.rs:66:8 | @@ -488,7 +578,7 @@ LL | #[diag(nonsense, code = "E0123")] | ^^^^^^^^ not found in `rustc_errors::fluent` error[E0277]: the trait bound `Hello: IntoDiagnosticArg` is not satisfied - --> $DIR/diagnostic-derive.rs:331:10 + --> $DIR/diagnostic-derive.rs:336:10 | LL | #[derive(Diagnostic)] | ^^^^^^^^^^ the trait `IntoDiagnosticArg` is not implemented for `Hello` @@ -501,7 +591,7 @@ LL | arg: impl IntoDiagnosticArg, | ^^^^^^^^^^^^^^^^^ required by this bound in `DiagnosticBuilder::<'a, G>::set_arg` = note: this error originates in the derive macro `Diagnostic` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 58 previous errors +error: aborting due to 72 previous errors Some errors have detailed explanations: E0277, E0425. For more information about an error, try `rustc --explain E0277`. From a1062b9bdcf691fc09f8683ae36d2b31c06c3d8f Mon Sep 17 00:00:00 2001 From: Rageking8 <106309953+Rageking8@users.noreply.github.com> Date: Thu, 22 Sep 2022 23:41:38 +0800 Subject: [PATCH 123/586] recover from struct nested in struct --- compiler/rustc_parse/src/parser/item.rs | 17 +++++++++++++++++ src/test/ui/parser/issues/issue-101540.rs | 7 +++++++ src/test/ui/parser/issues/issue-101540.stderr | 10 ++++++++++ 3 files changed, 34 insertions(+) create mode 100644 src/test/ui/parser/issues/issue-101540.rs create mode 100644 src/test/ui/parser/issues/issue-101540.stderr diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index e55b5ce71cded..e385ac44113a6 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -1715,6 +1715,7 @@ impl<'a> Parser<'a> { fn parse_field_ident(&mut self, adt_ty: &str, lo: Span) -> PResult<'a, Ident> { let (ident, is_raw) = self.ident_or_err()?; if !is_raw && ident.is_reserved() { + let snapshot = self.create_snapshot_for_diagnostic(); let err = if self.check_fn_front_matter(false) { let inherited_vis = Visibility { span: rustc_span::DUMMY_SP, @@ -1735,6 +1736,22 @@ impl<'a> Parser<'a> { err.help("unlike in C++, Java, and C#, functions are declared in `impl` blocks"); err.help("see https://doc.rust-lang.org/book/ch05-03-method-syntax.html for more information"); err + } else if self.eat_keyword(kw::Struct) { + match self.parse_item_struct() { + Ok((ident, _)) => { + let mut err = self.struct_span_err( + lo.with_hi(ident.span.hi()), + &format!("structs are not allowed in {adt_ty} definitions"), + ); + err.help("consider creating a new `struct` definition instead of nesting"); + err + } + Err(err) => { + err.cancel(); + self.restore_snapshot(snapshot); + self.expected_ident_found() + } + } } else { self.expected_ident_found() }; diff --git a/src/test/ui/parser/issues/issue-101540.rs b/src/test/ui/parser/issues/issue-101540.rs new file mode 100644 index 0000000000000..328ec6f906b1f --- /dev/null +++ b/src/test/ui/parser/issues/issue-101540.rs @@ -0,0 +1,7 @@ +struct S1 { + struct S2 { + //~^ ERROR structs are not allowed in struct definitions + } +} + +fn main() {} diff --git a/src/test/ui/parser/issues/issue-101540.stderr b/src/test/ui/parser/issues/issue-101540.stderr new file mode 100644 index 0000000000000..42e471cc13504 --- /dev/null +++ b/src/test/ui/parser/issues/issue-101540.stderr @@ -0,0 +1,10 @@ +error: structs are not allowed in struct definitions + --> $DIR/issue-101540.rs:2:5 + | +LL | struct S2 { + | _____-^^^^^ +LL | | +LL | | } + | |_____- help: consider creating a new `struct` definition instead of nesting + +error: aborting due to previous error From f4170b38c8735daa9e764ea395c6c32cd7b9ffa3 Mon Sep 17 00:00:00 2001 From: Rageking8 <106309953+Rageking8@users.noreply.github.com> Date: Fri, 23 Sep 2022 00:02:50 +0800 Subject: [PATCH 124/586] Change UI test stderr --- src/test/ui/parser/issues/issue-101540.stderr | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/test/ui/parser/issues/issue-101540.stderr b/src/test/ui/parser/issues/issue-101540.stderr index 42e471cc13504..d4e861b6061fa 100644 --- a/src/test/ui/parser/issues/issue-101540.stderr +++ b/src/test/ui/parser/issues/issue-101540.stderr @@ -2,9 +2,8 @@ error: structs are not allowed in struct definitions --> $DIR/issue-101540.rs:2:5 | LL | struct S2 { - | _____-^^^^^ -LL | | -LL | | } - | |_____- help: consider creating a new `struct` definition instead of nesting + | ^^^^^^^^^ + | + = help: consider creating a new `struct` definition instead of nesting error: aborting due to previous error From 5a5138df5940119744ba80b1d3ed29b1024b973d Mon Sep 17 00:00:00 2001 From: onestacked Date: Thu, 22 Sep 2022 18:21:34 +0200 Subject: [PATCH 125/586] Constify {FormResidual, Try} for ControlFlow --- library/core/src/ops/control_flow.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/library/core/src/ops/control_flow.rs b/library/core/src/ops/control_flow.rs index b1f5559dcfc17..fd567a8c68492 100644 --- a/library/core/src/ops/control_flow.rs +++ b/library/core/src/ops/control_flow.rs @@ -95,7 +95,8 @@ pub enum ControlFlow { } #[unstable(feature = "try_trait_v2", issue = "84277")] -impl ops::Try for ControlFlow { +#[rustc_const_unstable(feature = "const_convert", issue = "88674")] +impl const ops::Try for ControlFlow { type Output = C; type Residual = ControlFlow; @@ -114,7 +115,8 @@ impl ops::Try for ControlFlow { } #[unstable(feature = "try_trait_v2", issue = "84277")] -impl ops::FromResidual for ControlFlow { +#[rustc_const_unstable(feature = "const_convert", issue = "88674")] +impl const ops::FromResidual for ControlFlow { #[inline] fn from_residual(residual: ControlFlow) -> Self { match residual { From c66c2e82c1a405ed3fff99953ab96de03806ca09 Mon Sep 17 00:00:00 2001 From: Rageking8 <106309953+Rageking8@users.noreply.github.com> Date: Fri, 23 Sep 2022 00:24:30 +0800 Subject: [PATCH 126/586] Fix slight issues with stderr --- src/test/ui/parser/issues/issue-101540.stderr | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/test/ui/parser/issues/issue-101540.stderr b/src/test/ui/parser/issues/issue-101540.stderr index d4e861b6061fa..53c7c9590e6ca 100644 --- a/src/test/ui/parser/issues/issue-101540.stderr +++ b/src/test/ui/parser/issues/issue-101540.stderr @@ -1,9 +1,10 @@ error: structs are not allowed in struct definitions --> $DIR/issue-101540.rs:2:5 | -LL | struct S2 { - | ^^^^^^^^^ +LL | struct S2 { + | ^^^^^^^^^ | = help: consider creating a new `struct` definition instead of nesting error: aborting due to previous error + From 381bd2a836f96c9dede1f5ee740e70194d6fb149 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Tue, 20 Sep 2022 20:03:40 +0200 Subject: [PATCH 127/586] Revert "Auto merge of #101862 - cjgillot:lint-regression, r=oli-obk" This reverts commit bc7b17cfe3bf08b618d1c7b64838053faeb1f590, reversing changes made to 5253b0a0a1f366fad0ebed57597fcf2703b9e893. --- compiler/rustc_middle/src/hir/map/mod.rs | 20 ++++++++------------ compiler/rustc_middle/src/lint.rs | 2 +- 2 files changed, 9 insertions(+), 13 deletions(-) diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index ca5598f5ff10f..30a23c342b356 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -61,7 +61,7 @@ pub struct ParentHirIterator<'hir> { } impl<'hir> Iterator for ParentHirIterator<'hir> { - type Item = HirId; + type Item = (HirId, Node<'hir>); fn next(&mut self) -> Option { if self.current_id == CRATE_HIR_ID { @@ -77,7 +77,10 @@ impl<'hir> Iterator for ParentHirIterator<'hir> { } self.current_id = parent_id; - return Some(parent_id); + if let Some(node) = self.map.find(parent_id) { + return Some((parent_id, node)); + } + // If this `HirId` doesn't have an entry, skip it and look for its `parent_id`. } } } @@ -390,8 +393,8 @@ impl<'hir> Map<'hir> { } pub fn enclosing_body_owner(self, hir_id: HirId) -> LocalDefId { - for (_, node) in self.parent_iter(hir_id) { - if let Some(body) = associated_body(node) { + for (parent, _) in self.parent_iter(hir_id) { + if let Some(body) = self.find(parent).map(associated_body).flatten() { return self.body_owner_def_id(body); } } @@ -632,17 +635,10 @@ impl<'hir> Map<'hir> { /// Returns an iterator for the nodes in the ancestor tree of the `current_id` /// until the crate root is reached. Prefer this over your own loop using `get_parent_node`. #[inline] - pub fn parent_id_iter(self, current_id: HirId) -> impl Iterator + 'hir { + pub fn parent_iter(self, current_id: HirId) -> ParentHirIterator<'hir> { ParentHirIterator { current_id, map: self } } - /// Returns an iterator for the nodes in the ancestor tree of the `current_id` - /// until the crate root is reached. Prefer this over your own loop using `get_parent_node`. - #[inline] - pub fn parent_iter(self, current_id: HirId) -> impl Iterator)> { - self.parent_id_iter(current_id).filter_map(move |id| Some((id, self.find(id)?))) - } - /// Returns an iterator for the nodes in the ancestor tree of the `current_id` /// until the crate root is reached. Prefer this over your own loop using `get_parent_node`. #[inline] diff --git a/compiler/rustc_middle/src/lint.rs b/compiler/rustc_middle/src/lint.rs index bb9e1edf86cfe..4cb5ef7917774 100644 --- a/compiler/rustc_middle/src/lint.rs +++ b/compiler/rustc_middle/src/lint.rs @@ -126,7 +126,7 @@ impl ShallowLintLevelMap { return (Some(level), src); } - for parent in tcx.hir().parent_id_iter(start) { + for (parent, _) in tcx.hir().parent_iter(start) { let specs = tcx.shallow_lint_levels_on(parent); if let Some(&(level, src)) = specs.specs.get(&id) { return (Some(level), src); From fc43df0333d5862a219f16d294ae38b14b9191d3 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Tue, 20 Sep 2022 20:04:35 +0200 Subject: [PATCH 128/586] Revert "Auto merge of #101620 - cjgillot:compute_lint_levels_by_def, r=oli-obk" This reverts commit 2cb9a65684dba47c52de8fa938febf97a73e70a9, reversing changes made to 750bd1a7ff3e010611b97ee75d30b7cbf5f3a03c. --- compiler/rustc_errors/src/diagnostic.rs | 5 +- compiler/rustc_errors/src/lib.rs | 2 +- compiler/rustc_lint/src/context.rs | 2 +- compiler/rustc_lint/src/early.rs | 1 - compiler/rustc_lint/src/expect.rs | 4 +- compiler/rustc_lint/src/levels.rs | 680 ++++++++---------- compiler/rustc_lint/src/lib.rs | 1 - compiler/rustc_lint_defs/src/lib.rs | 31 +- .../rustc_middle/src/dep_graph/dep_node.rs | 38 +- compiler/rustc_middle/src/lint.rs | 222 +++--- compiler/rustc_middle/src/query/mod.rs | 10 +- compiler/rustc_middle/src/ty/context.rs | 42 +- compiler/rustc_middle/src/ty/query.rs | 4 +- compiler/rustc_query_impl/src/keys.rs | 17 - .../rustc_query_system/src/dep_graph/mod.rs | 6 +- ...te-non_exhaustive_omitted_patterns_lint.rs | 5 - ...on_exhaustive_omitted_patterns_lint.stderr | 72 +- ...force_warn_expected_lints_fulfilled.stderr | 16 +- 18 files changed, 488 insertions(+), 670 deletions(-) diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index a52e95e92d55c..1c440a0a07efc 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -339,10 +339,9 @@ impl Diagnostic { // The lint index inside the attribute is manually transferred here. let lint_index = expectation_id.get_lint_index(); expectation_id.set_lint_index(None); - let mut stable_id = unstable_to_stable + let mut stable_id = *unstable_to_stable .get(&expectation_id) - .expect("each unstable `LintExpectationId` must have a matching stable id") - .normalize(); + .expect("each unstable `LintExpectationId` must have a matching stable id"); stable_id.set_lint_index(lint_index); *expectation_id = stable_id; diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 68971cebc3527..b44cf352233e3 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -1205,7 +1205,7 @@ impl HandlerInner { if let Some(expectation_id) = diagnostic.level.get_expectation_id() { self.suppressed_expected_diag = true; - self.fulfilled_expectations.insert(expectation_id.normalize()); + self.fulfilled_expectations.insert(expectation_id); } if matches!(diagnostic.level, Warning(_)) diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index 34506c84cb8c7..7ca6ec5d96234 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -560,7 +560,7 @@ pub struct LateContext<'tcx> { /// Context for lint checking of the AST, after expansion, before lowering to HIR. pub struct EarlyContext<'a> { - pub builder: LintLevelsBuilder<'a, crate::levels::TopDown>, + pub builder: LintLevelsBuilder<'a>, pub buffered: LintBuffer, } diff --git a/compiler/rustc_lint/src/early.rs b/compiler/rustc_lint/src/early.rs index 45f54cfed2d59..96ecd79a69cfb 100644 --- a/compiler/rustc_lint/src/early.rs +++ b/compiler/rustc_lint/src/early.rs @@ -59,7 +59,6 @@ impl<'a, T: EarlyLintPass> EarlyContextAndPass<'a, T> { F: FnOnce(&mut Self), { let is_crate_node = id == ast::CRATE_NODE_ID; - debug!(?id); let push = self.context.builder.push(attrs, is_crate_node, None); self.check_id(id); diff --git a/compiler/rustc_lint/src/expect.rs b/compiler/rustc_lint/src/expect.rs index b9a3d52ca9b19..699e81543188f 100644 --- a/compiler/rustc_lint/src/expect.rs +++ b/compiler/rustc_lint/src/expect.rs @@ -16,10 +16,8 @@ fn check_expectations(tcx: TyCtxt<'_>, tool_filter: Option) { return; } - let lint_expectations = tcx.lint_expectations(()); let fulfilled_expectations = tcx.sess.diagnostic().steal_fulfilled_expectation_ids(); - - tracing::debug!(?lint_expectations, ?fulfilled_expectations); + let lint_expectations = &tcx.lint_levels(()).lint_expectations; for (id, expectation) in lint_expectations { // This check will always be true, since `lint_expectations` only diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs index a9ba2ad1d101d..1e16ac51e9e5d 100644 --- a/compiler/rustc_lint/src/levels.rs +++ b/compiler/rustc_lint/src/levels.rs @@ -6,11 +6,10 @@ use rustc_data_structures::fx::FxHashMap; use rustc_errors::{Applicability, Diagnostic, LintDiagnosticBuilder, MultiSpan}; use rustc_hir as hir; use rustc_hir::{intravisit, HirId}; -use rustc_index::vec::IndexVec; use rustc_middle::hir::nested_filter; use rustc_middle::lint::{ - reveal_actual_level, struct_lint_level, LevelAndSource, LintExpectation, LintLevelSource, - ShallowLintLevelMap, + struct_lint_level, LevelAndSource, LintExpectation, LintLevelMap, LintLevelSets, + LintLevelSource, LintSet, LintStackIndex, COMMAND_LINE, }; use rustc_middle::ty::query::Providers; use rustc_middle::ty::{RegisteredTools, TyCtxt}; @@ -28,292 +27,47 @@ use crate::errors::{ UnknownToolInScopedLint, }; -/// Collection of lint levels for the whole crate. -/// This is used by AST-based lints, which do not -/// wait until we have built HIR to be emitted. -#[derive(Debug)] -struct LintLevelSets { - /// Linked list of specifications. - list: IndexVec, -} - -rustc_index::newtype_index! { - struct LintStackIndex { - ENCODABLE = custom, // we don't need encoding - const COMMAND_LINE = 0, - } -} - -/// Specifications found at this position in the stack. This map only represents the lints -/// found for one set of attributes (like `shallow_lint_levels_on` does). -/// -/// We store the level specifications as a linked list. -/// Each `LintSet` represents a set of attributes on the same AST node. -/// The `parent` forms a linked list that matches the AST tree. -/// This way, walking the linked list is equivalent to walking the AST bottom-up -/// to find the specifications for a given lint. -#[derive(Debug)] -struct LintSet { - // -A,-W,-D flags, a `Symbol` for the flag itself and `Level` for which - // flag. - specs: FxHashMap, - parent: LintStackIndex, -} - -impl LintLevelSets { - fn new() -> Self { - LintLevelSets { list: IndexVec::new() } - } - - fn get_lint_level( - &self, - lint: &'static Lint, - idx: LintStackIndex, - aux: Option<&FxHashMap>, - sess: &Session, - ) -> LevelAndSource { - let lint = LintId::of(lint); - let (level, mut src) = self.raw_lint_id_level(lint, idx, aux); - let level = reveal_actual_level(level, &mut src, sess, lint, |id| { - self.raw_lint_id_level(id, idx, aux) - }); - (level, src) - } - - fn raw_lint_id_level( - &self, - id: LintId, - mut idx: LintStackIndex, - aux: Option<&FxHashMap>, - ) -> (Option, LintLevelSource) { - if let Some(specs) = aux { - if let Some(&(level, src)) = specs.get(&id) { - return (Some(level), src); - } - } - loop { - let LintSet { ref specs, parent } = self.list[idx]; - if let Some(&(level, src)) = specs.get(&id) { - return (Some(level), src); - } - if idx == COMMAND_LINE { - return (None, LintLevelSource::Default); - } - idx = parent; - } - } -} - -fn lint_expectations(tcx: TyCtxt<'_>, (): ()) -> Vec<(LintExpectationId, LintExpectation)> { +fn lint_levels(tcx: TyCtxt<'_>, (): ()) -> LintLevelMap { let store = unerased_lint_store(tcx); + let levels = + LintLevelsBuilder::new(tcx.sess, false, &store, &tcx.resolutions(()).registered_tools); + let mut builder = LintLevelMapBuilder { levels, tcx }; + let krate = tcx.hir().krate(); - let mut builder = LintLevelsBuilder { - sess: tcx.sess, - provider: QueryMapExpectationsWrapper { - tcx, - cur: hir::CRATE_HIR_ID, - specs: ShallowLintLevelMap::default(), - expectations: Vec::new(), - unstable_to_stable_ids: FxHashMap::default(), - }, - warn_about_weird_lints: false, - store, - registered_tools: &tcx.resolutions(()).registered_tools, - }; - - builder.add_command_line(); - builder.add_id(hir::CRATE_HIR_ID); - tcx.hir().walk_toplevel_module(&mut builder); - - tcx.sess.diagnostic().update_unstable_expectation_id(&builder.provider.unstable_to_stable_ids); + builder.levels.id_to_set.reserve(krate.owners.len() + 1); - builder.provider.expectations -} + let push = + builder.levels.push(tcx.hir().attrs(hir::CRATE_HIR_ID), true, Some(hir::CRATE_HIR_ID)); -fn shallow_lint_levels_on(tcx: TyCtxt<'_>, hir_id: HirId) -> ShallowLintLevelMap { - let store = unerased_lint_store(tcx); - - let mut levels = LintLevelsBuilder { - sess: tcx.sess, - provider: LintLevelQueryMap { tcx, cur: hir_id, specs: ShallowLintLevelMap::default() }, - warn_about_weird_lints: false, - store, - registered_tools: &tcx.resolutions(()).registered_tools, - }; - - let is_crate = hir::CRATE_HIR_ID == hir_id; - if is_crate { - levels.add_command_line(); - } - debug!(?hir_id); - levels.add(tcx.hir().attrs(hir_id), is_crate, Some(hir_id)); + builder.levels.register_id(hir::CRATE_HIR_ID); + tcx.hir().walk_toplevel_module(&mut builder); + builder.levels.pop(push); - levels.provider.specs + builder.levels.update_unstable_expectation_ids(); + builder.levels.build_map() } -pub struct TopDown { +pub struct LintLevelsBuilder<'s> { + sess: &'s Session, + lint_expectations: Vec<(LintExpectationId, LintExpectation)>, + /// Each expectation has a stable and an unstable identifier. This map + /// is used to map from unstable to stable [`LintExpectationId`]s. + expectation_id_map: FxHashMap, sets: LintLevelSets, + id_to_set: FxHashMap, cur: LintStackIndex, -} - -pub trait LintLevelsProvider { - fn current_specs(&self) -> &FxHashMap; - fn current_specs_mut(&mut self) -> &mut FxHashMap; - fn get_lint_level(&self, lint: &'static Lint, sess: &Session) -> LevelAndSource; - fn push_expectation(&mut self, _id: LintExpectationId, _expectation: LintExpectation) {} -} - -impl LintLevelsProvider for TopDown { - fn current_specs(&self) -> &FxHashMap { - &self.sets.list[self.cur].specs - } - - fn current_specs_mut(&mut self) -> &mut FxHashMap { - &mut self.sets.list[self.cur].specs - } - - fn get_lint_level(&self, lint: &'static Lint, sess: &Session) -> LevelAndSource { - self.sets.get_lint_level(lint, self.cur, Some(self.current_specs()), sess) - } -} - -struct LintLevelQueryMap<'tcx> { - tcx: TyCtxt<'tcx>, - cur: HirId, - specs: ShallowLintLevelMap, -} - -impl LintLevelsProvider for LintLevelQueryMap<'_> { - fn current_specs(&self) -> &FxHashMap { - &self.specs.specs - } - fn current_specs_mut(&mut self) -> &mut FxHashMap { - &mut self.specs.specs - } - fn get_lint_level(&self, lint: &'static Lint, _: &Session) -> LevelAndSource { - self.specs.lint_level_id_at_node(self.tcx, LintId::of(lint), self.cur) - } -} - -struct QueryMapExpectationsWrapper<'tcx> { - tcx: TyCtxt<'tcx>, - cur: HirId, - specs: ShallowLintLevelMap, - expectations: Vec<(LintExpectationId, LintExpectation)>, - unstable_to_stable_ids: FxHashMap, -} - -impl LintLevelsProvider for QueryMapExpectationsWrapper<'_> { - fn current_specs(&self) -> &FxHashMap { - &self.specs.specs - } - fn current_specs_mut(&mut self) -> &mut FxHashMap { - self.specs.specs.clear(); - &mut self.specs.specs - } - fn get_lint_level(&self, lint: &'static Lint, _: &Session) -> LevelAndSource { - self.specs.lint_level_id_at_node(self.tcx, LintId::of(lint), self.cur) - } - fn push_expectation(&mut self, id: LintExpectationId, expectation: LintExpectation) { - let LintExpectationId::Stable { attr_id: Some(attr_id), hir_id, attr_index, .. } = id else { bug!("unstable expectation id should already be mapped") }; - let key = LintExpectationId::Unstable { attr_id, lint_index: None }; - - if !self.unstable_to_stable_ids.contains_key(&key) { - self.unstable_to_stable_ids.insert( - key, - LintExpectationId::Stable { hir_id, attr_index, lint_index: None, attr_id: None }, - ); - } - - self.expectations.push((id.normalize(), expectation)); - } -} - -impl<'tcx> LintLevelsBuilder<'_, QueryMapExpectationsWrapper<'tcx>> { - fn add_id(&mut self, hir_id: HirId) { - self.add(self.provider.tcx.hir().attrs(hir_id), hir_id == hir::CRATE_HIR_ID, Some(hir_id)); - } -} - -impl<'tcx> intravisit::Visitor<'tcx> for LintLevelsBuilder<'_, QueryMapExpectationsWrapper<'tcx>> { - type NestedFilter = nested_filter::All; - - fn nested_visit_map(&mut self) -> Self::Map { - self.provider.tcx.hir() - } - - fn visit_param(&mut self, param: &'tcx hir::Param<'tcx>) { - self.add_id(param.hir_id); - intravisit::walk_param(self, param); - } - - fn visit_item(&mut self, it: &'tcx hir::Item<'tcx>) { - self.add_id(it.hir_id()); - intravisit::walk_item(self, it); - } - - fn visit_foreign_item(&mut self, it: &'tcx hir::ForeignItem<'tcx>) { - self.add_id(it.hir_id()); - intravisit::walk_foreign_item(self, it); - } - - fn visit_stmt(&mut self, e: &'tcx hir::Stmt<'tcx>) { - // We will call `add_id` when we walk - // the `StmtKind`. The outer statement itself doesn't - // define the lint levels. - intravisit::walk_stmt(self, e); - } - - fn visit_expr(&mut self, e: &'tcx hir::Expr<'tcx>) { - self.add_id(e.hir_id); - intravisit::walk_expr(self, e); - } - - fn visit_field_def(&mut self, s: &'tcx hir::FieldDef<'tcx>) { - self.add_id(s.hir_id); - intravisit::walk_field_def(self, s); - } - - fn visit_variant(&mut self, v: &'tcx hir::Variant<'tcx>) { - self.add_id(v.id); - intravisit::walk_variant(self, v); - } - - fn visit_local(&mut self, l: &'tcx hir::Local<'tcx>) { - self.add_id(l.hir_id); - intravisit::walk_local(self, l); - } - - fn visit_arm(&mut self, a: &'tcx hir::Arm<'tcx>) { - self.add_id(a.hir_id); - intravisit::walk_arm(self, a); - } - - fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem<'tcx>) { - self.add_id(trait_item.hir_id()); - intravisit::walk_trait_item(self, trait_item); - } - - fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem<'tcx>) { - self.add_id(impl_item.hir_id()); - intravisit::walk_impl_item(self, impl_item); - } -} - -pub struct LintLevelsBuilder<'s, P> { - sess: &'s Session, - provider: P, warn_about_weird_lints: bool, store: &'s LintStore, registered_tools: &'s RegisteredTools, } -pub(crate) struct BuilderPush { +pub struct BuilderPush { prev: LintStackIndex, + pub changed: bool, } -impl<'s> LintLevelsBuilder<'s, TopDown> { - pub(crate) fn new( +impl<'s> LintLevelsBuilder<'s> { + pub fn new( sess: &'s Session, warn_about_weird_lints: bool, store: &'s LintStore, @@ -321,66 +75,20 @@ impl<'s> LintLevelsBuilder<'s, TopDown> { ) -> Self { let mut builder = LintLevelsBuilder { sess, - provider: TopDown { sets: LintLevelSets::new(), cur: COMMAND_LINE }, + lint_expectations: Default::default(), + expectation_id_map: Default::default(), + sets: LintLevelSets::new(), + cur: COMMAND_LINE, + id_to_set: Default::default(), warn_about_weird_lints, store, registered_tools, }; - builder.process_command_line(); - assert_eq!(builder.provider.sets.list.len(), 1); + builder.process_command_line(sess, store); + assert_eq!(builder.sets.list.len(), 1); builder } - fn process_command_line(&mut self) { - self.provider.cur = self - .provider - .sets - .list - .push(LintSet { specs: FxHashMap::default(), parent: COMMAND_LINE }); - self.add_command_line(); - } - - /// Pushes a list of AST lint attributes onto this context. - /// - /// This function will return a `BuilderPush` object which should be passed - /// to `pop` when this scope for the attributes provided is exited. - /// - /// This function will perform a number of tasks: - /// - /// * It'll validate all lint-related attributes in `attrs` - /// * It'll mark all lint-related attributes as used - /// * Lint levels will be updated based on the attributes provided - /// * Lint attributes are validated, e.g., a `#[forbid]` can't be switched to - /// `#[allow]` - /// - /// Don't forget to call `pop`! - pub(crate) fn push( - &mut self, - attrs: &[ast::Attribute], - is_crate_node: bool, - source_hir_id: Option, - ) -> BuilderPush { - let prev = self.provider.cur; - self.provider.cur = - self.provider.sets.list.push(LintSet { specs: FxHashMap::default(), parent: prev }); - - self.add(attrs, is_crate_node, source_hir_id); - - if self.provider.current_specs().is_empty() { - self.provider.sets.list.pop(); - self.provider.cur = prev; - } - - BuilderPush { prev } - } - - /// Called after `push` when the scope of a set of attributes are exited. - pub(crate) fn pop(&mut self, push: BuilderPush) { - self.provider.cur = push.prev; - } -} - -impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { pub(crate) fn sess(&self) -> &Session { self.sess } @@ -390,20 +98,24 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { } fn current_specs(&self) -> &FxHashMap { - self.provider.current_specs() + &self.sets.list[self.cur].specs } fn current_specs_mut(&mut self) -> &mut FxHashMap { - self.provider.current_specs_mut() + &mut self.sets.list[self.cur].specs } - fn add_command_line(&mut self) { - for &(ref lint_name, level) in &self.sess.opts.lint_opts { - self.store.check_lint_name_cmdline(self.sess, &lint_name, level, self.registered_tools); + fn process_command_line(&mut self, sess: &Session, store: &LintStore) { + self.sets.lint_cap = sess.opts.lint_cap.unwrap_or(Level::Forbid); + + self.cur = + self.sets.list.push(LintSet { specs: FxHashMap::default(), parent: COMMAND_LINE }); + for &(ref lint_name, level) in &sess.opts.lint_opts { + store.check_lint_name_cmdline(sess, &lint_name, level, self.registered_tools); let orig_level = level; let lint_flag_val = Symbol::intern(lint_name); - let Ok(ids) = self.store.find_lints(&lint_name) else { + let Ok(ids) = store.find_lints(&lint_name) else { // errors handled in check_lint_name_cmdline above continue }; @@ -426,11 +138,9 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { /// Attempts to insert the `id` to `level_src` map entry. If unsuccessful /// (e.g. if a forbid was already inserted on the same scope), then emits a /// diagnostic with no change to `specs`. - fn insert_spec(&mut self, id: LintId, (mut level, src): LevelAndSource) { - let (old_level, old_src) = self.provider.get_lint_level(id.lint, &self.sess); - if let Level::Expect(id) = &mut level && let LintExpectationId::Stable { .. } = id { - *id = id.normalize(); - } + fn insert_spec(&mut self, id: LintId, (level, src): LevelAndSource) { + let (old_level, old_src) = + self.sets.get_lint_level(id.lint, self.cur, Some(self.current_specs()), &self.sess); // Setting to a non-forbid level is an error if the lint previously had // a forbid level. Note that this is not necessarily true even with a // `#[forbid(..)]` attribute present, as that is overridden by `--cap-lints`. @@ -448,7 +158,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { let id_name = id.lint.name_lower(); let fcw_warning = match old_src { LintLevelSource::Default => false, - LintLevelSource::Node { name, .. } => self.store.is_lint_group(name), + LintLevelSource::Node(symbol, _, _) => self.store.is_lint_group(symbol), LintLevelSource::CommandLine(symbol, _) => self.store.is_lint_group(symbol), }; debug!( @@ -468,8 +178,8 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { id.to_string() )); } - LintLevelSource::Node { span, reason, .. } => { - diag.span_label(span, "`forbid` level set here"); + LintLevelSource::Node(_, forbid_source_span, reason) => { + diag.span_label(forbid_source_span, "`forbid` level set here"); if let Some(rationale) = reason { diag.note(rationale.as_str()); } @@ -489,8 +199,11 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { LintLevelSource::Default => { OverruledAttributeSub::DefaultSource { id: id.to_string() } } - LintLevelSource::Node { span, reason, .. } => { - OverruledAttributeSub::NodeSource { span, reason } + LintLevelSource::Node(_, forbid_source_span, reason) => { + OverruledAttributeSub::NodeSource { + span: forbid_source_span, + reason, + } } LintLevelSource::CommandLine(_, _) => { OverruledAttributeSub::CommandLineSource @@ -543,7 +256,29 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { }; } - fn add(&mut self, attrs: &[ast::Attribute], is_crate_node: bool, source_hir_id: Option) { + /// Pushes a list of AST lint attributes onto this context. + /// + /// This function will return a `BuilderPush` object which should be passed + /// to `pop` when this scope for the attributes provided is exited. + /// + /// This function will perform a number of tasks: + /// + /// * It'll validate all lint-related attributes in `attrs` + /// * It'll mark all lint-related attributes as used + /// * Lint levels will be updated based on the attributes provided + /// * Lint attributes are validated, e.g., a `#[forbid]` can't be switched to + /// `#[allow]` + /// + /// Don't forget to call `pop`! + pub(crate) fn push( + &mut self, + attrs: &[ast::Attribute], + is_crate_node: bool, + source_hir_id: Option, + ) -> BuilderPush { + let prev = self.cur; + self.cur = self.sets.list.push(LintSet { specs: FxHashMap::default(), parent: prev }); + let sess = self.sess; for (attr_index, attr) in attrs.iter().enumerate() { if attr.has_name(sym::automatically_derived) { @@ -558,17 +293,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { None => continue, // This is the only lint level with a `LintExpectationId` that can be created from an attribute Some(Level::Expect(unstable_id)) if let Some(hir_id) = source_hir_id => { - let LintExpectationId::Unstable { attr_id, lint_index } = unstable_id - else { bug!("stable id Level::from_attr") }; - - let stable_id = LintExpectationId::Stable { - hir_id, - attr_index: attr_index.try_into().unwrap(), - lint_index, - // we pass the previous unstable attr_id such that we can trace the ast id when building a map - // to go from unstable to stable id. - attr_id: Some(attr_id), - }; + let stable_id = self.create_stable_id(unstable_id, hir_id, attr_index); Level::Expect(stable_id) } @@ -683,7 +408,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { [lint] => *lint == LintId::of(UNFULFILLED_LINT_EXPECTATIONS), _ => false, }; - self.provider.push_expectation( + self.lint_expectations.push(( expect_id, LintExpectation::new( reason, @@ -691,19 +416,13 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { is_unfulfilled_lint_expectations, tool_name, ), - ); + )); } - let src = LintLevelSource::Node { - name: meta_item - .path - .segments - .last() - .expect("empty lint name") - .ident - .name, - span: sp, + let src = LintLevelSource::Node( + meta_item.path.segments.last().expect("empty lint name").ident.name, + sp, reason, - }; + ); for &id in *ids { if self.check_gated_lint(id, attr.span) { self.insert_spec(id, (level, src)); @@ -716,26 +435,31 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { Ok(ids) => { let complete_name = &format!("{}::{}", tool_ident.unwrap().name, name); - let src = LintLevelSource::Node { - name: Symbol::intern(complete_name), - span: sp, + let src = LintLevelSource::Node( + Symbol::intern(complete_name), + sp, reason, - }; + ); for &id in ids { if self.check_gated_lint(id, attr.span) { self.insert_spec(id, (level, src)); } } if let Level::Expect(expect_id) = level { - self.provider.push_expectation( + self.lint_expectations.push(( expect_id, LintExpectation::new(reason, sp, false, tool_name), - ); + )); } } Err((Some(ids), ref new_lint_name)) => { let lint = builtin::RENAMED_AND_REMOVED_LINTS; - let (lvl, src) = self.provider.get_lint_level(lint, &sess); + let (lvl, src) = self.sets.get_lint_level( + lint, + self.cur, + Some(self.current_specs()), + &sess, + ); struct_lint_level( self.sess, lint, @@ -759,19 +483,19 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { }, ); - let src = LintLevelSource::Node { - name: Symbol::intern(&new_lint_name), - span: sp, + let src = LintLevelSource::Node( + Symbol::intern(&new_lint_name), + sp, reason, - }; + ); for id in ids { self.insert_spec(*id, (level, src)); } if let Level::Expect(expect_id) = level { - self.provider.push_expectation( + self.lint_expectations.push(( expect_id, LintExpectation::new(reason, sp, false, tool_name), - ); + )); } } Err((None, _)) => { @@ -797,7 +521,12 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { CheckLintNameResult::Warning(msg, renamed) => { let lint = builtin::RENAMED_AND_REMOVED_LINTS; - let (renamed_lint_level, src) = self.provider.get_lint_level(lint, &sess); + let (renamed_lint_level, src) = self.sets.get_lint_level( + lint, + self.cur, + Some(self.current_specs()), + &sess, + ); struct_lint_level( self.sess, lint, @@ -820,7 +549,12 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { } CheckLintNameResult::NoLint(suggestion) => { let lint = builtin::UNKNOWN_LINTS; - let (level, src) = self.provider.get_lint_level(lint, self.sess); + let (level, src) = self.sets.get_lint_level( + lint, + self.cur, + Some(self.current_specs()), + self.sess, + ); struct_lint_level(self.sess, lint, level, src, Some(sp.into()), |lint| { let name = if let Some(tool_ident) = tool_ident { format!("{}::{}", tool_ident.name, name) @@ -849,21 +583,17 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { if let CheckLintNameResult::Ok(ids) = self.store.check_lint_name(&new_name, None, self.registered_tools) { - let src = LintLevelSource::Node { - name: Symbol::intern(&new_name), - span: sp, - reason, - }; + let src = LintLevelSource::Node(Symbol::intern(&new_name), sp, reason); for &id in ids { if self.check_gated_lint(id, attr.span) { self.insert_spec(id, (level, src)); } } if let Level::Expect(expect_id) = level { - self.provider.push_expectation( + self.lint_expectations.push(( expect_id, LintExpectation::new(reason, sp, false, tool_name), - ); + )); } } else { panic!("renamed lint does not exist: {}", new_name); @@ -878,12 +608,13 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { continue; } - let LintLevelSource::Node { name: lint_attr_name, span: lint_attr_span, .. } = *src else { + let LintLevelSource::Node(lint_attr_name, lint_attr_span, _) = *src else { continue }; let lint = builtin::UNUSED_ATTRIBUTES; - let (lint_level, lint_src) = self.provider.get_lint_level(lint, &self.sess); + let (lint_level, lint_src) = + self.sets.get_lint_level(lint, self.cur, Some(self.current_specs()), self.sess); struct_lint_level( self.sess, lint, @@ -903,13 +634,32 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { break; } } + + if self.current_specs().is_empty() { + self.sets.list.pop(); + self.cur = prev; + } + + BuilderPush { prev, changed: prev != self.cur } + } + + fn create_stable_id( + &mut self, + unstable_id: LintExpectationId, + hir_id: HirId, + attr_index: usize, + ) -> LintExpectationId { + let stable_id = + LintExpectationId::Stable { hir_id, attr_index: attr_index as u16, lint_index: None }; + + self.expectation_id_map.insert(unstable_id, stable_id); + + stable_id } /// Checks if the lint is gated on a feature that is not enabled. /// /// Returns `true` if the lint's feature is enabled. - // FIXME only emit this once for each attribute, instead of repeating it 4 times for - // pre-expansion lints, post-expansion lints, `shallow_lint_levels_on` and `lint_expectations`. fn check_gated_lint(&self, lint_id: LintId, span: Span) -> bool { if let Some(feature) = lint_id.lint.feature_gate { if !self.sess.features_untracked().enabled(feature) { @@ -928,14 +678,19 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { true } + /// Called after `push` when the scope of a set of attributes are exited. + pub fn pop(&mut self, push: BuilderPush) { + self.cur = push.prev; + } + /// Find the lint level for a lint. - pub fn lint_level(&self, lint: &'static Lint) -> LevelAndSource { - self.provider.get_lint_level(lint, self.sess) + pub fn lint_level(&self, lint: &'static Lint) -> (Level, LintLevelSource) { + self.sets.get_lint_level(lint, self.cur, None, self.sess) } /// Used to emit a lint-related diagnostic based on the current state of /// this lint context. - pub(crate) fn struct_lint( + pub fn struct_lint( &self, lint: &'static Lint, span: Option, @@ -944,8 +699,141 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { let (level, src) = self.lint_level(lint); struct_lint_level(self.sess, lint, level, src, span, decorate) } + + /// Registers the ID provided with the current set of lints stored in + /// this context. + pub fn register_id(&mut self, id: HirId) { + self.id_to_set.insert(id, self.cur); + } + + fn update_unstable_expectation_ids(&self) { + self.sess.diagnostic().update_unstable_expectation_id(&self.expectation_id_map); + } + + pub fn build_map(self) -> LintLevelMap { + LintLevelMap { + sets: self.sets, + id_to_set: self.id_to_set, + lint_expectations: self.lint_expectations, + } + } +} + +struct LintLevelMapBuilder<'tcx> { + levels: LintLevelsBuilder<'tcx>, + tcx: TyCtxt<'tcx>, +} + +impl LintLevelMapBuilder<'_> { + fn with_lint_attrs(&mut self, id: hir::HirId, f: F) + where + F: FnOnce(&mut Self), + { + let is_crate_hir = id == hir::CRATE_HIR_ID; + let attrs = self.tcx.hir().attrs(id); + let push = self.levels.push(attrs, is_crate_hir, Some(id)); + + if push.changed { + self.levels.register_id(id); + } + f(self); + self.levels.pop(push); + } +} + +impl<'tcx> intravisit::Visitor<'tcx> for LintLevelMapBuilder<'tcx> { + type NestedFilter = nested_filter::All; + + fn nested_visit_map(&mut self) -> Self::Map { + self.tcx.hir() + } + + fn visit_param(&mut self, param: &'tcx hir::Param<'tcx>) { + self.with_lint_attrs(param.hir_id, |builder| { + intravisit::walk_param(builder, param); + }); + } + + fn visit_item(&mut self, it: &'tcx hir::Item<'tcx>) { + self.with_lint_attrs(it.hir_id(), |builder| { + intravisit::walk_item(builder, it); + }); + } + + fn visit_foreign_item(&mut self, it: &'tcx hir::ForeignItem<'tcx>) { + self.with_lint_attrs(it.hir_id(), |builder| { + intravisit::walk_foreign_item(builder, it); + }) + } + + fn visit_stmt(&mut self, e: &'tcx hir::Stmt<'tcx>) { + // We will call `with_lint_attrs` when we walk + // the `StmtKind`. The outer statement itself doesn't + // define the lint levels. + intravisit::walk_stmt(self, e); + } + + fn visit_expr(&mut self, e: &'tcx hir::Expr<'tcx>) { + self.with_lint_attrs(e.hir_id, |builder| { + intravisit::walk_expr(builder, e); + }) + } + + fn visit_expr_field(&mut self, field: &'tcx hir::ExprField<'tcx>) { + self.with_lint_attrs(field.hir_id, |builder| { + intravisit::walk_expr_field(builder, field); + }) + } + + fn visit_field_def(&mut self, s: &'tcx hir::FieldDef<'tcx>) { + self.with_lint_attrs(s.hir_id, |builder| { + intravisit::walk_field_def(builder, s); + }) + } + + fn visit_variant(&mut self, v: &'tcx hir::Variant<'tcx>) { + self.with_lint_attrs(v.id, |builder| { + intravisit::walk_variant(builder, v); + }) + } + + fn visit_local(&mut self, l: &'tcx hir::Local<'tcx>) { + self.with_lint_attrs(l.hir_id, |builder| { + intravisit::walk_local(builder, l); + }) + } + + fn visit_arm(&mut self, a: &'tcx hir::Arm<'tcx>) { + self.with_lint_attrs(a.hir_id, |builder| { + intravisit::walk_arm(builder, a); + }) + } + + fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem<'tcx>) { + self.with_lint_attrs(trait_item.hir_id(), |builder| { + intravisit::walk_trait_item(builder, trait_item); + }); + } + + fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem<'tcx>) { + self.with_lint_attrs(impl_item.hir_id(), |builder| { + intravisit::walk_impl_item(builder, impl_item); + }); + } + + fn visit_pat_field(&mut self, field: &'tcx hir::PatField<'tcx>) { + self.with_lint_attrs(field.hir_id, |builder| { + intravisit::walk_pat_field(builder, field); + }) + } + + fn visit_generic_param(&mut self, p: &'tcx hir::GenericParam<'tcx>) { + self.with_lint_attrs(p.hir_id, |builder| { + intravisit::walk_generic_param(builder, p); + }); + } } -pub(crate) fn provide(providers: &mut Providers) { - *providers = Providers { shallow_lint_levels_on, lint_expectations, ..*providers }; +pub fn provide(providers: &mut Providers) { + providers.lint_levels = lint_levels; } diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index c760e435699c6..752a751f6bcf5 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -35,7 +35,6 @@ #![feature(iter_order_by)] #![feature(let_chains)] #![cfg_attr(bootstrap, feature(let_else))] -#![feature(min_specialization)] #![feature(never_type)] #![recursion_limit = "256"] diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index cbe7afc8e5558..11b2d057a0769 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -92,7 +92,7 @@ pub enum LintExpectationId { /// stable and can be cached. The additional index ensures that nodes with /// several expectations can correctly match diagnostics to the individual /// expectation. - Stable { hir_id: HirId, attr_index: u16, lint_index: Option, attr_id: Option }, + Stable { hir_id: HirId, attr_index: u16, lint_index: Option }, } impl LintExpectationId { @@ -116,31 +116,13 @@ impl LintExpectationId { *lint_index = new_lint_index } - - /// Prepares the id for hashing. Removes references to the ast. - /// Should only be called when the id is stable. - pub fn normalize(self) -> Self { - match self { - Self::Stable { hir_id, attr_index, lint_index, .. } => { - Self::Stable { hir_id, attr_index, lint_index, attr_id: None } - } - Self::Unstable { .. } => { - unreachable!("`normalize` called when `ExpectationId` is unstable") - } - } - } } impl HashStable for LintExpectationId { #[inline] fn hash_stable(&self, hcx: &mut HCX, hasher: &mut StableHasher) { match self { - LintExpectationId::Stable { - hir_id, - attr_index, - lint_index: Some(lint_index), - attr_id: _, - } => { + LintExpectationId::Stable { hir_id, attr_index, lint_index: Some(lint_index) } => { hir_id.hash_stable(hcx, hasher); attr_index.hash_stable(hcx, hasher); lint_index.hash_stable(hcx, hasher); @@ -160,12 +142,9 @@ impl ToStableHashKey for LintExpectation #[inline] fn to_stable_hash_key(&self, _: &HCX) -> Self::KeyType { match self { - LintExpectationId::Stable { - hir_id, - attr_index, - lint_index: Some(lint_index), - attr_id: _, - } => (*hir_id, *attr_index, *lint_index), + LintExpectationId::Stable { hir_id, attr_index, lint_index: Some(lint_index) } => { + (*hir_id, *attr_index, *lint_index) + } _ => { unreachable!("HashStable should only be called for a filled `LintExpectationId`") } diff --git a/compiler/rustc_middle/src/dep_graph/dep_node.rs b/compiler/rustc_middle/src/dep_graph/dep_node.rs index eded3b3eedc6c..1fa0c6bababe4 100644 --- a/compiler/rustc_middle/src/dep_graph/dep_node.rs +++ b/compiler/rustc_middle/src/dep_graph/dep_node.rs @@ -62,7 +62,7 @@ use crate::ty::TyCtxt; use rustc_data_structures::fingerprint::Fingerprint; use rustc_hir::def_id::{CrateNum, DefId, LocalDefId}; use rustc_hir::definitions::DefPathHash; -use rustc_hir::{HirId, ItemLocalId}; +use rustc_hir::HirId; use rustc_query_system::dep_graph::FingerprintStyle; use rustc_span::symbol::Symbol; use std::hash::Hash; @@ -280,7 +280,7 @@ impl DepNodeExt for DepNode { let kind = dep_kind_from_label_string(label)?; match kind.fingerprint_style(tcx) { - FingerprintStyle::Opaque | FingerprintStyle::HirId => Err(()), + FingerprintStyle::Opaque => Err(()), FingerprintStyle::Unit => Ok(DepNode::new_no_params(tcx, kind)), FingerprintStyle::DefPathHash => { Ok(DepNode::from_def_path_hash(tcx, def_path_hash, kind)) @@ -408,7 +408,7 @@ impl<'tcx> DepNodeParams> for (DefId, DefId) { impl<'tcx> DepNodeParams> for HirId { #[inline(always)] fn fingerprint_style() -> FingerprintStyle { - FingerprintStyle::HirId + FingerprintStyle::Opaque } // We actually would not need to specialize the implementation of this @@ -417,36 +417,10 @@ impl<'tcx> DepNodeParams> for HirId { #[inline(always)] fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint { let HirId { owner, local_id } = *self; - let def_path_hash = tcx.def_path_hash(owner.to_def_id()); - Fingerprint::new( - // `owner` is local, so is completely defined by the local hash - def_path_hash.local_hash(), - local_id.as_u32().into(), - ) - } - #[inline(always)] - fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String { - let HirId { owner, local_id } = *self; - format!("{}.{}", tcx.def_path_str(owner.to_def_id()), local_id.as_u32()) - } + let def_path_hash = tcx.def_path_hash(owner.to_def_id()); + let local_id = Fingerprint::from_smaller_hash(local_id.as_u32().into()); - #[inline(always)] - fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option { - if dep_node.kind.fingerprint_style(tcx) == FingerprintStyle::HirId { - let (local_hash, local_id) = Fingerprint::from(dep_node.hash).as_value(); - let def_path_hash = DefPathHash::new(tcx.sess.local_stable_crate_id(), local_hash); - let owner = tcx - .def_path_hash_to_def_id(def_path_hash, &mut || { - panic!("Failed to extract HirId: {:?} {}", dep_node.kind, dep_node.hash) - }) - .expect_local(); - let local_id = local_id - .try_into() - .unwrap_or_else(|_| panic!("local id should be u32, found {:?}", local_id)); - Some(HirId { owner, local_id: ItemLocalId::from_u32(local_id) }) - } else { - None - } + def_path_hash.0.combine(local_id) } } diff --git a/compiler/rustc_middle/src/lint.rs b/compiler/rustc_middle/src/lint.rs index 4cb5ef7917774..2f45222de4728 100644 --- a/compiler/rustc_middle/src/lint.rs +++ b/compiler/rustc_middle/src/lint.rs @@ -1,19 +1,20 @@ use std::cmp; use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_errors::{Diagnostic, DiagnosticId, LintDiagnosticBuilder, MultiSpan}; use rustc_hir::HirId; +use rustc_index::vec::IndexVec; +use rustc_query_system::ich::StableHashingContext; use rustc_session::lint::{ builtin::{self, FORBIDDEN_LINT_GROUPS}, - FutureIncompatibilityReason, Level, Lint, LintId, + FutureIncompatibilityReason, Level, Lint, LintExpectationId, LintId, }; use rustc_session::Session; use rustc_span::hygiene::MacroKind; use rustc_span::source_map::{DesugaringKind, ExpnKind}; use rustc_span::{symbol, Span, Symbol, DUMMY_SP}; -use crate::ty::TyCtxt; - /// How a lint level was set. #[derive(Clone, Copy, PartialEq, Eq, HashStable, Debug)] pub enum LintLevelSource { @@ -22,12 +23,7 @@ pub enum LintLevelSource { Default, /// Lint level was set by an attribute. - Node { - name: Symbol, - span: Span, - /// RFC 2383 reason - reason: Option, - }, + Node(Symbol, Span, Option /* RFC 2383 reason */), /// Lint level was set by a command-line flag. /// The provided `Level` is the level specified on the command line. @@ -39,7 +35,7 @@ impl LintLevelSource { pub fn name(&self) -> Symbol { match *self { LintLevelSource::Default => symbol::kw::Default, - LintLevelSource::Node { name, .. } => name, + LintLevelSource::Node(name, _, _) => name, LintLevelSource::CommandLine(name, _) => name, } } @@ -47,7 +43,7 @@ impl LintLevelSource { pub fn span(&self) -> Span { match *self { LintLevelSource::Default => DUMMY_SP, - LintLevelSource::Node { span, .. } => span, + LintLevelSource::Node(_, span, _) => span, LintLevelSource::CommandLine(_, _) => DUMMY_SP, } } @@ -56,115 +52,145 @@ impl LintLevelSource { /// A tuple of a lint level and its source. pub type LevelAndSource = (Level, LintLevelSource); -/// Return type for the `shallow_lint_levels_on` query. -/// -/// This map represents the set of allowed lints and allowance levels given -/// by the attributes for *a single HirId*. -#[derive(Default, Debug, HashStable)] -pub struct ShallowLintLevelMap { +#[derive(Debug, HashStable)] +pub struct LintLevelSets { + pub list: IndexVec, + pub lint_cap: Level, +} + +rustc_index::newtype_index! { + #[derive(HashStable)] + pub struct LintStackIndex { + const COMMAND_LINE = 0, + } +} + +#[derive(Debug, HashStable)] +pub struct LintSet { + // -A,-W,-D flags, a `Symbol` for the flag itself and `Level` for which + // flag. pub specs: FxHashMap, + + pub parent: LintStackIndex, } -/// From an initial level and source, verify the effect of special annotations: -/// `warnings` lint level and lint caps. -/// -/// The return of this function is suitable for diagnostics. -pub fn reveal_actual_level( - level: Option, - src: &mut LintLevelSource, - sess: &Session, - lint: LintId, - probe_for_lint_level: impl FnOnce(LintId) -> (Option, LintLevelSource), -) -> Level { - // If `level` is none then we actually assume the default level for this lint. - let mut level = level.unwrap_or_else(|| lint.lint.default_level(sess.edition())); - - // If we're about to issue a warning, check at the last minute for any - // directives against the warnings "lint". If, for example, there's an - // `allow(warnings)` in scope then we want to respect that instead. - // - // We exempt `FORBIDDEN_LINT_GROUPS` from this because it specifically - // triggers in cases (like #80988) where you have `forbid(warnings)`, - // and so if we turned that into an error, it'd defeat the purpose of the - // future compatibility warning. - if level == Level::Warn && lint != LintId::of(FORBIDDEN_LINT_GROUPS) { - let (warnings_level, warnings_src) = probe_for_lint_level(LintId::of(builtin::WARNINGS)); - if let Some(configured_warning_level) = warnings_level { - if configured_warning_level != Level::Warn { - level = configured_warning_level; - *src = warnings_src; +impl LintLevelSets { + pub fn new() -> Self { + LintLevelSets { list: IndexVec::new(), lint_cap: Level::Forbid } + } + + pub fn get_lint_level( + &self, + lint: &'static Lint, + idx: LintStackIndex, + aux: Option<&FxHashMap>, + sess: &Session, + ) -> LevelAndSource { + let (level, mut src) = self.get_lint_id_level(LintId::of(lint), idx, aux); + + // If `level` is none then we actually assume the default level for this + // lint. + let mut level = level.unwrap_or_else(|| lint.default_level(sess.edition())); + + // If we're about to issue a warning, check at the last minute for any + // directives against the warnings "lint". If, for example, there's an + // `allow(warnings)` in scope then we want to respect that instead. + // + // We exempt `FORBIDDEN_LINT_GROUPS` from this because it specifically + // triggers in cases (like #80988) where you have `forbid(warnings)`, + // and so if we turned that into an error, it'd defeat the purpose of the + // future compatibility warning. + if level == Level::Warn && LintId::of(lint) != LintId::of(FORBIDDEN_LINT_GROUPS) { + let (warnings_level, warnings_src) = + self.get_lint_id_level(LintId::of(builtin::WARNINGS), idx, aux); + if let Some(configured_warning_level) = warnings_level { + if configured_warning_level != Level::Warn { + level = configured_warning_level; + src = warnings_src; + } } } - } - // Ensure that we never exceed the `--cap-lints` argument unless the source is a --force-warn - level = if let LintLevelSource::CommandLine(_, Level::ForceWarn(_)) = src { - level - } else { - cmp::min(level, sess.opts.lint_cap.unwrap_or(Level::Forbid)) - }; + // Ensure that we never exceed the `--cap-lints` argument + // unless the source is a --force-warn + level = if let LintLevelSource::CommandLine(_, Level::ForceWarn(_)) = src { + level + } else { + cmp::min(level, self.lint_cap) + }; + + if let Some(driver_level) = sess.driver_lint_caps.get(&LintId::of(lint)) { + // Ensure that we never exceed driver level. + level = cmp::min(*driver_level, level); + } - if let Some(driver_level) = sess.driver_lint_caps.get(&lint) { - // Ensure that we never exceed driver level. - level = cmp::min(*driver_level, level); + (level, src) } - level -} - -impl ShallowLintLevelMap { - /// Perform a deep probe in the HIR tree looking for the actual level for the lint. - /// This lint level is not usable for diagnostics, it needs to be corrected by - /// `reveal_actual_level` beforehand. - fn probe_for_lint_level( + pub fn get_lint_id_level( &self, - tcx: TyCtxt<'_>, id: LintId, - start: HirId, + mut idx: LintStackIndex, + aux: Option<&FxHashMap>, ) -> (Option, LintLevelSource) { - if let Some(&(level, src)) = self.specs.get(&id) { - return (Some(level), src); + if let Some(specs) = aux { + if let Some(&(level, src)) = specs.get(&id) { + return (Some(level), src); + } } - - for (parent, _) in tcx.hir().parent_iter(start) { - let specs = tcx.shallow_lint_levels_on(parent); - if let Some(&(level, src)) = specs.specs.get(&id) { + loop { + let LintSet { ref specs, parent } = self.list[idx]; + if let Some(&(level, src)) = specs.get(&id) { return (Some(level), src); } + if idx == COMMAND_LINE { + return (None, LintLevelSource::Default); + } + idx = parent; } - (None, LintLevelSource::Default) } +} + +#[derive(Debug)] +pub struct LintLevelMap { + /// This is a collection of lint expectations as described in RFC 2383, that + /// can be fulfilled during this compilation session. This means that at least + /// one expected lint is currently registered in the lint store. + /// + /// The [`LintExpectationId`] is stored as a part of the [`Expect`](Level::Expect) + /// lint level. + pub lint_expectations: Vec<(LintExpectationId, LintExpectation)>, + pub sets: LintLevelSets, + pub id_to_set: FxHashMap, +} - /// Fetch and return the user-visible lint level for the given lint at the given HirId. - pub fn lint_level_id_at_node( +impl LintLevelMap { + /// If the `id` was previously registered with `register_id` when building + /// this `LintLevelMap` this returns the corresponding lint level and source + /// of the lint level for the lint provided. + /// + /// If the `id` was not previously registered, returns `None`. If `None` is + /// returned then the parent of `id` should be acquired and this function + /// should be called again. + pub fn level_and_source( &self, - tcx: TyCtxt<'_>, - lint: LintId, + lint: &'static Lint, id: HirId, - ) -> (Level, LintLevelSource) { - let (level, mut src) = self.probe_for_lint_level(tcx, lint, id); - let level = reveal_actual_level(level, &mut src, tcx.sess, lint, |lint| { - self.probe_for_lint_level(tcx, lint, id) - }); - debug!(?id, ?level, ?src); - (level, src) + session: &Session, + ) -> Option { + self.id_to_set.get(&id).map(|idx| self.sets.get_lint_level(lint, *idx, None, session)) } } -impl TyCtxt<'_> { - /// Fetch and return the user-visible lint level for the given lint at the given HirId. - pub fn lint_level_at_node(self, lint: &'static Lint, id: HirId) -> (Level, LintLevelSource) { - self.shallow_lint_levels_on(id).lint_level_id_at_node(self, LintId::of(lint), id) - } +impl<'a> HashStable> for LintLevelMap { + #[inline] + fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { + let LintLevelMap { ref sets, ref id_to_set, ref lint_expectations } = *self; - /// Walks upwards from `id` to find a node which might change lint levels with attributes. - /// It stops at `bound` and just returns it if reached. - pub fn maybe_lint_level_root_bounded(self, mut id: HirId, bound: HirId) -> HirId { - let hir = self.hir(); - while id != bound && self.shallow_lint_levels_on(id).specs.is_empty() { - id = hir.get_parent_node(id) - } - id + id_to_set.hash_stable(hcx, hasher); + lint_expectations.hash_stable(hcx, hasher); + + hcx.while_hashing_spans(true, |hcx| sets.hash_stable(hcx, hasher)) } } @@ -235,11 +261,11 @@ pub fn explain_lint_level_source( )); } } - LintLevelSource::Node { name: lint_attr_name, span, reason, .. } => { + LintLevelSource::Node(lint_attr_name, src, reason) => { if let Some(rationale) = reason { err.note(rationale.as_str()); } - err.span_note_once(span, "the lint level is defined here"); + err.span_note_once(src, "the lint level is defined here"); if lint_attr_name.as_str() != name { let level_str = level.as_str(); err.note_once(&format!( diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 1afea4864b8dd..7ea8c9ed3d313 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -274,14 +274,10 @@ rustc_queries! { separate_provide_extern } - query shallow_lint_levels_on(key: HirId) -> rustc_middle::lint::ShallowLintLevelMap { + query lint_levels(_: ()) -> LintLevelMap { arena_cache - desc { |tcx| "looking up lint levels for `{}`", key } - } - - query lint_expectations(_: ()) -> Vec<(LintExpectationId, LintExpectation)> { - arena_cache - desc { "computing `#[expect]`ed lints in this crate" } + eval_always + desc { "computing the lint levels for items in this crate" } } query parent_module_from_def_id(key: LocalDefId) -> LocalDefId { diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 2b5b4017a5a11..8c44f4a98df5d 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -4,7 +4,7 @@ use crate::arena::Arena; use crate::dep_graph::{DepGraph, DepKind, DepKindStruct}; use crate::hir::place::Place as HirPlace; use crate::infer::canonical::{Canonical, CanonicalVarInfo, CanonicalVarInfos}; -use crate::lint::struct_lint_level; +use crate::lint::{struct_lint_level, LintLevelSource}; use crate::middle::codegen_fn_attrs::CodegenFnAttrs; use crate::middle::resolve_lifetime; use crate::middle::stability; @@ -54,7 +54,7 @@ use rustc_serialize::opaque::{FileEncodeResult, FileEncoder}; use rustc_session::config::{CrateType, OutputFilenames}; use rustc_session::cstore::CrateStoreDyn; use rustc_session::errors::TargetDataLayoutErrorsWrapper; -use rustc_session::lint::Lint; +use rustc_session::lint::{Level, Lint}; use rustc_session::Limit; use rustc_session::Session; use rustc_span::def_id::{DefPathHash, StableCrateId}; @@ -2813,6 +2813,44 @@ impl<'tcx> TyCtxt<'tcx> { iter.intern_with(|xs| self.intern_bound_variable_kinds(xs)) } + /// Walks upwards from `id` to find a node which might change lint levels with attributes. + /// It stops at `bound` and just returns it if reached. + pub fn maybe_lint_level_root_bounded(self, mut id: HirId, bound: HirId) -> HirId { + let hir = self.hir(); + loop { + if id == bound { + return bound; + } + + if hir.attrs(id).iter().any(|attr| Level::from_attr(attr).is_some()) { + return id; + } + let next = hir.get_parent_node(id); + if next == id { + bug!("lint traversal reached the root of the crate"); + } + id = next; + } + } + + pub fn lint_level_at_node( + self, + lint: &'static Lint, + mut id: hir::HirId, + ) -> (Level, LintLevelSource) { + let sets = self.lint_levels(()); + loop { + if let Some(pair) = sets.level_and_source(lint, id, self.sess) { + return pair; + } + let next = self.hir().get_parent_node(id); + if next == id { + bug!("lint traversal reached the root of the crate"); + } + id = next; + } + } + /// Emit a lint at `span` from a lint struct (some type that implements `DecorateLint`, /// typically generated by `#[derive(LintDiagnostic)]`). pub fn emit_spanned_lint( diff --git a/compiler/rustc_middle/src/ty/query.rs b/compiler/rustc_middle/src/ty/query.rs index be208a9fc7041..00da260b1dc36 100644 --- a/compiler/rustc_middle/src/ty/query.rs +++ b/compiler/rustc_middle/src/ty/query.rs @@ -1,6 +1,6 @@ use crate::dep_graph; use crate::infer::canonical::{self, Canonical}; -use crate::lint::LintExpectation; +use crate::lint::LintLevelMap; use crate::metadata::ModChild; use crate::middle::codegen_fn_attrs::CodegenFnAttrs; use crate::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo}; @@ -44,14 +44,12 @@ use rustc_errors::ErrorGuaranteed; use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, DefIdSet, LocalDefId}; -use rustc_hir::hir_id::HirId; use rustc_hir::lang_items::{LangItem, LanguageItems}; use rustc_hir::{Crate, ItemLocalId, TraitCandidate}; use rustc_index::{bit_set::FiniteBitSet, vec::IndexVec}; use rustc_session::config::{EntryFnType, OptLevel, OutputFilenames, SymbolManglingVersion}; use rustc_session::cstore::{CrateDepKind, CrateSource}; use rustc_session::cstore::{ExternCrate, ForeignModule, LinkagePreference, NativeLib}; -use rustc_session::lint::LintExpectationId; use rustc_session::utils::NativeLibKind; use rustc_session::Limits; use rustc_span::symbol::Symbol; diff --git a/compiler/rustc_query_impl/src/keys.rs b/compiler/rustc_query_impl/src/keys.rs index 31de83ee1418d..49175e97f4171 100644 --- a/compiler/rustc_query_impl/src/keys.rs +++ b/compiler/rustc_query_impl/src/keys.rs @@ -1,7 +1,6 @@ //! Defines the set of legal keys that can be used in queries. use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE}; -use rustc_hir::hir_id::HirId; use rustc_middle::infer::canonical::Canonical; use rustc_middle::mir; use rustc_middle::traits; @@ -544,19 +543,3 @@ impl<'tcx> Key for (Ty<'tcx>, ty::ValTree<'tcx>) { DUMMY_SP } } - -impl Key for HirId { - #[inline(always)] - fn query_crate_is_local(&self) -> bool { - true - } - - fn default_span(&self, tcx: TyCtxt<'_>) -> Span { - tcx.hir().span(*self) - } - - #[inline(always)] - fn key_as_def_id(&self) -> Option { - None - } -} diff --git a/compiler/rustc_query_system/src/dep_graph/mod.rs b/compiler/rustc_query_system/src/dep_graph/mod.rs index 6f3bd7762165c..342d95ca490ea 100644 --- a/compiler/rustc_query_system/src/dep_graph/mod.rs +++ b/compiler/rustc_query_system/src/dep_graph/mod.rs @@ -67,8 +67,6 @@ impl HasDepContext for T { pub enum FingerprintStyle { /// The fingerprint is actually a DefPathHash. DefPathHash, - /// The fingerprint is actually a HirId. - HirId, /// Query key was `()` or equivalent, so fingerprint is just zero. Unit, /// Some opaque hash. @@ -79,9 +77,7 @@ impl FingerprintStyle { #[inline] pub fn reconstructible(self) -> bool { match self { - FingerprintStyle::DefPathHash | FingerprintStyle::Unit | FingerprintStyle::HirId => { - true - } + FingerprintStyle::DefPathHash | FingerprintStyle::Unit => true, FingerprintStyle::Opaque => false, } } diff --git a/src/test/ui/feature-gates/feature-gate-non_exhaustive_omitted_patterns_lint.rs b/src/test/ui/feature-gates/feature-gate-non_exhaustive_omitted_patterns_lint.rs index 23457b8e0625c..9b646060adfd9 100644 --- a/src/test/ui/feature-gates/feature-gate-non_exhaustive_omitted_patterns_lint.rs +++ b/src/test/ui/feature-gates/feature-gate-non_exhaustive_omitted_patterns_lint.rs @@ -3,11 +3,9 @@ #![deny(non_exhaustive_omitted_patterns)] //~^ WARNING unknown lint: `non_exhaustive_omitted_patterns` //~| WARNING unknown lint: `non_exhaustive_omitted_patterns` -//~| WARNING unknown lint: `non_exhaustive_omitted_patterns` #![allow(non_exhaustive_omitted_patterns)] //~^ WARNING unknown lint: `non_exhaustive_omitted_patterns` //~| WARNING unknown lint: `non_exhaustive_omitted_patterns` -//~| WARNING unknown lint: `non_exhaustive_omitted_patterns` fn main() { enum Foo { @@ -19,8 +17,6 @@ fn main() { //~| WARNING unknown lint: `non_exhaustive_omitted_patterns` //~| WARNING unknown lint: `non_exhaustive_omitted_patterns` //~| WARNING unknown lint: `non_exhaustive_omitted_patterns` - //~| WARNING unknown lint: `non_exhaustive_omitted_patterns` - //~| WARNING unknown lint: `non_exhaustive_omitted_patterns` match Foo::A { Foo::A => {} Foo::B => {} @@ -35,5 +31,4 @@ fn main() { } //~^^^ WARNING unknown lint: `non_exhaustive_omitted_patterns` //~| WARNING unknown lint: `non_exhaustive_omitted_patterns` - //~| WARNING unknown lint: `non_exhaustive_omitted_patterns` } diff --git a/src/test/ui/feature-gates/feature-gate-non_exhaustive_omitted_patterns_lint.stderr b/src/test/ui/feature-gates/feature-gate-non_exhaustive_omitted_patterns_lint.stderr index 29023858e4f3e..3de08e215dada 100644 --- a/src/test/ui/feature-gates/feature-gate-non_exhaustive_omitted_patterns_lint.stderr +++ b/src/test/ui/feature-gates/feature-gate-non_exhaustive_omitted_patterns_lint.stderr @@ -10,7 +10,7 @@ LL | #![deny(non_exhaustive_omitted_patterns)] = help: add `#![feature(non_exhaustive_omitted_patterns_lint)]` to the crate attributes to enable warning: unknown lint: `non_exhaustive_omitted_patterns` - --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:7:1 + --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:6:1 | LL | #![allow(non_exhaustive_omitted_patterns)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -20,7 +20,7 @@ LL | #![allow(non_exhaustive_omitted_patterns)] = help: add `#![feature(non_exhaustive_omitted_patterns_lint)]` to the crate attributes to enable warning: unknown lint: `non_exhaustive_omitted_patterns` - --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:17:5 + --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:15:5 | LL | #[allow(non_exhaustive_omitted_patterns)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -30,7 +30,7 @@ LL | #[allow(non_exhaustive_omitted_patterns)] = help: add `#![feature(non_exhaustive_omitted_patterns_lint)]` to the crate attributes to enable warning: unknown lint: `non_exhaustive_omitted_patterns` - --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:17:5 + --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:15:5 | LL | #[allow(non_exhaustive_omitted_patterns)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -40,7 +40,7 @@ LL | #[allow(non_exhaustive_omitted_patterns)] = help: add `#![feature(non_exhaustive_omitted_patterns_lint)]` to the crate attributes to enable warning: unknown lint: `non_exhaustive_omitted_patterns` - --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:33:9 + --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:29:9 | LL | #[warn(non_exhaustive_omitted_patterns)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -60,7 +60,7 @@ LL | #![deny(non_exhaustive_omitted_patterns)] = help: add `#![feature(non_exhaustive_omitted_patterns_lint)]` to the crate attributes to enable warning: unknown lint: `non_exhaustive_omitted_patterns` - --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:7:1 + --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:6:1 | LL | #![allow(non_exhaustive_omitted_patterns)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -70,7 +70,7 @@ LL | #![allow(non_exhaustive_omitted_patterns)] = help: add `#![feature(non_exhaustive_omitted_patterns_lint)]` to the crate attributes to enable warning: unknown lint: `non_exhaustive_omitted_patterns` - --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:17:5 + --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:15:5 | LL | #[allow(non_exhaustive_omitted_patterns)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -80,7 +80,7 @@ LL | #[allow(non_exhaustive_omitted_patterns)] = help: add `#![feature(non_exhaustive_omitted_patterns_lint)]` to the crate attributes to enable warning: unknown lint: `non_exhaustive_omitted_patterns` - --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:17:5 + --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:15:5 | LL | #[allow(non_exhaustive_omitted_patterns)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -90,7 +90,7 @@ LL | #[allow(non_exhaustive_omitted_patterns)] = help: add `#![feature(non_exhaustive_omitted_patterns_lint)]` to the crate attributes to enable warning: unknown lint: `non_exhaustive_omitted_patterns` - --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:33:9 + --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:29:9 | LL | #[warn(non_exhaustive_omitted_patterns)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -100,13 +100,13 @@ LL | #[warn(non_exhaustive_omitted_patterns)] = help: add `#![feature(non_exhaustive_omitted_patterns_lint)]` to the crate attributes to enable error[E0004]: non-exhaustive patterns: `Foo::C` not covered - --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:24:11 + --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:20:11 | LL | match Foo::A { | ^^^^^^ pattern `Foo::C` not covered | note: `Foo` defined here - --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:14:15 + --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:12:15 | LL | enum Foo { | --- @@ -119,56 +119,6 @@ LL ~ Foo::B => {} LL + Foo::C => todo!() | -warning: unknown lint: `non_exhaustive_omitted_patterns` - --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:3:1 - | -LL | #![deny(non_exhaustive_omitted_patterns)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: the `non_exhaustive_omitted_patterns` lint is unstable - = note: see issue #89554 for more information - = help: add `#![feature(non_exhaustive_omitted_patterns_lint)]` to the crate attributes to enable - -warning: unknown lint: `non_exhaustive_omitted_patterns` - --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:7:1 - | -LL | #![allow(non_exhaustive_omitted_patterns)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: the `non_exhaustive_omitted_patterns` lint is unstable - = note: see issue #89554 for more information - = help: add `#![feature(non_exhaustive_omitted_patterns_lint)]` to the crate attributes to enable - -warning: unknown lint: `non_exhaustive_omitted_patterns` - --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:17:5 - | -LL | #[allow(non_exhaustive_omitted_patterns)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: the `non_exhaustive_omitted_patterns` lint is unstable - = note: see issue #89554 for more information - = help: add `#![feature(non_exhaustive_omitted_patterns_lint)]` to the crate attributes to enable - -warning: unknown lint: `non_exhaustive_omitted_patterns` - --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:17:5 - | -LL | #[allow(non_exhaustive_omitted_patterns)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: the `non_exhaustive_omitted_patterns` lint is unstable - = note: see issue #89554 for more information - = help: add `#![feature(non_exhaustive_omitted_patterns_lint)]` to the crate attributes to enable - -warning: unknown lint: `non_exhaustive_omitted_patterns` - --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:33:9 - | -LL | #[warn(non_exhaustive_omitted_patterns)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: the `non_exhaustive_omitted_patterns` lint is unstable - = note: see issue #89554 for more information - = help: add `#![feature(non_exhaustive_omitted_patterns_lint)]` to the crate attributes to enable - -error: aborting due to previous error; 15 warnings emitted +error: aborting due to previous error; 10 warnings emitted For more information about this error, try `rustc --explain E0004`. diff --git a/src/test/ui/lint/rfc-2383-lint-reason/force_warn_expected_lints_fulfilled.stderr b/src/test/ui/lint/rfc-2383-lint-reason/force_warn_expected_lints_fulfilled.stderr index 5942fa8aeb4f0..06befcbb5117e 100644 --- a/src/test/ui/lint/rfc-2383-lint-reason/force_warn_expected_lints_fulfilled.stderr +++ b/src/test/ui/lint/rfc-2383-lint-reason/force_warn_expected_lints_fulfilled.stderr @@ -1,3 +1,11 @@ +warning: denote infinite loops with `loop { ... }` + --> $DIR/force_warn_expected_lints_fulfilled.rs:10:5 + | +LL | while true { + | ^^^^^^^^^^ help: use `loop` + | + = note: requested on the command line with `--force-warn while-true` + warning: unused variable: `x` --> $DIR/force_warn_expected_lints_fulfilled.rs:20:9 | @@ -28,13 +36,5 @@ LL | let mut what_does_the_fox_say = "*ding* *deng* *dung*"; | = note: requested on the command line with `--force-warn unused-mut` -warning: denote infinite loops with `loop { ... }` - --> $DIR/force_warn_expected_lints_fulfilled.rs:10:5 - | -LL | while true { - | ^^^^^^^^^^ help: use `loop` - | - = note: requested on the command line with `--force-warn while-true` - warning: 5 warnings emitted From 8abf4870ce38a790c1f75ed17fab8fa7b1334861 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Thu, 22 Sep 2022 11:09:29 -0700 Subject: [PATCH 129/586] rustdoc: remove no-op CSS `.location:empty { border: none }` This rule was added in 2bb2a2975f25e8ba7a372898e7e112f1cec5db01 to remove a border placed around the location when it's empty. That rule was removed in 6a5f8b1aef1417d7dc85b5d0a229d2db1930eb7c, so this rule does nothing. --- src/librustdoc/html/static/css/rustdoc.css | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index f21179ec558f0..efb8a2369e870 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -522,10 +522,6 @@ img { width: 100px; } -.location:empty { - border: none; -} - .block ul, .block li { padding: 0; margin: 0; From 7927f0919f178c099f2824f691cfc79065bb419d Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 22 Sep 2022 21:01:13 +0200 Subject: [PATCH 130/586] add regression test for miri issue 2433 --- .../miri/tests/pass/issues/issue-miri-2433.rs | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 src/tools/miri/tests/pass/issues/issue-miri-2433.rs diff --git a/src/tools/miri/tests/pass/issues/issue-miri-2433.rs b/src/tools/miri/tests/pass/issues/issue-miri-2433.rs new file mode 100644 index 0000000000000..de719df0f1f30 --- /dev/null +++ b/src/tools/miri/tests/pass/issues/issue-miri-2433.rs @@ -0,0 +1,22 @@ +#![feature(type_alias_impl_trait)] + +trait T { type Item; } + +type Alias<'a> = impl T; + +struct S; +impl<'a> T for &'a S { + type Item = &'a (); +} + +fn filter_positive<'a>() -> Alias<'a> { + &S +} + +fn with_positive(fun: impl Fn(Alias<'_>)) { + fun(filter_positive()); +} + +fn main() { + with_positive(|_| ()); +} From a7cdfafafb78ddddaaf5ab0c7e14cefc71d3a1db Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 22 Sep 2022 21:01:23 +0200 Subject: [PATCH 131/586] make Miri build in stage 0 --- src/tools/miri/cargo-miri/src/main.rs | 1 + src/tools/miri/src/lib.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/src/tools/miri/cargo-miri/src/main.rs b/src/tools/miri/cargo-miri/src/main.rs index 331c4c9c2b0e7..da891ef077293 100644 --- a/src/tools/miri/cargo-miri/src/main.rs +++ b/src/tools/miri/cargo-miri/src/main.rs @@ -1,3 +1,4 @@ +#![cfg_attr(bootstrap, feature(let_else))] #![allow(clippy::useless_format, clippy::derive_partial_eq_without_eq, rustc::internal)] #[macro_use] diff --git a/src/tools/miri/src/lib.rs b/src/tools/miri/src/lib.rs index 6006d6c89dbca..cda27beab300f 100644 --- a/src/tools/miri/src/lib.rs +++ b/src/tools/miri/src/lib.rs @@ -10,6 +10,7 @@ #![feature(is_some_with)] #![feature(nonzero_ops)] #![feature(local_key_cell_methods)] +#![cfg_attr(bootstrap, feature(let_else))] // Configure clippy and other lints #![allow( clippy::collapsible_else_if, From 79c665b2a321f7d7a8826139171092baa42b0b56 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 22 Sep 2022 19:36:26 +0000 Subject: [PATCH 132/586] Calculate ProjectionTy::trait_def_id correctly --- compiler/rustc_middle/src/ty/sty.rs | 10 +++++-- .../ui/impl-trait/in-trait/issue-102140.rs | 30 +++++++++++++++++++ .../impl-trait/in-trait/issue-102140.stderr | 29 ++++++++++++++++++ 3 files changed, 66 insertions(+), 3 deletions(-) create mode 100644 src/test/ui/impl-trait/in-trait/issue-102140.rs create mode 100644 src/test/ui/impl-trait/in-trait/issue-102140.stderr diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index d2f73f274f8d9..37a1f2b550cac 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -1133,9 +1133,13 @@ pub struct ProjectionTy<'tcx> { impl<'tcx> ProjectionTy<'tcx> { pub fn trait_def_id(&self, tcx: TyCtxt<'tcx>) -> DefId { - let parent = tcx.parent(self.item_def_id); - assert_eq!(tcx.def_kind(parent), DefKind::Trait); - parent + match tcx.def_kind(self.item_def_id) { + DefKind::AssocTy | DefKind::AssocConst => tcx.parent(self.item_def_id), + DefKind::ImplTraitPlaceholder => { + tcx.parent(tcx.impl_trait_in_trait_parent(self.item_def_id)) + } + kind => bug!("unexpected DefKind in ProjectionTy: {kind:?}"), + } } /// Extracts the underlying trait reference and own substs from this projection. diff --git a/src/test/ui/impl-trait/in-trait/issue-102140.rs b/src/test/ui/impl-trait/in-trait/issue-102140.rs new file mode 100644 index 0000000000000..be1e012acb185 --- /dev/null +++ b/src/test/ui/impl-trait/in-trait/issue-102140.rs @@ -0,0 +1,30 @@ +#![feature(return_position_impl_trait_in_trait)] +#![allow(incomplete_features)] + +trait Marker {} +impl Marker for u32 {} + +trait MyTrait { + fn foo(&self) -> impl Marker + where + Self: Sized; +} + +struct Outer; + +impl MyTrait for Outer { + fn foo(&self) -> impl Marker { + 42 + } +} + +impl dyn MyTrait { + fn other(&self) -> impl Marker { + MyTrait::foo(&self) + //~^ ERROR the trait bound `&dyn MyTrait: MyTrait` is not satisfied + //~| ERROR the trait bound `&dyn MyTrait: MyTrait` is not satisfied + //~| ERROR the trait bound `&dyn MyTrait: MyTrait` is not satisfied + } +} + +fn main() {} diff --git a/src/test/ui/impl-trait/in-trait/issue-102140.stderr b/src/test/ui/impl-trait/in-trait/issue-102140.stderr new file mode 100644 index 0000000000000..08602185f50ca --- /dev/null +++ b/src/test/ui/impl-trait/in-trait/issue-102140.stderr @@ -0,0 +1,29 @@ +error[E0277]: the trait bound `&dyn MyTrait: MyTrait` is not satisfied + --> $DIR/issue-102140.rs:23:22 + | +LL | MyTrait::foo(&self) + | ------------ -^^^^ + | | | + | | the trait `MyTrait` is not implemented for `&dyn MyTrait` + | | help: consider removing the leading `&`-reference + | required by a bound introduced by this call + +error[E0277]: the trait bound `&dyn MyTrait: MyTrait` is not satisfied + --> $DIR/issue-102140.rs:23:9 + | +LL | MyTrait::foo(&self) + | ^^^^^^^^^^^^^^^^^^^ the trait `MyTrait` is not implemented for `&dyn MyTrait` + | + = help: the trait `MyTrait` is implemented for `Outer` + +error[E0277]: the trait bound `&dyn MyTrait: MyTrait` is not satisfied + --> $DIR/issue-102140.rs:23:9 + | +LL | MyTrait::foo(&self) + | ^^^^^^^^^^^^ the trait `MyTrait` is not implemented for `&dyn MyTrait` + | + = help: the trait `MyTrait` is implemented for `Outer` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0277`. From 9a206a78eb1c4d73bd55432e02a5a29d871afb7c Mon Sep 17 00:00:00 2001 From: khyperia <953151+khyperia@users.noreply.github.com> Date: Thu, 8 Sep 2022 15:37:15 +0200 Subject: [PATCH 133/586] Improve the help message for an invalid calling convention --- Cargo.lock | 1 + compiler/rustc_ast_lowering/src/errors.rs | 18 +- compiler/rustc_ast_lowering/src/item.rs | 18 +- compiler/rustc_ast_passes/src/feature_gate.rs | 220 ++---------------- compiler/rustc_driver/src/lib.rs | 5 + .../locales/en-US/ast_lowering.ftl | 4 +- compiler/rustc_session/src/config.rs | 6 +- compiler/rustc_target/Cargo.toml | 3 +- compiler/rustc_target/src/spec/abi.rs | 188 +++++++++++++++ .../print-calling-conventions/Makefile | 4 + src/test/ui/abi/abi-typo-unstable.rs | 6 + src/test/ui/abi/abi-typo-unstable.stderr | 11 + .../ui/codemap_tests/unicode.normal.stderr | 2 +- src/test/ui/parser/issues/issue-8537.stderr | 2 +- src/test/ui/suggestions/abi-typo.fixed | 6 + src/test/ui/suggestions/abi-typo.rs | 6 + src/test/ui/suggestions/abi-typo.stderr | 14 ++ 17 files changed, 300 insertions(+), 214 deletions(-) create mode 100644 src/test/run-make-fulldeps/print-calling-conventions/Makefile create mode 100644 src/test/ui/abi/abi-typo-unstable.rs create mode 100644 src/test/ui/abi/abi-typo-unstable.stderr create mode 100644 src/test/ui/suggestions/abi-typo.fixed create mode 100644 src/test/ui/suggestions/abi-typo.rs create mode 100644 src/test/ui/suggestions/abi-typo.stderr diff --git a/Cargo.lock b/Cargo.lock index 12fa14ee81782..cec227d2ed6e1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4110,6 +4110,7 @@ version = "0.0.0" dependencies = [ "bitflags", "rustc_data_structures", + "rustc_feature", "rustc_index", "rustc_macros", "rustc_serialize", diff --git a/compiler/rustc_ast_lowering/src/errors.rs b/compiler/rustc_ast_lowering/src/errors.rs index 1ad5fa21d8530..63ff64b00bed6 100644 --- a/compiler/rustc_ast_lowering/src/errors.rs +++ b/compiler/rustc_ast_lowering/src/errors.rs @@ -29,14 +29,28 @@ impl AddToDiagnostic for UseAngleBrackets { } #[derive(Diagnostic)] -#[help] #[diag(ast_lowering::invalid_abi, code = "E0703")] +#[note] pub struct InvalidAbi { #[primary_span] #[label] pub span: Span, pub abi: Symbol, - pub valid_abis: String, + pub command: String, + #[subdiagnostic] + pub suggestion: Option, +} + +#[derive(Subdiagnostic)] +#[suggestion( + ast_lowering::invalid_abi_suggestion, + code = "{suggestion}", + applicability = "maybe-incorrect" +)] +pub struct InvalidAbiSuggestion { + #[primary_span] + pub span: Span, + pub suggestion: String, } #[derive(Diagnostic, Clone, Copy)] diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 550833275e441..dfd04fe2974a9 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -1,4 +1,4 @@ -use super::errors::{InvalidAbi, MisplacedRelaxTraitBound}; +use super::errors::{InvalidAbi, InvalidAbiSuggestion, MisplacedRelaxTraitBound}; use super::ResolverAstLoweringExt; use super::{Arena, AstOwner, ImplTraitContext, ImplTraitPosition}; use super::{FnDeclKind, LoweringContext, ParamMode}; @@ -14,9 +14,10 @@ use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID}; use rustc_hir::PredicateOrigin; use rustc_index::vec::{Idx, IndexVec}; use rustc_middle::ty::{DefIdTree, ResolverAstLowering, TyCtxt}; +use rustc_span::lev_distance::find_best_match_for_name; use rustc_span::source_map::DesugaringKind; use rustc_span::symbol::{kw, sym, Ident}; -use rustc_span::Span; +use rustc_span::{Span, Symbol}; use rustc_target::spec::abi; use smallvec::{smallvec, SmallVec}; @@ -1280,10 +1281,19 @@ impl<'hir> LoweringContext<'_, 'hir> { } fn error_on_invalid_abi(&self, abi: StrLit) { + let abi_names = abi::enabled_names(self.tcx.features(), abi.span) + .iter() + .map(|s| Symbol::intern(s)) + .collect::>(); + let suggested_name = find_best_match_for_name(&abi_names, abi.symbol_unescaped, None); self.tcx.sess.emit_err(InvalidAbi { + abi: abi.symbol_unescaped, span: abi.span, - abi: abi.symbol, - valid_abis: abi::all_names().join(", "), + suggestion: suggested_name.map(|suggested_name| InvalidAbiSuggestion { + span: abi.span, + suggestion: format!("\"{suggested_name}\""), + }), + command: "rustc --print=calling-conventions".to_string(), }); } diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index aeff73c5bbbfb..0017a28cf1b18 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -3,13 +3,13 @@ use rustc_ast::visit::{self, AssocCtxt, FnCtxt, FnKind, Visitor}; use rustc_ast::{AssocConstraint, AssocConstraintKind, NodeId}; use rustc_ast::{PatKind, RangeEnd, VariantData}; use rustc_errors::{struct_span_err, Applicability, StashKey}; -use rustc_feature::Features; -use rustc_feature::{AttributeGate, BuiltinAttribute, BUILTIN_ATTRIBUTE_MAP}; -use rustc_session::parse::{feature_err, feature_warn}; +use rustc_feature::{AttributeGate, BuiltinAttribute, Features, GateIssue, BUILTIN_ATTRIBUTE_MAP}; +use rustc_session::parse::{feature_err, feature_err_issue, feature_warn}; use rustc_session::Session; use rustc_span::source_map::Spanned; use rustc_span::symbol::sym; use rustc_span::Span; +use rustc_target::spec::abi; macro_rules! gate_feature_fn { ($visitor: expr, $has_feature: expr, $span: expr, $name: expr, $explain: expr, $help: expr) => {{ @@ -84,210 +84,26 @@ impl<'a> PostExpansionVisitor<'a> { } } - match symbol_unescaped.as_str() { - // Stable - "Rust" | "C" | "cdecl" | "stdcall" | "fastcall" | "aapcs" | "win64" | "sysv64" - | "system" => {} - "rust-intrinsic" => { - gate_feature_post!(&self, intrinsics, span, "intrinsics are subject to change"); - } - "platform-intrinsic" => { - gate_feature_post!( - &self, - platform_intrinsics, - span, - "platform intrinsics are experimental and possibly buggy" - ); - } - "vectorcall" => { - gate_feature_post!( - &self, - abi_vectorcall, - span, - "vectorcall is experimental and subject to change" - ); - } - "thiscall" => { - gate_feature_post!( - &self, - abi_thiscall, - span, - "thiscall is experimental and subject to change" - ); - } - "rust-call" => { - gate_feature_post!( - &self, - unboxed_closures, - span, - "rust-call ABI is subject to change" - ); - } - "rust-cold" => { - gate_feature_post!( - &self, - rust_cold_cc, - span, - "rust-cold is experimental and subject to change" - ); - } - "ptx-kernel" => { - gate_feature_post!( - &self, - abi_ptx, - span, - "PTX ABIs are experimental and subject to change" - ); - } - "unadjusted" => { - gate_feature_post!( - &self, - abi_unadjusted, - span, - "unadjusted ABI is an implementation detail and perma-unstable" - ); - } - "msp430-interrupt" => { - gate_feature_post!( - &self, - abi_msp430_interrupt, - span, - "msp430-interrupt ABI is experimental and subject to change" - ); - } - "x86-interrupt" => { - gate_feature_post!( - &self, - abi_x86_interrupt, - span, - "x86-interrupt ABI is experimental and subject to change" - ); - } - "amdgpu-kernel" => { - gate_feature_post!( - &self, - abi_amdgpu_kernel, - span, - "amdgpu-kernel ABI is experimental and subject to change" - ); - } - "avr-interrupt" | "avr-non-blocking-interrupt" => { - gate_feature_post!( - &self, - abi_avr_interrupt, - span, - "avr-interrupt and avr-non-blocking-interrupt ABIs are experimental and subject to change" - ); - } - "efiapi" => { - gate_feature_post!( - &self, - abi_efiapi, - span, - "efiapi ABI is experimental and subject to change" - ); - } - "C-cmse-nonsecure-call" => { - gate_feature_post!( - &self, - abi_c_cmse_nonsecure_call, - span, - "C-cmse-nonsecure-call ABI is experimental and subject to change" - ); - } - "C-unwind" => { - gate_feature_post!( - &self, - c_unwind, - span, - "C-unwind ABI is experimental and subject to change" - ); - } - "stdcall-unwind" => { - gate_feature_post!( - &self, - c_unwind, + match abi::is_enabled(&self.features, span, symbol_unescaped.as_str()) { + Ok(()) => (), + Err(abi::AbiDisabled::Unstable { feature, explain }) => { + feature_err_issue( + &self.sess.parse_sess, + feature, span, - "stdcall-unwind ABI is experimental and subject to change" - ); - } - "system-unwind" => { - gate_feature_post!( - &self, - c_unwind, - span, - "system-unwind ABI is experimental and subject to change" - ); - } - "thiscall-unwind" => { - gate_feature_post!( - &self, - c_unwind, - span, - "thiscall-unwind ABI is experimental and subject to change" - ); - } - "cdecl-unwind" => { - gate_feature_post!( - &self, - c_unwind, - span, - "cdecl-unwind ABI is experimental and subject to change" - ); - } - "fastcall-unwind" => { - gate_feature_post!( - &self, - c_unwind, - span, - "fastcall-unwind ABI is experimental and subject to change" - ); - } - "vectorcall-unwind" => { - gate_feature_post!( - &self, - c_unwind, - span, - "vectorcall-unwind ABI is experimental and subject to change" - ); - } - "aapcs-unwind" => { - gate_feature_post!( - &self, - c_unwind, - span, - "aapcs-unwind ABI is experimental and subject to change" - ); - } - "win64-unwind" => { - gate_feature_post!( - &self, - c_unwind, - span, - "win64-unwind ABI is experimental and subject to change" - ); - } - "sysv64-unwind" => { - gate_feature_post!( - &self, - c_unwind, - span, - "sysv64-unwind ABI is experimental and subject to change" - ); - } - "wasm" => { - gate_feature_post!( - &self, - wasm_abi, - span, - "wasm ABI is experimental and subject to change" - ); + GateIssue::Language, + explain, + ) + .emit(); } - abi => { + Err(abi::AbiDisabled::Unrecognized) => { if self.sess.opts.pretty.map_or(true, |ppm| ppm.needs_hir()) { self.sess.parse_sess.span_diagnostic.delay_span_bug( span, - &format!("unrecognized ABI not caught in lowering: {}", abi), + &format!( + "unrecognized ABI not caught in lowering: {}", + symbol_unescaped.as_str() + ), ); } } diff --git a/compiler/rustc_driver/src/lib.rs b/compiler/rustc_driver/src/lib.rs index 8fb9508194b68..c768935eb6238 100644 --- a/compiler/rustc_driver/src/lib.rs +++ b/compiler/rustc_driver/src/lib.rs @@ -742,6 +742,11 @@ fn print_crate_info( println!("{}", cfg); } } + CallingConventions => { + let mut calling_conventions = rustc_target::spec::abi::all_names(); + calling_conventions.sort_unstable(); + println!("{}", calling_conventions.join("\n")); + } RelocationModels | CodeModels | TlsModels diff --git a/compiler/rustc_error_messages/locales/en-US/ast_lowering.ftl b/compiler/rustc_error_messages/locales/en-US/ast_lowering.ftl index c45e045b4dba0..03c88c6c0ebe5 100644 --- a/compiler/rustc_error_messages/locales/en-US/ast_lowering.ftl +++ b/compiler/rustc_error_messages/locales/en-US/ast_lowering.ftl @@ -7,7 +7,9 @@ ast_lowering_use_angle_brackets = use angle brackets instead ast_lowering_invalid_abi = invalid ABI: found `{$abi}` .label = invalid ABI - .help = valid ABIs: {$valid_abis} + .note = invoke `{$command}` for a full list of supported calling conventions. + +ast_lowering_invalid_abi_suggestion = did you mean ast_lowering_assoc_ty_parentheses = parenthesized generic arguments cannot be used in associated type constraints diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 57c9a3f4822dc..70b470f3811d5 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -538,6 +538,7 @@ pub enum PrintRequest { TargetLibdir, CrateName, Cfg, + CallingConventions, TargetList, TargetCPUs, TargetFeatures, @@ -1354,8 +1355,8 @@ pub fn rustc_short_optgroups() -> Vec { "", "print", "Compiler information to print on stdout", - "[crate-name|file-names|sysroot|target-libdir|cfg|target-list|\ - target-cpus|target-features|relocation-models|code-models|\ + "[crate-name|file-names|sysroot|target-libdir|cfg|calling-conventions|\ + target-list|target-cpus|target-features|relocation-models|code-models|\ tls-models|target-spec-json|native-static-libs|stack-protector-strategies|\ link-args]", ), @@ -1794,6 +1795,7 @@ fn collect_print_requests( "sysroot" => PrintRequest::Sysroot, "target-libdir" => PrintRequest::TargetLibdir, "cfg" => PrintRequest::Cfg, + "calling-conventions" => PrintRequest::CallingConventions, "target-list" => PrintRequest::TargetList, "target-cpus" => PrintRequest::TargetCPUs, "target-features" => PrintRequest::TargetFeatures, diff --git a/compiler/rustc_target/Cargo.toml b/compiler/rustc_target/Cargo.toml index 162376af45f15..fc37fdb1c43ca 100644 --- a/compiler/rustc_target/Cargo.toml +++ b/compiler/rustc_target/Cargo.toml @@ -8,7 +8,8 @@ bitflags = "1.2.1" tracing = "0.1" serde_json = "1.0.59" rustc_data_structures = { path = "../rustc_data_structures" } +rustc_feature = { path = "../rustc_feature" } +rustc_index = { path = "../rustc_index" } rustc_macros = { path = "../rustc_macros" } rustc_serialize = { path = "../rustc_serialize" } rustc_span = { path = "../rustc_span" } -rustc_index = { path = "../rustc_index" } diff --git a/compiler/rustc_target/src/spec/abi.rs b/compiler/rustc_target/src/spec/abi.rs index 337554dc96e82..c915124434b2d 100644 --- a/compiler/rustc_target/src/spec/abi.rs +++ b/compiler/rustc_target/src/spec/abi.rs @@ -1,6 +1,8 @@ use std::fmt; use rustc_macros::HashStable_Generic; +use rustc_span::symbol::sym; +use rustc_span::{Span, Symbol}; #[cfg(test)] mod tests; @@ -94,6 +96,192 @@ pub fn all_names() -> Vec<&'static str> { AbiDatas.iter().map(|d| d.name).collect() } +pub fn enabled_names(features: &rustc_feature::Features, span: Span) -> Vec<&'static str> { + AbiDatas + .iter() + .map(|d| d.name) + .filter(|name| is_enabled(features, span, name).is_ok()) + .collect() +} + +pub enum AbiDisabled { + Unstable { feature: Symbol, explain: &'static str }, + Unrecognized, +} + +fn gate_feature_post( + features: &rustc_feature::Features, + feature: Symbol, + span: Span, + explain: &'static str, +) -> Result<(), AbiDisabled> { + if !features.enabled(feature) && !span.allows_unstable(feature) { + Err(AbiDisabled::Unstable { feature, explain }) + } else { + Ok(()) + } +} + +pub fn is_enabled( + features: &rustc_feature::Features, + span: Span, + name: &str, +) -> Result<(), AbiDisabled> { + match name { + // Stable + "Rust" | "C" | "cdecl" | "stdcall" | "fastcall" | "aapcs" | "win64" | "sysv64" + | "system" => Ok(()), + "rust-intrinsic" => { + gate_feature_post(features, sym::intrinsics, span, "intrinsics are subject to change") + } + "platform-intrinsic" => gate_feature_post( + features, + sym::platform_intrinsics, + span, + "platform intrinsics are experimental and possibly buggy", + ), + "vectorcall" => gate_feature_post( + features, + sym::abi_vectorcall, + span, + "vectorcall is experimental and subject to change", + ), + "thiscall" => gate_feature_post( + features, + sym::abi_thiscall, + span, + "thiscall is experimental and subject to change", + ), + "rust-call" => gate_feature_post( + features, + sym::unboxed_closures, + span, + "rust-call ABI is subject to change", + ), + "rust-cold" => gate_feature_post( + features, + sym::rust_cold_cc, + span, + "rust-cold is experimental and subject to change", + ), + "ptx-kernel" => gate_feature_post( + features, + sym::abi_ptx, + span, + "PTX ABIs are experimental and subject to change", + ), + "unadjusted" => gate_feature_post( + features, + sym::abi_unadjusted, + span, + "unadjusted ABI is an implementation detail and perma-unstable", + ), + "msp430-interrupt" => gate_feature_post( + features, + sym::abi_msp430_interrupt, + span, + "msp430-interrupt ABI is experimental and subject to change", + ), + "x86-interrupt" => gate_feature_post( + features, + sym::abi_x86_interrupt, + span, + "x86-interrupt ABI is experimental and subject to change", + ), + "amdgpu-kernel" => gate_feature_post( + features, + sym::abi_amdgpu_kernel, + span, + "amdgpu-kernel ABI is experimental and subject to change", + ), + "avr-interrupt" | "avr-non-blocking-interrupt" => gate_feature_post( + features, + sym::abi_avr_interrupt, + span, + "avr-interrupt and avr-non-blocking-interrupt ABIs are experimental and subject to change", + ), + "efiapi" => gate_feature_post( + features, + sym::abi_efiapi, + span, + "efiapi ABI is experimental and subject to change", + ), + "C-cmse-nonsecure-call" => gate_feature_post( + features, + sym::abi_c_cmse_nonsecure_call, + span, + "C-cmse-nonsecure-call ABI is experimental and subject to change", + ), + "C-unwind" => gate_feature_post( + features, + sym::c_unwind, + span, + "C-unwind ABI is experimental and subject to change", + ), + "stdcall-unwind" => gate_feature_post( + features, + sym::c_unwind, + span, + "stdcall-unwind ABI is experimental and subject to change", + ), + "system-unwind" => gate_feature_post( + features, + sym::c_unwind, + span, + "system-unwind ABI is experimental and subject to change", + ), + "thiscall-unwind" => gate_feature_post( + features, + sym::c_unwind, + span, + "thiscall-unwind ABI is experimental and subject to change", + ), + "cdecl-unwind" => gate_feature_post( + features, + sym::c_unwind, + span, + "cdecl-unwind ABI is experimental and subject to change", + ), + "fastcall-unwind" => gate_feature_post( + features, + sym::c_unwind, + span, + "fastcall-unwind ABI is experimental and subject to change", + ), + "vectorcall-unwind" => gate_feature_post( + features, + sym::c_unwind, + span, + "vectorcall-unwind ABI is experimental and subject to change", + ), + "aapcs-unwind" => gate_feature_post( + features, + sym::c_unwind, + span, + "aapcs-unwind ABI is experimental and subject to change", + ), + "win64-unwind" => gate_feature_post( + features, + sym::c_unwind, + span, + "win64-unwind ABI is experimental and subject to change", + ), + "sysv64-unwind" => gate_feature_post( + features, + sym::c_unwind, + span, + "sysv64-unwind ABI is experimental and subject to change", + ), + "wasm" => gate_feature_post( + features, + sym::wasm_abi, + span, + "wasm ABI is experimental and subject to change", + ), + _ => Err(AbiDisabled::Unrecognized), + } +} + impl Abi { /// Default ABI chosen for `extern fn` declarations without an explicit ABI. pub const FALLBACK: Abi = Abi::C { unwind: false }; diff --git a/src/test/run-make-fulldeps/print-calling-conventions/Makefile b/src/test/run-make-fulldeps/print-calling-conventions/Makefile new file mode 100644 index 0000000000000..d3fd06392b0ed --- /dev/null +++ b/src/test/run-make-fulldeps/print-calling-conventions/Makefile @@ -0,0 +1,4 @@ +-include ../tools.mk + +all: + $(RUSTC) --print calling-conventions diff --git a/src/test/ui/abi/abi-typo-unstable.rs b/src/test/ui/abi/abi-typo-unstable.rs new file mode 100644 index 0000000000000..94991a5eb17e8 --- /dev/null +++ b/src/test/ui/abi/abi-typo-unstable.rs @@ -0,0 +1,6 @@ +// rust-intrinsic is unstable and not enabled, so it should not be suggested as a fix +extern "rust-intrinsec" fn rust_intrinsic() {} //~ ERROR invalid ABI + +fn main() { + rust_intrinsic(); +} diff --git a/src/test/ui/abi/abi-typo-unstable.stderr b/src/test/ui/abi/abi-typo-unstable.stderr new file mode 100644 index 0000000000000..3b346e00227a3 --- /dev/null +++ b/src/test/ui/abi/abi-typo-unstable.stderr @@ -0,0 +1,11 @@ +error[E0703]: invalid ABI: found `rust-intrinsec` + --> $DIR/abi-typo-unstable.rs:2:8 + | +LL | extern "rust-intrinsec" fn rust_intrinsic() {} + | ^^^^^^^^^^^^^^^^ invalid ABI + | + = note: invoke `rustc --print=calling-conventions` for a full list of supported calling conventions. + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0703`. diff --git a/src/test/ui/codemap_tests/unicode.normal.stderr b/src/test/ui/codemap_tests/unicode.normal.stderr index 60f8cff84b30c..05ceb6910dadd 100644 --- a/src/test/ui/codemap_tests/unicode.normal.stderr +++ b/src/test/ui/codemap_tests/unicode.normal.stderr @@ -4,7 +4,7 @@ error[E0703]: invalid ABI: found `路濫狼á́́` LL | extern "路濫狼á́́" fn foo() {} | ^^^^^^^^^ invalid ABI | - = help: valid ABIs: Rust, C, C-unwind, cdecl, cdecl-unwind, stdcall, stdcall-unwind, fastcall, fastcall-unwind, vectorcall, vectorcall-unwind, thiscall, thiscall-unwind, aapcs, aapcs-unwind, win64, win64-unwind, sysv64, sysv64-unwind, ptx-kernel, msp430-interrupt, x86-interrupt, amdgpu-kernel, efiapi, avr-interrupt, avr-non-blocking-interrupt, C-cmse-nonsecure-call, wasm, system, system-unwind, rust-intrinsic, rust-call, platform-intrinsic, unadjusted, rust-cold + = note: invoke `rustc --print=calling-conventions` for a full list of supported calling conventions. error: aborting due to previous error diff --git a/src/test/ui/parser/issues/issue-8537.stderr b/src/test/ui/parser/issues/issue-8537.stderr index 505d830ef3e8f..523cc9dc588f4 100644 --- a/src/test/ui/parser/issues/issue-8537.stderr +++ b/src/test/ui/parser/issues/issue-8537.stderr @@ -4,7 +4,7 @@ error[E0703]: invalid ABI: found `invalid-ab_isize` LL | "invalid-ab_isize" | ^^^^^^^^^^^^^^^^^^ invalid ABI | - = help: valid ABIs: Rust, C, C-unwind, cdecl, cdecl-unwind, stdcall, stdcall-unwind, fastcall, fastcall-unwind, vectorcall, vectorcall-unwind, thiscall, thiscall-unwind, aapcs, aapcs-unwind, win64, win64-unwind, sysv64, sysv64-unwind, ptx-kernel, msp430-interrupt, x86-interrupt, amdgpu-kernel, efiapi, avr-interrupt, avr-non-blocking-interrupt, C-cmse-nonsecure-call, wasm, system, system-unwind, rust-intrinsic, rust-call, platform-intrinsic, unadjusted, rust-cold + = note: invoke `rustc --print=calling-conventions` for a full list of supported calling conventions. error: aborting due to previous error diff --git a/src/test/ui/suggestions/abi-typo.fixed b/src/test/ui/suggestions/abi-typo.fixed new file mode 100644 index 0000000000000..04d265865f0f8 --- /dev/null +++ b/src/test/ui/suggestions/abi-typo.fixed @@ -0,0 +1,6 @@ +// run-rustfix +extern "cdecl" fn cdedl() {} //~ ERROR invalid ABI + +fn main() { + cdedl(); +} diff --git a/src/test/ui/suggestions/abi-typo.rs b/src/test/ui/suggestions/abi-typo.rs new file mode 100644 index 0000000000000..6d80db522ebc1 --- /dev/null +++ b/src/test/ui/suggestions/abi-typo.rs @@ -0,0 +1,6 @@ +// run-rustfix +extern "cdedl" fn cdedl() {} //~ ERROR invalid ABI + +fn main() { + cdedl(); +} diff --git a/src/test/ui/suggestions/abi-typo.stderr b/src/test/ui/suggestions/abi-typo.stderr new file mode 100644 index 0000000000000..67a84f119f6c7 --- /dev/null +++ b/src/test/ui/suggestions/abi-typo.stderr @@ -0,0 +1,14 @@ +error[E0703]: invalid ABI: found `cdedl` + --> $DIR/abi-typo.rs:2:8 + | +LL | extern "cdedl" fn cdedl() {} + | ^^^^^^^ + | | + | invalid ABI + | help: did you mean: `"cdecl"` + | + = note: invoke `rustc --print=calling-conventions` for a full list of supported calling conventions. + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0703`. From dedf6fcde48ccebe8b81654aa0e3ac1c78347a9b Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Thu, 22 Sep 2022 14:54:38 -0700 Subject: [PATCH 134/586] rustdoc: clean up CSS/DOM for deprecation warnings --- src/librustdoc/html/markdown.rs | 19 ++++++++----------- src/librustdoc/html/render/mod.rs | 13 ++++--------- src/librustdoc/html/static/css/rustdoc.css | 4 ---- 3 files changed, 12 insertions(+), 24 deletions(-) diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index 43d07d4a53337..8e53fbbcd1975 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -111,14 +111,9 @@ pub(crate) struct MarkdownWithToc<'a>( pub(crate) Edition, pub(crate) &'a Option, ); -/// A tuple struct like `Markdown` that renders the markdown escaping HTML tags. -pub(crate) struct MarkdownHtml<'a>( - pub(crate) &'a str, - pub(crate) &'a mut IdMap, - pub(crate) ErrorCodes, - pub(crate) Edition, - pub(crate) &'a Option, -); +/// A tuple struct like `Markdown` that renders the markdown escaping HTML tags +/// and includes no paragraph tags. +pub(crate) struct MarkdownItemInfo<'a>(pub(crate) &'a str, pub(crate) &'a mut IdMap); /// A tuple struct like `Markdown` that renders only the first paragraph. pub(crate) struct MarkdownSummaryLine<'a>(pub &'a str, pub &'a [RenderedLink]); @@ -1072,9 +1067,9 @@ impl MarkdownWithToc<'_> { } } -impl MarkdownHtml<'_> { +impl MarkdownItemInfo<'_> { pub(crate) fn into_string(self) -> String { - let MarkdownHtml(md, ids, codes, edition, playground) = self; + let MarkdownItemInfo(md, ids) = self; // This is actually common enough to special-case if md.is_empty() { @@ -1093,7 +1088,9 @@ impl MarkdownHtml<'_> { let p = HeadingLinks::new(p, None, ids, HeadingOffset::H1); let p = Footnotes::new(p); let p = TableWrapper::new(p.map(|(ev, _)| ev)); - let p = CodeBlocks::new(p, codes, edition, playground); + let p = p.filter(|event| { + !matches!(event, Event::Start(Tag::Paragraph) | Event::End(Tag::Paragraph)) + }); html::push_html(&mut s, p); s diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 7e5e4df43d291..ca4e65d70287c 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -74,7 +74,9 @@ use crate::html::format::{ PrintWithSpace, }; use crate::html::highlight; -use crate::html::markdown::{HeadingOffset, IdMap, Markdown, MarkdownHtml, MarkdownSummaryLine}; +use crate::html::markdown::{ + HeadingOffset, IdMap, Markdown, MarkdownItemInfo, MarkdownSummaryLine, +}; use crate::html::sources; use crate::html::static_files::SCRAPE_EXAMPLES_HELP_MD; use crate::scrape_examples::{CallData, CallLocation}; @@ -582,7 +584,6 @@ fn short_item_info( parent: Option<&clean::Item>, ) -> Vec { let mut extra_info = vec![]; - let error_codes = cx.shared.codes; if let Some(depr @ Deprecation { note, since, is_since_rustc_version: _, suggestion: _ }) = item.deprecation(cx.tcx()) @@ -606,13 +607,7 @@ fn short_item_info( if let Some(note) = note { let note = note.as_str(); - let html = MarkdownHtml( - note, - &mut cx.id_map, - error_codes, - cx.shared.edition(), - &cx.shared.playground, - ); + let html = MarkdownItemInfo(note, &mut cx.id_map); message.push_str(&format!(": {}", html.into_string())); } extra_info.push(format!( diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index f21179ec558f0..3ce9407cb2dda 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -1078,10 +1078,6 @@ so that we can apply CSS-filters to change the arrow color in themes */ font-size: 0.875rem; font-weight: normal; } -.stab p { - display: inline; - margin: 0; -} .stab .emoji { font-size: 1.25rem; From ed812c7addb8871d9f644604513679263cebc43f Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Tue, 13 Sep 2022 09:42:03 -0700 Subject: [PATCH 135/586] Add `AsFd` implementations for stdio lock types on WASI. This mirrors the implementations on Unix platforms, and also mirrors the existing `AsRawFd` impls. This is similar to #100892, but is for the `*Lock` types. --- library/std/src/sys/wasi/stdio.rs | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/library/std/src/sys/wasi/stdio.rs b/library/std/src/sys/wasi/stdio.rs index d2081771b6ec7..07f5fbe384259 100644 --- a/library/std/src/sys/wasi/stdio.rs +++ b/library/std/src/sys/wasi/stdio.rs @@ -30,6 +30,13 @@ impl AsFd for Stdin { } } +impl<'a> AsFd for StdinLock<'a> { + #[inline] + fn as_fd(&self) -> BorrowedFd<'_> { + unsafe { BorrowedFd::borrow_raw(0) } + } +} + impl io::Read for Stdin { fn read(&mut self, data: &mut [u8]) -> io::Result { self.read_vectored(&mut [IoSliceMut::new(data)]) @@ -65,6 +72,13 @@ impl AsFd for Stdout { } } +impl<'a> AsFd for StdoutLock<'a> { + #[inline] + fn as_fd(&self) -> BorrowedFd<'_> { + unsafe { BorrowedFd::borrow_raw(1) } + } +} + impl io::Write for Stdout { fn write(&mut self, data: &[u8]) -> io::Result { self.write_vectored(&[IoSlice::new(data)]) @@ -103,6 +117,13 @@ impl AsFd for Stderr { } } +impl<'a> AsFd for StderrLock<'a> { + #[inline] + fn as_fd(&self) -> BorrowedFd<'_> { + unsafe { BorrowedFd::borrow_raw(2) } + } +} + impl io::Write for Stderr { fn write(&mut self, data: &[u8]) -> io::Result { self.write_vectored(&[IoSlice::new(data)]) From 51f335deca435bd4899b3cde0555bbaaa6afdbef Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Thu, 22 Sep 2022 15:41:32 -0700 Subject: [PATCH 136/586] rustdoc: fix unit tests --- src/librustdoc/html/markdown/tests.rs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/librustdoc/html/markdown/tests.rs b/src/librustdoc/html/markdown/tests.rs index 5c0bf0ed942f4..e4f72a057892f 100644 --- a/src/librustdoc/html/markdown/tests.rs +++ b/src/librustdoc/html/markdown/tests.rs @@ -1,5 +1,5 @@ use super::{find_testable_code, plain_text_summary, short_markdown_summary}; -use super::{ErrorCodes, HeadingOffset, IdMap, Ignore, LangString, Markdown, MarkdownHtml}; +use super::{ErrorCodes, HeadingOffset, IdMap, Ignore, LangString, Markdown, MarkdownItemInfo}; use rustc_span::edition::{Edition, DEFAULT_EDITION}; #[test] @@ -279,14 +279,13 @@ fn test_plain_text_summary() { fn test_markdown_html_escape() { fn t(input: &str, expect: &str) { let mut idmap = IdMap::new(); - let output = - MarkdownHtml(input, &mut idmap, ErrorCodes::Yes, DEFAULT_EDITION, &None).into_string(); + let output = MarkdownItemInfo(input, &mut idmap).into_string(); assert_eq!(output, expect, "original: {}", input); } - t("`Struct<'a, T>`", "

Struct<'a, T>

\n"); - t("Struct<'a, T>", "

Struct<’a, T>

\n"); - t("Struct
", "

Struct<br>

\n"); + t("`Struct<'a, T>`", "Struct<'a, T>"); + t("Struct<'a, T>", "Struct<’a, T>"); + t("Struct
", "Struct<br>"); } #[test] From 2fa31d3e78d8ee9d9a5118516f69f5017a1ca984 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 23 Sep 2022 00:56:55 +0000 Subject: [PATCH 137/586] Serialize RPITIT values in libs --- .../src/rmeta/decoder/cstore_impl.rs | 9 +++++ compiler/rustc_metadata/src/rmeta/encoder.rs | 33 +++++++++++++++++++ compiler/rustc_metadata/src/rmeta/mod.rs | 3 ++ compiler/rustc_middle/src/ty/parameterized.rs | 5 +++ .../impl-trait/in-trait/auxiliary/rpitit.rs | 11 +++++++ src/test/ui/impl-trait/in-trait/foreign.rs | 9 +++++ 6 files changed, 70 insertions(+) create mode 100644 src/test/ui/impl-trait/in-trait/auxiliary/rpitit.rs create mode 100644 src/test/ui/impl-trait/in-trait/foreign.rs diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index dede1b2122a3c..466da175810d5 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -223,6 +223,15 @@ provide! { tcx, def_id, other, cdata, fn_arg_names => { table } generator_kind => { table } trait_def => { table } + collect_trait_impl_trait_tys => { + Ok(cdata + .root + .tables + .trait_impl_trait_tys + .get(cdata, def_id.index) + .map(|lazy| lazy.decode((cdata, tcx))) + .process_decoded(tcx, || panic!("{:?} does not have trait_impl_trait_tys", def_id))) + } visibility => { cdata.get_visibility(def_id.index) } adt_def => { cdata.get_adt_def(def_id.index, tcx) } diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 67c28461ce5cf..734e9a31bb90c 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1059,6 +1059,34 @@ fn should_encode_const(def_kind: DefKind) -> bool { } } +fn should_encode_trait_impl_trait_tys<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> bool { + if tcx.def_kind(def_id) != DefKind::AssocFn { + return false; + } + + let Some(item) = tcx.opt_associated_item(def_id) else { return false; }; + if item.container != ty::AssocItemContainer::ImplContainer { + return false; + } + + let Some(trait_item_def_id) = item.trait_item_def_id else { return false; }; + + // FIXME(RPITIT): This does a somewhat manual walk through the signature + // of the trait fn to look for any RPITITs, but that's kinda doing a lot + // of work. We can probably remove this when we refactor RPITITs to be + // associated types. + tcx.fn_sig(trait_item_def_id).skip_binder().output().walk().any(|arg| { + if let ty::GenericArgKind::Type(ty) = arg.unpack() + && let ty::Projection(data) = ty.kind() + && tcx.def_kind(data.item_def_id) == DefKind::ImplTraitPlaceholder + { + true + } else { + false + } + }) +} + impl<'a, 'tcx> EncodeContext<'a, 'tcx> { fn encode_attrs(&mut self, def_id: LocalDefId) { let mut attrs = self @@ -1128,6 +1156,11 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { if let DefKind::Trait | DefKind::TraitAlias = def_kind { record!(self.tables.super_predicates_of[def_id] <- self.tcx.super_predicates_of(def_id)); } + if should_encode_trait_impl_trait_tys(tcx, def_id) + && let Ok(table) = self.tcx.collect_trait_impl_trait_tys(def_id) + { + record!(self.tables.trait_impl_trait_tys[def_id] <- table); + } } let inherent_impls = tcx.crate_inherent_impls(()); for (def_id, implementations) in inherent_impls.inherent_impls.iter() { diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index 748b3afec37c7..6d7345570af85 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -1,6 +1,7 @@ use crate::creader::CrateMetadataRef; use decoder::Metadata; use def_path_hash_map::DefPathHashMapRef; +use rustc_data_structures::fx::FxHashMap; use table::TableBuilder; use rustc_ast as ast; @@ -399,6 +400,8 @@ define_tables! { macro_definition: Table>, proc_macro: Table, module_reexports: Table>, + + trait_impl_trait_tys: Table>>>, } #[derive(TyEncodable, TyDecodable)] diff --git a/compiler/rustc_middle/src/ty/parameterized.rs b/compiler/rustc_middle/src/ty/parameterized.rs index 9c8dc30e2db3f..0257ca7b29c71 100644 --- a/compiler/rustc_middle/src/ty/parameterized.rs +++ b/compiler/rustc_middle/src/ty/parameterized.rs @@ -1,3 +1,4 @@ +use rustc_data_structures::fx::FxHashMap; use rustc_hir::def_id::{DefId, DefIndex}; use rustc_index::vec::{Idx, IndexVec}; @@ -29,6 +30,10 @@ impl ParameterizedOverTcx for IndexVe type Value<'tcx> = IndexVec>; } +impl ParameterizedOverTcx for FxHashMap { + type Value<'tcx> = FxHashMap>; +} + impl ParameterizedOverTcx for ty::Binder<'static, T> { type Value<'tcx> = ty::Binder<'tcx, T::Value<'tcx>>; } diff --git a/src/test/ui/impl-trait/in-trait/auxiliary/rpitit.rs b/src/test/ui/impl-trait/in-trait/auxiliary/rpitit.rs new file mode 100644 index 0000000000000..74df300f85a6b --- /dev/null +++ b/src/test/ui/impl-trait/in-trait/auxiliary/rpitit.rs @@ -0,0 +1,11 @@ +#![feature(return_position_impl_trait_in_trait)] + +pub trait Foo { + fn bar() -> impl Sized; +} + +pub struct Foreign; + +impl Foo for Foreign { + fn bar() {} +} diff --git a/src/test/ui/impl-trait/in-trait/foreign.rs b/src/test/ui/impl-trait/in-trait/foreign.rs new file mode 100644 index 0000000000000..6341f5b428429 --- /dev/null +++ b/src/test/ui/impl-trait/in-trait/foreign.rs @@ -0,0 +1,9 @@ +// check-pass +// aux-build: rpitit.rs + +extern crate rpitit; + +fn main() { + // Witness an RPITIT from another crate + let () = ::bar(); +} From 29efe8c78920e9cd74bb8f7dacff7eaa5370fcf6 Mon Sep 17 00:00:00 2001 From: Thom Chiovoloni Date: Thu, 22 Sep 2022 22:15:27 -0700 Subject: [PATCH 138/586] Add `#[inline]` to trivial functions on `core::sync::Exclusive` --- library/core/src/sync/exclusive.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/library/core/src/sync/exclusive.rs b/library/core/src/sync/exclusive.rs index a7519ab5ab633..c65c275000ce8 100644 --- a/library/core/src/sync/exclusive.rs +++ b/library/core/src/sync/exclusive.rs @@ -100,6 +100,7 @@ impl Exclusive { /// Wrap a value in an `Exclusive` #[unstable(feature = "exclusive_wrapper", issue = "98407")] #[must_use] + #[inline] pub const fn new(t: T) -> Self { Self { inner: t } } @@ -107,6 +108,7 @@ impl Exclusive { /// Unwrap the value contained in the `Exclusive` #[unstable(feature = "exclusive_wrapper", issue = "98407")] #[must_use] + #[inline] pub const fn into_inner(self) -> T { self.inner } @@ -116,6 +118,7 @@ impl Exclusive { /// Get exclusive access to the underlying value. #[unstable(feature = "exclusive_wrapper", issue = "98407")] #[must_use] + #[inline] pub const fn get_mut(&mut self) -> &mut T { &mut self.inner } @@ -128,6 +131,7 @@ impl Exclusive { /// produce _pinned_ access to the underlying value. #[unstable(feature = "exclusive_wrapper", issue = "98407")] #[must_use] + #[inline] pub const fn get_pin_mut(self: Pin<&mut Self>) -> Pin<&mut T> { // SAFETY: `Exclusive` can only produce `&mut T` if itself is unpinned // `Pin::map_unchecked_mut` is not const, so we do this conversion manually @@ -139,6 +143,7 @@ impl Exclusive { /// building an `Exclusive` with [`Exclusive::new`]. #[unstable(feature = "exclusive_wrapper", issue = "98407")] #[must_use] + #[inline] pub const fn from_mut(r: &'_ mut T) -> &'_ mut Exclusive { // SAFETY: repr is ≥ C, so refs have the same layout; and `Exclusive` properties are `&mut`-agnostic unsafe { &mut *(r as *mut T as *mut Exclusive) } @@ -149,6 +154,7 @@ impl Exclusive { /// building an `Exclusive` with [`Exclusive::new`]. #[unstable(feature = "exclusive_wrapper", issue = "98407")] #[must_use] + #[inline] pub const fn from_pin_mut(r: Pin<&'_ mut T>) -> Pin<&'_ mut Exclusive> { // SAFETY: `Exclusive` can only produce `&mut T` if itself is unpinned // `Pin::map_unchecked_mut` is not const, so we do this conversion manually @@ -158,6 +164,7 @@ impl Exclusive { #[unstable(feature = "exclusive_wrapper", issue = "98407")] impl From for Exclusive { + #[inline] fn from(t: T) -> Self { Self::new(t) } @@ -166,7 +173,7 @@ impl From for Exclusive { #[unstable(feature = "exclusive_wrapper", issue = "98407")] impl Future for Exclusive { type Output = T::Output; - + #[inline] fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { self.get_pin_mut().poll(cx) } From 44b4ce1d61206dcb5351644ceeac2490f60fc512 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Thu, 22 Sep 2022 23:12:29 -0700 Subject: [PATCH 139/586] Make ZST checks in core/alloc more readable There's a bunch of these checks because of special handing for ZSTs in various unsafe implementations of stuff. This lets them be `T::IS_ZST` instead of `mem::size_of::() == 0` every time, making them both more readable and more terse. *Not* proposed for stabilization at this time. Would be `pub(crate)` except `alloc` wants to use it too. (And while it doesn't matter now, if we ever get something like 85836 making it a const can help codegen be simpler.) --- library/alloc/src/collections/vec_deque/mod.rs | 8 ++++---- library/alloc/src/lib.rs | 1 + library/alloc/src/raw_vec.rs | 12 ++++++------ library/alloc/src/slice.rs | 6 ++---- library/alloc/src/vec/drain.rs | 4 ++-- library/alloc/src/vec/in_place_collect.rs | 4 ++-- library/alloc/src/vec/into_iter.rs | 16 ++++++++-------- library/alloc/src/vec/mod.rs | 6 +++--- library/core/src/mem/mod.rs | 15 +++++++++++++++ library/core/src/slice/iter.rs | 6 +++--- library/core/src/slice/iter/macros.rs | 8 ++++---- library/core/src/slice/mod.rs | 10 +++++----- library/core/src/slice/rotate.rs | 4 ++-- library/core/src/slice/sort.rs | 6 +++--- 14 files changed, 60 insertions(+), 46 deletions(-) diff --git a/library/alloc/src/collections/vec_deque/mod.rs b/library/alloc/src/collections/vec_deque/mod.rs index e3f4deb0875b9..5546c9383de9c 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, MaybeUninit}; +use core::mem::{ManuallyDrop, MaybeUninit, SizedTypeProperties}; use core::ops::{Index, IndexMut, Range, RangeBounds}; use core::ptr::{self, NonNull}; use core::slice; @@ -177,7 +177,7 @@ impl VecDeque { /// Marginally more convenient #[inline] fn cap(&self) -> usize { - if mem::size_of::() == 0 { + if T::IS_ZST { // For zero sized types, we are always at maximum capacity MAXIMUM_ZST_CAPACITY } else { @@ -3038,7 +3038,7 @@ impl From> for VecDeque { /// `Vec` came from `From>` and hasn't been reallocated. fn from(mut other: Vec) -> Self { let len = other.len(); - if mem::size_of::() == 0 { + if T::IS_ZST { // There's no actual allocation for ZSTs to worry about capacity, // but `VecDeque` can't handle as much length as `Vec`. assert!(len < MAXIMUM_ZST_CAPACITY, "capacity overflow"); @@ -3124,7 +3124,7 @@ impl From<[T; N]> for VecDeque { fn from(arr: [T; N]) -> Self { let mut deq = VecDeque::with_capacity(N); let arr = ManuallyDrop::new(arr); - if mem::size_of::() != 0 { + if !::IS_ZST { // SAFETY: VecDeque::with_capacity ensures that there is enough capacity. unsafe { ptr::copy_nonoverlapping(arr.as_ptr(), deq.ptr(), N); diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index 8619467c2d928..2641942f962ce 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -136,6 +136,7 @@ #![feature(receiver_trait)] #![feature(saturating_int_impl)] #![feature(set_ptr_value)] +#![feature(sized_type_properties)] #![feature(slice_from_ptr_range)] #![feature(slice_group_by)] #![feature(slice_ptr_get)] diff --git a/library/alloc/src/raw_vec.rs b/library/alloc/src/raw_vec.rs index b0f4529abdfa5..5a10121bbbe4b 100644 --- a/library/alloc/src/raw_vec.rs +++ b/library/alloc/src/raw_vec.rs @@ -3,7 +3,7 @@ use core::alloc::LayoutError; use core::cmp; use core::intrinsics; -use core::mem::{self, ManuallyDrop, MaybeUninit}; +use core::mem::{self, ManuallyDrop, MaybeUninit, SizedTypeProperties}; use core::ops::Drop; use core::ptr::{self, NonNull, Unique}; use core::slice; @@ -168,7 +168,7 @@ impl RawVec { #[cfg(not(no_global_oom_handling))] fn allocate_in(capacity: usize, init: AllocInit, alloc: A) -> Self { // Don't allocate here because `Drop` will not deallocate when `capacity` is 0. - if mem::size_of::() == 0 || capacity == 0 { + if T::IS_ZST || capacity == 0 { Self::new_in(alloc) } else { // We avoid `unwrap_or_else` here because it bloats the amount of @@ -229,7 +229,7 @@ impl RawVec { /// This will always be `usize::MAX` if `T` is zero-sized. #[inline(always)] pub fn capacity(&self) -> usize { - if mem::size_of::() == 0 { usize::MAX } else { self.cap } + if T::IS_ZST { usize::MAX } else { self.cap } } /// Returns a shared reference to the allocator backing this `RawVec`. @@ -238,7 +238,7 @@ impl RawVec { } fn current_memory(&self) -> Option<(NonNull, Layout)> { - if mem::size_of::() == 0 || self.cap == 0 { + if T::IS_ZST || self.cap == 0 { None } else { // We have an allocated chunk of memory, so we can bypass runtime @@ -380,7 +380,7 @@ impl RawVec { // This is ensured by the calling contexts. debug_assert!(additional > 0); - if mem::size_of::() == 0 { + if T::IS_ZST { // Since we return a capacity of `usize::MAX` when `elem_size` is // 0, getting to here necessarily means the `RawVec` is overfull. return Err(CapacityOverflow.into()); @@ -406,7 +406,7 @@ impl RawVec { // `grow_amortized`, but this method is usually instantiated less often so // it's less critical. fn grow_exact(&mut self, len: usize, additional: usize) -> Result<(), TryReserveError> { - if mem::size_of::() == 0 { + if T::IS_ZST { // Since we return a capacity of `usize::MAX` when the type size is // 0, getting to here necessarily means the `RawVec` is overfull. return Err(CapacityOverflow.into()); diff --git a/library/alloc/src/slice.rs b/library/alloc/src/slice.rs index bcd3f49e20892..2e24c3c652d11 100644 --- a/library/alloc/src/slice.rs +++ b/library/alloc/src/slice.rs @@ -16,9 +16,7 @@ use core::borrow::{Borrow, BorrowMut}; #[cfg(not(no_global_oom_handling))] use core::cmp::Ordering::{self, Less}; #[cfg(not(no_global_oom_handling))] -use core::mem; -#[cfg(not(no_global_oom_handling))] -use core::mem::size_of; +use core::mem::{self, SizedTypeProperties}; #[cfg(not(no_global_oom_handling))] use core::ptr; @@ -1018,7 +1016,7 @@ where const MIN_RUN: usize = 10; // Sorting has no meaningful behavior on zero-sized types. - if size_of::() == 0 { + if T::IS_ZST { return; } diff --git a/library/alloc/src/vec/drain.rs b/library/alloc/src/vec/drain.rs index 5b73906a1c97c..541f99bcfaba4 100644 --- a/library/alloc/src/vec/drain.rs +++ b/library/alloc/src/vec/drain.rs @@ -1,7 +1,7 @@ use crate::alloc::{Allocator, Global}; use core::fmt; use core::iter::{FusedIterator, TrustedLen}; -use core::mem::{self, ManuallyDrop}; +use core::mem::{self, ManuallyDrop, SizedTypeProperties}; use core::ptr::{self, NonNull}; use core::slice::{self}; @@ -202,7 +202,7 @@ impl Drop for Drain<'_, T, A> { let mut vec = self.vec; - if mem::size_of::() == 0 { + if T::IS_ZST { // ZSTs have no identity, so we don't need to move them around, we only need to drop the correct amount. // this can be achieved by manipulating the Vec length instead of moving values out from `iter`. unsafe { diff --git a/library/alloc/src/vec/in_place_collect.rs b/library/alloc/src/vec/in_place_collect.rs index b211421b20270..a3f8fe40fd5ce 100644 --- a/library/alloc/src/vec/in_place_collect.rs +++ b/library/alloc/src/vec/in_place_collect.rs @@ -135,7 +135,7 @@ //! vec.truncate(write_idx); //! ``` use core::iter::{InPlaceIterable, SourceIter, TrustedRandomAccessNoCoerce}; -use core::mem::{self, ManuallyDrop}; +use core::mem::{self, ManuallyDrop, SizedTypeProperties}; use core::ptr::{self}; use super::{InPlaceDrop, SpecFromIter, SpecFromIterNested, Vec}; @@ -154,7 +154,7 @@ where default fn from_iter(mut iterator: I) -> Self { // See "Layout constraints" section in the module documentation. We rely on const // optimization here since these conditions currently cannot be expressed as trait bounds - if mem::size_of::() == 0 + if T::IS_ZST || mem::size_of::() != mem::size_of::<<::Source as AsVecIntoIter>::Item>() || mem::align_of::() diff --git a/library/alloc/src/vec/into_iter.rs b/library/alloc/src/vec/into_iter.rs index b4157fd589541..d74e77637bdc4 100644 --- a/library/alloc/src/vec/into_iter.rs +++ b/library/alloc/src/vec/into_iter.rs @@ -8,7 +8,7 @@ use core::iter::{ FusedIterator, InPlaceIterable, SourceIter, TrustedLen, TrustedRandomAccessNoCoerce, }; use core::marker::PhantomData; -use core::mem::{self, ManuallyDrop, MaybeUninit}; +use core::mem::{self, ManuallyDrop, MaybeUninit, SizedTypeProperties}; #[cfg(not(no_global_oom_handling))] use core::ops::Deref; use core::ptr::{self, NonNull}; @@ -149,7 +149,7 @@ impl Iterator for IntoIter { fn next(&mut self) -> Option { if self.ptr == self.end { None - } else if mem::size_of::() == 0 { + } else if T::IS_ZST { // purposefully don't use 'ptr.offset' because for // vectors with 0-size elements this would return the // same pointer. @@ -167,7 +167,7 @@ impl Iterator for IntoIter { #[inline] fn size_hint(&self) -> (usize, Option) { - let exact = if mem::size_of::() == 0 { + let exact = if T::IS_ZST { self.end.addr().wrapping_sub(self.ptr.addr()) } else { unsafe { self.end.sub_ptr(self.ptr) } @@ -179,7 +179,7 @@ impl Iterator for IntoIter { fn advance_by(&mut self, n: usize) -> Result<(), usize> { let step_size = self.len().min(n); let to_drop = ptr::slice_from_raw_parts_mut(self.ptr as *mut T, step_size); - if mem::size_of::() == 0 { + if T::IS_ZST { // SAFETY: due to unchecked casts of unsigned amounts to signed offsets the wraparound // effectively results in unsigned pointers representing positions 0..usize::MAX, // which is valid for ZSTs. @@ -209,7 +209,7 @@ impl Iterator for IntoIter { let len = self.len(); - if mem::size_of::() == 0 { + if T::IS_ZST { if len < N { self.forget_remaining_elements(); // Safety: ZSTs can be conjured ex nihilo, only the amount has to be correct @@ -253,7 +253,7 @@ impl Iterator for IntoIter { // that `T: Copy` so reading elements from the buffer doesn't invalidate // them for `Drop`. unsafe { - if mem::size_of::() == 0 { mem::zeroed() } else { ptr::read(self.ptr.add(i)) } + if T::IS_ZST { mem::zeroed() } else { ptr::read(self.ptr.add(i)) } } } } @@ -264,7 +264,7 @@ impl DoubleEndedIterator for IntoIter { fn next_back(&mut self) -> Option { if self.end == self.ptr { None - } else if mem::size_of::() == 0 { + } else if T::IS_ZST { // See above for why 'ptr.offset' isn't used self.end = self.end.wrapping_byte_sub(1); @@ -280,7 +280,7 @@ impl DoubleEndedIterator for IntoIter { #[inline] fn advance_back_by(&mut self, n: usize) -> Result<(), usize> { let step_size = self.len().min(n); - if mem::size_of::() == 0 { + if T::IS_ZST { // SAFETY: same as for advance_by() self.end = self.end.wrapping_byte_sub(step_size); } else { diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 60b36af5e67fc..d6d986905e6c1 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -64,7 +64,7 @@ use core::iter; #[cfg(not(no_global_oom_handling))] use core::iter::FromIterator; use core::marker::PhantomData; -use core::mem::{self, ManuallyDrop, MaybeUninit}; +use core::mem::{self, ManuallyDrop, MaybeUninit, SizedTypeProperties}; use core::ops::{self, Index, IndexMut, Range, RangeBounds}; use core::ptr::{self, NonNull}; use core::slice::{self, SliceIndex}; @@ -2347,7 +2347,7 @@ impl Vec<[T; N], A> { #[unstable(feature = "slice_flatten", issue = "95629")] pub fn into_flattened(self) -> Vec { let (ptr, len, cap, alloc) = self.into_raw_parts_with_alloc(); - let (new_len, new_cap) = if mem::size_of::() == 0 { + let (new_len, new_cap) = if T::IS_ZST { (len.checked_mul(N).expect("vec len overflow"), usize::MAX) } else { // SAFETY: @@ -2677,7 +2677,7 @@ impl IntoIterator for Vec { let mut me = ManuallyDrop::new(self); let alloc = ManuallyDrop::new(ptr::read(me.allocator())); let begin = me.as_mut_ptr(); - let end = if mem::size_of::() == 0 { + let end = if T::IS_ZST { begin.wrapping_byte_add(me.len()) } else { begin.add(me.len()) as *const T diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs index d2dd2941d590f..cd92ea24b6171 100644 --- a/library/core/src/mem/mod.rs +++ b/library/core/src/mem/mod.rs @@ -1178,3 +1178,18 @@ pub const fn discriminant(v: &T) -> Discriminant { pub const fn variant_count() -> usize { intrinsics::variant_count::() } + +/// This is here only to simplify all the ZST checks we need in the library. +/// It's not on a stabilization track right now. +#[doc(hidden)] +#[unstable(feature = "sized_type_properties", issue = "none")] +pub trait SizedTypeProperties: Sized { + /// `true` if this type requires no storage. + /// `false` if its [size](size_of) is greater than zero. + #[doc(hidden)] + #[unstable(feature = "sized_type_properties", issue = "none")] + const IS_ZST: bool = size_of::() == 0; +} +#[doc(hidden)] +#[unstable(feature = "sized_type_properties", issue = "none")] +impl SizedTypeProperties for T {} diff --git a/library/core/src/slice/iter.rs b/library/core/src/slice/iter.rs index 395c5678451cd..d9dfc56ab6347 100644 --- a/library/core/src/slice/iter.rs +++ b/library/core/src/slice/iter.rs @@ -9,7 +9,7 @@ use crate::fmt; use crate::intrinsics::{assume, exact_div, unchecked_sub}; use crate::iter::{FusedIterator, TrustedLen, TrustedRandomAccess, TrustedRandomAccessNoCoerce}; use crate::marker::{PhantomData, Send, Sized, Sync}; -use crate::mem; +use crate::mem::{self, SizedTypeProperties}; use crate::num::NonZeroUsize; use crate::ptr::NonNull; @@ -91,7 +91,7 @@ impl<'a, T> Iter<'a, T> { unsafe { assume(!ptr.is_null()); - let end = if mem::size_of::() == 0 { + let end = if T::IS_ZST { ptr.wrapping_byte_add(slice.len()) } else { ptr.add(slice.len()) @@ -227,7 +227,7 @@ impl<'a, T> IterMut<'a, T> { unsafe { assume(!ptr.is_null()); - let end = if mem::size_of::() == 0 { + let end = if T::IS_ZST { ptr.wrapping_byte_add(slice.len()) } else { ptr.add(slice.len()) diff --git a/library/core/src/slice/iter/macros.rs b/library/core/src/slice/iter/macros.rs index 6c9e7574e1746..ce51d48e3e551 100644 --- a/library/core/src/slice/iter/macros.rs +++ b/library/core/src/slice/iter/macros.rs @@ -100,7 +100,7 @@ macro_rules! iterator { // Unsafe because the offset must not exceed `self.len()`. #[inline(always)] unsafe fn pre_dec_end(&mut self, offset: usize) -> * $raw_mut T { - if mem::size_of::() == 0 { + if T::IS_ZST { zst_shrink!(self, offset); self.ptr.as_ptr() } else { @@ -140,7 +140,7 @@ macro_rules! iterator { // since we check if the iterator is empty first. unsafe { assume(!self.ptr.as_ptr().is_null()); - if mem::size_of::() != 0 { + if !::IS_ZST { assume(!self.end.is_null()); } if is_empty!(self) { @@ -166,7 +166,7 @@ macro_rules! iterator { fn nth(&mut self, n: usize) -> Option<$elem> { if n >= len!(self) { // This iterator is now empty. - if mem::size_of::() == 0 { + if T::IS_ZST { // We have to do it this way as `ptr` may never be 0, but `end` // could be (due to wrapping). self.end = self.ptr.as_ptr(); @@ -355,7 +355,7 @@ macro_rules! iterator { // empty first. unsafe { assume(!self.ptr.as_ptr().is_null()); - if mem::size_of::() != 0 { + if !::IS_ZST { assume(!self.end.is_null()); } if is_empty!(self) { diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index 6a7150d2986ed..bf5c0cb46ae46 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -9,7 +9,7 @@ use crate::cmp::Ordering::{self, Greater, Less}; use crate::intrinsics::{assert_unsafe_precondition, exact_div}; use crate::marker::Copy; -use crate::mem; +use crate::mem::{self, SizedTypeProperties}; use crate::num::NonZeroUsize; use crate::ops::{Bound, FnMut, OneSidedRange, Range, RangeBounds}; use crate::option::Option; @@ -3459,7 +3459,7 @@ impl [T] { #[must_use] pub unsafe fn align_to(&self) -> (&[T], &[U], &[T]) { // Note that most of this function will be constant-evaluated, - if mem::size_of::() == 0 || mem::size_of::() == 0 { + if U::IS_ZST || T::IS_ZST { // handle ZSTs specially, which is – don't handle them at all. return (self, &[], &[]); } @@ -3520,7 +3520,7 @@ impl [T] { #[must_use] pub unsafe fn align_to_mut(&mut self) -> (&mut [T], &mut [U], &mut [T]) { // Note that most of this function will be constant-evaluated, - if mem::size_of::() == 0 || mem::size_of::() == 0 { + if U::IS_ZST || T::IS_ZST { // handle ZSTs specially, which is – don't handle them at all. return (self, &mut [], &mut []); } @@ -4066,7 +4066,7 @@ impl [[T; N]] { /// ``` #[unstable(feature = "slice_flatten", issue = "95629")] pub fn flatten(&self) -> &[T] { - let len = if crate::mem::size_of::() == 0 { + let len = if T::IS_ZST { self.len().checked_mul(N).expect("slice len overflow") } else { // SAFETY: `self.len() * N` cannot overflow because `self` is @@ -4104,7 +4104,7 @@ impl [[T; N]] { /// ``` #[unstable(feature = "slice_flatten", issue = "95629")] pub fn flatten_mut(&mut self) -> &mut [T] { - let len = if crate::mem::size_of::() == 0 { + let len = if T::IS_ZST { self.len().checked_mul(N).expect("slice len overflow") } else { // SAFETY: `self.len() * N` cannot overflow because `self` is diff --git a/library/core/src/slice/rotate.rs b/library/core/src/slice/rotate.rs index 4589c6c0f04a5..fa8c238f8e7a2 100644 --- a/library/core/src/slice/rotate.rs +++ b/library/core/src/slice/rotate.rs @@ -1,5 +1,5 @@ use crate::cmp; -use crate::mem::{self, MaybeUninit}; +use crate::mem::{self, MaybeUninit, SizedTypeProperties}; use crate::ptr; /// Rotates the range `[mid-left, mid+right)` such that the element at `mid` becomes the first @@ -63,7 +63,7 @@ use crate::ptr; /// when `left < right` the swapping happens from the left instead. pub unsafe fn ptr_rotate(mut left: usize, mut mid: *mut T, mut right: usize) { type BufType = [usize; 32]; - if mem::size_of::() == 0 { + if T::IS_ZST { return; } loop { diff --git a/library/core/src/slice/sort.rs b/library/core/src/slice/sort.rs index c6c03c0b0db96..87f77b7f21d62 100644 --- a/library/core/src/slice/sort.rs +++ b/library/core/src/slice/sort.rs @@ -7,7 +7,7 @@ //! stable sorting implementation. use crate::cmp; -use crate::mem::{self, MaybeUninit}; +use crate::mem::{self, MaybeUninit, SizedTypeProperties}; use crate::ptr; /// When dropped, copies from `src` into `dest`. @@ -813,7 +813,7 @@ where F: FnMut(&T, &T) -> bool, { // Sorting has no meaningful behavior on zero-sized types. - if mem::size_of::() == 0 { + if T::IS_ZST { return; } @@ -898,7 +898,7 @@ where panic!("partition_at_index index {} greater than length of slice {}", index, v.len()); } - if mem::size_of::() == 0 { + if T::IS_ZST { // Sorting has no meaningful behavior on zero-sized types. Do nothing. } else if index == v.len() - 1 { // Find max element and place it in the last position of the array. We're free to use From cbbcd9f52ceef47a2855379c9b476667d0e81429 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Thu, 22 Sep 2022 23:13:12 -0700 Subject: [PATCH 140/586] rustfmt --- library/core/src/slice/iter.rs | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/library/core/src/slice/iter.rs b/library/core/src/slice/iter.rs index d9dfc56ab6347..ad39ce38319dd 100644 --- a/library/core/src/slice/iter.rs +++ b/library/core/src/slice/iter.rs @@ -91,11 +91,8 @@ impl<'a, T> Iter<'a, T> { unsafe { assume(!ptr.is_null()); - let end = if T::IS_ZST { - ptr.wrapping_byte_add(slice.len()) - } else { - ptr.add(slice.len()) - }; + let end = + if T::IS_ZST { ptr.wrapping_byte_add(slice.len()) } else { ptr.add(slice.len()) }; Self { ptr: NonNull::new_unchecked(ptr as *mut T), end, _marker: PhantomData } } @@ -227,11 +224,8 @@ impl<'a, T> IterMut<'a, T> { unsafe { assume(!ptr.is_null()); - let end = if T::IS_ZST { - ptr.wrapping_byte_add(slice.len()) - } else { - ptr.add(slice.len()) - }; + let end = + if T::IS_ZST { ptr.wrapping_byte_add(slice.len()) } else { ptr.add(slice.len()) }; Self { ptr: NonNull::new_unchecked(ptr), end, _marker: PhantomData } } From 7bfbaa3881fe0a6e4a12b4ff2197e044cb05aff8 Mon Sep 17 00:00:00 2001 From: Florian Bartels Date: Thu, 22 Sep 2022 12:40:37 +0200 Subject: [PATCH 141/586] Detect panic strategy using `rustc --print cfg` Instead of relying on a command line parameter, detect if a target is able to unwind or not. Ignore tests that require unwinding on targets that don't support it. --- src/tools/compiletest/src/common.rs | 18 ++++++++++++++---- src/tools/compiletest/src/header.rs | 5 ++--- src/tools/compiletest/src/main.rs | 10 +--------- 3 files changed, 17 insertions(+), 16 deletions(-) diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index 64df76e27720d..4994fb9bbf941 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -278,10 +278,6 @@ pub struct Config { /// override this setting. pub optimize_tests: bool, - /// What panic strategy the target is built with. Unwind supports Abort, but - /// not vice versa. - pub target_panic: PanicStrategy, - /// Target system to be tested pub target: String, @@ -426,6 +422,10 @@ impl Config { *&self.target_cfg().pointer_width } + pub fn can_unwind(&self) -> bool { + self.target_cfg().panic == PanicStrategy::Unwind + } + pub fn has_asm_support(&self) -> bool { static ASM_SUPPORTED_ARCHS: &[&str] = &[ "x86", "x86_64", "arm", "aarch64", "riscv32", @@ -446,6 +446,7 @@ pub struct TargetCfg { families: Vec, pointer_width: u32, endian: Endian, + panic: PanicStrategy, } #[derive(Eq, PartialEq, Clone, Debug)] @@ -481,6 +482,7 @@ impl TargetCfg { let mut families = Vec::new(); let mut pointer_width = None; let mut endian = None; + let mut panic = None; for line in print_cfg.lines() { if let Some((name, value)) = line.split_once('=') { let value = value.trim_matches('"'); @@ -498,6 +500,13 @@ impl TargetCfg { s => panic!("unexpected {s}"), }) } + "panic" => { + panic = match value { + "abort" => Some(PanicStrategy::Abort), + "unwind" => Some(PanicStrategy::Unwind), + s => panic!("unexpected {s}"), + } + } _ => {} } } @@ -510,6 +519,7 @@ impl TargetCfg { families, pointer_width: pointer_width.unwrap(), endian: endian.unwrap(), + panic: panic.unwrap(), } } } diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index 3ff1cbf20cd26..6f85227500361 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -7,7 +7,7 @@ use std::path::{Path, PathBuf}; use tracing::*; -use crate::common::{CompareMode, Config, Debugger, FailMode, Mode, PanicStrategy, PassMode}; +use crate::common::{CompareMode, Config, Debugger, FailMode, Mode, PassMode}; use crate::util; use crate::{extract_cdb_version, extract_gdb_version}; @@ -949,8 +949,7 @@ pub fn make_test_description( ignore |= !has_memtag && config.parse_name_directive(ln, "needs-sanitizer-memtag"); ignore |= !has_shadow_call_stack && config.parse_name_directive(ln, "needs-sanitizer-shadow-call-stack"); - ignore |= config.target_panic == PanicStrategy::Abort - && config.parse_name_directive(ln, "needs-unwind"); + ignore |= !config.can_unwind() && config.parse_name_directive(ln, "needs-unwind"); ignore |= config.target == "wasm32-unknown-unknown" && config.parse_name_directive(ln, directives::CHECK_RUN_RESULTS); ignore |= config.debugger == Some(Debugger::Cdb) && ignore_cdb(config, ln); diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs index 38c7b87fc0d9d..dccfd4e0d9807 100644 --- a/src/tools/compiletest/src/main.rs +++ b/src/tools/compiletest/src/main.rs @@ -5,9 +5,7 @@ extern crate test; -use crate::common::{ - expected_output_path, output_base_dir, output_relative_path, PanicStrategy, UI_EXTENSIONS, -}; +use crate::common::{expected_output_path, output_base_dir, output_relative_path, UI_EXTENSIONS}; use crate::common::{CompareMode, Config, Debugger, Mode, PassMode, TestPaths}; use crate::util::logv; use getopts::Options; @@ -105,7 +103,6 @@ pub fn parse_config(args: Vec) -> Config { .optmulti("", "host-rustcflags", "flags to pass to rustc for host", "FLAGS") .optmulti("", "target-rustcflags", "flags to pass to rustc for target", "FLAGS") .optflag("", "optimize-tests", "run tests with optimizations enabled") - .optopt("", "target-panic", "what panic strategy the target supports", "unwind | abort") .optflag("", "verbose", "run tests verbosely, showing all output") .optflag( "", @@ -258,11 +255,6 @@ pub fn parse_config(args: Vec) -> Config { host_rustcflags: Some(matches.opt_strs("host-rustcflags").join(" ")), target_rustcflags: Some(matches.opt_strs("target-rustcflags").join(" ")), optimize_tests: matches.opt_present("optimize-tests"), - target_panic: match matches.opt_str("target-panic").as_deref() { - Some("unwind") | None => PanicStrategy::Unwind, - Some("abort") => PanicStrategy::Abort, - _ => panic!("unknown `--target-panic` option `{}` given", mode), - }, target, host: opt_str2(matches.opt_str("host")), cdb, From 0b0027fd2ed31e355fa560407a32c924f7f8cad3 Mon Sep 17 00:00:00 2001 From: Florian Bartels Date: Thu, 22 Sep 2022 14:25:10 +0200 Subject: [PATCH 142/586] Restore ignore tag This test case actually requires std::process. --- src/test/ui/async-await/async-fn-size-moved-locals.rs | 1 - .../issue-65419/issue-65419-async-fn-resume-after-panic.rs | 1 - src/test/ui/binding/fn-arg-incomplete-pattern-drop-order.rs | 1 - src/test/ui/builtin-clone-unwind.rs | 1 - src/test/ui/catch-unwind-bang.rs | 1 - src/test/ui/cfg/cfg-panic.rs | 3 --- .../2229_closure_analysis/migrations/mir_calls_to_shims.rs | 1 - src/test/ui/drop/dynamic-drop-async.rs | 1 - src/test/ui/drop/dynamic-drop.rs | 1 - src/test/ui/drop/repeat-drop.rs | 3 --- src/test/ui/extern-flag/empty-extern-arg.rs | 1 - .../issue-64655-allow-unwind-when-calling-panic-directly.rs | 1 - .../ui/extern/issue-64655-extern-rust-must-allow-unwind.rs | 1 - src/test/ui/generator/panic-drops-resume.rs | 2 -- src/test/ui/generator/panic-drops.rs | 1 - src/test/ui/generator/panic-safe.rs | 1 - src/test/ui/generator/resume-after-return.rs | 1 - src/test/ui/intrinsics/panic-uninitialized-zeroed.rs | 1 - src/test/ui/issues/issue-14875.rs | 1 - src/test/ui/issues/issue-29948.rs | 1 - src/test/ui/issues/issue-43853.rs | 1 - src/test/ui/issues/issue-46519.rs | 1 - src/test/ui/iterators/iter-count-overflow-debug.rs | 1 - src/test/ui/iterators/iter-position-overflow-debug.rs | 1 - src/test/ui/iterators/iter-step-overflow-debug.rs | 1 - src/test/ui/iterators/iter-sum-overflow-debug.rs | 1 - src/test/ui/iterators/iter-sum-overflow-overflow-checks.rs | 1 - src/test/ui/macros/macro-comma-behavior-rpass.rs | 1 - src/test/ui/mir/mir_calls_to_shims.rs | 1 - src/test/ui/mir/mir_codegen_calls_diverging_drops.rs | 1 - src/test/ui/mir/mir_drop_order.rs | 1 - src/test/ui/mir/mir_drop_panics.rs | 1 - src/test/ui/mir/mir_let_chains_drop_order.rs | 1 - .../ui/numbers-arithmetic/next-power-of-two-overflow-debug.rs | 1 - src/test/ui/panic-handler/weak-lang-item.rs | 1 - src/test/ui/panic-runtime/need-abort-got-unwind.rs | 1 - src/test/ui/panic-runtime/transitive-link-a-bunch.rs | 1 - src/test/ui/panic-runtime/want-unwind-got-abort.rs | 1 - src/test/ui/panic-runtime/want-unwind-got-abort2.rs | 1 - src/test/ui/panic-while-printing.rs | 1 - src/test/ui/privacy/reachable-unnameable-items.rs | 1 - src/test/ui/proc-macro/expand-with-a-macro.rs | 1 - .../ui/rfc-1937-termination-trait/termination-trait-in-test.rs | 1 - src/test/ui/rfc-2091-track-caller/std-panic-locations.rs | 1 - src/test/ui/rfcs/rfc1857-drop-order.rs | 1 - src/test/ui/runtime/rt-explody-panic-payloads.rs | 3 --- src/test/ui/test-attrs/test-panic-while-printing.rs | 1 - src/test/ui/test-attrs/test-should-fail-good-message.rs | 1 - src/test/ui/unwind-abis/ffi-unwind-calls-lint.rs | 1 - src/test/ui/unwind-no-uwtable.rs | 1 - 50 files changed, 57 deletions(-) diff --git a/src/test/ui/async-await/async-fn-size-moved-locals.rs b/src/test/ui/async-await/async-fn-size-moved-locals.rs index 9e3794b0484e7..79b7239f3590d 100644 --- a/src/test/ui/async-await/async-fn-size-moved-locals.rs +++ b/src/test/ui/async-await/async-fn-size-moved-locals.rs @@ -7,7 +7,6 @@ // // See issue #59123 for a full explanation. -// ignore-emscripten (sizes don't match) // needs-unwind Size of Futures change on panic=abort // run-pass diff --git a/src/test/ui/async-await/issues/issue-65419/issue-65419-async-fn-resume-after-panic.rs b/src/test/ui/async-await/issues/issue-65419/issue-65419-async-fn-resume-after-panic.rs index 5e71229beb5f9..b4ea4c9f68664 100644 --- a/src/test/ui/async-await/issues/issue-65419/issue-65419-async-fn-resume-after-panic.rs +++ b/src/test/ui/async-await/issues/issue-65419/issue-65419-async-fn-resume-after-panic.rs @@ -6,7 +6,6 @@ // error-pattern: thread 'main' panicked at '`async fn` resumed after panicking' // edition:2018 // ignore-wasm no panic or subprocess support -// ignore-emscripten no panic or subprocess support #![feature(generators, generator_trait)] diff --git a/src/test/ui/binding/fn-arg-incomplete-pattern-drop-order.rs b/src/test/ui/binding/fn-arg-incomplete-pattern-drop-order.rs index 684172ca61cca..0450fe8abbd14 100644 --- a/src/test/ui/binding/fn-arg-incomplete-pattern-drop-order.rs +++ b/src/test/ui/binding/fn-arg-incomplete-pattern-drop-order.rs @@ -3,7 +3,6 @@ // Check that partially moved from function parameters are dropped after the // named bindings that move from them. -// ignore-wasm32-bare compiled with panic=abort by default use std::{panic, cell::RefCell}; diff --git a/src/test/ui/builtin-clone-unwind.rs b/src/test/ui/builtin-clone-unwind.rs index 3623c4a4dd05d..16add6ff2f68f 100644 --- a/src/test/ui/builtin-clone-unwind.rs +++ b/src/test/ui/builtin-clone-unwind.rs @@ -3,7 +3,6 @@ #![allow(unused_variables)] #![allow(unused_imports)] -// ignore-wasm32-bare compiled with panic=abort by default // Test that builtin implementations of `Clone` cleanup everything // in case of unwinding. diff --git a/src/test/ui/catch-unwind-bang.rs b/src/test/ui/catch-unwind-bang.rs index b31b5cab5b724..fb3503937cb54 100644 --- a/src/test/ui/catch-unwind-bang.rs +++ b/src/test/ui/catch-unwind-bang.rs @@ -1,6 +1,5 @@ // run-pass // needs-unwind -// ignore-wasm32-bare compiled with panic=abort by default fn worker() -> ! { panic!() diff --git a/src/test/ui/cfg/cfg-panic.rs b/src/test/ui/cfg/cfg-panic.rs index fb3e5059c8199..2de72d54a481a 100644 --- a/src/test/ui/cfg/cfg-panic.rs +++ b/src/test/ui/cfg/cfg-panic.rs @@ -1,9 +1,6 @@ // build-pass // compile-flags: -C panic=unwind // needs-unwind -// ignore-emscripten no panic_unwind implementation -// ignore-wasm32 no panic_unwind implementation -// ignore-wasm64 no panic_unwind implementation #[cfg(panic = "abort")] diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.rs b/src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.rs index 6b0b10521740e..52e96d013a265 100644 --- a/src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.rs +++ b/src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.rs @@ -3,7 +3,6 @@ #![deny(rust_2021_incompatible_closure_captures)] //~^ NOTE: the lint level is defined here -// ignore-wasm32-bare compiled with panic=abort by default #![feature(fn_traits)] #![feature(never_type)] diff --git a/src/test/ui/drop/dynamic-drop-async.rs b/src/test/ui/drop/dynamic-drop-async.rs index 13bd71ecb3389..8f1cc6691cd8d 100644 --- a/src/test/ui/drop/dynamic-drop-async.rs +++ b/src/test/ui/drop/dynamic-drop-async.rs @@ -6,7 +6,6 @@ // run-pass // needs-unwind // edition:2018 -// ignore-wasm32-bare compiled with panic=abort by default #![allow(unused)] diff --git a/src/test/ui/drop/dynamic-drop.rs b/src/test/ui/drop/dynamic-drop.rs index e706867742337..9e51d3adaaa68 100644 --- a/src/test/ui/drop/dynamic-drop.rs +++ b/src/test/ui/drop/dynamic-drop.rs @@ -1,6 +1,5 @@ // run-pass // needs-unwind -// ignore-wasm32-bare compiled with panic=abort by default #![feature(generators, generator_trait)] diff --git a/src/test/ui/drop/repeat-drop.rs b/src/test/ui/drop/repeat-drop.rs index a43612e5d8587..8fd46ecaf4420 100644 --- a/src/test/ui/drop/repeat-drop.rs +++ b/src/test/ui/drop/repeat-drop.rs @@ -1,8 +1,5 @@ // run-pass // needs-unwind -// ignore-wasm32-bare no unwinding panic -// ignore-avr no unwinding panic -// ignore-nvptx64 no unwinding panic static mut CHECK: usize = 0; diff --git a/src/test/ui/extern-flag/empty-extern-arg.rs b/src/test/ui/extern-flag/empty-extern-arg.rs index 3170537b0e0a0..a371afb128cab 100644 --- a/src/test/ui/extern-flag/empty-extern-arg.rs +++ b/src/test/ui/extern-flag/empty-extern-arg.rs @@ -1,6 +1,5 @@ // compile-flags: --extern std= // error-pattern: extern location for std does not exist // needs-unwind since it affects the error output -// ignore-emscripten compiled with panic=abort, personality not required fn main() {} diff --git a/src/test/ui/extern/issue-64655-allow-unwind-when-calling-panic-directly.rs b/src/test/ui/extern/issue-64655-allow-unwind-when-calling-panic-directly.rs index 7a91cbdc2f5d4..233120c92f38b 100644 --- a/src/test/ui/extern/issue-64655-allow-unwind-when-calling-panic-directly.rs +++ b/src/test/ui/extern/issue-64655-allow-unwind-when-calling-panic-directly.rs @@ -1,6 +1,5 @@ // run-pass // needs-unwind -// ignore-wasm32-bare compiled with panic=abort by default // ignore-emscripten no threads support // rust-lang/rust#64655: with panic=unwind, a panic from a subroutine diff --git a/src/test/ui/extern/issue-64655-extern-rust-must-allow-unwind.rs b/src/test/ui/extern/issue-64655-extern-rust-must-allow-unwind.rs index e84ff41b344a7..3b263e58cbe84 100644 --- a/src/test/ui/extern/issue-64655-extern-rust-must-allow-unwind.rs +++ b/src/test/ui/extern/issue-64655-extern-rust-must-allow-unwind.rs @@ -1,6 +1,5 @@ // run-pass // needs-unwind -// ignore-wasm32-bare compiled with panic=abort by default // ignore-emscripten no threads support // rust-lang/rust#64655: with panic=unwind, a panic from a subroutine diff --git a/src/test/ui/generator/panic-drops-resume.rs b/src/test/ui/generator/panic-drops-resume.rs index 8d8eb6a97b15a..4c3caeb14d67e 100644 --- a/src/test/ui/generator/panic-drops-resume.rs +++ b/src/test/ui/generator/panic-drops-resume.rs @@ -2,8 +2,6 @@ // run-pass // needs-unwind -// ignore-wasm no unwind support -// ignore-emscripten no unwind support #![feature(generators, generator_trait)] diff --git a/src/test/ui/generator/panic-drops.rs b/src/test/ui/generator/panic-drops.rs index a9de4e7fc7d25..65001fd879bb0 100644 --- a/src/test/ui/generator/panic-drops.rs +++ b/src/test/ui/generator/panic-drops.rs @@ -1,7 +1,6 @@ // run-pass // needs-unwind -// ignore-wasm32-bare compiled with panic=abort by default #![feature(generators, generator_trait)] diff --git a/src/test/ui/generator/panic-safe.rs b/src/test/ui/generator/panic-safe.rs index 14a0c8dbaf1da..3db80bb582151 100644 --- a/src/test/ui/generator/panic-safe.rs +++ b/src/test/ui/generator/panic-safe.rs @@ -1,7 +1,6 @@ // run-pass // needs-unwind -// ignore-wasm32-bare compiled with panic=abort by default #![feature(generators, generator_trait)] diff --git a/src/test/ui/generator/resume-after-return.rs b/src/test/ui/generator/resume-after-return.rs index 538609b981adf..01a059a161cea 100644 --- a/src/test/ui/generator/resume-after-return.rs +++ b/src/test/ui/generator/resume-after-return.rs @@ -1,7 +1,6 @@ // run-pass // needs-unwind -// ignore-wasm32-bare compiled with panic=abort by default #![feature(generators, generator_trait)] diff --git a/src/test/ui/intrinsics/panic-uninitialized-zeroed.rs b/src/test/ui/intrinsics/panic-uninitialized-zeroed.rs index 255151a96032c..4aa869cca35be 100644 --- a/src/test/ui/intrinsics/panic-uninitialized-zeroed.rs +++ b/src/test/ui/intrinsics/panic-uninitialized-zeroed.rs @@ -1,6 +1,5 @@ // run-pass // needs-unwind -// ignore-wasm32-bare compiled with panic=abort by default // revisions: mir thir strict // [thir]compile-flags: -Zthir-unsafeck // [strict]compile-flags: -Zstrict-init-checks diff --git a/src/test/ui/issues/issue-14875.rs b/src/test/ui/issues/issue-14875.rs index aaef2aab9fc76..fca3309155d54 100644 --- a/src/test/ui/issues/issue-14875.rs +++ b/src/test/ui/issues/issue-14875.rs @@ -1,6 +1,5 @@ // run-pass // needs-unwind -// ignore-wasm32-bare compiled with panic=abort by default // Check that values are not leaked when a dtor panics (#14875) diff --git a/src/test/ui/issues/issue-29948.rs b/src/test/ui/issues/issue-29948.rs index 01c3ec64861fe..3ed701480b5ed 100644 --- a/src/test/ui/issues/issue-29948.rs +++ b/src/test/ui/issues/issue-29948.rs @@ -1,6 +1,5 @@ // run-pass // needs-unwind -// ignore-wasm32-bare compiled with panic=abort by default use std::panic; diff --git a/src/test/ui/issues/issue-43853.rs b/src/test/ui/issues/issue-43853.rs index 3162c091c8786..dd42c1e3cb831 100644 --- a/src/test/ui/issues/issue-43853.rs +++ b/src/test/ui/issues/issue-43853.rs @@ -1,6 +1,5 @@ // run-pass // needs-unwind -// ignore-wasm32-bare compiled with panic=abort by default use std::panic; diff --git a/src/test/ui/issues/issue-46519.rs b/src/test/ui/issues/issue-46519.rs index 9bd3c0948517b..0567923b7fc69 100644 --- a/src/test/ui/issues/issue-46519.rs +++ b/src/test/ui/issues/issue-46519.rs @@ -2,7 +2,6 @@ // compile-flags:--test -O // needs-unwind -// ignore-wasm32-bare compiled with panic=abort by default #[test] #[should_panic(expected = "creating inhabited type")] diff --git a/src/test/ui/iterators/iter-count-overflow-debug.rs b/src/test/ui/iterators/iter-count-overflow-debug.rs index 15f25f1ca5373..8e59c11e9dccb 100644 --- a/src/test/ui/iterators/iter-count-overflow-debug.rs +++ b/src/test/ui/iterators/iter-count-overflow-debug.rs @@ -1,7 +1,6 @@ // run-pass // only-32bit too impatient for 2⁶⁴ items // needs-unwind -// ignore-wasm32-bare compiled with panic=abort by default // compile-flags: -C debug_assertions=yes -C opt-level=3 use std::panic; diff --git a/src/test/ui/iterators/iter-position-overflow-debug.rs b/src/test/ui/iterators/iter-position-overflow-debug.rs index 65124c282412c..7a871e744c984 100644 --- a/src/test/ui/iterators/iter-position-overflow-debug.rs +++ b/src/test/ui/iterators/iter-position-overflow-debug.rs @@ -1,7 +1,6 @@ // run-pass // only-32bit too impatient for 2⁶⁴ items // needs-unwind -// ignore-wasm32-bare compiled with panic=abort by default // compile-flags: -C debug_assertions=yes -C opt-level=3 use std::panic; diff --git a/src/test/ui/iterators/iter-step-overflow-debug.rs b/src/test/ui/iterators/iter-step-overflow-debug.rs index e16f984de79a6..6aa349ebed29b 100644 --- a/src/test/ui/iterators/iter-step-overflow-debug.rs +++ b/src/test/ui/iterators/iter-step-overflow-debug.rs @@ -1,6 +1,5 @@ // run-pass // needs-unwind -// ignore-wasm32-bare compiled with panic=abort by default // compile-flags: -C debug_assertions=yes use std::panic; diff --git a/src/test/ui/iterators/iter-sum-overflow-debug.rs b/src/test/ui/iterators/iter-sum-overflow-debug.rs index d8ce43848a77e..24c764ff95873 100644 --- a/src/test/ui/iterators/iter-sum-overflow-debug.rs +++ b/src/test/ui/iterators/iter-sum-overflow-debug.rs @@ -1,6 +1,5 @@ // run-pass // needs-unwind -// ignore-wasm32-bare compiled with panic=abort by default // compile-flags: -C debug_assertions=yes use std::panic; diff --git a/src/test/ui/iterators/iter-sum-overflow-overflow-checks.rs b/src/test/ui/iterators/iter-sum-overflow-overflow-checks.rs index bc8dcbdbb0e03..be45c075d7331 100644 --- a/src/test/ui/iterators/iter-sum-overflow-overflow-checks.rs +++ b/src/test/ui/iterators/iter-sum-overflow-overflow-checks.rs @@ -1,6 +1,5 @@ // run-pass // needs-unwind -// ignore-wasm32-bare compiled with panic=abort by default // compile-flags: -C overflow-checks use std::panic; diff --git a/src/test/ui/macros/macro-comma-behavior-rpass.rs b/src/test/ui/macros/macro-comma-behavior-rpass.rs index dfd58b25d089d..8406b4e78f6be 100644 --- a/src/test/ui/macros/macro-comma-behavior-rpass.rs +++ b/src/test/ui/macros/macro-comma-behavior-rpass.rs @@ -14,7 +14,6 @@ // compile-flags: --test -C debug_assertions=yes // revisions: std core -// ignore-wasm32-bare compiled with panic=abort by default #![cfg_attr(core, no_std)] #[cfg(core)] diff --git a/src/test/ui/mir/mir_calls_to_shims.rs b/src/test/ui/mir/mir_calls_to_shims.rs index 42eaab77da9f1..9dc0acfbfda48 100644 --- a/src/test/ui/mir/mir_calls_to_shims.rs +++ b/src/test/ui/mir/mir_calls_to_shims.rs @@ -1,6 +1,5 @@ // run-pass // needs-unwind -// ignore-wasm32-bare compiled with panic=abort by default #![feature(fn_traits)] #![feature(never_type)] diff --git a/src/test/ui/mir/mir_codegen_calls_diverging_drops.rs b/src/test/ui/mir/mir_codegen_calls_diverging_drops.rs index 3d215610593f3..19dba497001cc 100644 --- a/src/test/ui/mir/mir_codegen_calls_diverging_drops.rs +++ b/src/test/ui/mir/mir_codegen_calls_diverging_drops.rs @@ -1,7 +1,6 @@ // run-fail // error-pattern:diverging_fn called // error-pattern:0 dropped -// ignore-emscripten no processes // needs-unwind this test checks that a destructor is called after panicking struct Droppable(u8); diff --git a/src/test/ui/mir/mir_drop_order.rs b/src/test/ui/mir/mir_drop_order.rs index 853efb0fed2b9..75f5b171af352 100644 --- a/src/test/ui/mir/mir_drop_order.rs +++ b/src/test/ui/mir/mir_drop_order.rs @@ -1,6 +1,5 @@ // run-pass // needs-unwind -// ignore-wasm32-bare compiled with panic=abort by default use std::cell::RefCell; use std::panic; diff --git a/src/test/ui/mir/mir_drop_panics.rs b/src/test/ui/mir/mir_drop_panics.rs index b4093d704150a..0d00426d6d2d5 100644 --- a/src/test/ui/mir/mir_drop_panics.rs +++ b/src/test/ui/mir/mir_drop_panics.rs @@ -2,7 +2,6 @@ // needs-unwind // error-pattern:panic 1 // error-pattern:drop 2 -// ignore-emscripten no processes struct Droppable(u32); impl Drop for Droppable { diff --git a/src/test/ui/mir/mir_let_chains_drop_order.rs b/src/test/ui/mir/mir_let_chains_drop_order.rs index 6498a51957194..536a84a352a49 100644 --- a/src/test/ui/mir/mir_let_chains_drop_order.rs +++ b/src/test/ui/mir/mir_let_chains_drop_order.rs @@ -1,6 +1,5 @@ // run-pass // needs-unwind -// ignore-wasm32-bare compiled with panic=abort by default // See `mir_drop_order.rs` for more information diff --git a/src/test/ui/numbers-arithmetic/next-power-of-two-overflow-debug.rs b/src/test/ui/numbers-arithmetic/next-power-of-two-overflow-debug.rs index f857d4f4c7f27..79d78da3328a9 100644 --- a/src/test/ui/numbers-arithmetic/next-power-of-two-overflow-debug.rs +++ b/src/test/ui/numbers-arithmetic/next-power-of-two-overflow-debug.rs @@ -1,7 +1,6 @@ // run-pass // compile-flags: -C debug_assertions=yes // needs-unwind -// ignore-wasm32-bare compiled with panic=abort by default // ignore-emscripten dies with an LLVM error use std::panic; diff --git a/src/test/ui/panic-handler/weak-lang-item.rs b/src/test/ui/panic-handler/weak-lang-item.rs index df31e614cf809..aef5e1b2c1c7a 100644 --- a/src/test/ui/panic-handler/weak-lang-item.rs +++ b/src/test/ui/panic-handler/weak-lang-item.rs @@ -2,7 +2,6 @@ // error-pattern: `#[panic_handler]` function required, but not found // error-pattern: language item required, but not found: `eh_personality` // needs-unwind since it affects the error output -// ignore-emscripten compiled with panic=abort, personality not required #![no_std] diff --git a/src/test/ui/panic-runtime/need-abort-got-unwind.rs b/src/test/ui/panic-runtime/need-abort-got-unwind.rs index c72fb96e357f0..e92400931d231 100644 --- a/src/test/ui/panic-runtime/need-abort-got-unwind.rs +++ b/src/test/ui/panic-runtime/need-abort-got-unwind.rs @@ -2,7 +2,6 @@ // needs-unwind // error-pattern:is incompatible with this crate's strategy of `unwind` // aux-build:needs-abort.rs -// ignore-wasm32-bare compiled with panic=abort by default extern crate needs_abort; diff --git a/src/test/ui/panic-runtime/transitive-link-a-bunch.rs b/src/test/ui/panic-runtime/transitive-link-a-bunch.rs index 622535a75aff6..0e74e300f00f0 100644 --- a/src/test/ui/panic-runtime/transitive-link-a-bunch.rs +++ b/src/test/ui/panic-runtime/transitive-link-a-bunch.rs @@ -6,7 +6,6 @@ // aux-build:wants-panic-runtime-abort.rs // aux-build:panic-runtime-lang-items.rs // error-pattern: is not compiled with this crate's panic strategy `unwind` -// ignore-wasm32-bare compiled with panic=abort by default #![no_std] #![no_main] diff --git a/src/test/ui/panic-runtime/want-unwind-got-abort.rs b/src/test/ui/panic-runtime/want-unwind-got-abort.rs index 23bfea6af15c1..b6174dc4efee8 100644 --- a/src/test/ui/panic-runtime/want-unwind-got-abort.rs +++ b/src/test/ui/panic-runtime/want-unwind-got-abort.rs @@ -3,7 +3,6 @@ // error-pattern:is not compiled with this crate's panic strategy `unwind` // aux-build:panic-runtime-abort.rs // aux-build:panic-runtime-lang-items.rs -// ignore-wasm32-bare compiled with panic=abort by default #![no_std] #![no_main] diff --git a/src/test/ui/panic-runtime/want-unwind-got-abort2.rs b/src/test/ui/panic-runtime/want-unwind-got-abort2.rs index 7a2e48e2f10a9..b54babbeffa32 100644 --- a/src/test/ui/panic-runtime/want-unwind-got-abort2.rs +++ b/src/test/ui/panic-runtime/want-unwind-got-abort2.rs @@ -4,7 +4,6 @@ // aux-build:panic-runtime-abort.rs // aux-build:wants-panic-runtime-abort.rs // aux-build:panic-runtime-lang-items.rs -// ignore-wasm32-bare compiled with panic=abort by default #![no_std] #![no_main] diff --git a/src/test/ui/panic-while-printing.rs b/src/test/ui/panic-while-printing.rs index 098f54ac23f6a..3abedf2a764e2 100644 --- a/src/test/ui/panic-while-printing.rs +++ b/src/test/ui/panic-while-printing.rs @@ -1,6 +1,5 @@ // run-pass // needs-unwind -// ignore-emscripten no subprocess support #![feature(internal_output_capture)] diff --git a/src/test/ui/privacy/reachable-unnameable-items.rs b/src/test/ui/privacy/reachable-unnameable-items.rs index 1c91541e64229..1babe011996b0 100644 --- a/src/test/ui/privacy/reachable-unnameable-items.rs +++ b/src/test/ui/privacy/reachable-unnameable-items.rs @@ -1,5 +1,4 @@ // run-pass -// ignore-wasm32-bare compiled with panic=abort by default // needs-unwind // aux-build:reachable-unnameable-items.rs diff --git a/src/test/ui/proc-macro/expand-with-a-macro.rs b/src/test/ui/proc-macro/expand-with-a-macro.rs index 21a4547d11e1c..042a283659517 100644 --- a/src/test/ui/proc-macro/expand-with-a-macro.rs +++ b/src/test/ui/proc-macro/expand-with-a-macro.rs @@ -2,7 +2,6 @@ // needs-unwind // aux-build:expand-with-a-macro.rs -// ignore-wasm32-bare compiled with panic=abort by default #![deny(warnings)] diff --git a/src/test/ui/rfc-1937-termination-trait/termination-trait-in-test.rs b/src/test/ui/rfc-1937-termination-trait/termination-trait-in-test.rs index cd57d9bca9429..43888cecedab3 100644 --- a/src/test/ui/rfc-1937-termination-trait/termination-trait-in-test.rs +++ b/src/test/ui/rfc-1937-termination-trait/termination-trait-in-test.rs @@ -2,7 +2,6 @@ // run-pass // needs-unwind -// ignore-wasm32-bare compiled with panic=abort by default #![feature(test)] diff --git a/src/test/ui/rfc-2091-track-caller/std-panic-locations.rs b/src/test/ui/rfc-2091-track-caller/std-panic-locations.rs index b067994a5c6d8..f11456250d874 100644 --- a/src/test/ui/rfc-2091-track-caller/std-panic-locations.rs +++ b/src/test/ui/rfc-2091-track-caller/std-panic-locations.rs @@ -1,6 +1,5 @@ // run-pass // needs-unwind -// ignore-wasm32-bare compiled with panic=abort by default // revisions: default mir-opt //[mir-opt] compile-flags: -Zmir-opt-level=4 diff --git a/src/test/ui/rfcs/rfc1857-drop-order.rs b/src/test/ui/rfcs/rfc1857-drop-order.rs index 243b7fb6fadec..4c4816c2fbc8d 100644 --- a/src/test/ui/rfcs/rfc1857-drop-order.rs +++ b/src/test/ui/rfcs/rfc1857-drop-order.rs @@ -1,6 +1,5 @@ // run-pass // needs-unwind -// ignore-wasm32-bare compiled with panic=abort by default #![allow(dead_code, unreachable_code)] diff --git a/src/test/ui/runtime/rt-explody-panic-payloads.rs b/src/test/ui/runtime/rt-explody-panic-payloads.rs index eb5bf8f67a849..e2221e5df8ea1 100644 --- a/src/test/ui/runtime/rt-explody-panic-payloads.rs +++ b/src/test/ui/runtime/rt-explody-panic-payloads.rs @@ -2,9 +2,6 @@ // needs-unwind // ignore-emscripten no processes // ignore-sgx no processes -// ignore-wasm32-bare no unwinding panic -// ignore-avr no unwinding panic -// ignore-nvptx64 no unwinding panic use std::env; use std::process::Command; diff --git a/src/test/ui/test-attrs/test-panic-while-printing.rs b/src/test/ui/test-attrs/test-panic-while-printing.rs index 01e460da5ab57..033c8beb475df 100644 --- a/src/test/ui/test-attrs/test-panic-while-printing.rs +++ b/src/test/ui/test-attrs/test-panic-while-printing.rs @@ -1,7 +1,6 @@ // compile-flags:--test // run-pass // needs-unwind -// ignore-emscripten no subprocess support use std::fmt; use std::fmt::{Display, Formatter}; diff --git a/src/test/ui/test-attrs/test-should-fail-good-message.rs b/src/test/ui/test-attrs/test-should-fail-good-message.rs index 3260b6938f07d..83519c4524a62 100644 --- a/src/test/ui/test-attrs/test-should-fail-good-message.rs +++ b/src/test/ui/test-attrs/test-should-fail-good-message.rs @@ -1,6 +1,5 @@ // run-pass // needs-unwind -// ignore-wasm32-bare compiled with panic=abort by default // compile-flags: --test #[test] #[should_panic(expected = "foo")] diff --git a/src/test/ui/unwind-abis/ffi-unwind-calls-lint.rs b/src/test/ui/unwind-abis/ffi-unwind-calls-lint.rs index dadf4b1218784..9a324f00435c7 100644 --- a/src/test/ui/unwind-abis/ffi-unwind-calls-lint.rs +++ b/src/test/ui/unwind-abis/ffi-unwind-calls-lint.rs @@ -1,6 +1,5 @@ // build-pass // needs-unwind -// ignore-wasm32-bare compiled with panic=abort by default #![feature(c_unwind)] #![warn(ffi_unwind_calls)] diff --git a/src/test/ui/unwind-no-uwtable.rs b/src/test/ui/unwind-no-uwtable.rs index 0440cf488e8bb..3bc309233a7ac 100644 --- a/src/test/ui/unwind-no-uwtable.rs +++ b/src/test/ui/unwind-no-uwtable.rs @@ -1,7 +1,6 @@ // run-pass // needs-unwind // ignore-windows target requires uwtable -// ignore-wasm32-bare no proper panic=unwind support // compile-flags: -C panic=unwind -C force-unwind-tables=n use std::panic::{self, AssertUnwindSafe}; From 10f3657936e3aec6671b8135ec34e8ba69d12899 Mon Sep 17 00:00:00 2001 From: Florian Bartels Date: Thu, 22 Sep 2022 15:18:17 +0200 Subject: [PATCH 143/586] Adapt test results --- .../migrations/mir_calls_to_shims.fixed | 1 - .../migrations/mir_calls_to_shims.stderr | 2 +- src/test/ui/panic-handler/weak-lang-item.stderr | 2 +- src/test/ui/unwind-abis/ffi-unwind-calls-lint.stderr | 6 +++--- 4 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.fixed b/src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.fixed index 89f3931418dac..ff2244a8e31b9 100644 --- a/src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.fixed +++ b/src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.fixed @@ -3,7 +3,6 @@ #![deny(rust_2021_incompatible_closure_captures)] //~^ NOTE: the lint level is defined here -// ignore-wasm32-bare compiled with panic=abort by default #![feature(fn_traits)] #![feature(never_type)] diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.stderr b/src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.stderr index 2648b00435b31..62cfcbe95bc2c 100644 --- a/src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.stderr +++ b/src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.stderr @@ -1,5 +1,5 @@ error: changes to closure capture in Rust 2021 will affect which traits the closure implements - --> $DIR/mir_calls_to_shims.rs:21:38 + --> $DIR/mir_calls_to_shims.rs:20:38 | LL | let result = panic::catch_unwind(move || { | ^^^^^^^ diff --git a/src/test/ui/panic-handler/weak-lang-item.stderr b/src/test/ui/panic-handler/weak-lang-item.stderr index 202f3309d035e..3bce1e26fe276 100644 --- a/src/test/ui/panic-handler/weak-lang-item.stderr +++ b/src/test/ui/panic-handler/weak-lang-item.stderr @@ -1,5 +1,5 @@ error[E0259]: the name `core` is defined multiple times - --> $DIR/weak-lang-item.rs:9:1 + --> $DIR/weak-lang-item.rs:8:1 | LL | extern crate core; | ^^^^^^^^^^^^^^^^^^ `core` reimported here diff --git a/src/test/ui/unwind-abis/ffi-unwind-calls-lint.stderr b/src/test/ui/unwind-abis/ffi-unwind-calls-lint.stderr index ed41cb74623cb..937a2b3dff8b6 100644 --- a/src/test/ui/unwind-abis/ffi-unwind-calls-lint.stderr +++ b/src/test/ui/unwind-abis/ffi-unwind-calls-lint.stderr @@ -1,17 +1,17 @@ warning: call to foreign function with FFI-unwind ABI - --> $DIR/ffi-unwind-calls-lint.rs:21:14 + --> $DIR/ffi-unwind-calls-lint.rs:20:14 | LL | unsafe { foo(); } | ^^^^^ call to foreign function with FFI-unwind ABI | note: the lint level is defined here - --> $DIR/ffi-unwind-calls-lint.rs:6:9 + --> $DIR/ffi-unwind-calls-lint.rs:5:9 | LL | #![warn(ffi_unwind_calls)] | ^^^^^^^^^^^^^^^^ warning: call to function pointer with FFI-unwind ABI - --> $DIR/ffi-unwind-calls-lint.rs:25:5 + --> $DIR/ffi-unwind-calls-lint.rs:24:5 | LL | ptr(); | ^^^^^ call to function pointer with FFI-unwind ABI From 5ace12c409ef59c654e3f683dd5534a258945a77 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 23 Sep 2022 07:10:11 +0000 Subject: [PATCH 144/586] Showcase a broken diagnostic --- src/test/ui/impl-trait/unactionable_diagnostic.rs | 6 +++--- src/test/ui/impl-trait/unactionable_diagnostic.stderr | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/test/ui/impl-trait/unactionable_diagnostic.rs b/src/test/ui/impl-trait/unactionable_diagnostic.rs index 9b82332f9b067..016d7c3b7ef21 100644 --- a/src/test/ui/impl-trait/unactionable_diagnostic.rs +++ b/src/test/ui/impl-trait/unactionable_diagnostic.rs @@ -4,10 +4,10 @@ struct Foo; impl Trait for Foo {} -fn foo<'t, P>( +fn foo<'x, P>( post: P, - x: &'t Foo, -) -> &'t impl Trait { + x: &'x Foo, +) -> &'x impl Trait { //~^ HELP: consider adding an explicit lifetime bound... x } diff --git a/src/test/ui/impl-trait/unactionable_diagnostic.stderr b/src/test/ui/impl-trait/unactionable_diagnostic.stderr index a36e89f58b98e..c9b3f61254484 100644 --- a/src/test/ui/impl-trait/unactionable_diagnostic.stderr +++ b/src/test/ui/impl-trait/unactionable_diagnostic.stderr @@ -6,7 +6,7 @@ LL | foo(post, x) | help: consider adding an explicit lifetime bound... | -LL | ) -> &'t impl Trait + 't { +LL | ) -> &'x impl Trait + 't { | ++++ error: aborting due to previous error From 90ec6f847fe54e751a045044dabb7e0d252981e3 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 23 Sep 2022 07:12:59 +0000 Subject: [PATCH 145/586] Show errors instead of hiding them due to an earlier error --- .../implied_lifetime_wf_check3.rs | 17 +++++----- .../implied_lifetime_wf_check3.stderr | 34 +++++++++++++++---- .../implied_lifetime_wf_check4_static.rs | 11 ++++++ .../implied_lifetime_wf_check4_static.stderr | 14 ++++++++ 4 files changed, 61 insertions(+), 15 deletions(-) create mode 100644 src/test/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.rs create mode 100644 src/test/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.stderr diff --git a/src/test/ui/type-alias-impl-trait/implied_lifetime_wf_check3.rs b/src/test/ui/type-alias-impl-trait/implied_lifetime_wf_check3.rs index 4cbb6b63670ac..6e5b8f491eab5 100644 --- a/src/test/ui/type-alias-impl-trait/implied_lifetime_wf_check3.rs +++ b/src/test/ui/type-alias-impl-trait/implied_lifetime_wf_check3.rs @@ -6,6 +6,7 @@ mod test_lifetime_param { fn assert_static<'a: 'static>() {} //~^ WARN: unnecessary lifetime parameter `'a` fn test<'a>() where Ty<'a>: 'static { assert_static::<'a>() } + //~^ ERROR: lifetime may not live long enough } mod test_higher_kinded_lifetime_param { @@ -14,14 +15,14 @@ mod test_higher_kinded_lifetime_param { fn assert_static<'a: 'static>() {} //~^ WARN: unnecessary lifetime parameter `'a` fn test<'a>() where for<'b> Ty<'b>: 'a { assert_static::<'a>() } + //~^ ERROR: lifetime may not live long enough } mod test_higher_kinded_lifetime_param2 { fn assert_static<'a: 'static>() {} //~^ WARN: unnecessary lifetime parameter `'a` fn test<'a>() { assert_static::<'a>() } - // no error because all the other errors happen first and then we abort before - // emitting an error here. + //~^ ERROR: lifetime may not live long enough } mod test_type_param { @@ -29,14 +30,14 @@ mod test_type_param { fn defining
(s: A) -> Ty { s } fn assert_static() {} fn test() where Ty: 'static { assert_static::() } + //~^ ERROR: parameter type `A` may not live long enough } -mod test_type_param_static { - type Ty = impl Sized + 'static; - //~^ ERROR: the parameter type `A` may not live long enough - fn defining(s: A) -> Ty { s } - fn assert_static() {} - fn test() where Ty: 'static { assert_static::() } +mod test_implied_from_fn_sig { + type Opaque = impl Sized; + fn defining() -> Opaque {} + fn assert_static() {} + fn test(_: Opaque) { assert_static::(); } } fn main() {} diff --git a/src/test/ui/type-alias-impl-trait/implied_lifetime_wf_check3.stderr b/src/test/ui/type-alias-impl-trait/implied_lifetime_wf_check3.stderr index 16d529698f4d6..887620a4d50ec 100644 --- a/src/test/ui/type-alias-impl-trait/implied_lifetime_wf_check3.stderr +++ b/src/test/ui/type-alias-impl-trait/implied_lifetime_wf_check3.stderr @@ -7,7 +7,7 @@ LL | fn assert_static<'a: 'static>() {} = help: you can use the `'static` lifetime directly, in place of `'a` warning: unnecessary lifetime parameter `'a` - --> $DIR/implied_lifetime_wf_check3.rs:14:22 + --> $DIR/implied_lifetime_wf_check3.rs:15:22 | LL | fn assert_static<'a: 'static>() {} | ^^ @@ -15,24 +15,44 @@ LL | fn assert_static<'a: 'static>() {} = help: you can use the `'static` lifetime directly, in place of `'a` warning: unnecessary lifetime parameter `'a` - --> $DIR/implied_lifetime_wf_check3.rs:20:22 + --> $DIR/implied_lifetime_wf_check3.rs:22:22 | LL | fn assert_static<'a: 'static>() {} | ^^ | = help: you can use the `'static` lifetime directly, in place of `'a` +error: lifetime may not live long enough + --> $DIR/implied_lifetime_wf_check3.rs:8:43 + | +LL | fn test<'a>() where Ty<'a>: 'static { assert_static::<'a>() } + | -- lifetime `'a` defined here ^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/implied_lifetime_wf_check3.rs:17:46 + | +LL | fn test<'a>() where for<'b> Ty<'b>: 'a { assert_static::<'a>() } + | -- lifetime `'a` defined here ^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/implied_lifetime_wf_check3.rs:24:21 + | +LL | fn test<'a>() { assert_static::<'a>() } + | -- ^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static` + | | + | lifetime `'a` defined here + error[E0310]: the parameter type `A` may not live long enough - --> $DIR/implied_lifetime_wf_check3.rs:35:18 + --> $DIR/implied_lifetime_wf_check3.rs:32:41 | -LL | type Ty = impl Sized + 'static; - | ^^^^^^^^^^^^^^^^^^^^ ...so that the type `A` will meet its required lifetime bounds +LL | fn test() where Ty: 'static { assert_static::() } + | ^^^^^^^^^^^^^^^^^^ ...so that the type `A` will meet its required lifetime bounds | help: consider adding an explicit lifetime bound... | -LL | type Ty = impl Sized + 'static; +LL | fn test() where Ty: 'static { assert_static::() } | +++++++++ -error: aborting due to previous error; 3 warnings emitted +error: aborting due to 4 previous errors; 3 warnings emitted For more information about this error, try `rustc --explain E0310`. diff --git a/src/test/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.rs b/src/test/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.rs new file mode 100644 index 0000000000000..ac32dbde04b1c --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.rs @@ -0,0 +1,11 @@ +#![feature(type_alias_impl_trait)] + +mod test_type_param_static { + type Ty = impl Sized + 'static; + //~^ ERROR: the parameter type `A` may not live long enough + fn defining(s: A) -> Ty { s } + fn assert_static() {} + fn test() where Ty: 'static { assert_static::() } +} + +fn main() {} diff --git a/src/test/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.stderr b/src/test/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.stderr new file mode 100644 index 0000000000000..47bc31e78c34f --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.stderr @@ -0,0 +1,14 @@ +error[E0310]: the parameter type `A` may not live long enough + --> $DIR/implied_lifetime_wf_check4_static.rs:4:18 + | +LL | type Ty = impl Sized + 'static; + | ^^^^^^^^^^^^^^^^^^^^ ...so that the type `A` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound... + | +LL | type Ty = impl Sized + 'static; + | +++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0310`. From e9d219e97c9b87e928d131ac071fef96e906c464 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 23 Sep 2022 07:15:55 +0000 Subject: [PATCH 146/586] Make the test actually show the problematic case --- .../implied_lifetime_wf_check.rs | 29 ++++++++++++------- .../implied_lifetime_wf_check.stderr | 9 ------ 2 files changed, 19 insertions(+), 19 deletions(-) delete mode 100644 src/test/ui/type-alias-impl-trait/implied_lifetime_wf_check.stderr diff --git a/src/test/ui/type-alias-impl-trait/implied_lifetime_wf_check.rs b/src/test/ui/type-alias-impl-trait/implied_lifetime_wf_check.rs index a2063cf5e3ee5..b6a7264a529fd 100644 --- a/src/test/ui/type-alias-impl-trait/implied_lifetime_wf_check.rs +++ b/src/test/ui/type-alias-impl-trait/implied_lifetime_wf_check.rs @@ -1,18 +1,27 @@ -trait Mirror<'a> { - type Item; -} +#![feature(type_alias_impl_trait)] + +// known-bug: #99840 +// this should not compile +// check-pass + +type Alias = impl Sized; -impl<'a, T> Mirror<'a> for T { - type Item = T; +fn constrain() -> Alias { + 1i32 } -trait AnotherTrait { - type Blah; +trait HideIt { + type Assoc; } -impl<'a> AnotherTrait for >::Item { - //~^ ERROR: the lifetime parameter `'a` is not constrained - type Blah = &'a u32; +impl HideIt for () { + type Assoc = Alias; } +pub trait Yay {} + +impl Yay for <() as HideIt>::Assoc {} +// impl Yay for i32 {} // this already errors +// impl Yay for u32 {} // this also already errors + fn main() {} diff --git a/src/test/ui/type-alias-impl-trait/implied_lifetime_wf_check.stderr b/src/test/ui/type-alias-impl-trait/implied_lifetime_wf_check.stderr deleted file mode 100644 index cadf2ce4a9d5d..0000000000000 --- a/src/test/ui/type-alias-impl-trait/implied_lifetime_wf_check.stderr +++ /dev/null @@ -1,9 +0,0 @@ -error[E0207]: the lifetime parameter `'a` is not constrained by the impl trait, self type, or predicates - --> $DIR/implied_lifetime_wf_check.rs:13:6 - | -LL | impl<'a> AnotherTrait for >::Item { - | ^^ unconstrained lifetime parameter - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0207`. From e237aaef25db05a7f18c1a32b248fdaa06ff8669 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 23 Sep 2022 07:18:33 +0000 Subject: [PATCH 147/586] Some test cleanups --- compiler/rustc_typeck/src/outlives/utils.rs | 2 +- .../ui/generic-associated-types/issue-86218-2.rs | 1 - .../implied_lifetime_wf_check2.rs | 13 ------------- .../type-alias-impl-trait/unbounded_opaque_type.rs | 6 ++++++ 4 files changed, 7 insertions(+), 15 deletions(-) delete mode 100644 src/test/ui/type-alias-impl-trait/implied_lifetime_wf_check2.rs diff --git a/compiler/rustc_typeck/src/outlives/utils.rs b/compiler/rustc_typeck/src/outlives/utils.rs index f582fdf903ddd..0409c7081dc4f 100644 --- a/compiler/rustc_typeck/src/outlives/utils.rs +++ b/compiler/rustc_typeck/src/outlives/utils.rs @@ -105,7 +105,7 @@ pub(crate) fn insert_outlives_predicate<'tcx>( // struct Ss<'a, T>(&'a Opaque); // ``` // - // Here we want to require an explicit `where Opaque: 'a` + // Here we want to have an implied bound `Opaque: 'a` let ty = tcx.mk_opaque(def_id, substs); required_predicates diff --git a/src/test/ui/generic-associated-types/issue-86218-2.rs b/src/test/ui/generic-associated-types/issue-86218-2.rs index 897836af6b0b8..63c839ea8712d 100644 --- a/src/test/ui/generic-associated-types/issue-86218-2.rs +++ b/src/test/ui/generic-associated-types/issue-86218-2.rs @@ -17,7 +17,6 @@ trait Yay { impl Yay for () { type InnerStream<'s> = impl Stream + 's; - //^ ERROR does not fulfill the required lifetime fn foo<'s>() -> Self::InnerStream<'s> { () } } diff --git a/src/test/ui/type-alias-impl-trait/implied_lifetime_wf_check2.rs b/src/test/ui/type-alias-impl-trait/implied_lifetime_wf_check2.rs deleted file mode 100644 index 4f52f7a34af8e..0000000000000 --- a/src/test/ui/type-alias-impl-trait/implied_lifetime_wf_check2.rs +++ /dev/null @@ -1,13 +0,0 @@ -#![feature(type_alias_impl_trait)] - -// check-pass - -trait Tr { type Assoc; } -impl<'a> Tr for &'a str { type Assoc = &'a str; } - -type OpaqueTy<'a> = impl Tr; -fn defining(s: &str) -> OpaqueTy<'_> { s } - -// now we must be able to conclude `'a: 'static` from `Opaque<'a>: 'static` - -fn main() {} diff --git a/src/test/ui/type-alias-impl-trait/unbounded_opaque_type.rs b/src/test/ui/type-alias-impl-trait/unbounded_opaque_type.rs index a5ab3e1acae52..f43ad7dce1d40 100644 --- a/src/test/ui/type-alias-impl-trait/unbounded_opaque_type.rs +++ b/src/test/ui/type-alias-impl-trait/unbounded_opaque_type.rs @@ -5,4 +5,10 @@ type Opaque = impl Sized; fn defining() -> Opaque {} struct Ss<'a, T>(&'a Opaque); + +fn test<'a, T>(_: Ss<'a, T>) { + // test that we have an implied bound `Opaque: 'a` from fn signature + None::<&'a Opaque>; +} + fn main() {} From 0be3cc82345b22c898fb46a93e69fa7b1f6c710f Mon Sep 17 00:00:00 2001 From: Florian Bartels Date: Fri, 23 Sep 2022 09:41:12 +0200 Subject: [PATCH 148/586] ignore test cases when checking emscripten --- src/test/ui/extern-flag/empty-extern-arg.rs | 1 + src/test/ui/panic-handler/weak-lang-item.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/src/test/ui/extern-flag/empty-extern-arg.rs b/src/test/ui/extern-flag/empty-extern-arg.rs index a371afb128cab..2f4ae7d8e70fa 100644 --- a/src/test/ui/extern-flag/empty-extern-arg.rs +++ b/src/test/ui/extern-flag/empty-extern-arg.rs @@ -1,5 +1,6 @@ // compile-flags: --extern std= // error-pattern: extern location for std does not exist // needs-unwind since it affects the error output +// ignore-emscripten missing eh_catch_typeinfo lang item fn main() {} diff --git a/src/test/ui/panic-handler/weak-lang-item.rs b/src/test/ui/panic-handler/weak-lang-item.rs index aef5e1b2c1c7a..14a07a9ef1b55 100644 --- a/src/test/ui/panic-handler/weak-lang-item.rs +++ b/src/test/ui/panic-handler/weak-lang-item.rs @@ -2,6 +2,7 @@ // error-pattern: `#[panic_handler]` function required, but not found // error-pattern: language item required, but not found: `eh_personality` // needs-unwind since it affects the error output +// ignore-emscripten missing eh_catch_typeinfo lang item #![no_std] From 59e285ff34796585a61a711e11a056c2999368ea Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 23 Sep 2022 08:00:02 +0000 Subject: [PATCH 149/586] Report diagnostics at the actually actionable site --- .../src/infer/error_reporting/mod.rs | 10 +------- .../src/infer/outlives/obligations.rs | 5 +++- .../impl-trait/unactionable_diagnostic.fixed | 25 +++++++++++++++++++ .../ui/impl-trait/unactionable_diagnostic.rs | 14 ++++++----- .../impl-trait/unactionable_diagnostic.stderr | 10 ++++---- 5 files changed, 43 insertions(+), 21 deletions(-) create mode 100644 src/test/ui/impl-trait/unactionable_diagnostic.fixed diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index 8b8cff0dbbe64..e33035381e0a9 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -2314,7 +2314,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { &self, generic_param_scope: LocalDefId, span: Span, - mut origin: Option>, + origin: Option>, bound_kind: GenericKind<'tcx>, sub: Region<'tcx>, ) -> DiagnosticBuilder<'a, ErrorGuaranteed> { @@ -2349,14 +2349,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { None } } - GenericKind::Opaque(def_id, _substs) => { - // Avoid emitting a `... so that the type` message at the error site. - // It would be out of order for return position impl trait - origin = None; - // Make sure the lifetime suggestion is on the RPIT instead of proposing - // to add a bound for opaque types (which isn't possible) - Some((self.tcx.def_span(def_id).shrink_to_hi(), true)) - } _ => None, }; diff --git a/compiler/rustc_infer/src/infer/outlives/obligations.rs b/compiler/rustc_infer/src/infer/outlives/obligations.rs index 5af76b5d610db..229b69b92e68e 100644 --- a/compiler/rustc_infer/src/infer/outlives/obligations.rs +++ b/compiler/rustc_infer/src/infer/outlives/obligations.rs @@ -336,6 +336,7 @@ where GenericKind::Opaque(def_id, substs), def_id, substs, + true, |ty| match *ty.kind() { ty::Opaque(def_id, substs) => (def_id, substs), _ => bug!("expected only projection types from env, not {:?}", ty), @@ -356,6 +357,7 @@ where GenericKind::Projection(projection_ty), projection_ty.item_def_id, projection_ty.substs, + false, |ty| match ty.kind() { ty::Projection(projection_ty) => (projection_ty.item_def_id, projection_ty.substs), _ => bug!("expected only projection types from env, not {:?}", ty), @@ -371,6 +373,7 @@ where generic: GenericKind<'tcx>, def_id: DefId, substs: SubstsRef<'tcx>, + is_opaque: bool, filter: impl Fn(Ty<'tcx>) -> (DefId, SubstsRef<'tcx>), ) { // An optimization for a common case with opaque types. @@ -437,7 +440,7 @@ where // inference variables, we use a verify constraint instead of adding // edges, which winds up enforcing the same condition. let needs_infer = substs.needs_infer(); - if approx_env_bounds.is_empty() && trait_bounds.is_empty() && needs_infer { + if approx_env_bounds.is_empty() && trait_bounds.is_empty() && (needs_infer || is_opaque) { debug!("no declared bounds"); self.substs_must_outlive(substs, origin, region); diff --git a/src/test/ui/impl-trait/unactionable_diagnostic.fixed b/src/test/ui/impl-trait/unactionable_diagnostic.fixed new file mode 100644 index 0000000000000..6c2505177fef8 --- /dev/null +++ b/src/test/ui/impl-trait/unactionable_diagnostic.fixed @@ -0,0 +1,25 @@ +// run-rustfix + +pub trait Trait {} + +pub struct Foo; + +impl Trait for Foo {} + +fn foo<'x, P>( + _post: P, + x: &'x Foo, +) -> &'x impl Trait { + x +} + +pub fn bar<'t, T: 't>( + //~^ HELP: consider adding an explicit lifetime bound... + post: T, + x: &'t Foo, +) -> &'t impl Trait { + foo(post, x) + //~^ ERROR: the parameter type `T` may not live long enough +} + +fn main() {} diff --git a/src/test/ui/impl-trait/unactionable_diagnostic.rs b/src/test/ui/impl-trait/unactionable_diagnostic.rs index 016d7c3b7ef21..bce35cbdd0d38 100644 --- a/src/test/ui/impl-trait/unactionable_diagnostic.rs +++ b/src/test/ui/impl-trait/unactionable_diagnostic.rs @@ -1,23 +1,25 @@ -trait Trait {} +// run-rustfix -struct Foo; +pub trait Trait {} + +pub struct Foo; impl Trait for Foo {} fn foo<'x, P>( - post: P, + _post: P, x: &'x Foo, ) -> &'x impl Trait { - //~^ HELP: consider adding an explicit lifetime bound... x } -fn bar<'t, T>( +pub fn bar<'t, T>( + //~^ HELP: consider adding an explicit lifetime bound... post: T, x: &'t Foo, ) -> &'t impl Trait { foo(post, x) - //~^ ERROR: the opaque type `foo::{opaque#0}` may not live long enough + //~^ ERROR: the parameter type `T` may not live long enough } fn main() {} diff --git a/src/test/ui/impl-trait/unactionable_diagnostic.stderr b/src/test/ui/impl-trait/unactionable_diagnostic.stderr index c9b3f61254484..a32004cda1a6f 100644 --- a/src/test/ui/impl-trait/unactionable_diagnostic.stderr +++ b/src/test/ui/impl-trait/unactionable_diagnostic.stderr @@ -1,13 +1,13 @@ -error[E0309]: the opaque type `foo::{opaque#0}` may not live long enough - --> $DIR/unactionable_diagnostic.rs:19:5 +error[E0309]: the parameter type `T` may not live long enough + --> $DIR/unactionable_diagnostic.rs:21:5 | LL | foo(post, x) - | ^^^^^^^^^^^^ + | ^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds | help: consider adding an explicit lifetime bound... | -LL | ) -> &'x impl Trait + 't { - | ++++ +LL | pub fn bar<'t, T: 't>( + | ++++ error: aborting due to previous error From 7ed999b616a7be1014af93760c4f8fc5851eef76 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 23 Sep 2022 08:03:10 +0000 Subject: [PATCH 150/586] Also require other subtrees to always build successfully --- src/bootstrap/dist.rs | 44 +++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index 05664ca21794f..72b189e1bab2e 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -1430,7 +1430,7 @@ impl Step for Extended { let xform = |p: &Path| { let mut contents = t!(fs::read_to_string(p)); - for tool in &["rust-demangler", "rust-analyzer", "rustfmt"] { + for tool in &["rust-demangler"] { if !built_tools.contains(tool) { contents = filter(&contents, tool); } @@ -1471,7 +1471,8 @@ impl Step for Extended { prepare("rust-analysis"); prepare("clippy"); prepare("miri"); - for tool in &["rust-docs", "rust-demangler", "rust-analyzer"] { + prepare("rust-analyzer"); + for tool in &["rust-docs", "rust-demangler"] { if built_tools.contains(tool) { prepare(tool); } @@ -1531,7 +1532,8 @@ impl Step for Extended { prepare("rust-std"); prepare("clippy"); prepare("miri"); - for tool in &["rust-demangler", "rust-analyzer"] { + prepare("rust-analyzer"); + for tool in &["rust-demangler"] { if built_tools.contains(tool) { prepare(tool); } @@ -1615,25 +1617,23 @@ impl Step for Extended { .arg("-out") .arg(exe.join("StdGroup.wxs")), ); - if built_tools.contains("rust-analyzer") { - builder.run( - Command::new(&heat) - .current_dir(&exe) - .arg("dir") - .arg("rust-analyzer") - .args(&heat_flags) - .arg("-cg") - .arg("RustAnalyzerGroup") - .arg("-dr") - .arg("RustAnalyzer") - .arg("-var") - .arg("var.RustAnalyzerDir") - .arg("-out") - .arg(exe.join("RustAnalyzerGroup.wxs")) - .arg("-t") - .arg(etc.join("msi/remove-duplicates.xsl")), - ); - } + builder.run( + Command::new(&heat) + .current_dir(&exe) + .arg("dir") + .arg("rust-analyzer") + .args(&heat_flags) + .arg("-cg") + .arg("RustAnalyzerGroup") + .arg("-dr") + .arg("RustAnalyzer") + .arg("-var") + .arg("var.RustAnalyzerDir") + .arg("-out") + .arg(exe.join("RustAnalyzerGroup.wxs")) + .arg("-t") + .arg(etc.join("msi/remove-duplicates.xsl")), + ); builder.run( Command::new(&heat) .current_dir(&exe) From ccd19c7e9ede1cdb6606045bbab19d452ca39929 Mon Sep 17 00:00:00 2001 From: Florian Bartels Date: Fri, 23 Sep 2022 10:10:07 +0200 Subject: [PATCH 151/586] Repair stderr test result to added line --- src/test/ui/panic-handler/weak-lang-item.stderr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/ui/panic-handler/weak-lang-item.stderr b/src/test/ui/panic-handler/weak-lang-item.stderr index 3bce1e26fe276..202f3309d035e 100644 --- a/src/test/ui/panic-handler/weak-lang-item.stderr +++ b/src/test/ui/panic-handler/weak-lang-item.stderr @@ -1,5 +1,5 @@ error[E0259]: the name `core` is defined multiple times - --> $DIR/weak-lang-item.rs:8:1 + --> $DIR/weak-lang-item.rs:9:1 | LL | extern crate core; | ^^^^^^^^^^^^^^^^^^ `core` reimported here From cb8a9c496f037722378a36e4a0a54ccf9a7bb7c1 Mon Sep 17 00:00:00 2001 From: Miguel Ojeda Date: Thu, 22 Sep 2022 15:03:38 +0200 Subject: [PATCH 152/586] Add `llvm-dis` to the set of tools in `ci-llvm` The LLVM disassembler is needed for the test introduced in https://github.com/rust-lang/rust/pull/97550. Signed-off-by: Miguel Ojeda --- src/bootstrap/dist.rs | 1 + src/bootstrap/download-ci-llvm-stamp | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index c9ee3c1c7d65d..642831a66a22b 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -2059,6 +2059,7 @@ impl Step for RustDev { "llvm-dwp", "llvm-nm", "llvm-dwarfdump", + "llvm-dis", ] { tarball.add_file(src_bindir.join(exe(bin, target)), "bin", 0o755); } diff --git a/src/bootstrap/download-ci-llvm-stamp b/src/bootstrap/download-ci-llvm-stamp index 19504a51a584b..2e11cf19c3f6a 100644 --- a/src/bootstrap/download-ci-llvm-stamp +++ b/src/bootstrap/download-ci-llvm-stamp @@ -1,4 +1,4 @@ Change this file to make users of the `download-ci-llvm` configuration download a new version of LLVM from CI, even if the LLVM submodule hasn’t changed. -Last change is for: https://github.com/rust-lang/rust/pull/96867 +Last change is for: https://github.com/rust-lang/rust/pull/97550 From a0eb46788aa273598fb895d782ae417ed9d14950 Mon Sep 17 00:00:00 2001 From: inquisitivecrystal <22333129+inquisitivecrystal@users.noreply.github.com> Date: Fri, 23 Sep 2022 01:40:57 -0700 Subject: [PATCH 153/586] Fix a typo in `std`'s root docs --- library/std/src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 07b40f64ac2b4..3131dd4726984 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -145,8 +145,8 @@ //! abstracting over differences in common platforms, most notably Windows and //! Unix derivatives. //! -//! Common types of I/O, including [files], [TCP], [UDP], are defined in the -//! [`io`], [`fs`], and [`net`] modules. +//! Common types of I/O, including [files], [TCP], and [UDP], are defined in +//! the [`io`], [`fs`], and [`net`] modules. //! //! The [`thread`] module contains Rust's threading abstractions. [`sync`] //! contains further primitive shared memory types, including [`atomic`] and From c8d346e527fc556e3d3715c963c98a474a543320 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 23 Sep 2022 11:06:30 +0200 Subject: [PATCH 154/586] bootstrap: the backtrace feature is stable, no need to allow it any more --- src/bootstrap/builder.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index bc6283ef467d6..742e614d0fff9 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -1556,13 +1556,12 @@ impl<'a> Builder<'a> { match mode { Mode::ToolBootstrap => { // Restrict the allowed features to those passed by rustbuild, so we don't depend on nightly accidentally. - // HACK: because anyhow does feature detection in build.rs, we need to allow the backtrace feature too. - rustflags.arg("-Zallow-features=binary-dep-depinfo,backtrace"); + rustflags.arg("-Zallow-features=binary-dep-depinfo"); } Mode::ToolStd => { // Right now this is just compiletest and a few other tools that build on stable. // Allow them to use `feature(test)`, but nothing else. - rustflags.arg("-Zallow-features=binary-dep-depinfo,test,backtrace,proc_macro_internals,proc_macro_diagnostic,proc_macro_span"); + rustflags.arg("-Zallow-features=binary-dep-depinfo,test,proc_macro_internals,proc_macro_diagnostic,proc_macro_span"); } Mode::Std | Mode::Rustc | Mode::Codegen | Mode::ToolRustc => {} } From 0b2f717dfaf4835aa644d925a12c93db8f15dd61 Mon Sep 17 00:00:00 2001 From: onestacked Date: Fri, 23 Sep 2022 13:42:31 +0200 Subject: [PATCH 155/586] Added const_closure --- library/core/src/const_closure.rs | 178 ++++++++++++++++++++++++++++++ library/core/src/lib.rs | 2 + 2 files changed, 180 insertions(+) create mode 100644 library/core/src/const_closure.rs diff --git a/library/core/src/const_closure.rs b/library/core/src/const_closure.rs new file mode 100644 index 0000000000000..bd24c10bd0053 --- /dev/null +++ b/library/core/src/const_closure.rs @@ -0,0 +1,178 @@ +use crate::marker::Destruct; + +/// Struct representing a closure with owned data. +/// +/// Example: +/// ```rust +/// use const_closure::ConstFnOnceClosure; +/// const fn imp(state: i32, (arg,): (i32,)) -> i32 { +/// state + arg +/// } +/// let i = 5; +/// let cl = ConstFnOnceClosure::new(i, imp); +/// +/// assert!(7 == cl(2)); +/// ``` +pub(crate) struct ConstFnOnceClosure { + data: CapturedData, + func: Function, +} +impl ConstFnOnceClosure { + /// Function for creating a new closure. + /// + /// `data` is the owned data that is captured from the environment (this data must be `~const Destruct`). + /// + /// `func` is the function of the closure, it gets the data and a tuple of the arguments closure + /// and return the return value of the closure. + #[allow(dead_code)] + pub(crate) const fn new( + data: CapturedData, + func: Function, + ) -> Self + where + CapturedData: ~const Destruct, + Function: ~const Fn(CapturedData, ClosureArguments) -> ClosureReturnValue + ~const Destruct, + { + Self { data, func } + } +} +impl const FnOnce + for ConstFnOnceClosure +where + CapturedData: ~const Destruct, + Function: ~const Fn<(CapturedData, ClosureArguments)> + ~const Destruct, +{ + type Output = Function::Output; + + extern "rust-call" fn call_once(self, args: ClosureArguments) -> Self::Output { + (self.func)(self.data, args) + } +} +/// Struct representing a closure with mutably borrowed data. +/// +/// Example: +/// ```rust +/// #![feature(const_mut_refs)] +/// use const_closure::ConstFnMutClosure; +/// const fn imp(state: &mut i32, (arg,): (i32,)) -> i32 { +/// *state += arg; +/// *state +/// } +/// let mut i = 5; +/// let mut cl = ConstFnMutClosure::new(&mut i, imp); +/// +/// assert!(7 == cl(2)); +/// assert!(8 == cl(1)); +/// ``` +pub(crate) struct ConstFnMutClosure<'a, CapturedData: ?Sized, Function> { + data: &'a mut CapturedData, + func: Function, +} +impl<'a, CapturedData: ?Sized, Function> ConstFnMutClosure<'a, CapturedData, Function> { + /// Function for creating a new closure. + /// + /// `data` is the a mutable borrow of data that is captured from the environment. + /// + /// `func` is the function of the closure, it gets the data and a tuple of the arguments closure + /// and return the return value of the closure. + pub(crate) const fn new( + data: &'a mut CapturedData, + func: Function, + ) -> Self + where + Function: ~const Fn(&mut CapturedData, ClosureArguments) -> ClosureReturnValue, + { + Self { data, func } + } +} +impl<'a, CapturedData: ?Sized, ClosureArguments, Function, ClosureReturnValue> const + FnOnce for ConstFnMutClosure<'a, CapturedData, Function> +where + Function: + ~const Fn(&mut CapturedData, ClosureArguments) -> ClosureReturnValue + ~const Destruct, +{ + type Output = ClosureReturnValue; + + extern "rust-call" fn call_once(mut self, args: ClosureArguments) -> Self::Output { + self.call_mut(args) + } +} +impl<'a, CapturedData: ?Sized, ClosureArguments, Function, ClosureReturnValue> const + FnMut for ConstFnMutClosure<'a, CapturedData, Function> +where + Function: ~const Fn(&mut CapturedData, ClosureArguments) -> ClosureReturnValue, +{ + extern "rust-call" fn call_mut(&mut self, args: ClosureArguments) -> Self::Output { + (self.func)(self.data, args) + } +} + +/// Struct representing a closure with borrowed data. +/// +/// Example: +/// ```rust +/// use const_closure::ConstFnClosure; +/// +/// const fn imp(state: &i32, (arg,): (i32,)) -> i32 { +/// *state + arg +/// } +/// let i = 5; +/// let cl = ConstFnClosure::new(&i, imp); +/// +/// assert!(7 == cl(2)); +/// assert!(6 == cl(1)); +/// ``` +pub(crate) struct ConstFnClosure<'a, CapturedData: ?Sized, Function> { + data: &'a CapturedData, + func: Function, +} +impl<'a, CapturedData: ?Sized, Function> ConstFnClosure<'a, CapturedData, Function> { + /// Function for creating a new closure. + /// + /// `data` is the a mutable borrow of data that is captured from the environment. + /// + /// `func` is the function of the closure, it gets the data and a tuple of the arguments closure + /// and return the return value of the closure. + #[allow(dead_code)] + pub(crate) const fn new( + data: &'a CapturedData, + func: Function, + ) -> Self + where + Function: ~const Fn(&CapturedData, ClosureArguments) -> ClosureReturnValue, + { + Self { data, func } + } +} +impl<'a, CapturedData: ?Sized, Function, ClosureArguments, ClosureReturnValue> const + FnOnce for ConstFnClosure<'a, CapturedData, Function> +where + Function: ~const Fn(&CapturedData, ClosureArguments) -> ClosureReturnValue + ~const Destruct, +{ + type Output = ClosureReturnValue; + + extern "rust-call" fn call_once(mut self, args: ClosureArguments) -> Self::Output { + self.call_mut(args) + } +} +impl<'a, CapturedData: ?Sized, Function, ClosureArguments, ClosureReturnValue> const + FnMut for ConstFnClosure<'a, CapturedData, Function> +where + Function: ~const Fn(&CapturedData, ClosureArguments) -> ClosureReturnValue, +{ + extern "rust-call" fn call_mut(&mut self, args: ClosureArguments) -> Self::Output { + self.call(args) + } +} +impl< + 'a, + CapturedData: ?Sized, + Function: ~const Fn(&CapturedData, ClosureArguments) -> ClosureReturnValue, + ClosureArguments, + ClosureReturnValue, +> const Fn for ConstFnClosure<'a, CapturedData, Function> +{ + extern "rust-call" fn call(&self, args: ClosureArguments) -> Self::Output { + (self.func)(self.data, args) + } +} diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 21775c0a6ab0b..6fbe7ade73255 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -356,6 +356,8 @@ mod bool; mod tuple; mod unit; +mod const_closure; + #[stable(feature = "core_primitive", since = "1.43.0")] pub mod primitive; From 8e0ea60a04c463bf52fc81dbbf182f4739525681 Mon Sep 17 00:00:00 2001 From: onestacked Date: Fri, 23 Sep 2022 13:43:34 +0200 Subject: [PATCH 156/586] Constifed Try trait --- .../core/src/iter/adapters/array_chunks.rs | 9 +++++---- .../core/src/iter/adapters/by_ref_sized.rs | 19 ++++++++++++++----- library/core/src/iter/adapters/mod.rs | 5 +++-- library/core/src/ops/control_flow.rs | 2 +- library/core/src/ops/try_trait.rs | 18 +++++++++++------- 5 files changed, 34 insertions(+), 19 deletions(-) diff --git a/library/core/src/iter/adapters/array_chunks.rs b/library/core/src/iter/adapters/array_chunks.rs index 9b479a9f8adfb..489fb13c0dc97 100644 --- a/library/core/src/iter/adapters/array_chunks.rs +++ b/library/core/src/iter/adapters/array_chunks.rs @@ -1,4 +1,5 @@ use crate::array; +use crate::const_closure::ConstFnMutClosure; use crate::iter::{ByRefSized, FusedIterator, Iterator}; use crate::ops::{ControlFlow, NeverShortCircuit, Try}; @@ -82,12 +83,12 @@ where } } - fn fold(mut self, init: B, f: F) -> B + fn fold(mut self, init: B, mut f: F) -> B where Self: Sized, F: FnMut(B, Self::Item) -> B, { - self.try_fold(init, NeverShortCircuit::wrap_mut_2(f)).0 + self.try_fold(init, ConstFnMutClosure::new(&mut f, NeverShortCircuit::wrap_mut_2_imp)).0 } } @@ -126,12 +127,12 @@ where try { acc } } - fn rfold(mut self, init: B, f: F) -> B + fn rfold(mut self, init: B, mut f: F) -> B where Self: Sized, F: FnMut(B, Self::Item) -> B, { - self.try_rfold(init, NeverShortCircuit::wrap_mut_2(f)).0 + self.try_rfold(init, ConstFnMutClosure::new(&mut f, NeverShortCircuit::wrap_mut_2_imp)).0 } } diff --git a/library/core/src/iter/adapters/by_ref_sized.rs b/library/core/src/iter/adapters/by_ref_sized.rs index 477e7117c3ea1..1945e402ff50e 100644 --- a/library/core/src/iter/adapters/by_ref_sized.rs +++ b/library/core/src/iter/adapters/by_ref_sized.rs @@ -1,4 +1,7 @@ -use crate::ops::{NeverShortCircuit, Try}; +use crate::{ + const_closure::ConstFnMutClosure, + ops::{NeverShortCircuit, Try}, +}; /// Like `Iterator::by_ref`, but requiring `Sized` so it can forward generics. /// @@ -36,12 +39,13 @@ impl Iterator for ByRefSized<'_, I> { } #[inline] - fn fold(self, init: B, f: F) -> B + fn fold(self, init: B, mut f: F) -> B where F: FnMut(B, Self::Item) -> B, { // `fold` needs ownership, so this can't forward directly. - I::try_fold(self.0, init, NeverShortCircuit::wrap_mut_2(f)).0 + I::try_fold(self.0, init, ConstFnMutClosure::new(&mut f, NeverShortCircuit::wrap_mut_2_imp)) + .0 } #[inline] @@ -72,12 +76,17 @@ impl DoubleEndedIterator for ByRefSized<'_, I> { } #[inline] - fn rfold(self, init: B, f: F) -> B + fn rfold(self, init: B, mut f: F) -> B where F: FnMut(B, Self::Item) -> B, { // `rfold` needs ownership, so this can't forward directly. - I::try_rfold(self.0, init, NeverShortCircuit::wrap_mut_2(f)).0 + I::try_rfold( + self.0, + init, + ConstFnMutClosure::new(&mut f, NeverShortCircuit::wrap_mut_2_imp), + ) + .0 } #[inline] diff --git a/library/core/src/iter/adapters/mod.rs b/library/core/src/iter/adapters/mod.rs index bf4fabad32a37..de3a534f81b8a 100644 --- a/library/core/src/iter/adapters/mod.rs +++ b/library/core/src/iter/adapters/mod.rs @@ -1,3 +1,4 @@ +use crate::const_closure::ConstFnMutClosure; use crate::iter::{InPlaceIterable, Iterator}; use crate::ops::{ChangeOutputType, ControlFlow, FromResidual, NeverShortCircuit, Residual, Try}; @@ -203,12 +204,12 @@ where .into_try() } - fn fold(mut self, init: B, fold: F) -> B + fn fold(mut self, init: B, mut fold: F) -> B where Self: Sized, F: FnMut(B, Self::Item) -> B, { - self.try_fold(init, NeverShortCircuit::wrap_mut_2(fold)).0 + self.try_fold(init, ConstFnMutClosure::new(&mut fold, NeverShortCircuit::wrap_mut_2_imp)).0 } } diff --git a/library/core/src/ops/control_flow.rs b/library/core/src/ops/control_flow.rs index fd567a8c68492..8d236a9fecaea 100644 --- a/library/core/src/ops/control_flow.rs +++ b/library/core/src/ops/control_flow.rs @@ -126,7 +126,7 @@ impl const ops::FromResidual for ControlFlow { } #[unstable(feature = "try_trait_v2_residual", issue = "91285")] -impl ops::Residual for ControlFlow { +impl const ops::Residual for ControlFlow { type TryType = ControlFlow; } diff --git a/library/core/src/ops/try_trait.rs b/library/core/src/ops/try_trait.rs index dfde0b37acf43..4d0d4e12adbf8 100644 --- a/library/core/src/ops/try_trait.rs +++ b/library/core/src/ops/try_trait.rs @@ -129,7 +129,7 @@ use crate::ops::ControlFlow; #[doc(alias = "?")] #[lang = "Try"] #[const_trait] -pub trait Try: FromResidual { +pub trait Try: ~const FromResidual { /// The type of the value produced by `?` when *not* short-circuiting. #[unstable(feature = "try_trait_v2", issue = "84277")] type Output; @@ -438,10 +438,11 @@ where /// and in the other direction, /// ` as Residual>::TryType = Result`. #[unstable(feature = "try_trait_v2_residual", issue = "91285")] +#[const_trait] pub trait Residual { /// The "return" type of this meta-function. #[unstable(feature = "try_trait_v2_residual", issue = "91285")] - type TryType: Try; + type TryType: ~const Try; } #[unstable(feature = "pub_crate_should_not_need_unstable_attr", issue = "none")] @@ -460,14 +461,17 @@ pub(crate) struct NeverShortCircuit(pub T); impl NeverShortCircuit { /// Wrap a binary `FnMut` to return its result wrapped in a `NeverShortCircuit`. #[inline] - pub fn wrap_mut_2(mut f: impl FnMut(A, B) -> T) -> impl FnMut(A, B) -> Self { - move |a, b| NeverShortCircuit(f(a, b)) + pub const fn wrap_mut_2_imp T>( + f: &mut F, + (a, b): (A, B), + ) -> NeverShortCircuit { + NeverShortCircuit(f(a, b)) } } pub(crate) enum NeverShortCircuitResidual {} -impl Try for NeverShortCircuit { +impl const Try for NeverShortCircuit { type Output = T; type Residual = NeverShortCircuitResidual; @@ -482,14 +486,14 @@ impl Try for NeverShortCircuit { } } -impl FromResidual for NeverShortCircuit { +impl const FromResidual for NeverShortCircuit { #[inline] fn from_residual(never: NeverShortCircuitResidual) -> Self { match never {} } } -impl Residual for NeverShortCircuitResidual { +impl const Residual for NeverShortCircuitResidual { type TryType = NeverShortCircuit; } From 8eeeac69db88f92514bba042d9e0dbd4077d0124 Mon Sep 17 00:00:00 2001 From: Florian Bartels Date: Fri, 23 Sep 2022 14:16:35 +0200 Subject: [PATCH 157/586] Update doc after renaming fn is_zero `fn is_zero` has been renamed to `fn count_is_zero` in 1b1bf2463619e23eba1b36b6d7df276ce73563dd. This patch updates the documentation accordingly. --- library/std/src/panicking.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/std/src/panicking.rs b/library/std/src/panicking.rs index 38dcf6cbf7db7..4b07b393a2f5a 100644 --- a/library/std/src/panicking.rs +++ b/library/std/src/panicking.rs @@ -300,7 +300,7 @@ pub mod panic_count { thread_local! { static LOCAL_PANIC_COUNT: Cell = const { Cell::new(0) } } // Sum of panic counts from all threads. The purpose of this is to have - // a fast path in `is_zero` (which is used by `panicking`). In any particular + // a fast path in `count_is_zero` (which is used by `panicking`). In any particular // thread, if that thread currently views `GLOBAL_PANIC_COUNT` as being zero, // then `LOCAL_PANIC_COUNT` in that thread is zero. This invariant holds before // and after increase and decrease, but not necessarily during their execution. @@ -369,7 +369,7 @@ pub mod panic_count { } // Slow path is in a separate function to reduce the amount of code - // inlined from `is_zero`. + // inlined from `count_is_zero`. #[inline(never)] #[cold] fn is_zero_slow_path() -> bool { From ded3edac9ad2dd014eed22d5c9050af6eb22882f Mon Sep 17 00:00:00 2001 From: b-naber Date: Fri, 23 Sep 2022 14:25:30 +0200 Subject: [PATCH 158/586] fix test --- .../wrong-type-assume.rs | 4 -- .../wrong-type-assume.stderr | 37 +++---------------- 2 files changed, 6 insertions(+), 35 deletions(-) diff --git a/src/test/ui/transmutability/malformed-program-gracefulness/wrong-type-assume.rs b/src/test/ui/transmutability/malformed-program-gracefulness/wrong-type-assume.rs index 354abf99d4d07..52aa4bb31016c 100644 --- a/src/test/ui/transmutability/malformed-program-gracefulness/wrong-type-assume.rs +++ b/src/test/ui/transmutability/malformed-program-gracefulness/wrong-type-assume.rs @@ -24,10 +24,6 @@ mod assert { Src, Context, { from_options(ASSUME_ALIGNMENT, ASSUME_LIFETIMES, ASSUME_SAFETY, ASSUME_VALIDITY) } - //~^ ERROR E0080 - //~| ERROR E0080 - //~| ERROR E0080 - //~| ERROR E0080 >, {} diff --git a/src/test/ui/transmutability/malformed-program-gracefulness/wrong-type-assume.stderr b/src/test/ui/transmutability/malformed-program-gracefulness/wrong-type-assume.stderr index a258f2ecea6d9..c6d93876cfafa 100644 --- a/src/test/ui/transmutability/malformed-program-gracefulness/wrong-type-assume.stderr +++ b/src/test/ui/transmutability/malformed-program-gracefulness/wrong-type-assume.stderr @@ -1,52 +1,27 @@ error[E0308]: mismatched types - --> $DIR/wrong-type-assume.rs:53:51 + --> $DIR/wrong-type-assume.rs:49:51 | LL | assert::is_transmutable::(); | ^^^ expected `bool`, found `u8` -error[E0080]: evaluation of `assert::is_transmutable::::{constant#0}` failed - --> $DIR/wrong-type-assume.rs:26:15 - | -LL | { from_options(ASSUME_ALIGNMENT, ASSUME_LIFETIMES, ASSUME_SAFETY, ASSUME_VALIDITY) } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors - error[E0308]: mismatched types - --> $DIR/wrong-type-assume.rs:54:58 + --> $DIR/wrong-type-assume.rs:50:58 | LL | assert::is_transmutable::(); | ^^^ expected `bool`, found `u8` -error[E0080]: evaluation of `assert::is_transmutable::::{constant#0}` failed - --> $DIR/wrong-type-assume.rs:26:15 - | -LL | { from_options(ASSUME_ALIGNMENT, ASSUME_LIFETIMES, ASSUME_SAFETY, ASSUME_VALIDITY) } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors - error[E0308]: mismatched types - --> $DIR/wrong-type-assume.rs:55:65 + --> $DIR/wrong-type-assume.rs:51:65 | LL | assert::is_transmutable::(); | ^^^ expected `bool`, found `u8` -error[E0080]: evaluation of `assert::is_transmutable::::{constant#0}` failed - --> $DIR/wrong-type-assume.rs:26:15 - | -LL | { from_options(ASSUME_ALIGNMENT, ASSUME_LIFETIMES, ASSUME_SAFETY, ASSUME_VALIDITY) } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors - error[E0308]: mismatched types - --> $DIR/wrong-type-assume.rs:56:72 + --> $DIR/wrong-type-assume.rs:52:72 | LL | assert::is_transmutable::(); | ^^^ expected `bool`, found `u8` -error[E0080]: evaluation of `assert::is_transmutable::::{constant#0}` failed - --> $DIR/wrong-type-assume.rs:26:15 - | -LL | { from_options(ASSUME_ALIGNMENT, ASSUME_LIFETIMES, ASSUME_SAFETY, ASSUME_VALIDITY) } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors - -error: aborting due to 8 previous errors +error: aborting due to 4 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`. From a705e65605868adb0879734a984b445d3c40fd6f Mon Sep 17 00:00:00 2001 From: b-naber Date: Thu, 22 Sep 2022 12:34:23 +0200 Subject: [PATCH 159/586] rename Unevaluated to UnevaluatedConst --- .../rustc_codegen_cranelift/src/constant.rs | 2 +- .../src/transform/check_consts/qualifs.rs | 3 ++- .../src/transform/promote_consts.rs | 2 +- compiler/rustc_infer/src/infer/combine.rs | 8 +++--- compiler/rustc_infer/src/infer/mod.rs | 10 +++---- .../rustc_middle/src/mir/interpret/queries.rs | 6 ++--- compiler/rustc_middle/src/mir/mod.rs | 25 ++++++++++-------- .../rustc_middle/src/mir/type_foldable.rs | 6 ++--- .../rustc_middle/src/mir/type_visitable.rs | 4 +-- compiler/rustc_middle/src/query/mod.rs | 2 +- .../rustc_middle/src/ty/abstract_const.rs | 2 +- compiler/rustc_middle/src/ty/consts.rs | 2 +- compiler/rustc_middle/src/ty/consts/kind.rs | 23 +++++++++------- compiler/rustc_middle/src/ty/flags.rs | 4 +-- compiler/rustc_middle/src/ty/fold.rs | 26 ++++++++++++------- compiler/rustc_middle/src/ty/mod.rs | 4 +-- compiler/rustc_middle/src/ty/print/pretty.rs | 2 +- compiler/rustc_middle/src/ty/relate.rs | 2 +- .../rustc_middle/src/ty/structural_impls.rs | 10 +++---- compiler/rustc_middle/src/ty/visit.rs | 20 +++++++++++--- .../src/build/expr/as_constant.rs | 6 +++-- .../src/const_prop_lint.rs | 2 +- compiler/rustc_mir_transform/src/inline.rs | 2 +- .../rustc_monomorphize/src/polymorphize.rs | 4 +-- compiler/rustc_query_impl/src/keys.rs | 2 +- compiler/rustc_trait_selection/src/errors.rs | 4 +-- .../src/traits/const_evaluatable.rs | 4 +-- .../src/traits/object_safety.rs | 2 +- .../src/traits/project.rs | 2 +- compiler/rustc_ty_utils/src/consts.rs | 3 ++- compiler/rustc_typeck/src/check/wfcheck.rs | 10 ++++--- src/librustdoc/clean/utils.rs | 2 +- .../mir-opt/issue_99325.main.mir_map.0.mir | 2 +- .../clippy/clippy_lints/src/non_copy_const.rs | 2 +- src/tools/clippy/clippy_utils/src/consts.rs | 2 +- 35 files changed, 121 insertions(+), 91 deletions(-) diff --git a/compiler/rustc_codegen_cranelift/src/constant.rs b/compiler/rustc_codegen_cranelift/src/constant.rs index aac64d854a6b5..e12805b093cc7 100644 --- a/compiler/rustc_codegen_cranelift/src/constant.rs +++ b/compiler/rustc_codegen_cranelift/src/constant.rs @@ -109,7 +109,7 @@ pub(crate) fn codegen_constant<'tcx>( ) -> CValue<'tcx> { let (const_val, ty) = match fx.monomorphize(constant.literal) { ConstantKind::Ty(const_) => unreachable!("{:?}", const_), - ConstantKind::Unevaluated(mir::Unevaluated { def, substs, promoted }, ty) + ConstantKind::Unevaluated(mir::UnevaluatedConst { def, substs, promoted }, ty) if fx.tcx.is_static(def.did) => { assert!(substs.is_empty()); diff --git a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs index b1d140726d11f..60deb0abd344d 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs @@ -357,7 +357,7 @@ where ConstantKind::Val(..) => None, }; - if let Some(mir::Unevaluated { def, substs: _, promoted }) = uneval { + if let Some(mir::UnevaluatedConst { def, substs: _, promoted }) = uneval { // Use qualifs of the type for the promoted. Promoteds in MIR body should be possible // only for `NeedsNonConstDrop` with precise drop checking. This is the only const // check performed after the promotion. Verify that with an assertion. @@ -365,6 +365,7 @@ where // Don't peek inside trait associated constants. if promoted.is_none() && cx.tcx.trait_of_item(def.did).is_none() { + assert_eq!(def.const_param_did, None, "expected associated const: {def:?}"); let qualifs = cx.tcx.at(constant.span).mir_const_qualif(def.did); if !Q::in_qualifs(&qualifs) { diff --git a/compiler/rustc_const_eval/src/transform/promote_consts.rs b/compiler/rustc_const_eval/src/transform/promote_consts.rs index 733683bf7baa2..4b219300739c0 100644 --- a/compiler/rustc_const_eval/src/transform/promote_consts.rs +++ b/compiler/rustc_const_eval/src/transform/promote_consts.rs @@ -841,7 +841,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { promoted.span = span; promoted.local_decls[RETURN_PLACE] = LocalDecl::new(ty, span); let substs = tcx.erase_regions(InternalSubsts::identity_for_item(tcx, def.did)); - let uneval = mir::Unevaluated { def, substs, promoted: Some(promoted_id) }; + let uneval = mir::UnevaluatedConst { def, substs, promoted: Some(promoted_id) }; Operand::Constant(Box::new(Constant { span, diff --git a/compiler/rustc_infer/src/infer/combine.rs b/compiler/rustc_infer/src/infer/combine.rs index 18e05fa37f71f..65b60eec5957f 100644 --- a/compiler/rustc_infer/src/infer/combine.rs +++ b/compiler/rustc_infer/src/infer/combine.rs @@ -742,7 +742,7 @@ impl<'tcx> TypeRelation<'tcx> for Generalizer<'_, 'tcx> { } } } - ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs }) => { + ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, substs }) => { let substs = self.relate_with_variance( ty::Variance::Invariant, ty::VarianceDiagInfo::default(), @@ -751,7 +751,7 @@ impl<'tcx> TypeRelation<'tcx> for Generalizer<'_, 'tcx> { )?; Ok(self.tcx().mk_const(ty::ConstS { ty: c.ty(), - kind: ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs }), + kind: ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, substs }), })) } _ => relate::super_relate_consts(self, c, c), @@ -962,7 +962,7 @@ impl<'tcx> TypeRelation<'tcx> for ConstInferUnifier<'_, 'tcx> { } } } - ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs }) => { + ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, substs }) => { let substs = self.relate_with_variance( ty::Variance::Invariant, ty::VarianceDiagInfo::default(), @@ -972,7 +972,7 @@ impl<'tcx> TypeRelation<'tcx> for ConstInferUnifier<'_, 'tcx> { Ok(self.tcx().mk_const(ty::ConstS { ty: c.ty(), - kind: ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs }), + kind: ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, substs }), })) } _ => relate::super_relate_consts(self, c, c), diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 0a37aa035c2a0..55cf9b7a2ea18 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -705,8 +705,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { #[instrument(skip(self), level = "debug")] pub fn try_unify_abstract_consts( &self, - a: ty::Unevaluated<'tcx>, - b: ty::Unevaluated<'tcx>, + a: ty::UnevaluatedConst<'tcx>, + b: ty::UnevaluatedConst<'tcx>, param_env: ty::ParamEnv<'tcx>, ) -> bool { // Reject any attempt to unify two unevaluated constants that contain inference @@ -1690,7 +1690,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { pub fn try_const_eval_resolve( &self, param_env: ty::ParamEnv<'tcx>, - unevaluated: ty::Unevaluated<'tcx>, + unevaluated: ty::UnevaluatedConst<'tcx>, ty: Ty<'tcx>, span: Option, ) -> Result, ErrorHandled> { @@ -1725,7 +1725,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { pub fn const_eval_resolve( &self, mut param_env: ty::ParamEnv<'tcx>, - unevaluated: ty::Unevaluated<'tcx>, + unevaluated: ty::UnevaluatedConst<'tcx>, span: Option, ) -> EvalToValTreeResult<'tcx> { let mut substs = self.resolve_vars_if_possible(unevaluated.substs); @@ -1756,7 +1756,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { debug!(?param_env_erased); debug!(?substs_erased); - let unevaluated = ty::Unevaluated { def: unevaluated.def, substs: substs_erased }; + let unevaluated = ty::UnevaluatedConst { def: unevaluated.def, substs: substs_erased }; // The return value is the evaluated value which doesn't contain any reference to inference // variables, thus we don't need to substitute back the original values. diff --git a/compiler/rustc_middle/src/mir/interpret/queries.rs b/compiler/rustc_middle/src/mir/interpret/queries.rs index 5f3124e482d49..734c31192c7c3 100644 --- a/compiler/rustc_middle/src/mir/interpret/queries.rs +++ b/compiler/rustc_middle/src/mir/interpret/queries.rs @@ -36,7 +36,7 @@ impl<'tcx> TyCtxt<'tcx> { pub fn const_eval_resolve( self, param_env: ty::ParamEnv<'tcx>, - ct: mir::Unevaluated<'tcx>, + ct: mir::UnevaluatedConst<'tcx>, span: Option, ) -> EvalToConstValueResult<'tcx> { // Cannot resolve `Unevaluated` constants that contain inference @@ -51,7 +51,7 @@ impl<'tcx> TyCtxt<'tcx> { match ty::Instance::resolve_opt_const_arg( self, param_env, - // FIXME: maybe have a seperate version for resolving mir::Unevaluated? + // FIXME: maybe have a seperate version for resolving mir::UnevaluatedConst? ct.def, ct.substs, ) { Ok(Some(instance)) => { @@ -67,7 +67,7 @@ impl<'tcx> TyCtxt<'tcx> { pub fn const_eval_resolve_for_typeck( self, param_env: ty::ParamEnv<'tcx>, - ct: ty::Unevaluated<'tcx>, + ct: ty::UnevaluatedConst<'tcx>, span: Option, ) -> EvalToValTreeResult<'tcx> { // Cannot resolve `Unevaluated` constants that contain inference diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 9ff57502a385e..78a1678881583 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -2055,7 +2055,7 @@ pub enum ConstantKind<'tcx> { Ty(ty::Const<'tcx>), /// An unevaluated mir constant which is not part of the type system. - Unevaluated(Unevaluated<'tcx>, Ty<'tcx>), + Unevaluated(UnevaluatedConst<'tcx>, Ty<'tcx>), /// This constant cannot go back into the type system, as it represents /// something the type system cannot handle (e.g. pointers). @@ -2315,7 +2315,7 @@ impl<'tcx> ConstantKind<'tcx> { ty::InlineConstSubsts::new(tcx, ty::InlineConstSubstsParts { parent_substs, ty }) .substs; - let uneval = Unevaluated { + let uneval = UnevaluatedConst { def: ty::WithOptConstParam::unknown(def_id).to_global(), substs, promoted: None, @@ -2403,7 +2403,7 @@ impl<'tcx> ConstantKind<'tcx> { let hir_id = tcx.hir().local_def_id_to_hir_id(def.did); let span = tcx.hir().span(hir_id); - let uneval = Unevaluated::new(def.to_global(), substs); + let uneval = UnevaluatedConst::new(def.to_global(), substs); debug!(?span, ?param_env); match tcx.const_eval_resolve(param_env, uneval, Some(span)) { @@ -2416,7 +2416,7 @@ impl<'tcx> ConstantKind<'tcx> { // Error was handled in `const_eval_resolve`. Here we just create a // new unevaluated const and error hard later in codegen Self::Unevaluated( - Unevaluated { + UnevaluatedConst { def: def.to_global(), substs: InternalSubsts::identity_for_item(tcx, def.did.to_def_id()), promoted: None, @@ -2442,25 +2442,28 @@ impl<'tcx> ConstantKind<'tcx> { /// An unevaluated (potentially generic) constant used in MIR. #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable, Lift)] #[derive(Hash, HashStable)] -pub struct Unevaluated<'tcx> { +pub struct UnevaluatedConst<'tcx> { pub def: ty::WithOptConstParam, pub substs: SubstsRef<'tcx>, pub promoted: Option, } -impl<'tcx> Unevaluated<'tcx> { +impl<'tcx> UnevaluatedConst<'tcx> { // FIXME: probably should get rid of this method. It's also wrong to // shrink and then later expand a promoted. #[inline] - pub fn shrink(self) -> ty::Unevaluated<'tcx> { - ty::Unevaluated { def: self.def, substs: self.substs } + pub fn shrink(self) -> ty::UnevaluatedConst<'tcx> { + ty::UnevaluatedConst { def: self.def, substs: self.substs } } } -impl<'tcx> Unevaluated<'tcx> { +impl<'tcx> UnevaluatedConst<'tcx> { #[inline] - pub fn new(def: ty::WithOptConstParam, substs: SubstsRef<'tcx>) -> Unevaluated<'tcx> { - Unevaluated { def, substs, promoted: Default::default() } + pub fn new( + def: ty::WithOptConstParam, + substs: SubstsRef<'tcx>, + ) -> UnevaluatedConst<'tcx> { + UnevaluatedConst { def, substs, promoted: Default::default() } } } diff --git a/compiler/rustc_middle/src/mir/type_foldable.rs b/compiler/rustc_middle/src/mir/type_foldable.rs index 88c07ca17e204..8e18cad442ed9 100644 --- a/compiler/rustc_middle/src/mir/type_foldable.rs +++ b/compiler/rustc_middle/src/mir/type_foldable.rs @@ -51,18 +51,18 @@ impl<'tcx, R: Idx, C: Idx> TypeFoldable<'tcx> for BitMatrix { } } -impl<'tcx> TypeFoldable<'tcx> for mir::Unevaluated<'tcx> { +impl<'tcx> TypeFoldable<'tcx> for mir::UnevaluatedConst<'tcx> { fn try_fold_with>(self, folder: &mut F) -> Result { folder.try_fold_mir_unevaluated(self) } } -impl<'tcx> TypeSuperFoldable<'tcx> for mir::Unevaluated<'tcx> { +impl<'tcx> TypeSuperFoldable<'tcx> for mir::UnevaluatedConst<'tcx> { fn try_super_fold_with>( self, folder: &mut F, ) -> Result { - Ok(mir::Unevaluated { + Ok(mir::UnevaluatedConst { def: self.def, substs: self.substs.try_fold_with(folder)?, promoted: self.promoted, diff --git a/compiler/rustc_middle/src/mir/type_visitable.rs b/compiler/rustc_middle/src/mir/type_visitable.rs index 3f213697884ae..a136ca4d8c37f 100644 --- a/compiler/rustc_middle/src/mir/type_visitable.rs +++ b/compiler/rustc_middle/src/mir/type_visitable.rs @@ -9,13 +9,13 @@ impl<'tcx, R: Idx, C: Idx> TypeVisitable<'tcx> for BitMatrix { } } -impl<'tcx> TypeVisitable<'tcx> for mir::Unevaluated<'tcx> { +impl<'tcx> TypeVisitable<'tcx> for mir::UnevaluatedConst<'tcx> { fn visit_with>(&self, visitor: &mut V) -> ControlFlow { visitor.visit_mir_unevaluated(*self) } } -impl<'tcx> TypeSuperVisitable<'tcx> for mir::Unevaluated<'tcx> { +impl<'tcx> TypeSuperVisitable<'tcx> for mir::UnevaluatedConst<'tcx> { fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow { self.substs.visit_with(visitor) } diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 9b112dcdb1b98..b4ae13edf08d2 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -381,7 +381,7 @@ rustc_queries! { } query try_unify_abstract_consts(key: - ty::ParamEnvAnd<'tcx, (ty::Unevaluated<'tcx>, ty::Unevaluated<'tcx> + ty::ParamEnvAnd<'tcx, (ty::UnevaluatedConst<'tcx>, ty::UnevaluatedConst<'tcx> )>) -> bool { desc { |tcx| "trying to unify the generic constants {} and {}", diff --git a/compiler/rustc_middle/src/ty/abstract_const.rs b/compiler/rustc_middle/src/ty/abstract_const.rs index f6f86540dd061..641e53f2a154c 100644 --- a/compiler/rustc_middle/src/ty/abstract_const.rs +++ b/compiler/rustc_middle/src/ty/abstract_const.rs @@ -30,7 +30,7 @@ pub struct AbstractConst<'tcx> { impl<'tcx> AbstractConst<'tcx> { pub fn new( tcx: TyCtxt<'tcx>, - uv: ty::Unevaluated<'tcx>, + uv: ty::UnevaluatedConst<'tcx>, ) -> Result>, ErrorGuaranteed> { let inner = tcx.thir_abstract_const_opt_const_arg(uv.def)?; debug!("AbstractConst::new({:?}) = {:?}", uv, inner); diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs index c2c6076e12b98..315e3794f15e9 100644 --- a/compiler/rustc_middle/src/ty/consts.rs +++ b/compiler/rustc_middle/src/ty/consts.rs @@ -78,7 +78,7 @@ impl<'tcx> Const<'tcx> { match Self::try_eval_lit_or_param(tcx, ty, expr) { Some(v) => v, None => tcx.mk_const(ty::ConstS { - kind: ty::ConstKind::Unevaluated(ty::Unevaluated { + kind: ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def: def.to_global(), substs: InternalSubsts::identity_for_item(tcx, def.did.to_def_id()), }), diff --git a/compiler/rustc_middle/src/ty/consts/kind.rs b/compiler/rustc_middle/src/ty/consts/kind.rs index a04bdb1319ef8..c444ec23563ce 100644 --- a/compiler/rustc_middle/src/ty/consts/kind.rs +++ b/compiler/rustc_middle/src/ty/consts/kind.rs @@ -15,28 +15,31 @@ use super::ScalarInt; /// An unevaluated (potentially generic) constant used in the type-system. #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable, Lift)] #[derive(Hash, HashStable)] -pub struct Unevaluated<'tcx> { +pub struct UnevaluatedConst<'tcx> { pub def: ty::WithOptConstParam, pub substs: SubstsRef<'tcx>, } -impl rustc_errors::IntoDiagnosticArg for Unevaluated<'_> { +impl rustc_errors::IntoDiagnosticArg for UnevaluatedConst<'_> { fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> { format!("{:?}", self).into_diagnostic_arg() } } -impl<'tcx> Unevaluated<'tcx> { +impl<'tcx> UnevaluatedConst<'tcx> { #[inline] - pub fn expand(self) -> mir::Unevaluated<'tcx> { - mir::Unevaluated { def: self.def, substs: self.substs, promoted: None } + pub fn expand(self) -> mir::UnevaluatedConst<'tcx> { + mir::UnevaluatedConst { def: self.def, substs: self.substs, promoted: None } } } -impl<'tcx> Unevaluated<'tcx> { +impl<'tcx> UnevaluatedConst<'tcx> { #[inline] - pub fn new(def: ty::WithOptConstParam, substs: SubstsRef<'tcx>) -> Unevaluated<'tcx> { - Unevaluated { def, substs } + pub fn new( + def: ty::WithOptConstParam, + substs: SubstsRef<'tcx>, + ) -> UnevaluatedConst<'tcx> { + UnevaluatedConst { def, substs } } } @@ -58,7 +61,7 @@ pub enum ConstKind<'tcx> { /// Used in the HIR by using `Unevaluated` everywhere and later normalizing to one of the other /// variants when the code is monomorphic enough for that. - Unevaluated(Unevaluated<'tcx>), + Unevaluated(UnevaluatedConst<'tcx>), /// Used to hold computed value. Value(ty::ValTree<'tcx>), @@ -193,7 +196,7 @@ impl<'tcx> ConstKind<'tcx> { // FIXME(eddyb, skinny121) pass `InferCtxt` into here when it's available, so that // we can call `infcx.const_eval_resolve` which handles inference variables. let param_env_and = if param_env_and.needs_infer() { - tcx.param_env(unevaluated.def.did).and(ty::Unevaluated { + tcx.param_env(unevaluated.def.did).and(ty::UnevaluatedConst { def: unevaluated.def, substs: InternalSubsts::identity_for_item(tcx, unevaluated.def.did), }) diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs index 2c2acfa0697b7..a6d0678e99d6d 100644 --- a/compiler/rustc_middle/src/ty/flags.rs +++ b/compiler/rustc_middle/src/ty/flags.rs @@ -34,7 +34,7 @@ impl FlagComputation { result.flags } - pub fn for_unevaluated_const(uv: ty::Unevaluated<'_>) -> TypeFlags { + pub fn for_unevaluated_const(uv: ty::UnevaluatedConst<'_>) -> TypeFlags { let mut result = FlagComputation::new(); result.add_unevaluated_const(uv); result.flags @@ -313,7 +313,7 @@ impl FlagComputation { } } - fn add_unevaluated_const(&mut self, ct: ty::Unevaluated<'_>) { + fn add_unevaluated_const(&mut self, ct: ty::UnevaluatedConst<'_>) { self.add_substs(ct.substs); self.add_flags(TypeFlags::HAS_CT_PROJECTION); } diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs index b921ae829e550..e4234442faef5 100644 --- a/compiler/rustc_middle/src/ty/fold.rs +++ b/compiler/rustc_middle/src/ty/fold.rs @@ -128,11 +128,17 @@ pub trait TypeFolder<'tcx>: FallibleTypeFolder<'tcx, Error = !> { c.super_fold_with(self) } - fn fold_ty_unevaluated(&mut self, uv: ty::Unevaluated<'tcx>) -> ty::Unevaluated<'tcx> { + fn fold_ty_unevaluated( + &mut self, + uv: ty::UnevaluatedConst<'tcx>, + ) -> ty::UnevaluatedConst<'tcx> { uv.super_fold_with(self) } - fn fold_mir_unevaluated(&mut self, uv: mir::Unevaluated<'tcx>) -> mir::Unevaluated<'tcx> { + fn fold_mir_unevaluated( + &mut self, + uv: mir::UnevaluatedConst<'tcx>, + ) -> mir::UnevaluatedConst<'tcx> { uv.super_fold_with(self) } @@ -178,15 +184,15 @@ pub trait FallibleTypeFolder<'tcx>: Sized { fn try_fold_ty_unevaluated( &mut self, - c: ty::Unevaluated<'tcx>, - ) -> Result, Self::Error> { + c: ty::UnevaluatedConst<'tcx>, + ) -> Result, Self::Error> { c.try_super_fold_with(self) } fn try_fold_mir_unevaluated( &mut self, - c: mir::Unevaluated<'tcx>, - ) -> Result, Self::Error> { + c: mir::UnevaluatedConst<'tcx>, + ) -> Result, Self::Error> { c.try_super_fold_with(self) } @@ -238,15 +244,15 @@ where fn try_fold_ty_unevaluated( &mut self, - c: ty::Unevaluated<'tcx>, - ) -> Result, !> { + c: ty::UnevaluatedConst<'tcx>, + ) -> Result, !> { Ok(self.fold_ty_unevaluated(c)) } fn try_fold_mir_unevaluated( &mut self, - c: mir::Unevaluated<'tcx>, - ) -> Result, !> { + c: mir::UnevaluatedConst<'tcx>, + ) -> Result, !> { Ok(self.fold_mir_unevaluated(c)) } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 6cc73f2561fa7..63dd213a0854f 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -73,7 +73,7 @@ pub use self::closure::{ CAPTURE_STRUCT_LOCAL, }; pub use self::consts::{ - Const, ConstInt, ConstKind, ConstS, InferConst, ScalarInt, Unevaluated, ValTree, + Const, ConstInt, ConstKind, ConstS, InferConst, ScalarInt, UnevaluatedConst, ValTree, }; pub use self::context::{ tls, CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, @@ -682,7 +682,7 @@ pub enum PredicateKind<'tcx> { Coerce(CoercePredicate<'tcx>), /// Constant initializer must evaluate successfully. - ConstEvaluatable(ty::Unevaluated<'tcx>), + ConstEvaluatable(ty::UnevaluatedConst<'tcx>), /// Constants must be equal. The first component is the const that is expected. ConstEquate(Const<'tcx>, Const<'tcx>), diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 6318fe679df38..b76e899980800 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -1201,7 +1201,7 @@ pub trait PrettyPrinter<'tcx>: } match ct.kind() { - ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs }) => { + ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, substs }) => { match self.tcx().def_kind(def.did) { DefKind::Static(..) | DefKind::Const | DefKind::AssocConst => { p!(print_value_path(def.did, substs)) diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs index a56010146c09e..cdb618e030afe 100644 --- a/compiler/rustc_middle/src/ty/relate.rs +++ b/compiler/rustc_middle/src/ty/relate.rs @@ -629,7 +629,7 @@ pub fn super_relate_consts<'tcx, R: TypeRelation<'tcx>>( bu.substs, )?; return Ok(tcx.mk_const(ty::ConstS { - kind: ty::ConstKind::Unevaluated(ty::Unevaluated { def: au.def, substs }), + kind: ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def: au.def, substs }), ty: a.ty(), })); } diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index 9cabce5f82cc0..3b42f4b51fc49 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -829,28 +829,28 @@ impl<'tcx> TypeVisitable<'tcx> for InferConst<'tcx> { } } -impl<'tcx> TypeFoldable<'tcx> for ty::Unevaluated<'tcx> { +impl<'tcx> TypeFoldable<'tcx> for ty::UnevaluatedConst<'tcx> { fn try_fold_with>(self, folder: &mut F) -> Result { folder.try_fold_ty_unevaluated(self) } } -impl<'tcx> TypeVisitable<'tcx> for ty::Unevaluated<'tcx> { +impl<'tcx> TypeVisitable<'tcx> for ty::UnevaluatedConst<'tcx> { fn visit_with>(&self, visitor: &mut V) -> ControlFlow { visitor.visit_ty_unevaluated(*self) } } -impl<'tcx> TypeSuperFoldable<'tcx> for ty::Unevaluated<'tcx> { +impl<'tcx> TypeSuperFoldable<'tcx> for ty::UnevaluatedConst<'tcx> { fn try_super_fold_with>( self, folder: &mut F, ) -> Result { - Ok(ty::Unevaluated { def: self.def, substs: self.substs.try_fold_with(folder)? }) + Ok(ty::UnevaluatedConst { def: self.def, substs: self.substs.try_fold_with(folder)? }) } } -impl<'tcx> TypeSuperVisitable<'tcx> for ty::Unevaluated<'tcx> { +impl<'tcx> TypeSuperVisitable<'tcx> for ty::UnevaluatedConst<'tcx> { fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow { self.substs.visit_with(visitor) } diff --git a/compiler/rustc_middle/src/ty/visit.rs b/compiler/rustc_middle/src/ty/visit.rs index 7b913de83ac26..9c3b6a794e19a 100644 --- a/compiler/rustc_middle/src/ty/visit.rs +++ b/compiler/rustc_middle/src/ty/visit.rs @@ -199,11 +199,17 @@ pub trait TypeVisitor<'tcx>: Sized { c.super_visit_with(self) } - fn visit_ty_unevaluated(&mut self, uv: ty::Unevaluated<'tcx>) -> ControlFlow { + fn visit_ty_unevaluated( + &mut self, + uv: ty::UnevaluatedConst<'tcx>, + ) -> ControlFlow { uv.super_visit_with(self) } - fn visit_mir_unevaluated(&mut self, uv: mir::Unevaluated<'tcx>) -> ControlFlow { + fn visit_mir_unevaluated( + &mut self, + uv: mir::UnevaluatedConst<'tcx>, + ) -> ControlFlow { uv.super_visit_with(self) } @@ -601,7 +607,10 @@ impl<'tcx> TypeVisitor<'tcx> for HasTypeFlagsVisitor { #[inline] #[instrument(level = "trace", ret)] - fn visit_ty_unevaluated(&mut self, uv: ty::Unevaluated<'tcx>) -> ControlFlow { + fn visit_ty_unevaluated( + &mut self, + uv: ty::UnevaluatedConst<'tcx>, + ) -> ControlFlow { let flags = FlagComputation::for_unevaluated_const(uv); trace!(r.flags=?flags); if flags.intersects(self.flags) { @@ -611,7 +620,10 @@ impl<'tcx> TypeVisitor<'tcx> for HasTypeFlagsVisitor { } } - fn visit_mir_unevaluated(&mut self, uv: mir::Unevaluated<'tcx>) -> ControlFlow { + fn visit_mir_unevaluated( + &mut self, + uv: mir::UnevaluatedConst<'tcx>, + ) -> ControlFlow { let flags = FlagComputation::for_unevaluated_const(uv.shrink()); trace!(r.flags=?flags); if flags.intersects(self.flags) { diff --git a/compiler/rustc_mir_build/src/build/expr/as_constant.rs b/compiler/rustc_mir_build/src/build/expr/as_constant.rs index 00fbdb42435be..37dc1ad9f0d4e 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_constant.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_constant.rs @@ -67,7 +67,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { }) }); - let uneval = mir::Unevaluated::new(ty::WithOptConstParam::unknown(def_id), substs); + let uneval = + mir::UnevaluatedConst::new(ty::WithOptConstParam::unknown(def_id), substs); let literal = ConstantKind::Unevaluated(uneval, ty); Constant { user_ty, span, literal } @@ -80,7 +81,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { Constant { user_ty: None, span, literal } } ExprKind::ConstBlock { did: def_id, substs } => { - let uneval = mir::Unevaluated::new(ty::WithOptConstParam::unknown(def_id), substs); + let uneval = + mir::UnevaluatedConst::new(ty::WithOptConstParam::unknown(def_id), substs); let literal = ConstantKind::Unevaluated(uneval, ty); Constant { user_ty: None, span, literal } diff --git a/compiler/rustc_mir_transform/src/const_prop_lint.rs b/compiler/rustc_mir_transform/src/const_prop_lint.rs index 351c86b5d63d5..973f55437eeb3 100644 --- a/compiler/rustc_mir_transform/src/const_prop_lint.rs +++ b/compiler/rustc_mir_transform/src/const_prop_lint.rs @@ -301,7 +301,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { let lint_only = match c.literal { ConstantKind::Ty(ct) => ct.needs_subst(), ConstantKind::Unevaluated( - mir::Unevaluated { def: _, substs: _, promoted: Some(_) }, + mir::UnevaluatedConst { def: _, substs: _, promoted: Some(_) }, _, ) => { // Promoteds must lint and not error as the user didn't ask for them diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index b60bd3cea233f..852557ba7969f 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -605,7 +605,7 @@ impl<'tcx> Inliner<'tcx> { caller_body.required_consts.extend( callee_body.required_consts.iter().copied().filter(|&ct| match ct.literal { ConstantKind::Ty(_) => { - bug!("should never encounter ty::Unevaluated in `required_consts`") + bug!("should never encounter ty::UnevaluatedConst in `required_consts`") } ConstantKind::Val(..) | ConstantKind::Unevaluated(..) => true, }), diff --git a/compiler/rustc_monomorphize/src/polymorphize.rs b/compiler/rustc_monomorphize/src/polymorphize.rs index a054bc6746295..b7e3ca571e10b 100644 --- a/compiler/rustc_monomorphize/src/polymorphize.rs +++ b/compiler/rustc_monomorphize/src/polymorphize.rs @@ -300,7 +300,7 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> { self.unused_parameters.clear(param.index); ControlFlow::CONTINUE } - ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs }) + ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, substs }) if matches!(self.tcx.def_kind(def.did), DefKind::AnonConst) => { self.visit_child_body(def.did, substs); @@ -317,7 +317,7 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> { match constant { ConstantKind::Ty(ct) => ct.visit_with(self), - ConstantKind::Unevaluated(mir::Unevaluated { def, substs: _, promoted: Some(p) }, _) + ConstantKind::Unevaluated(mir::UnevaluatedConst { def, substs: _, promoted: Some(p) }, _) // Avoid considering `T` unused when constants are of the form: // `>::foo::promoted[p]` if self.def_id == def.did && !self.tcx.generics_of(def.did).has_self => diff --git a/compiler/rustc_query_impl/src/keys.rs b/compiler/rustc_query_impl/src/keys.rs index 046b3f405e911..f1c2d03b9be3f 100644 --- a/compiler/rustc_query_impl/src/keys.rs +++ b/compiler/rustc_query_impl/src/keys.rs @@ -276,7 +276,7 @@ impl<'tcx> Key for (DefId, SubstsRef<'tcx>) { } } -impl<'tcx> Key for (ty::Unevaluated<'tcx>, ty::Unevaluated<'tcx>) { +impl<'tcx> Key for (ty::UnevaluatedConst<'tcx>, ty::UnevaluatedConst<'tcx>) { #[inline(always)] fn query_crate_is_local(&self) -> bool { (self.0).def.did.krate == LOCAL_CRATE diff --git a/compiler/rustc_trait_selection/src/errors.rs b/compiler/rustc_trait_selection/src/errors.rs index 5e1b80eae393a..617934685949b 100644 --- a/compiler/rustc_trait_selection/src/errors.rs +++ b/compiler/rustc_trait_selection/src/errors.rs @@ -1,6 +1,6 @@ use rustc_errors::{fluent, ErrorGuaranteed, Handler, IntoDiagnostic}; use rustc_macros::Diagnostic; -use rustc_middle::ty::{PolyTraitRef, Ty, Unevaluated}; +use rustc_middle::ty::{self, PolyTraitRef, Ty}; use rustc_session::Limit; use rustc_span::{Span, Symbol}; @@ -18,7 +18,7 @@ pub struct DumpVTableEntries<'a> { pub struct UnableToConstructConstantValue<'a> { #[primary_span] pub span: Span, - pub unevaluated: Unevaluated<'a>, + pub unevaluated: ty::UnevaluatedConst<'a>, } #[derive(Diagnostic)] diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs index 37a0278f0b15a..dc585fca34f8c 100644 --- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs +++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs @@ -138,7 +138,7 @@ impl<'tcx> ConstUnifyCtxt<'tcx> { #[instrument(skip(tcx), level = "debug")] pub fn try_unify_abstract_consts<'tcx>( tcx: TyCtxt<'tcx>, - (a, b): (ty::Unevaluated<'tcx>, ty::Unevaluated<'tcx>), + (a, b): (ty::UnevaluatedConst<'tcx>, ty::UnevaluatedConst<'tcx>), param_env: ty::ParamEnv<'tcx>, ) -> bool { (|| { @@ -161,7 +161,7 @@ pub fn try_unify_abstract_consts<'tcx>( #[instrument(skip(infcx), level = "debug")] pub fn is_const_evaluatable<'cx, 'tcx>( infcx: &InferCtxt<'cx, 'tcx>, - uv: ty::Unevaluated<'tcx>, + uv: ty::UnevaluatedConst<'tcx>, param_env: ty::ParamEnv<'tcx>, span: Span, ) -> Result<(), NotConstEvaluatable> { diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs index 163c5f2c0899e..2773b61e9ba62 100644 --- a/compiler/rustc_trait_selection/src/traits/object_safety.rs +++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs @@ -840,7 +840,7 @@ fn contains_illegal_self_type_reference<'tcx, T: TypeVisitable<'tcx>>( fn visit_ty_unevaluated( &mut self, - uv: ty::Unevaluated<'tcx>, + uv: ty::UnevaluatedConst<'tcx>, ) -> ControlFlow { // Constants can only influence object safety if they reference `Self`. // This is only possible for unevaluated constants, so we walk these here. diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 6f41cbeb7af2a..3befd4b6ffbd7 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -2141,7 +2141,7 @@ fn confirm_impl_candidate<'cx, 'tcx>( let identity_substs = crate::traits::InternalSubsts::identity_for_item(tcx, assoc_ty.item.def_id); let did = ty::WithOptConstParam::unknown(assoc_ty.item.def_id); - let kind = ty::ConstKind::Unevaluated(ty::Unevaluated::new(did, identity_substs)); + let kind = ty::ConstKind::Unevaluated(ty::UnevaluatedConst::new(did, identity_substs)); ty.map_bound(|ty| tcx.mk_const(ty::ConstS { ty, kind }).into()) } else { ty.map_bound(|ty| ty.into()) diff --git a/compiler/rustc_ty_utils/src/consts.rs b/compiler/rustc_ty_utils/src/consts.rs index 44c4fc48d3f0f..493ef33511355 100644 --- a/compiler/rustc_ty_utils/src/consts.rs +++ b/compiler/rustc_ty_utils/src/consts.rs @@ -258,7 +258,8 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> { self.nodes.push(Node::Leaf(ty::Const::from_value(self.tcx, val, node.ty))) } &ExprKind::NamedConst { def_id, substs, user_ty: _ } => { - let uneval = ty::Unevaluated::new(ty::WithOptConstParam::unknown(def_id), substs); + let uneval = + ty::UnevaluatedConst::new(ty::WithOptConstParam::unknown(def_id), substs); let constant = self .tcx diff --git a/compiler/rustc_typeck/src/check/wfcheck.rs b/compiler/rustc_typeck/src/check/wfcheck.rs index fd5df0d9fa1ed..e4124185d153d 100644 --- a/compiler/rustc_typeck/src/check/wfcheck.rs +++ b/compiler/rustc_typeck/src/check/wfcheck.rs @@ -1113,10 +1113,12 @@ fn check_type_defn<'tcx, F>( wfcx.register_obligation(traits::Obligation::new( cause, wfcx.param_env, - ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(ty::Unevaluated::new( - ty::WithOptConstParam::unknown(discr_def_id.to_def_id()), - discr_substs, - ))) + ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable( + ty::UnevaluatedConst::new( + ty::WithOptConstParam::unknown(discr_def_id.to_def_id()), + discr_substs, + ), + )) .to_predicate(tcx), )); } diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index af0b300e22b88..edcd81061f831 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -234,7 +234,7 @@ pub(crate) fn name_from_pat(p: &hir::Pat<'_>) -> Symbol { pub(crate) fn print_const(cx: &DocContext<'_>, n: ty::Const<'_>) -> String { match n.kind() { - ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs: _ }) => { + ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, substs: _ }) => { let s = if let Some(def) = def.as_local() { print_const_expr(cx.tcx, cx.tcx.hir().body_owned_by(def.did)) } else { diff --git a/src/test/mir-opt/issue_99325.main.mir_map.0.mir b/src/test/mir-opt/issue_99325.main.mir_map.0.mir index 8b1ffe1599b4d..35ad0df69c0b4 100644 --- a/src/test/mir-opt/issue_99325.main.mir_map.0.mir +++ b/src/test/mir-opt/issue_99325.main.mir_map.0.mir @@ -2,7 +2,7 @@ | User Type Annotations | 0: user_ty: Canonical { max_universe: U0, variables: [], value: TypeOf(DefId(0:3 ~ issue_99325[8f58]::function_with_bytes), UserSubsts { substs: [Const { ty: &'static [u8; 4], kind: Value(Branch([Leaf(0x41), Leaf(0x41), Leaf(0x41), Leaf(0x41)])) }], user_self_ty: None }) }, span: $DIR/issue-99325.rs:10:16: 10:46, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">} -| 1: user_ty: Canonical { max_universe: U0, variables: [], value: TypeOf(DefId(0:3 ~ issue_99325[8f58]::function_with_bytes), UserSubsts { substs: [Const { ty: &'static [u8; 4], kind: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:8 ~ issue_99325[8f58]::main::{constant#1}), const_param_did: Some(DefId(0:4 ~ issue_99325[8f58]::function_with_bytes::BYTES)) }, substs: [] }) }], user_self_ty: None }) }, span: $DIR/issue-99325.rs:11:16: 11:68, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">} +| 1: user_ty: Canonical { max_universe: U0, variables: [], value: TypeOf(DefId(0:3 ~ issue_99325[8f58]::function_with_bytes), UserSubsts { substs: [Const { ty: &'static [u8; 4], kind: Unevaluated(UnevaluatedConst { def: WithOptConstParam { did: DefId(0:8 ~ issue_99325[8f58]::main::{constant#1}), const_param_did: Some(DefId(0:4 ~ issue_99325[8f58]::function_with_bytes::BYTES)) }, substs: [] }) }], user_self_ty: None }) }, span: $DIR/issue-99325.rs:11:16: 11:68, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">} | fn main() -> () { let mut _0: (); // return place in scope 0 at $DIR/issue-99325.rs:+0:15: +0:15 diff --git a/src/tools/clippy/clippy_lints/src/non_copy_const.rs b/src/tools/clippy/clippy_lints/src/non_copy_const.rs index 85024b0b05c8f..b15884527321c 100644 --- a/src/tools/clippy/clippy_lints/src/non_copy_const.rs +++ b/src/tools/clippy/clippy_lints/src/non_copy_const.rs @@ -195,7 +195,7 @@ fn is_value_unfrozen_expr<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId, def_id: D let result = cx.tcx.const_eval_resolve( cx.param_env, - mir::Unevaluated::new(ty::WithOptConstParam::unknown(def_id), substs), + mir::UnevaluatedConst::new(ty::WithOptConstParam::unknown(def_id), substs), None, ); is_value_unfrozen_raw(cx, result, ty) diff --git a/src/tools/clippy/clippy_utils/src/consts.rs b/src/tools/clippy/clippy_utils/src/consts.rs index ac5bac3714f0e..fa6766f7cfe19 100644 --- a/src/tools/clippy/clippy_utils/src/consts.rs +++ b/src/tools/clippy/clippy_utils/src/consts.rs @@ -424,7 +424,7 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> { .tcx .const_eval_resolve( self.param_env, - mir::Unevaluated::new(ty::WithOptConstParam::unknown(def_id), substs), + mir::UnevaluatedConst::new(ty::WithOptConstParam::unknown(def_id), substs), None, ) .ok() From c057d04b926314803769f7fda31b75fe01e911ec Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Fri, 23 Sep 2022 11:17:52 +0200 Subject: [PATCH 160/586] make remote-test-server cli parsing more consistent --- src/tools/remote-test-server/src/main.rs | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/tools/remote-test-server/src/main.rs b/src/tools/remote-test-server/src/main.rs index cd9d530096496..8164b2b29ee6b 100644 --- a/src/tools/remote-test-server/src/main.rs +++ b/src/tools/remote-test-server/src/main.rs @@ -41,8 +41,8 @@ static TEST: AtomicUsize = AtomicUsize::new(0); #[derive(Copy, Clone)] struct Config { - pub remote: bool, - pub verbose: bool, + remote: bool, + verbose: bool, } impl Config { @@ -56,12 +56,8 @@ impl Config { let args = env::args().skip(1); for argument in args { match &argument[..] { - "remote" => { - config.remote = true; - } - "verbose" | "-v" => { - config.verbose = true; - } + "--remote" => config.remote = true, + "--verbose" | "-v" => config.verbose = true, arg => panic!("unknown argument: {}", arg), } } From 02869e3041cf7c30d8cb71c967931352dea66b80 Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Fri, 23 Sep 2022 14:53:38 +0200 Subject: [PATCH 161/586] replace --remote with the --bind flag in remote-test-server --- src/tools/remote-test-server/src/main.rs | 32 ++++++++++++++++-------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/src/tools/remote-test-server/src/main.rs b/src/tools/remote-test-server/src/main.rs index 8164b2b29ee6b..058cf9a911a9b 100644 --- a/src/tools/remote-test-server/src/main.rs +++ b/src/tools/remote-test-server/src/main.rs @@ -12,6 +12,7 @@ #[cfg(not(windows))] use std::fs::Permissions; +use std::net::SocketAddr; #[cfg(not(windows))] use std::os::unix::prelude::*; @@ -41,26 +42,41 @@ static TEST: AtomicUsize = AtomicUsize::new(0); #[derive(Copy, Clone)] struct Config { - remote: bool, verbose: bool, + bind: SocketAddr, } impl Config { pub fn default() -> Config { - Config { remote: false, verbose: false } + Config { + verbose: false, + bind: if cfg!(target_os = "android") || cfg!(windows) { + ([0, 0, 0, 0], 12345).into() + } else { + ([10, 0, 2, 15], 12345).into() + }, + } } pub fn parse_args() -> Config { let mut config = Config::default(); let args = env::args().skip(1); + let mut next_is_bind = false; for argument in args { match &argument[..] { - "--remote" => config.remote = true, + bind if next_is_bind => { + config.bind = t!(bind.parse()); + next_is_bind = false; + } + "--bind" => next_is_bind = true, "--verbose" | "-v" => config.verbose = true, arg => panic!("unknown argument: {}", arg), } } + if next_is_bind { + panic!("missing value for --bind"); + } config } @@ -77,13 +93,7 @@ fn main() { let config = Config::parse_args(); - let bind_addr = if cfg!(target_os = "android") || cfg!(windows) || config.remote { - "0.0.0.0:12345" - } else { - "10.0.2.15:12345" - }; - - let listener = t!(TcpListener::bind(bind_addr)); + let listener = t!(TcpListener::bind(config.bind)); let (work, tmp): (PathBuf, PathBuf) = if cfg!(target_os = "android") { ("/data/tmp/work".into(), "/data/tmp/work/tmp".into()) } else { @@ -93,7 +103,7 @@ fn main() { tmp_dir.push("tmp"); (work_dir, tmp_dir) }; - println!("listening on {}!", bind_addr); + println!("listening on {}!", config.bind); t!(fs::create_dir_all(&work)); t!(fs::create_dir_all(&tmp)); From db14a527139355a13c61e109884c0b1f31d67c94 Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Fri, 23 Sep 2022 14:54:55 +0200 Subject: [PATCH 162/586] add the --sequential flag to compiletest --- src/tools/remote-test-server/src/main.rs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/tools/remote-test-server/src/main.rs b/src/tools/remote-test-server/src/main.rs index 058cf9a911a9b..0c60d500a80bf 100644 --- a/src/tools/remote-test-server/src/main.rs +++ b/src/tools/remote-test-server/src/main.rs @@ -43,6 +43,7 @@ static TEST: AtomicUsize = AtomicUsize::new(0); #[derive(Copy, Clone)] struct Config { verbose: bool, + sequential: bool, bind: SocketAddr, } @@ -50,6 +51,7 @@ impl Config { pub fn default() -> Config { Config { verbose: false, + sequential: false, bind: if cfg!(target_os = "android") || cfg!(windows) { ([0, 0, 0, 0], 12345).into() } else { @@ -70,6 +72,7 @@ impl Config { next_is_bind = false; } "--bind" => next_is_bind = true, + "--sequential" => config.sequential = true, "--verbose" | "-v" => config.verbose = true, arg => panic!("unknown argument: {}", arg), } @@ -125,7 +128,12 @@ fn main() { let lock = lock.clone(); let work = work.clone(); let tmp = tmp.clone(); - thread::spawn(move || handle_run(socket, &work, &tmp, &lock, config)); + let f = move || handle_run(socket, &work, &tmp, &lock, config); + if config.sequential { + f(); + } else { + thread::spawn(f); + } } else { panic!("unknown command {:?}", buf); } From 53049f7dcd382246fb1f7ad975b81e9a293acccd Mon Sep 17 00:00:00 2001 From: onestacked Date: Fri, 23 Sep 2022 15:39:13 +0200 Subject: [PATCH 163/586] Fixed Doc-Tests --- library/core/src/const_closure.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/library/core/src/const_closure.rs b/library/core/src/const_closure.rs index bd24c10bd0053..536c3eb0022fd 100644 --- a/library/core/src/const_closure.rs +++ b/library/core/src/const_closure.rs @@ -3,8 +3,8 @@ use crate::marker::Destruct; /// Struct representing a closure with owned data. /// /// Example: -/// ```rust -/// use const_closure::ConstFnOnceClosure; +/// ```no_build +/// use crate::const_closure::ConstFnOnceClosure; /// const fn imp(state: i32, (arg,): (i32,)) -> i32 { /// state + arg /// } @@ -51,9 +51,9 @@ where /// Struct representing a closure with mutably borrowed data. /// /// Example: -/// ```rust +/// ```no_build /// #![feature(const_mut_refs)] -/// use const_closure::ConstFnMutClosure; +/// use crate::const_closure::ConstFnMutClosure; /// const fn imp(state: &mut i32, (arg,): (i32,)) -> i32 { /// *state += arg; /// *state @@ -110,8 +110,8 @@ where /// Struct representing a closure with borrowed data. /// /// Example: -/// ```rust -/// use const_closure::ConstFnClosure; +/// ```no_build +/// use crate::const_closure::ConstFnClosure; /// /// const fn imp(state: &i32, (arg,): (i32,)) -> i32 { /// *state + arg From 20638eba8029ba471233ced4f38efade33a6dea7 Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Fri, 23 Sep 2022 15:43:01 +0200 Subject: [PATCH 164/586] add changelog lines for the remote-test-server changes --- src/bootstrap/CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/bootstrap/CHANGELOG.md b/src/bootstrap/CHANGELOG.md index 85afc1f5f6c68..64b74ecc9defd 100644 --- a/src/bootstrap/CHANGELOG.md +++ b/src/bootstrap/CHANGELOG.md @@ -13,6 +13,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - Change the names for `dist` commands to match the component they generate. [#90684](https://github.com/rust-lang/rust/pull/90684) - The `build.fast-submodules` option has been removed. Fast submodule checkouts are enabled unconditionally. Automatic submodule handling can still be disabled with `build.submodules = false`. - Several unsupported `./configure` options have been removed: `optimize`, `parallel-compiler`. These can still be enabled with `--set`, although it isn't recommended. +- `remote-test-server`'s `verbose` argument has been removed in favor of the `--verbose` flag +- `remote-test-server`'s `remote` argument has been removed in favor of the `--bind` flag. Use `--bind 0.0.0.0:12345` to replicate the behavior of the `remote` argument. ### Non-breaking changes From 557b700fbdb059b1ce41b8112258f9f128cc55c0 Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Thu, 5 May 2022 15:39:05 -0400 Subject: [PATCH 165/586] Remove mention of "compiler-rt" from COPYRIGHT file The compiler-rt dependency was removed in 7e6c9f363501c49d3a1f666d85d41891f50890b8 in favor of a vendored dependency on rust-lang/compiler-builtins (dual UIUC and MIT licensed). That vendored dependency was converted to a regular Cargo dependency in 4c21a3bc2afc5933f31f1368f6b3406c5f1bdeb3. --- COPYRIGHT | 81 ------------------------------------------------------- 1 file changed, 81 deletions(-) diff --git a/COPYRIGHT b/COPYRIGHT index dc9abf84b8e5a..e0b6e69f4d58e 100644 --- a/COPYRIGHT +++ b/COPYRIGHT @@ -76,87 +76,6 @@ their own copyright notices and license terms: BSD-compatible licenses. See src/llvm-project/llvm/LICENSE.TXT for details. -* compiler-rt, in src/compiler-rt is dual licensed under - LLVM's license and MIT: - - Copyright (c) 2009-2014 by the contributors listed in - CREDITS.TXT - - All rights reserved. - - Developed by: - - LLVM Team - - University of Illinois at Urbana-Champaign - - http://llvm.org - - Permission is hereby granted, free of charge, to any - person obtaining a copy of this software and associated - documentation files (the "Software"), to deal with the - Software without restriction, including without - limitation the rights to use, copy, modify, merge, - publish, distribute, sublicense, and/or sell copies of - the Software, and to permit persons to whom the Software - is furnished to do so, subject to the following - conditions: - - * Redistributions of source code must retain the - above copyright notice, this list of conditions - and the following disclaimers. - - * Redistributions in binary form must reproduce the - above copyright notice, this list of conditions - and the following disclaimers in the documentation - and/or other materials provided with the - distribution. - - * Neither the names of the LLVM Team, University of - Illinois at Urbana-Champaign, nor the names of its - contributors may be used to endorse or promote - products derived from this Software without - specific prior written permission. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF - ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED - TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A - PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT - SHALL THE CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE - FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT - OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - OTHER DEALINGS WITH THE SOFTWARE. - - ======================================================== - - Copyright (c) 2009-2014 by the contributors listed in - CREDITS.TXT - - Permission is hereby granted, free of charge, to any - person obtaining a copy of this software and associated - documentation files (the "Software"), to deal in the - Software without restriction, including without - limitation the rights to use, copy, modify, merge, - publish, distribute, sublicense, and/or sell copies of - the Software, and to permit persons to whom the Software - is furnished to do so, subject to the following - conditions: - - The above copyright notice and this permission notice - shall be included in all copies or substantial portions - of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF - ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED - TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A - PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT - SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR - IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - DEALINGS IN THE SOFTWARE. - * Portions of the FFI code for interacting with the native ABI is derived from the Clay programming language, which carries the following license. From 4e790a8732ccb311bb1bcc5b702a88d1166294d2 Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Thu, 5 May 2022 15:47:17 -0400 Subject: [PATCH 166/586] Remove mentions of libbacktrace from COPYRIGHT Use of libbacktrace was removed in 06d565c967bfb7c6ff52a991bbe47b4a2a25de3e where we switched to using the gimili library instead. Note: the backtrace submodule located at library/backtrace points to backtrace-rs which removed support for using libbacktrace in https://github.com/rust-lang/backtrace-rs/pull/423. --- COPYRIGHT | 38 -------------------------------------- 1 file changed, 38 deletions(-) diff --git a/COPYRIGHT b/COPYRIGHT index e0b6e69f4d58e..e6ab805c9d6fb 100644 --- a/COPYRIGHT +++ b/COPYRIGHT @@ -110,41 +110,3 @@ their own copyright notices and license terms: NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -* libbacktrace, under src/libbacktrace: - - Copyright (C) 2012-2014 Free Software Foundation, Inc. - Written by Ian Lance Taylor, Google. - - Redistribution and use in source and binary forms, with - or without modification, are permitted provided that the - following conditions are met: - - (1) Redistributions of source code must retain the - above copyright notice, this list of conditions and - the following disclaimer. - - (2) Redistributions in binary form must reproduce - the above copyright notice, this list of conditions - and the following disclaimer in the documentation - and/or other materials provided with the - distribution. - - (3) The name of the author may not be used to - endorse or promote products derived from this - software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND - ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, - INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE - USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - OF SUCH DAMAGE. */ From 99adba67025c46e59639ef4dfdf8e137635c8916 Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Thu, 5 May 2022 16:55:57 -0400 Subject: [PATCH 167/586] Update the LLVM license mentioned in COPYRIGHT LLVM has relicensed their codebase. Remove the old UIUC license text from the LLVM section and include the licensing text used by LLVM itself. --- COPYRIGHT | 313 ++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 271 insertions(+), 42 deletions(-) diff --git a/COPYRIGHT b/COPYRIGHT index e6ab805c9d6fb..11335879bd4a7 100644 --- a/COPYRIGHT +++ b/COPYRIGHT @@ -23,10 +23,252 @@ The Rust Project includes packages written by third parties. The following third party packages are included, and carry their own copyright notices and license terms: -* LLVM. Code for this package is found in src/llvm-project. +* LLVM, located in src/llvm-project, is licensed under the following + terms. - Copyright (c) 2003-2013 University of Illinois at - Urbana-Champaign. All rights reserved. + ============================================================================== + The LLVM Project is under the Apache License v2.0 with LLVM Exceptions: + ============================================================================== + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + + ---- LLVM Exceptions to the Apache 2.0 License ---- + + As an exception, if, as a result of your compiling your source code, portions + of this Software are embedded into an Object form of such source code, you + may redistribute such embedded portions in such Object form without complying + with the conditions of Sections 4(a), 4(b) and 4(d) of the License. + + In addition, if you combine or link compiled forms of this Software with + software that is licensed under the GPLv2 ("Combined Software") and if a + court of competent jurisdiction determines that the patent provision (Section + 3), the indemnity provision (Section 9) or other Section of the License + conflicts with the conditions of the GPLv2, you may retroactively and + prospectively choose to deem waived or otherwise exclude such Section(s) of + the License, but only in their entirety and only with respect to the Combined + Software. + + ============================================================================== + Software from third parties included in the LLVM Project: + ============================================================================== + The LLVM Project contains third party software which is under different license + terms. All such code will be identified clearly using at least one of two + mechanisms: + 1) It will be in a separate directory tree with its own `LICENSE.txt` or + `LICENSE` file at the top containing the specific license and restrictions + which apply to that software, or + 2) It will contain specific license and restriction terms at the top of every + file. + + ============================================================================== + Legacy LLVM License (https://llvm.org/docs/DeveloperPolicy.html#legacy): + ============================================================================== + University of Illinois/NCSA + Open Source License + + Copyright (c) 2003-2019 University of Illinois at Urbana-Champaign. + All rights reserved. Developed by: @@ -36,45 +278,32 @@ their own copyright notices and license terms: http://llvm.org - Permission is hereby granted, free of charge, to any - person obtaining a copy of this software and associated - documentation files (the "Software"), to deal with the - Software without restriction, including without - limitation the rights to use, copy, modify, merge, - publish, distribute, sublicense, and/or sell copies of - the Software, and to permit persons to whom the Software - is furnished to do so, subject to the following - conditions: - - * Redistributions of source code must retain the - above copyright notice, this list of conditions - and the following disclaimers. - - * Redistributions in binary form must reproduce the - above copyright notice, this list of conditions - and the following disclaimers in the documentation - and/or other materials provided with the - distribution. - - * Neither the names of the LLVM Team, University of - Illinois at Urbana-Champaign, nor the names of its - contributors may be used to endorse or promote - products derived from this Software without - specific prior written permission. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF - ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED - TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A - PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT - SHALL THE CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE - FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT - OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - OTHER DEALINGS WITH THE SOFTWARE. - -* Additional libraries included in LLVM carry separate - BSD-compatible licenses. See src/llvm-project/llvm/LICENSE.TXT - for details. + Permission is hereby granted, free of charge, to any person obtaining a copy of + this software and associated documentation files (the "Software"), to deal with + the Software without restriction, including without limitation the rights to + use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is furnished to do + so, subject to the following conditions: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimers. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimers in the + documentation and/or other materials provided with the distribution. + + * Neither the names of the LLVM Team, University of Illinois at + Urbana-Champaign, nor the names of its contributors may be used to + endorse or promote products derived from this Software without specific + prior written permission. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE + SOFTWARE. * Portions of the FFI code for interacting with the native ABI is derived from the Clay programming language, which carries From ee8e0bda342bb0b873aeafbd0f8722deb09339b3 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Thu, 22 Sep 2022 10:25:54 -0700 Subject: [PATCH 168/586] rustdoc: CSS prevent sidebar width change jank This commit makes the `width` and `min-width` of the sidebar the same. They originally were when cad0fce2053d52b7ba04c458f4c124c8b5c6141e added the `min-width` rule, but 6a5f8b1aef1417d7dc85b5d0a229d2db1930eb7c changed the width without changing the `min-width`, causing it to sometimes oscilate between 200 and 250 pixels depending on the main content. --- src/librustdoc/html/static/css/rustdoc.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index 3461d083c604d..b7a52cb0c33b8 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -411,7 +411,7 @@ img { .sidebar { font-size: 0.875rem; - width: 250px; + width: 200px; min-width: 200px; overflow-y: scroll; position: sticky; From e3cb0a84c2543b7745cf58f0ed757061a9d2c0e5 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Thu, 22 Sep 2022 10:42:15 -0700 Subject: [PATCH 169/586] rustdoc: add regression test for sidebar width jank --- src/test/rustdoc-gui/sidebar.goml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/test/rustdoc-gui/sidebar.goml b/src/test/rustdoc-gui/sidebar.goml index 32fe3334f3644..ea7bcc669945a 100644 --- a/src/test/rustdoc-gui/sidebar.goml +++ b/src/test/rustdoc-gui/sidebar.goml @@ -1,5 +1,6 @@ // Checks multiple things on the sidebar display (width of its elements, colors, etc). goto: file://|DOC_PATH|/test_docs/index.html +assert-property: (".sidebar", {"clientWidth": "200"}) show-text: true local-storage: {"rustdoc-theme": "light"} // We reload the page so the local storage settings are being used. @@ -39,11 +40,13 @@ assert-property: ("html", {"scrollTop": "0"}) // We now go back to the crate page to click on the "lib2" crate link. goto: file://|DOC_PATH|/test_docs/index.html +assert-property: (".sidebar", {"clientWidth": "200"}) assert-css: (".sidebar-elems .crate > ul > li:first-child > a", {"color": "rgb(53, 109, 164)"}) click: ".sidebar-elems .crate > ul > li:first-child > a" // PAGE: lib2/index.html goto: file://|DOC_PATH|/lib2/index.html +assert-property: (".sidebar", {"clientWidth": "200"}) assert-text: (".sidebar > .location", "Crate lib2") // We check that we have the crates list and that the "current" on is now "lib2". assert-text: (".sidebar-elems .crate > ul > li > a.current", "lib2") @@ -65,11 +68,13 @@ assert-text: (".sidebar .sidebar-elems .location", "In lib2") assert-false: ".sidebar-elems > .crate" goto: ./module/index.html +assert-property: (".sidebar", {"clientWidth": "200"}) assert-text: (".sidebar > .location", "Module module") // We check that we don't have the crate list. assert-false: ".sidebar-elems > .crate" goto: ./sub_module/sub_sub_module/index.html +assert-property: (".sidebar", {"clientWidth": "200"}) assert-text: (".sidebar > .location", "Module sub_sub_module") // We check that we don't have the crate list. assert-false: ".sidebar-elems .crate" @@ -78,11 +83,21 @@ assert-text: ("#functions + .item-table .item-left > a", "foo") // Links to trait implementations in the sidebar should not wrap even if they are long. goto: file://|DOC_PATH|/lib2/struct.HasALongTraitWithParams.html +assert-property: (".sidebar", {"clientWidth": "200"}) assert-property: (".sidebar-elems section .block li > a", {"offsetHeight": 29}) // Test that clicking on of the "In " headings in the sidebar links to the // appropriate anchor in index.html. goto: file://|DOC_PATH|/test_docs/struct.Foo.html +assert-property: (".sidebar", {"clientWidth": "200"}) click: ".block.mod h3 a" // PAGE: index.html assert-css: ("#modules", {"background-color": "rgb(253, 255, 211)"}) + +// Finally, assert that the `[+]/[−]` toggle doesn't affect sidebar width. +click: "#toggle-all-docs" +assert-text: ("#toggle-all-docs", "[+]") +assert-property: (".sidebar", {"clientWidth": "200"}) +click: "#toggle-all-docs" +assert-text: ("#toggle-all-docs", "[−]") +assert-property: (".sidebar", {"clientWidth": "200"}) \ No newline at end of file From 449326aaad21ad6e0d104d506d6d1e197e6b9719 Mon Sep 17 00:00:00 2001 From: onestacked Date: Fri, 23 Sep 2022 17:53:59 +0200 Subject: [PATCH 170/586] Added const Default impls for Arrays and Tuples. --- library/core/src/array/mod.rs | 3 ++- library/core/src/tuple.rs | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs index 165b9d24d934b..36e89a95fd212 100644 --- a/library/core/src/array/mod.rs +++ b/library/core/src/array/mod.rs @@ -434,7 +434,8 @@ impl SpecArrayClone for T { macro_rules! array_impl_default { {$n:expr, $t:ident $($ts:ident)*} => { #[stable(since = "1.4.0", feature = "array_default")] - impl Default for [T; $n] where T: Default { + #[rustc_const_unstable(feature = "const_default_impls", issue = "87864")] + impl const Default for [T; $n] where T: ~const Default { fn default() -> [T; $n] { [$t::default(), $($ts::default()),*] } diff --git a/library/core/src/tuple.rs b/library/core/src/tuple.rs index aa8a2425bf416..fc91fe468cc29 100644 --- a/library/core/src/tuple.rs +++ b/library/core/src/tuple.rs @@ -93,7 +93,8 @@ macro_rules! tuple_impls { maybe_tuple_doc! { $($T)+ @ #[stable(feature = "rust1", since = "1.0.0")] - impl<$($T:Default),+> Default for ($($T,)+) { + #[rustc_const_unstable(feature = "const_default_impls", issue = "87864")] + impl<$($T: ~const Default),+> const Default for ($($T,)+) { #[inline] fn default() -> ($($T,)+) { ($({ let x: $T = Default::default(); x},)+) From a4046e93e2d22af856e16aaa0b281785d4df8c1c Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 23 Sep 2022 18:12:23 +0200 Subject: [PATCH 171/586] Update browser-ui-test version to 0.11.0 --- .../docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version b/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version index 2774f8587f40e..142464bf22b42 100644 --- a/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version +++ b/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version @@ -1 +1 @@ -0.10.0 \ No newline at end of file +0.11.0 \ No newline at end of file From d30cb5b6633bef645e076fedcc77c5e1d55349b6 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 23 Sep 2022 18:12:37 +0200 Subject: [PATCH 172/586] Improve GUI tests by using variables --- src/test/rustdoc-gui/check-stab-in-docblock.goml | 12 +++++++++--- src/test/rustdoc-gui/type-declation-overflow.goml | 4 ++-- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/test/rustdoc-gui/check-stab-in-docblock.goml b/src/test/rustdoc-gui/check-stab-in-docblock.goml index 7f965ada594d8..afe25195100c5 100644 --- a/src/test/rustdoc-gui/check-stab-in-docblock.goml +++ b/src/test/rustdoc-gui/check-stab-in-docblock.goml @@ -7,15 +7,21 @@ size: (786, 600) // Confirms that there 3 paragraphs. assert-count: (".top-doc .docblock p", 3) // Checking that there is no scrollable content. +store-property: (clientHeight, ".top-doc .docblock p:nth-of-type(1)", "clientHeight") +store-property: (clientWidth, ".top-doc .docblock p:nth-of-type(1)", "clientWidth") assert-property: ( ".top-doc .docblock p:nth-of-type(1)", - {"scrollHeight": "120", "clientHeight": "120", "scrollWidth": "502", "clientWidth": "502"}, + {"scrollHeight": |clientHeight|, "scrollWidth": |clientWidth|}, ) +store-property: (clientHeight, ".top-doc .docblock p:nth-of-type(2)", "clientHeight") +store-property: (clientWidth, ".top-doc .docblock p:nth-of-type(2)", "clientWidth") assert-property: ( ".top-doc .docblock p:nth-of-type(2)", - {"scrollHeight": "48", "clientHeight": "48", "scrollWidth": "502", "clientWidth": "502"}, + {"scrollHeight": |clientHeight|, "scrollWidth": |clientWidth|}, ) +store-property: (clientHeight, ".top-doc .docblock p:nth-of-type(3)", "clientHeight") +store-property: (clientWidth, ".top-doc .docblock p:nth-of-type(3)", "clientWidth") assert-property: ( ".top-doc .docblock p:nth-of-type(3)", - {"scrollHeight": "48", "clientHeight": "48", "scrollWidth": "502", "clientWidth": "502"}, + {"scrollHeight": |clientHeight|, "scrollWidth": |clientWidth|}, ) diff --git a/src/test/rustdoc-gui/type-declation-overflow.goml b/src/test/rustdoc-gui/type-declation-overflow.goml index 9a46908f9333b..e54ff8ddabe23 100644 --- a/src/test/rustdoc-gui/type-declation-overflow.goml +++ b/src/test/rustdoc-gui/type-declation-overflow.goml @@ -32,6 +32,6 @@ assert-property: (".item-decl pre", {"scrollWidth": "950"}) size: (600, 600) goto: file://|DOC_PATH|/lib2/too_long/struct.SuperIncrediblyLongLongLongLongLongLongLongGigaGigaGigaMegaLongLongLongStructName.html // It shouldn't have an overflow in the topbar either. -assert-property: (".mobile-topbar .location", {"scrollWidth": "500"}) -assert-property: (".mobile-topbar .location", {"clientWidth": "500"}) +store-property: (scrollWidth, ".mobile-topbar .location", "scrollWidth") +assert-property: (".mobile-topbar .location", {"clientWidth": |scrollWidth|}) assert-css: (".mobile-topbar .location", {"overflow-x": "hidden"}) From cd481542df325ad8fd7db5f5c58a72969b1497b3 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Thu, 22 Sep 2022 11:51:48 -0700 Subject: [PATCH 173/586] rustdoc: fix GUI tests to deal with slightly changed width --- src/test/rustdoc-gui/code-blocks-overflow.goml | 2 +- src/test/rustdoc-gui/docblock-table-overflow.goml | 4 ++-- src/test/rustdoc-gui/item-info-overflow.goml | 4 ++-- src/test/rustdoc-gui/item-info.goml | 4 ++-- src/test/rustdoc-gui/notable-trait.goml | 4 ++-- src/test/rustdoc-gui/search-result-display.goml | 2 +- src/test/rustdoc-gui/type-declation-overflow.goml | 4 ++-- 7 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/test/rustdoc-gui/code-blocks-overflow.goml b/src/test/rustdoc-gui/code-blocks-overflow.goml index f93f3f0aefc51..ee4dad444e932 100644 --- a/src/test/rustdoc-gui/code-blocks-overflow.goml +++ b/src/test/rustdoc-gui/code-blocks-overflow.goml @@ -5,4 +5,4 @@ size: (1080, 600) assert-count: (".docblock > .example-wrap", 2) assert: ".docblock > .example-wrap > .language-txt" assert: ".docblock > .example-wrap > .rust-example-rendered" -assert-css: (".docblock > .example-wrap > pre", {"width": "785.25px", "overflow-x": "auto"}, ALL) +assert-css: (".docblock > .example-wrap > pre", {"width": "796px", "overflow-x": "auto"}, ALL) diff --git a/src/test/rustdoc-gui/docblock-table-overflow.goml b/src/test/rustdoc-gui/docblock-table-overflow.goml index 7f97cf220cc55..ef0d37c902e09 100644 --- a/src/test/rustdoc-gui/docblock-table-overflow.goml +++ b/src/test/rustdoc-gui/docblock-table-overflow.goml @@ -4,7 +4,7 @@ goto: file://|DOC_PATH|/lib2/long_table/struct.Foo.html size: (1100, 800) // Logically, the ".docblock" and the "

" should have the same scroll width. compare-elements-property: (".top-doc .docblock", ".top-doc .docblock > p", ["scrollWidth"]) -assert-property: (".top-doc .docblock", {"scrollWidth": "801"}) +assert-property: (".top-doc .docblock", {"scrollWidth": "816"}) // However, since there is overflow in the , its scroll width is bigger. assert-property: (".top-doc .docblock table", {"scrollWidth": "1572"}) @@ -16,6 +16,6 @@ compare-elements-property: ( "#implementations-list > details .docblock > p", ["scrollWidth"], ) -assert-property: ("#implementations-list > details .docblock", {"scrollWidth": "801"}) +assert-property: ("#implementations-list > details .docblock", {"scrollWidth": "816"}) // However, since there is overflow in the
, its scroll width is bigger. assert-property: ("#implementations-list > details .docblock table", {"scrollWidth": "1572"}) diff --git a/src/test/rustdoc-gui/item-info-overflow.goml b/src/test/rustdoc-gui/item-info-overflow.goml index 17478da4fea29..bc3addd33dd38 100644 --- a/src/test/rustdoc-gui/item-info-overflow.goml +++ b/src/test/rustdoc-gui/item-info-overflow.goml @@ -4,7 +4,7 @@ goto: file://|DOC_PATH|/lib2/struct.LongItemInfo.html size: (1200, 870) // Logically, the "item-decl" and the "item-info" should have the same scroll width. compare-elements-property: (".item-decl", ".item-info", ["scrollWidth"]) -assert-property: (".item-info", {"scrollWidth": "890"}) +assert-property: (".item-info", {"scrollWidth": "940"}) // Just to be sure we're comparing the correct "item-info": assert-text: ( ".item-info", @@ -21,7 +21,7 @@ compare-elements-property: ( ) assert-property: ( "#impl-SimpleTrait-for-LongItemInfo2 .item-info", - {"scrollWidth": "866"}, + {"scrollWidth": "916"}, ) // Just to be sure we're comparing the correct "item-info": assert-text: ( diff --git a/src/test/rustdoc-gui/item-info.goml b/src/test/rustdoc-gui/item-info.goml index 50c45b76bd630..8750d5c53606f 100644 --- a/src/test/rustdoc-gui/item-info.goml +++ b/src/test/rustdoc-gui/item-info.goml @@ -4,9 +4,9 @@ goto: file://|DOC_PATH|/lib2/struct.Foo.html // We set a fixed size so there is no chance of "random" resize. size: (1100, 800) // We check that ".item-info" is bigger than its content. -assert-css: (".item-info", {"width": "790px"}) +assert-css: (".item-info", {"width": "840px"}) assert-css: (".item-info .stab", {"width": "289px"}) -assert-position: (".item-info .stab", {"x": 295}) +assert-position: (".item-info .stab", {"x": 245}) // Now we ensure that they're not rendered on the same line. goto: file://|DOC_PATH|/lib2/trait.Trait.html diff --git a/src/test/rustdoc-gui/notable-trait.goml b/src/test/rustdoc-gui/notable-trait.goml index 7eb00d825a5c3..20a129f9d9da6 100644 --- a/src/test/rustdoc-gui/notable-trait.goml +++ b/src/test/rustdoc-gui/notable-trait.goml @@ -18,11 +18,11 @@ compare-elements-position-false: ( // The `i` should be *after* the type. assert-position: ( "//*[@id='method.create_an_iterator_from_read']//a[text()='NotableStructWithLongName']", - {"x": 692}, + {"x": 677}, ) assert-position: ( "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits']", - {"x": 966}, + {"x": 951}, ) diff --git a/src/test/rustdoc-gui/search-result-display.goml b/src/test/rustdoc-gui/search-result-display.goml index efbbfb925bd3b..e33693e27eaf6 100644 --- a/src/test/rustdoc-gui/search-result-display.goml +++ b/src/test/rustdoc-gui/search-result-display.goml @@ -7,7 +7,7 @@ press-key: 'Enter' wait-for: "#crate-search" // The width is returned by "getComputedStyle" which returns the exact number instead of the // CSS rule which is "50%"... -assert-css: (".search-results div.desc", {"width": "293px"}) +assert-css: (".search-results div.desc", {"width": "318px"}) size: (600, 100) // As counter-intuitive as it may seem, in this width, the width is "100%", which is why // when computed it's larger. diff --git a/src/test/rustdoc-gui/type-declation-overflow.goml b/src/test/rustdoc-gui/type-declation-overflow.goml index 9a46908f9333b..7b3e9ad5a5717 100644 --- a/src/test/rustdoc-gui/type-declation-overflow.goml +++ b/src/test/rustdoc-gui/type-declation-overflow.goml @@ -15,7 +15,7 @@ assert-property: (".item-table .struct", {"offsetWidth": "684"}) goto: file://|DOC_PATH|/lib2/too_long/type.ReallyLongTypeNameLongLongLong.html assert-property: ("body", {"scrollWidth": "1100"}) // We now check that the section width hasn't grown because of it. -assert-property: ("#main-content", {"scrollWidth": "825"}) +assert-property: ("#main-content", {"scrollWidth": "840"}) // And now checking that it has scrollable content. assert-property: (".item-decl pre", {"scrollWidth": "1103"}) @@ -24,7 +24,7 @@ assert-property: (".item-decl pre", {"scrollWidth": "1103"}) goto: file://|DOC_PATH|/lib2/too_long/constant.ReallyLongTypeNameLongLongLongConstBecauseWhyNotAConstRightGigaGigaSupraLong.html assert-property: ("body", {"scrollWidth": "1100"}) // We now check that the section width hasn't grown because of it. -assert-property: ("#main-content", {"scrollWidth": "825"}) +assert-property: ("#main-content", {"scrollWidth": "840"}) // And now checking that it has scrollable content. assert-property: (".item-decl pre", {"scrollWidth": "950"}) From 6267c60f6a1eb8bb135bb3d37edd4ab9ab352d6e Mon Sep 17 00:00:00 2001 From: onestacked Date: Fri, 23 Sep 2022 18:20:57 +0200 Subject: [PATCH 174/586] Added some spacing in const closure --- library/core/src/const_closure.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/library/core/src/const_closure.rs b/library/core/src/const_closure.rs index 536c3eb0022fd..6ea94c95473dd 100644 --- a/library/core/src/const_closure.rs +++ b/library/core/src/const_closure.rs @@ -17,6 +17,7 @@ pub(crate) struct ConstFnOnceClosure { data: CapturedData, func: Function, } + impl ConstFnOnceClosure { /// Function for creating a new closure. /// @@ -36,6 +37,7 @@ impl ConstFnOnceClosure { Self { data, func } } } + impl const FnOnce for ConstFnOnceClosure where @@ -48,6 +50,7 @@ where (self.func)(self.data, args) } } + /// Struct representing a closure with mutably borrowed data. /// /// Example: @@ -68,6 +71,7 @@ pub(crate) struct ConstFnMutClosure<'a, CapturedData: ?Sized, Function> { data: &'a mut CapturedData, func: Function, } + impl<'a, CapturedData: ?Sized, Function> ConstFnMutClosure<'a, CapturedData, Function> { /// Function for creating a new closure. /// @@ -85,6 +89,7 @@ impl<'a, CapturedData: ?Sized, Function> ConstFnMutClosure<'a, CapturedData, Fun Self { data, func } } } + impl<'a, CapturedData: ?Sized, ClosureArguments, Function, ClosureReturnValue> const FnOnce for ConstFnMutClosure<'a, CapturedData, Function> where @@ -97,6 +102,7 @@ where self.call_mut(args) } } + impl<'a, CapturedData: ?Sized, ClosureArguments, Function, ClosureReturnValue> const FnMut for ConstFnMutClosure<'a, CapturedData, Function> where @@ -126,6 +132,7 @@ pub(crate) struct ConstFnClosure<'a, CapturedData: ?Sized, Function> { data: &'a CapturedData, func: Function, } + impl<'a, CapturedData: ?Sized, Function> ConstFnClosure<'a, CapturedData, Function> { /// Function for creating a new closure. /// @@ -144,6 +151,7 @@ impl<'a, CapturedData: ?Sized, Function> ConstFnClosure<'a, CapturedData, Functi Self { data, func } } } + impl<'a, CapturedData: ?Sized, Function, ClosureArguments, ClosureReturnValue> const FnOnce for ConstFnClosure<'a, CapturedData, Function> where @@ -155,6 +163,7 @@ where self.call_mut(args) } } + impl<'a, CapturedData: ?Sized, Function, ClosureArguments, ClosureReturnValue> const FnMut for ConstFnClosure<'a, CapturedData, Function> where @@ -164,6 +173,7 @@ where self.call(args) } } + impl< 'a, CapturedData: ?Sized, From aac2c7ddd887a410e44a2cdc4cb4735765b2924e Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sun, 11 Sep 2022 14:37:55 +0200 Subject: [PATCH 175/586] Always print '_, even for erased lifetimes. --- compiler/rustc_middle/src/ty/print/pretty.rs | 25 +++---------------- .../derefer_complex_case.main.Derefer.diff | 12 ++++----- ...ness.no_downcast.EarlyOtherwiseBranch.diff | 6 ++--- ...float_to_exponential_common.ConstProp.diff | 18 ++++++------- .../issue_73223.main.SimplifyArmIdentity.diff | 2 +- .../mir-opt/issue_99325.main.mir_map.0.mir | 8 +++--- ...asts.SimplifyCfg-elaborate-drops.after.mir | 2 +- .../const-generics/issues/issue-83765.stderr | 8 +++--- .../const-ptr/forbidden_slices.64bit.stderr | 16 ++++++------ src/test/ui/issues/issue-21174.stderr | 4 +-- .../ui/polymorphization/predicates.stderr | 2 +- ...recursive-types-are-not-uninhabited.stderr | 4 +-- .../ui/specialization/issue-38091-2.stderr | 2 +- src/test/ui/transmute/main.stderr | 2 +- 14 files changed, 46 insertions(+), 65 deletions(-) diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index b6cd5396b1d23..1546f55101134 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -1088,17 +1088,9 @@ pub trait PrettyPrinter<'tcx>: .generics_of(principal.def_id) .own_substs_no_defaults(cx.tcx(), principal.substs); - // Don't print `'_` if there's no unerased regions. - let print_regions = args.iter().any(|arg| match arg.unpack() { - GenericArgKind::Lifetime(r) => !r.is_erased(), - _ => false, - }); - let mut args = args.iter().cloned().filter(|arg| match arg.unpack() { - GenericArgKind::Lifetime(_) => print_regions, - _ => true, - }); let mut projections = predicates.projection_bounds(); + let mut args = args.iter().cloned(); let arg0 = args.next(); let projection0 = projections.next(); if arg0.is_some() || projection0.is_some() { @@ -1847,22 +1839,11 @@ impl<'tcx> Printer<'tcx> for FmtPrinter<'_, 'tcx> { ) -> Result { self = print_prefix(self)?; - // Don't print `'_` if there's no unerased regions. - let print_regions = self.tcx.sess.verbose() - || args.iter().any(|arg| match arg.unpack() { - GenericArgKind::Lifetime(r) => !r.is_erased(), - _ => false, - }); - let args = args.iter().cloned().filter(|arg| match arg.unpack() { - GenericArgKind::Lifetime(_) => print_regions, - _ => true, - }); - - if args.clone().next().is_some() { + if args.first().is_some() { if self.in_value { write!(self, "::")?; } - self.generic_delimiters(|cx| cx.comma_sep(args)) + self.generic_delimiters(|cx| cx.comma_sep(args.iter().cloned())) } else { Ok(self) } diff --git a/src/test/mir-opt/derefer_complex_case.main.Derefer.diff b/src/test/mir-opt/derefer_complex_case.main.Derefer.diff index c353c375aa963..1e1c80aad34e7 100644 --- a/src/test/mir-opt/derefer_complex_case.main.Derefer.diff +++ b/src/test/mir-opt/derefer_complex_case.main.Derefer.diff @@ -3,15 +3,15 @@ fn main() -> () { let mut _0: (); // return place in scope 0 at $DIR/derefer_complex_case.rs:+0:11: +0:11 - let mut _1: std::slice::Iter; // in scope 0 at $DIR/derefer_complex_case.rs:+1:17: +1:26 + let mut _1: std::slice::Iter<'_, i32>; // in scope 0 at $DIR/derefer_complex_case.rs:+1:17: +1:26 let mut _2: &[i32; 2]; // in scope 0 at $DIR/derefer_complex_case.rs:+1:17: +1:26 let _3: [i32; 2]; // in scope 0 at $DIR/derefer_complex_case.rs:+1:18: +1:26 - let mut _4: std::slice::Iter; // in scope 0 at $DIR/derefer_complex_case.rs:+1:17: +1:26 + let mut _4: std::slice::Iter<'_, i32>; // in scope 0 at $DIR/derefer_complex_case.rs:+1:17: +1:26 let mut _5: (); // in scope 0 at $DIR/derefer_complex_case.rs:+0:1: +2:2 let _6: (); // in scope 0 at $DIR/derefer_complex_case.rs:+1:17: +1:26 let mut _7: std::option::Option<&i32>; // in scope 0 at $DIR/derefer_complex_case.rs:+1:17: +1:26 - let mut _8: &mut std::slice::Iter; // in scope 0 at $DIR/derefer_complex_case.rs:+1:17: +1:26 - let mut _9: &mut std::slice::Iter; // in scope 0 at $DIR/derefer_complex_case.rs:+1:17: +1:26 + let mut _8: &mut std::slice::Iter<'_, i32>; // in scope 0 at $DIR/derefer_complex_case.rs:+1:17: +1:26 + let mut _9: &mut std::slice::Iter<'_, i32>; // in scope 0 at $DIR/derefer_complex_case.rs:+1:17: +1:26 let mut _10: isize; // in scope 0 at $DIR/derefer_complex_case.rs:+1:5: +1:40 let mut _11: !; // in scope 0 at $DIR/derefer_complex_case.rs:+1:5: +1:40 let mut _13: i32; // in scope 0 at $DIR/derefer_complex_case.rs:+1:34: +1:37 @@ -53,10 +53,10 @@ StorageLive(_9); // scope 1 at $DIR/derefer_complex_case.rs:+1:17: +1:26 _9 = &mut _4; // scope 1 at $DIR/derefer_complex_case.rs:+1:17: +1:26 _8 = &mut (*_9); // scope 1 at $DIR/derefer_complex_case.rs:+1:17: +1:26 - _7 = as Iterator>::next(move _8) -> bb3; // scope 1 at $DIR/derefer_complex_case.rs:+1:17: +1:26 + _7 = as Iterator>::next(move _8) -> bb3; // scope 1 at $DIR/derefer_complex_case.rs:+1:17: +1:26 // mir::Constant // + span: $DIR/derefer_complex_case.rs:6:17: 6:26 - // + literal: Const { ty: for<'r> fn(&'r mut std::slice::Iter) -> Option< as Iterator>::Item> { as Iterator>::next}, val: Value() } + // + literal: Const { ty: for<'r> fn(&'r mut std::slice::Iter<'_, i32>) -> Option< as Iterator>::Item> { as Iterator>::next}, val: Value() } } bb3: { diff --git a/src/test/mir-opt/early_otherwise_branch_soundness.no_downcast.EarlyOtherwiseBranch.diff b/src/test/mir-opt/early_otherwise_branch_soundness.no_downcast.EarlyOtherwiseBranch.diff index 9e089b01b0f34..659aed18f0436 100644 --- a/src/test/mir-opt/early_otherwise_branch_soundness.no_downcast.EarlyOtherwiseBranch.diff +++ b/src/test/mir-opt/early_otherwise_branch_soundness.no_downcast.EarlyOtherwiseBranch.diff @@ -1,12 +1,12 @@ - // MIR for `no_downcast` before EarlyOtherwiseBranch + // MIR for `no_downcast` after EarlyOtherwiseBranch - fn no_downcast(_1: &E) -> u32 { + fn no_downcast(_1: &E<'_>) -> u32 { debug e => _1; // in scope 0 at $DIR/early_otherwise_branch_soundness.rs:+0:16: +0:17 let mut _0: u32; // return place in scope 0 at $DIR/early_otherwise_branch_soundness.rs:+0:26: +0:29 let mut _2: isize; // in scope 0 at $DIR/early_otherwise_branch_soundness.rs:+1:20: +1:30 let mut _3: isize; // in scope 0 at $DIR/early_otherwise_branch_soundness.rs:+1:12: +1:31 - let mut _4: &E; // in scope 0 at $DIR/early_otherwise_branch_soundness.rs:+0:16: +0:17 + let mut _4: &E<'_>; // in scope 0 at $DIR/early_otherwise_branch_soundness.rs:+0:16: +0:17 scope 1 { } @@ -16,7 +16,7 @@ } bb1: { - _4 = deref_copy (((*_1) as Some).0: &E); // scope 1 at $DIR/early_otherwise_branch_soundness.rs:+1:12: +1:31 + _4 = deref_copy (((*_1) as Some).0: &E<'_>); // scope 1 at $DIR/early_otherwise_branch_soundness.rs:+1:12: +1:31 _2 = discriminant((*_4)); // scope 1 at $DIR/early_otherwise_branch_soundness.rs:+1:12: +1:31 switchInt(move _2) -> [1_isize: bb2, otherwise: bb3]; // scope 1 at $DIR/early_otherwise_branch_soundness.rs:+1:12: +1:31 } diff --git a/src/test/mir-opt/funky_arms.float_to_exponential_common.ConstProp.diff b/src/test/mir-opt/funky_arms.float_to_exponential_common.ConstProp.diff index dca36b1a76d0f..b789ae22974da 100644 --- a/src/test/mir-opt/funky_arms.float_to_exponential_common.ConstProp.diff +++ b/src/test/mir-opt/funky_arms.float_to_exponential_common.ConstProp.diff @@ -1,24 +1,24 @@ - // MIR for `float_to_exponential_common` before ConstProp + // MIR for `float_to_exponential_common` after ConstProp - fn float_to_exponential_common(_1: &mut Formatter, _2: &T, _3: bool) -> Result<(), std::fmt::Error> { + fn float_to_exponential_common(_1: &mut Formatter<'_>, _2: &T, _3: bool) -> Result<(), std::fmt::Error> { debug fmt => _1; // in scope 0 at $DIR/funky_arms.rs:+0:35: +0:38 debug num => _2; // in scope 0 at $DIR/funky_arms.rs:+0:60: +0:63 debug upper => _3; // in scope 0 at $DIR/funky_arms.rs:+0:69: +0:74 let mut _0: std::result::Result<(), std::fmt::Error>; // return place in scope 0 at $DIR/funky_arms.rs:+0:85: +0:91 let _4: bool; // in scope 0 at $DIR/funky_arms.rs:+4:9: +4:19 - let mut _5: &std::fmt::Formatter; // in scope 0 at $DIR/funky_arms.rs:+4:22: +4:37 + let mut _5: &std::fmt::Formatter<'_>; // in scope 0 at $DIR/funky_arms.rs:+4:22: +4:37 let mut _7: std::option::Option; // in scope 0 at $DIR/funky_arms.rs:+13:30: +13:45 - let mut _8: &std::fmt::Formatter; // in scope 0 at $DIR/funky_arms.rs:+13:30: +13:45 + let mut _8: &std::fmt::Formatter<'_>; // in scope 0 at $DIR/funky_arms.rs:+13:30: +13:45 let mut _9: isize; // in scope 0 at $DIR/funky_arms.rs:+13:12: +13:27 - let mut _11: &mut std::fmt::Formatter; // in scope 0 at $DIR/funky_arms.rs:+15:43: +15:46 + let mut _11: &mut std::fmt::Formatter<'_>; // in scope 0 at $DIR/funky_arms.rs:+15:43: +15:46 let mut _12: &T; // in scope 0 at $DIR/funky_arms.rs:+15:48: +15:51 let mut _13: core::num::flt2dec::Sign; // in scope 0 at $DIR/funky_arms.rs:+15:53: +15:57 let mut _14: u32; // in scope 0 at $DIR/funky_arms.rs:+15:59: +15:79 let mut _15: u32; // in scope 0 at $DIR/funky_arms.rs:+15:59: +15:75 let mut _16: usize; // in scope 0 at $DIR/funky_arms.rs:+15:59: +15:68 let mut _17: bool; // in scope 0 at $DIR/funky_arms.rs:+15:81: +15:86 - let mut _18: &mut std::fmt::Formatter; // in scope 0 at $DIR/funky_arms.rs:+17:46: +17:49 + let mut _18: &mut std::fmt::Formatter<'_>; // in scope 0 at $DIR/funky_arms.rs:+17:46: +17:49 let mut _19: &T; // in scope 0 at $DIR/funky_arms.rs:+17:51: +17:54 let mut _20: core::num::flt2dec::Sign; // in scope 0 at $DIR/funky_arms.rs:+17:56: +17:60 let mut _21: bool; // in scope 0 at $DIR/funky_arms.rs:+17:62: +17:67 @@ -38,10 +38,10 @@ StorageLive(_4); // scope 0 at $DIR/funky_arms.rs:+4:9: +4:19 StorageLive(_5); // scope 0 at $DIR/funky_arms.rs:+4:22: +4:37 _5 = &(*_1); // scope 0 at $DIR/funky_arms.rs:+4:22: +4:37 - _4 = Formatter::sign_plus(move _5) -> bb1; // scope 0 at $DIR/funky_arms.rs:+4:22: +4:37 + _4 = Formatter::<'_>::sign_plus(move _5) -> bb1; // scope 0 at $DIR/funky_arms.rs:+4:22: +4:37 // mir::Constant // + span: $DIR/funky_arms.rs:15:26: 15:35 - // + literal: Const { ty: for<'r> fn(&'r Formatter) -> bool {Formatter::sign_plus}, val: Value() } + // + literal: Const { ty: for<'r> fn(&'r Formatter<'_>) -> bool {Formatter::<'_>::sign_plus}, val: Value() } } bb1: { @@ -66,10 +66,10 @@ StorageLive(_7); // scope 3 at $DIR/funky_arms.rs:+13:30: +13:45 StorageLive(_8); // scope 3 at $DIR/funky_arms.rs:+13:30: +13:45 _8 = &(*_1); // scope 3 at $DIR/funky_arms.rs:+13:30: +13:45 - _7 = Formatter::precision(move _8) -> bb5; // scope 3 at $DIR/funky_arms.rs:+13:30: +13:45 + _7 = Formatter::<'_>::precision(move _8) -> bb5; // scope 3 at $DIR/funky_arms.rs:+13:30: +13:45 // mir::Constant // + span: $DIR/funky_arms.rs:24:34: 24:43 - // + literal: Const { ty: for<'r> fn(&'r Formatter) -> Option {Formatter::precision}, val: Value() } + // + literal: Const { ty: for<'r> fn(&'r Formatter<'_>) -> Option {Formatter::<'_>::precision}, val: Value() } } bb5: { diff --git a/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.diff b/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.diff index 76d8d9396255b..533907e704093 100644 --- a/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.diff +++ b/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.diff @@ -25,7 +25,7 @@ let _24: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL let mut _25: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL let _26: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let mut _27: std::option::Option; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + let mut _27: std::option::Option>; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL scope 1 { debug split => _1; // in scope 1 at $DIR/issue-73223.rs:+1:9: +1:14 let _6: std::option::Option; // in scope 1 at $DIR/issue-73223.rs:+6:9: +6:14 diff --git a/src/test/mir-opt/issue_99325.main.mir_map.0.mir b/src/test/mir-opt/issue_99325.main.mir_map.0.mir index 8659ddfdb00cc..5428d865cd5e2 100644 --- a/src/test/mir-opt/issue_99325.main.mir_map.0.mir +++ b/src/test/mir-opt/issue_99325.main.mir_map.0.mir @@ -26,7 +26,7 @@ fn main() -> () { let _19: &&[u8]; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL let mut _20: &&[u8; 4]; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL let _21: &&[u8; 4]; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let mut _22: std::option::Option; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + let mut _22: std::option::Option>; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL let _23: (); // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL let mut _24: (&&[u8], &&[u8; 4]); // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL let mut _25: &&[u8]; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL @@ -46,7 +46,7 @@ fn main() -> () { let _40: &&[u8]; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL let mut _41: &&[u8; 4]; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL let _42: &&[u8; 4]; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let mut _43: std::option::Option; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + let mut _43: std::option::Option>; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL scope 1 { debug left_val => _8; // in scope 1 at $SRC_DIR/core/src/macros/mod.rs:LL:COL debug right_val => _9; // in scope 1 at $SRC_DIR/core/src/macros/mod.rs:LL:COL @@ -128,7 +128,7 @@ fn main() -> () { _21 = &(*_9); // scope 2 at $SRC_DIR/core/src/macros/mod.rs:LL:COL _20 = &(*_21); // scope 2 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageLive(_22); // scope 2 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _22 = Option::::None; // scope 2 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + _22 = Option::>::None; // scope 2 at $SRC_DIR/core/src/macros/mod.rs:LL:COL _16 = core::panicking::assert_failed::<&[u8], &[u8; 4]>(move _17, move _18, move _20, move _22) -> bb19; // scope 2 at $SRC_DIR/core/src/macros/mod.rs:LL:COL // mir::Constant // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL @@ -237,7 +237,7 @@ fn main() -> () { _42 = &(*_30); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL _41 = &(*_42); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageLive(_43); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _43 = Option::::None; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + _43 = Option::>::None; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL _37 = core::panicking::assert_failed::<&[u8], &[u8; 4]>(move _38, move _39, move _41, move _43) -> bb19; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL // mir::Constant // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL diff --git a/src/test/mir-opt/retag.array_casts.SimplifyCfg-elaborate-drops.after.mir b/src/test/mir-opt/retag.array_casts.SimplifyCfg-elaborate-drops.after.mir index 899bb67fb3ae5..318b241fa737a 100644 --- a/src/test/mir-opt/retag.array_casts.SimplifyCfg-elaborate-drops.after.mir +++ b/src/test/mir-opt/retag.array_casts.SimplifyCfg-elaborate-drops.after.mir @@ -29,7 +29,7 @@ fn array_casts() -> () { let _31: &usize; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL let mut _32: &usize; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL let _33: &usize; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let mut _34: std::option::Option; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + let mut _34: std::option::Option>; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL scope 1 { debug x => _1; // in scope 1 at $DIR/retag.rs:+1:9: +1:14 let _2: *mut usize; // in scope 1 at $DIR/retag.rs:+2:9: +2:10 diff --git a/src/test/ui/const-generics/issues/issue-83765.stderr b/src/test/ui/const-generics/issues/issue-83765.stderr index d5f914f46f873..4becf3a364cf1 100644 --- a/src/test/ui/const-generics/issues/issue-83765.stderr +++ b/src/test/ui/const-generics/issues/issue-83765.stderr @@ -1,16 +1,16 @@ -error[E0391]: cycle detected when resolving instance ` as TensorDimension>::DIM` +error[E0391]: cycle detected when resolving instance ` as TensorDimension>::DIM` --> $DIR/issue-83765.rs:5:5 | LL | const DIM: usize; | ^^^^^^^^^^^^^^^^ | -note: ...which requires computing candidate for ` as TensorDimension>`... +note: ...which requires computing candidate for ` as TensorDimension>`... --> $DIR/issue-83765.rs:4:1 | LL | trait TensorDimension { | ^^^^^^^^^^^^^^^^^^^^^ - = note: ...which again requires resolving instance ` as TensorDimension>::DIM`, completing the cycle -note: cycle used when computing candidate for ` as TensorDimension>` + = note: ...which again requires resolving instance ` as TensorDimension>::DIM`, completing the cycle +note: cycle used when computing candidate for ` as TensorDimension>` --> $DIR/issue-83765.rs:4:1 | LL | trait TensorDimension { diff --git a/src/test/ui/const-ptr/forbidden_slices.64bit.stderr b/src/test/ui/const-ptr/forbidden_slices.64bit.stderr index f88746af9769d..db42b7c98307d 100644 --- a/src/test/ui/const-ptr/forbidden_slices.64bit.stderr +++ b/src/test/ui/const-ptr/forbidden_slices.64bit.stderr @@ -5,7 +5,7 @@ LL | &*ptr::slice_from_raw_parts(data, len) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | | | dereferencing pointer failed: null pointer is a dangling pointer (it has no provenance) - | inside `std::slice::from_raw_parts::` at $SRC_DIR/core/src/slice/raw.rs:LL:COL + | inside `std::slice::from_raw_parts::<'_, u32>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL | ::: $DIR/forbidden_slices.rs:18:34 | @@ -19,7 +19,7 @@ LL | &*ptr::slice_from_raw_parts(data, len) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | | | dereferencing pointer failed: null pointer is a dangling pointer (it has no provenance) - | inside `std::slice::from_raw_parts::<()>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL + | inside `std::slice::from_raw_parts::<'_, ()>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL | ::: $DIR/forbidden_slices.rs:19:33 | @@ -33,7 +33,7 @@ LL | &*ptr::slice_from_raw_parts(data, len) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | | | dereferencing pointer failed: ALLOC_ID has size 4, so pointer to 8 bytes starting at offset 0 is out-of-bounds - | inside `std::slice::from_raw_parts::` at $SRC_DIR/core/src/slice/raw.rs:LL:COL + | inside `std::slice::from_raw_parts::<'_, u32>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL | ::: $DIR/forbidden_slices.rs:22:34 | @@ -92,7 +92,7 @@ LL | &*ptr::slice_from_raw_parts(data, len) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | | | dereferencing pointer failed: ALLOC_ID has size 8, so pointer to 8 bytes starting at offset 1 is out-of-bounds - | inside `std::slice::from_raw_parts::` at $SRC_DIR/core/src/slice/raw.rs:LL:COL + | inside `std::slice::from_raw_parts::<'_, u64>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL | ::: $DIR/forbidden_slices.rs:43:5 | @@ -111,7 +111,7 @@ LL | unsafe { intrinsics::ptr_offset_from_unsigned(self, origin) } ::: $SRC_DIR/core/src/slice/raw.rs:LL:COL | LL | unsafe { from_raw_parts(range.start, range.end.sub_ptr(range.start)) } - | ------------------------------ inside `from_ptr_range::` at $SRC_DIR/core/src/slice/raw.rs:LL:COL + | ------------------------------ inside `from_ptr_range::<'_, u32>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL | ::: $DIR/forbidden_slices.rs:46:34 | @@ -130,7 +130,7 @@ LL | assert!(0 < pointee_size && pointee_size <= isize::MAX as usize); ::: $SRC_DIR/core/src/slice/raw.rs:LL:COL | LL | unsafe { from_raw_parts(range.start, range.end.sub_ptr(range.start)) } - | ------------------------------ inside `from_ptr_range::<()>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL + | ------------------------------ inside `from_ptr_range::<'_, ()>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL | ::: $DIR/forbidden_slices.rs:47:33 | @@ -230,7 +230,7 @@ LL | unsafe { intrinsics::ptr_offset_from_unsigned(self, origin) } ::: $SRC_DIR/core/src/slice/raw.rs:LL:COL | LL | unsafe { from_raw_parts(range.start, range.end.sub_ptr(range.start)) } - | ------------------------------ inside `from_ptr_range::` at $SRC_DIR/core/src/slice/raw.rs:LL:COL + | ------------------------------ inside `from_ptr_range::<'_, u32>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL | ::: $DIR/forbidden_slices.rs:79:34 | @@ -249,7 +249,7 @@ LL | unsafe { intrinsics::ptr_offset_from_unsigned(self, origin) } ::: $SRC_DIR/core/src/slice/raw.rs:LL:COL | LL | unsafe { from_raw_parts(range.start, range.end.sub_ptr(range.start)) } - | ------------------------------ inside `from_ptr_range::` at $SRC_DIR/core/src/slice/raw.rs:LL:COL + | ------------------------------ inside `from_ptr_range::<'_, u32>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL | ::: $DIR/forbidden_slices.rs:80:35 | diff --git a/src/test/ui/issues/issue-21174.stderr b/src/test/ui/issues/issue-21174.stderr index 09402c3d81410..5981d9dc73303 100644 --- a/src/test/ui/issues/issue-21174.stderr +++ b/src/test/ui/issues/issue-21174.stderr @@ -4,8 +4,8 @@ error[E0512]: cannot transmute between types of different sizes, or dependently- LL | let new: T::B = unsafe { std::mem::transmute(value) }; | ^^^^^^^^^^^^^^^^^^^ | - = note: source type: `::A` (this type does not have a fixed size) - = note: target type: `::B` (this type does not have a fixed size) + = note: source type: `>::A` (this type does not have a fixed size) + = note: target type: `>::B` (this type does not have a fixed size) error: aborting due to previous error diff --git a/src/test/ui/polymorphization/predicates.stderr b/src/test/ui/polymorphization/predicates.stderr index e5af1d7515f6c..80bb2af25cc21 100644 --- a/src/test/ui/polymorphization/predicates.stderr +++ b/src/test/ui/polymorphization/predicates.stderr @@ -41,7 +41,7 @@ error: item has unused generic parameters LL | fn bar() { | ^^^ - generic parameter `I` is unused -note: the above error was encountered while instantiating `fn foo::, T>` +note: the above error was encountered while instantiating `fn foo::, T>` --> $DIR/predicates.rs:86:5 | LL | foo(x.iter()); 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 321ee0a36942e..f2307899d3c47 100644 --- a/src/test/ui/recursion/recursive-types-are-not-uninhabited.stderr +++ b/src/test/ui/recursion/recursive-types-are-not-uninhabited.stderr @@ -6,7 +6,7 @@ LL | let Ok(x) = res; | = 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: `Result` defined here +note: `Result>` defined here --> $SRC_DIR/core/src/result.rs:LL:COL | LL | pub enum Result { @@ -14,7 +14,7 @@ LL | pub enum Result { ... LL | Err(#[stable(feature = "rust1", since = "1.0.0")] E), | ^^^ not covered - = note: the matched value is of type `Result` + = 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 | let x = if let Ok(x) = res { x } else { todo!() }; diff --git a/src/test/ui/specialization/issue-38091-2.stderr b/src/test/ui/specialization/issue-38091-2.stderr index 146a56358bebe..31ae4b26e45d2 100644 --- a/src/test/ui/specialization/issue-38091-2.stderr +++ b/src/test/ui/specialization/issue-38091-2.stderr @@ -10,7 +10,7 @@ LL | #![feature(specialization)] error[E0275]: overflow evaluating the requirement `i32: Check` | -note: required for `i32` to implement `Iterate` +note: required for `i32` to implement `Iterate<'_>` --> $DIR/issue-38091-2.rs:11:13 | LL | impl<'a, T> Iterate<'a> for T diff --git a/src/test/ui/transmute/main.stderr b/src/test/ui/transmute/main.stderr index f48562094a4bc..d519f03682b5d 100644 --- a/src/test/ui/transmute/main.stderr +++ b/src/test/ui/transmute/main.stderr @@ -4,7 +4,7 @@ error[E0512]: cannot transmute between types of different sizes, or dependently- LL | transmute(x) | ^^^^^^^^^ | - = note: `::T` does not have a fixed size + = note: `>::T` does not have a fixed size error[E0512]: cannot transmute between types of different sizes, or dependently-sized types --> $DIR/main.rs:17:17 From f11499189e1d4b1f7a5f8cad7e3106477bb444ca Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Tue, 20 Sep 2022 23:19:43 +0200 Subject: [PATCH 176/586] Bless cgu test. --- src/test/codegen-units/item-collection/generic-impl.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/test/codegen-units/item-collection/generic-impl.rs b/src/test/codegen-units/item-collection/generic-impl.rs index dd5367ef0380a..4260230c2c674 100644 --- a/src/test/codegen-units/item-collection/generic-impl.rs +++ b/src/test/codegen-units/item-collection/generic-impl.rs @@ -30,11 +30,11 @@ pub struct LifeTimeOnly<'a> { impl<'a> LifeTimeOnly<'a> { - //~ MONO_ITEM fn LifeTimeOnly::foo + //~ MONO_ITEM fn LifeTimeOnly::<'_>::foo pub fn foo(&self) {} - //~ MONO_ITEM fn LifeTimeOnly::bar + //~ MONO_ITEM fn LifeTimeOnly::<'_>::bar pub fn bar(&'a self) {} - //~ MONO_ITEM fn LifeTimeOnly::baz + //~ MONO_ITEM fn LifeTimeOnly::<'_>::baz pub fn baz<'b>(&'b self) {} pub fn non_instantiated(&self) {} From 8de8115262ee518689b8cbd73eb16cac4d3cda72 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Wed, 21 Sep 2022 19:09:43 +0200 Subject: [PATCH 177/586] Bless pretty tests. --- src/test/pretty/issue-4264.pp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/test/pretty/issue-4264.pp b/src/test/pretty/issue-4264.pp index 752c36a0fbc5a..10958a7727c4b 100644 --- a/src/test/pretty/issue-4264.pp +++ b/src/test/pretty/issue-4264.pp @@ -34,10 +34,10 @@ ((::alloc::fmt::format as for<'r> fn(Arguments<'r>) -> String {format})(((::core::fmt::Arguments::new_v1 as - fn(&[&'static str], &[ArgumentV1]) -> Arguments {Arguments::new_v1})((&([("test" + fn(&[&'static str], &[ArgumentV1<'_>]) -> Arguments<'_> {Arguments::<'_>::new_v1})((&([("test" as &str)] as [&str; 1]) as &[&str; 1]), - (&([] as [ArgumentV1; 0]) as &[ArgumentV1; 0])) as - Arguments)) as String); + (&([] as [ArgumentV1<'_>; 0]) as &[ArgumentV1<'_>; 0])) as + Arguments<'_>)) as String); (res as String) } as String); } as ()) From 8077d03b3f768e34fe3d9a9be813989444b93af5 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Wed, 21 Sep 2022 20:14:18 +0200 Subject: [PATCH 178/586] Bless 32bit ui. --- .../ui/const-ptr/forbidden_slices.32bit.stderr | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/test/ui/const-ptr/forbidden_slices.32bit.stderr b/src/test/ui/const-ptr/forbidden_slices.32bit.stderr index 82a3c92e66fdf..8978ab436d07d 100644 --- a/src/test/ui/const-ptr/forbidden_slices.32bit.stderr +++ b/src/test/ui/const-ptr/forbidden_slices.32bit.stderr @@ -5,7 +5,7 @@ LL | &*ptr::slice_from_raw_parts(data, len) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | | | dereferencing pointer failed: null pointer is a dangling pointer (it has no provenance) - | inside `std::slice::from_raw_parts::` at $SRC_DIR/core/src/slice/raw.rs:LL:COL + | inside `std::slice::from_raw_parts::<'_, u32>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL | ::: $DIR/forbidden_slices.rs:18:34 | @@ -19,7 +19,7 @@ LL | &*ptr::slice_from_raw_parts(data, len) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | | | dereferencing pointer failed: null pointer is a dangling pointer (it has no provenance) - | inside `std::slice::from_raw_parts::<()>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL + | inside `std::slice::from_raw_parts::<'_, ()>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL | ::: $DIR/forbidden_slices.rs:19:33 | @@ -33,7 +33,7 @@ LL | &*ptr::slice_from_raw_parts(data, len) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | | | dereferencing pointer failed: ALLOC_ID has size 4, so pointer to 8 bytes starting at offset 0 is out-of-bounds - | inside `std::slice::from_raw_parts::` at $SRC_DIR/core/src/slice/raw.rs:LL:COL + | inside `std::slice::from_raw_parts::<'_, u32>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL | ::: $DIR/forbidden_slices.rs:22:34 | @@ -92,7 +92,7 @@ LL | &*ptr::slice_from_raw_parts(data, len) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | | | dereferencing pointer failed: ALLOC_ID has size 8, so pointer to 8 bytes starting at offset 1 is out-of-bounds - | inside `std::slice::from_raw_parts::` at $SRC_DIR/core/src/slice/raw.rs:LL:COL + | inside `std::slice::from_raw_parts::<'_, u64>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL | ::: $DIR/forbidden_slices.rs:43:5 | @@ -111,7 +111,7 @@ LL | unsafe { intrinsics::ptr_offset_from_unsigned(self, origin) } ::: $SRC_DIR/core/src/slice/raw.rs:LL:COL | LL | unsafe { from_raw_parts(range.start, range.end.sub_ptr(range.start)) } - | ------------------------------ inside `from_ptr_range::` at $SRC_DIR/core/src/slice/raw.rs:LL:COL + | ------------------------------ inside `from_ptr_range::<'_, u32>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL | ::: $DIR/forbidden_slices.rs:46:34 | @@ -130,7 +130,7 @@ LL | assert!(0 < pointee_size && pointee_size <= isize::MAX as usize); ::: $SRC_DIR/core/src/slice/raw.rs:LL:COL | LL | unsafe { from_raw_parts(range.start, range.end.sub_ptr(range.start)) } - | ------------------------------ inside `from_ptr_range::<()>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL + | ------------------------------ inside `from_ptr_range::<'_, ()>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL | ::: $DIR/forbidden_slices.rs:47:33 | @@ -230,7 +230,7 @@ LL | unsafe { intrinsics::ptr_offset_from_unsigned(self, origin) } ::: $SRC_DIR/core/src/slice/raw.rs:LL:COL | LL | unsafe { from_raw_parts(range.start, range.end.sub_ptr(range.start)) } - | ------------------------------ inside `from_ptr_range::` at $SRC_DIR/core/src/slice/raw.rs:LL:COL + | ------------------------------ inside `from_ptr_range::<'_, u32>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL | ::: $DIR/forbidden_slices.rs:79:34 | @@ -249,7 +249,7 @@ LL | unsafe { intrinsics::ptr_offset_from_unsigned(self, origin) } ::: $SRC_DIR/core/src/slice/raw.rs:LL:COL | LL | unsafe { from_raw_parts(range.start, range.end.sub_ptr(range.start)) } - | ------------------------------ inside `from_ptr_range::` at $SRC_DIR/core/src/slice/raw.rs:LL:COL + | ------------------------------ inside `from_ptr_range::<'_, u32>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL | ::: $DIR/forbidden_slices.rs:80:35 | From 9b83e316c8f2afc688755f42e6853a73e7d7c424 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Thu, 22 Sep 2022 19:39:38 +0200 Subject: [PATCH 179/586] Bless clippy. --- src/tools/clippy/tests/ui/inefficient_to_string.stderr | 8 ++++---- src/tools/clippy/tests/ui/suspicious_to_owned.stderr | 8 ++++---- src/tools/clippy/tests/ui/transmute_ptr_to_ref.stderr | 4 ++-- src/tools/clippy/tests/ui/useless_conversion.stderr | 2 +- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/tools/clippy/tests/ui/inefficient_to_string.stderr b/src/tools/clippy/tests/ui/inefficient_to_string.stderr index 4be46161e8b74..1c0490ffa44cc 100644 --- a/src/tools/clippy/tests/ui/inefficient_to_string.stderr +++ b/src/tools/clippy/tests/ui/inefficient_to_string.stderr @@ -35,21 +35,21 @@ LL | let _: String = rrrstring.to_string(); | = help: `&&std::string::String` implements `ToString` through a slower blanket impl, but `std::string::String` has a fast specialization of `ToString` -error: calling `to_string` on `&&std::borrow::Cow` +error: calling `to_string` on `&&std::borrow::Cow<'_, str>` --> $DIR/inefficient_to_string.rs:29:21 | LL | let _: String = rrcow.to_string(); | ^^^^^^^^^^^^^^^^^ help: try dereferencing the receiver: `(*rrcow).to_string()` | - = help: `&std::borrow::Cow` implements `ToString` through a slower blanket impl, but `std::borrow::Cow` has a fast specialization of `ToString` + = help: `&std::borrow::Cow<'_, str>` implements `ToString` through a slower blanket impl, but `std::borrow::Cow<'_, str>` has a fast specialization of `ToString` -error: calling `to_string` on `&&&std::borrow::Cow` +error: calling `to_string` on `&&&std::borrow::Cow<'_, str>` --> $DIR/inefficient_to_string.rs:30:21 | LL | let _: String = rrrcow.to_string(); | ^^^^^^^^^^^^^^^^^^ help: try dereferencing the receiver: `(**rrrcow).to_string()` | - = help: `&&std::borrow::Cow` implements `ToString` through a slower blanket impl, but `std::borrow::Cow` has a fast specialization of `ToString` + = help: `&&std::borrow::Cow<'_, str>` implements `ToString` through a slower blanket impl, but `std::borrow::Cow<'_, str>` has a fast specialization of `ToString` error: aborting due to 6 previous errors diff --git a/src/tools/clippy/tests/ui/suspicious_to_owned.stderr b/src/tools/clippy/tests/ui/suspicious_to_owned.stderr index 92e1024bf1f4e..ae1aec34d82e0 100644 --- a/src/tools/clippy/tests/ui/suspicious_to_owned.stderr +++ b/src/tools/clippy/tests/ui/suspicious_to_owned.stderr @@ -1,4 +1,4 @@ -error: this `to_owned` call clones the std::borrow::Cow itself and does not cause the std::borrow::Cow contents to become owned +error: this `to_owned` call clones the std::borrow::Cow<'_, str> itself and does not cause the std::borrow::Cow<'_, str> contents to become owned --> $DIR/suspicious_to_owned.rs:16:13 | LL | let _ = cow.to_owned(); @@ -6,19 +6,19 @@ LL | let _ = cow.to_owned(); | = note: `-D clippy::suspicious-to-owned` implied by `-D warnings` -error: this `to_owned` call clones the std::borrow::Cow<[char; 3]> itself and does not cause the std::borrow::Cow<[char; 3]> contents to become owned +error: this `to_owned` call clones the std::borrow::Cow<'_, [char; 3]> itself and does not cause the std::borrow::Cow<'_, [char; 3]> contents to become owned --> $DIR/suspicious_to_owned.rs:26:13 | LL | let _ = cow.to_owned(); | ^^^^^^^^^^^^^^ help: consider using, depending on intent: `cow.clone()` or `cow.into_owned()` -error: this `to_owned` call clones the std::borrow::Cow> itself and does not cause the std::borrow::Cow> contents to become owned +error: this `to_owned` call clones the std::borrow::Cow<'_, std::vec::Vec> itself and does not cause the std::borrow::Cow<'_, std::vec::Vec> contents to become owned --> $DIR/suspicious_to_owned.rs:36:13 | LL | let _ = cow.to_owned(); | ^^^^^^^^^^^^^^ help: consider using, depending on intent: `cow.clone()` or `cow.into_owned()` -error: this `to_owned` call clones the std::borrow::Cow itself and does not cause the std::borrow::Cow contents to become owned +error: this `to_owned` call clones the std::borrow::Cow<'_, str> itself and does not cause the std::borrow::Cow<'_, str> contents to become owned --> $DIR/suspicious_to_owned.rs:46:13 | LL | let _ = cow.to_owned(); diff --git a/src/tools/clippy/tests/ui/transmute_ptr_to_ref.stderr b/src/tools/clippy/tests/ui/transmute_ptr_to_ref.stderr index 2993e5e7b0c91..10117ee9182ab 100644 --- a/src/tools/clippy/tests/ui/transmute_ptr_to_ref.stderr +++ b/src/tools/clippy/tests/ui/transmute_ptr_to_ref.stderr @@ -42,13 +42,13 @@ error: transmute from a pointer type (`*mut U`) to a reference type (`&T`) LL | let _: &T = std::mem::transmute(om); | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(om as *const T)` -error: transmute from a pointer type (`*const i32`) to a reference type (`&_issue1231::Foo`) +error: transmute from a pointer type (`*const i32`) to a reference type (`&_issue1231::Foo<'_, u8>`) --> $DIR/transmute_ptr_to_ref.rs:36:32 | LL | let _: &Foo = unsafe { std::mem::transmute::<_, &Foo<_>>(raw) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*raw.cast::>()` -error: transmute from a pointer type (`*const i32`) to a reference type (`&_issue1231::Foo<&u8>`) +error: transmute from a pointer type (`*const i32`) to a reference type (`&_issue1231::Foo<'_, &u8>`) --> $DIR/transmute_ptr_to_ref.rs:38:33 | LL | let _: &Foo<&u8> = unsafe { std::mem::transmute::<_, &Foo<&_>>(raw) }; diff --git a/src/tools/clippy/tests/ui/useless_conversion.stderr b/src/tools/clippy/tests/ui/useless_conversion.stderr index e6760f700f342..65ee3807fa9d9 100644 --- a/src/tools/clippy/tests/ui/useless_conversion.stderr +++ b/src/tools/clippy/tests/ui/useless_conversion.stderr @@ -46,7 +46,7 @@ error: useless conversion to the same type: `std::string::String` LL | let _ = String::from(format!("A: {:04}", 123)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `String::from()`: `format!("A: {:04}", 123)` -error: useless conversion to the same type: `std::str::Lines` +error: useless conversion to the same type: `std::str::Lines<'_>` --> $DIR/useless_conversion.rs:65:13 | LL | let _ = "".lines().into_iter(); From 8b0feb86222cfbe46d3c20fd760b7935fa60ed2d Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Fri, 23 Sep 2022 10:32:17 -0700 Subject: [PATCH 180/586] rustdoc: remove no-op mobile CSS `#source-sidebar { z-index: 11 }` This rule became redundant in 07e3f998b1ceb4b8d2a7992782e60f5e776aa114. When `#source-sidebar` became nested below `.sidebar`, it went from being `position: fixed` to `position: static`, and according to MDN's [z-index] documentation, this means it has no effect. [z-index]: https://developer.mozilla.org/en-US/docs/Web/CSS/z-index --- src/librustdoc/html/static/css/rustdoc.css | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index 3461d083c604d..651f05284ffb4 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -1922,10 +1922,6 @@ in storage.js plus the media query with (min-width: 701px) border-bottom: 1px solid; } - #source-sidebar { - z-index: 11; - } - #main-content > .line-numbers { margin-top: 0; } From f570d310b790142f5e77120f0a099b54996a748e Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Fri, 23 Sep 2022 10:48:24 -0700 Subject: [PATCH 181/586] rustdoc: remove no-op CSS rule `#source-sidebar { z-index: 1 }` This rule became redundant in 07e3f998b1ceb4b8d2a7992782e60f5e776aa114. When `#source-sidebar` became nested below `.sidebar`, it went from being `position: fixed` to `position: static`, and according to MDN's [z-index] documentation, this means it has no effect. [z-index]: https://developer.mozilla.org/en-US/docs/Web/CSS/z-index --- src/librustdoc/html/static/css/rustdoc.css | 1 - 1 file changed, 1 deletion(-) diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index 651f05284ffb4..df60018c5d88f 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -1416,7 +1416,6 @@ pre.rust { } #source-sidebar { width: 100%; - z-index: 1; overflow: auto; } #source-sidebar > .title { From d78bc41785aaa5be7eff96b100268d3c5daa5401 Mon Sep 17 00:00:00 2001 From: onestacked Date: Fri, 23 Sep 2022 19:55:51 +0200 Subject: [PATCH 182/586] Remove unused `ConstFn(Once)Closure` structs. --- library/core/src/const_closure.rs | 125 ------------------------------ 1 file changed, 125 deletions(-) diff --git a/library/core/src/const_closure.rs b/library/core/src/const_closure.rs index 6ea94c95473dd..d2e80e8e7e5df 100644 --- a/library/core/src/const_closure.rs +++ b/library/core/src/const_closure.rs @@ -1,56 +1,5 @@ use crate::marker::Destruct; -/// Struct representing a closure with owned data. -/// -/// Example: -/// ```no_build -/// use crate::const_closure::ConstFnOnceClosure; -/// const fn imp(state: i32, (arg,): (i32,)) -> i32 { -/// state + arg -/// } -/// let i = 5; -/// let cl = ConstFnOnceClosure::new(i, imp); -/// -/// assert!(7 == cl(2)); -/// ``` -pub(crate) struct ConstFnOnceClosure { - data: CapturedData, - func: Function, -} - -impl ConstFnOnceClosure { - /// Function for creating a new closure. - /// - /// `data` is the owned data that is captured from the environment (this data must be `~const Destruct`). - /// - /// `func` is the function of the closure, it gets the data and a tuple of the arguments closure - /// and return the return value of the closure. - #[allow(dead_code)] - pub(crate) const fn new( - data: CapturedData, - func: Function, - ) -> Self - where - CapturedData: ~const Destruct, - Function: ~const Fn(CapturedData, ClosureArguments) -> ClosureReturnValue + ~const Destruct, - { - Self { data, func } - } -} - -impl const FnOnce - for ConstFnOnceClosure -where - CapturedData: ~const Destruct, - Function: ~const Fn<(CapturedData, ClosureArguments)> + ~const Destruct, -{ - type Output = Function::Output; - - extern "rust-call" fn call_once(self, args: ClosureArguments) -> Self::Output { - (self.func)(self.data, args) - } -} - /// Struct representing a closure with mutably borrowed data. /// /// Example: @@ -112,77 +61,3 @@ where (self.func)(self.data, args) } } - -/// Struct representing a closure with borrowed data. -/// -/// Example: -/// ```no_build -/// use crate::const_closure::ConstFnClosure; -/// -/// const fn imp(state: &i32, (arg,): (i32,)) -> i32 { -/// *state + arg -/// } -/// let i = 5; -/// let cl = ConstFnClosure::new(&i, imp); -/// -/// assert!(7 == cl(2)); -/// assert!(6 == cl(1)); -/// ``` -pub(crate) struct ConstFnClosure<'a, CapturedData: ?Sized, Function> { - data: &'a CapturedData, - func: Function, -} - -impl<'a, CapturedData: ?Sized, Function> ConstFnClosure<'a, CapturedData, Function> { - /// Function for creating a new closure. - /// - /// `data` is the a mutable borrow of data that is captured from the environment. - /// - /// `func` is the function of the closure, it gets the data and a tuple of the arguments closure - /// and return the return value of the closure. - #[allow(dead_code)] - pub(crate) const fn new( - data: &'a CapturedData, - func: Function, - ) -> Self - where - Function: ~const Fn(&CapturedData, ClosureArguments) -> ClosureReturnValue, - { - Self { data, func } - } -} - -impl<'a, CapturedData: ?Sized, Function, ClosureArguments, ClosureReturnValue> const - FnOnce for ConstFnClosure<'a, CapturedData, Function> -where - Function: ~const Fn(&CapturedData, ClosureArguments) -> ClosureReturnValue + ~const Destruct, -{ - type Output = ClosureReturnValue; - - extern "rust-call" fn call_once(mut self, args: ClosureArguments) -> Self::Output { - self.call_mut(args) - } -} - -impl<'a, CapturedData: ?Sized, Function, ClosureArguments, ClosureReturnValue> const - FnMut for ConstFnClosure<'a, CapturedData, Function> -where - Function: ~const Fn(&CapturedData, ClosureArguments) -> ClosureReturnValue, -{ - extern "rust-call" fn call_mut(&mut self, args: ClosureArguments) -> Self::Output { - self.call(args) - } -} - -impl< - 'a, - CapturedData: ?Sized, - Function: ~const Fn(&CapturedData, ClosureArguments) -> ClosureReturnValue, - ClosureArguments, - ClosureReturnValue, -> const Fn for ConstFnClosure<'a, CapturedData, Function> -{ - extern "rust-call" fn call(&self, args: ClosureArguments) -> Self::Output { - (self.func)(self.data, args) - } -} From a74eba4ad56fe3138a23c471ad00d0e906bc3809 Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Fri, 23 Sep 2022 18:07:36 +0000 Subject: [PATCH 183/586] Make `ManuallyDrop` satisfy `~const Destruct` --- .../rustc_trait_selection/src/traits/select/confirmation.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index e08f03a270c89..27fbfb6dd21fb 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -1224,6 +1224,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { | ty::Never | ty::Foreign(_) => {} + // `ManuallyDrop` is trivially drop + ty::Adt(def, _) if Some(def.did()) == tcx.lang_items().manually_drop() => {} + // These types are built-in, so we can fast-track by registering // nested predicates for their constituent type(s) ty::Array(ty, _) | ty::Slice(ty) => { From 84666afb36365c3dafe0acfdcd17ea177f58af19 Mon Sep 17 00:00:00 2001 From: onestacked Date: Fri, 23 Sep 2022 20:17:31 +0200 Subject: [PATCH 184/586] Constify Residual behind const_try --- library/core/src/ops/control_flow.rs | 1 + library/core/src/option.rs | 3 ++- library/core/src/result.rs | 3 ++- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/library/core/src/ops/control_flow.rs b/library/core/src/ops/control_flow.rs index 8d236a9fecaea..72ebe653caff3 100644 --- a/library/core/src/ops/control_flow.rs +++ b/library/core/src/ops/control_flow.rs @@ -126,6 +126,7 @@ impl const ops::FromResidual for ControlFlow { } #[unstable(feature = "try_trait_v2_residual", issue = "91285")] +#[rustc_const_unstable(feature = "const_try", issue = "74935")] impl const ops::Residual for ControlFlow { type TryType = ControlFlow; } diff --git a/library/core/src/option.rs b/library/core/src/option.rs index 934175863630f..96b16b13256ce 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -2321,7 +2321,8 @@ impl ops::FromResidual> for Option { } #[unstable(feature = "try_trait_v2_residual", issue = "91285")] -impl ops::Residual for Option { +#[rustc_const_unstable(feature = "const_try", issue = "74935")] +impl const ops::Residual for Option { type TryType = Option; } diff --git a/library/core/src/result.rs b/library/core/src/result.rs index 76eaa191f7811..dc90e90402c8e 100644 --- a/library/core/src/result.rs +++ b/library/core/src/result.rs @@ -2116,6 +2116,7 @@ impl> ops::FromResidual> for Result { } #[unstable(feature = "try_trait_v2_residual", issue = "91285")] -impl ops::Residual for Result { +#[rustc_const_unstable(feature = "const_try", issue = "74935")] +impl const ops::Residual for Result { type TryType = Result; } From aa35ab81ea4bd427a86e0c781c342835a020e6fe Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Fri, 23 Sep 2022 18:03:44 +0200 Subject: [PATCH 185/586] Stabilize const `BTree{Map,Set}::new` Since `len` and `is_empty` are not const stable yet, this also creates a new feature for them since they previously used the same `const_btree_new` feature. --- compiler/rustc_hir/src/lib.rs | 2 +- library/alloc/src/collections/btree/map.rs | 6 +++--- library/alloc/src/collections/btree/set.rs | 6 +++--- library/alloc/src/lib.rs | 2 +- library/alloc/tests/lib.rs | 2 +- src/test/ui/consts/issue-88071.rs | 2 -- src/tools/clippy/tests/ui/crashes/ice-7126.rs | 6 +++--- 7 files changed, 12 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_hir/src/lib.rs b/compiler/rustc_hir/src/lib.rs index 946da9265ba09..556ff1cc48e4d 100644 --- a/compiler/rustc_hir/src/lib.rs +++ b/compiler/rustc_hir/src/lib.rs @@ -4,7 +4,7 @@ #![feature(associated_type_defaults)] #![feature(closure_track_caller)] -#![feature(const_btree_new)] +#![feature(const_btree_len)] #![cfg_attr(bootstrap, feature(let_else))] #![feature(once_cell)] #![feature(min_specialization)] diff --git a/library/alloc/src/collections/btree/map.rs b/library/alloc/src/collections/btree/map.rs index cacbd54b6c246..3018d1c9125bf 100644 --- a/library/alloc/src/collections/btree/map.rs +++ b/library/alloc/src/collections/btree/map.rs @@ -580,7 +580,7 @@ impl BTreeMap { /// map.insert(1, "a"); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_btree_new", issue = "71835")] + #[rustc_const_stable(feature = "const_btree_new", since = "CURRENT_RUSTC_VERSION")] #[must_use] pub const fn new() -> BTreeMap { BTreeMap { root: None, length: 0, alloc: ManuallyDrop::new(Global), _marker: PhantomData } @@ -2392,7 +2392,7 @@ impl BTreeMap { /// ``` #[must_use] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_btree_new", issue = "71835")] + #[rustc_const_unstable(feature = "const_btree_len", issue = "71835")] pub const fn len(&self) -> usize { self.length } @@ -2413,7 +2413,7 @@ impl BTreeMap { /// ``` #[must_use] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_btree_new", issue = "71835")] + #[rustc_const_unstable(feature = "const_btree_len", issue = "71835")] pub const fn is_empty(&self) -> bool { self.len() == 0 } diff --git a/library/alloc/src/collections/btree/set.rs b/library/alloc/src/collections/btree/set.rs index 2cfc080740921..3caaf521240d2 100644 --- a/library/alloc/src/collections/btree/set.rs +++ b/library/alloc/src/collections/btree/set.rs @@ -343,7 +343,7 @@ impl BTreeSet { /// let mut set: BTreeSet = BTreeSet::new(); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_btree_new", issue = "71835")] + #[rustc_const_stable(feature = "const_btree_new", since = "CURRENT_RUSTC_VERSION")] #[must_use] pub const fn new() -> BTreeSet { BTreeSet { map: BTreeMap::new() } @@ -1174,7 +1174,7 @@ impl BTreeSet { /// ``` #[must_use] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_btree_new", issue = "71835")] + #[rustc_const_unstable(feature = "const_btree_len", issue = "71835")] pub const fn len(&self) -> usize { self.map.len() } @@ -1193,7 +1193,7 @@ impl BTreeSet { /// ``` #[must_use] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_btree_new", issue = "71835")] + #[rustc_const_unstable(feature = "const_btree_len", issue = "71835")] pub const fn is_empty(&self) -> bool { self.len() == 0 } diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index 6b3b1c222229c..fe89394dda928 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -99,7 +99,7 @@ #![feature(coerce_unsized)] #![cfg_attr(not(no_global_oom_handling), feature(const_alloc_error))] #![feature(const_box)] -#![cfg_attr(not(no_global_oom_handling), feature(const_btree_new))] +#![cfg_attr(not(no_global_oom_handling), feature(const_btree_len))] #![feature(const_cow_is_borrowed)] #![feature(const_convert)] #![feature(const_size_of_val)] diff --git a/library/alloc/tests/lib.rs b/library/alloc/tests/lib.rs index 490c0d8f76cda..55aced5106c94 100644 --- a/library/alloc/tests/lib.rs +++ b/library/alloc/tests/lib.rs @@ -32,7 +32,7 @@ #![feature(slice_group_by)] #![feature(slice_partition_dedup)] #![feature(string_remove_matches)] -#![feature(const_btree_new)] +#![feature(const_btree_len)] #![feature(const_default_impls)] #![feature(const_trait_impl)] #![feature(const_str_from_utf8)] diff --git a/src/test/ui/consts/issue-88071.rs b/src/test/ui/consts/issue-88071.rs index 1c38c43e6c0c5..f58cdb5945e53 100644 --- a/src/test/ui/consts/issue-88071.rs +++ b/src/test/ui/consts/issue-88071.rs @@ -2,8 +2,6 @@ // // regression test for #88071 -#![feature(const_btree_new)] - use std::collections::BTreeMap; pub struct CustomMap(BTreeMap); diff --git a/src/tools/clippy/tests/ui/crashes/ice-7126.rs b/src/tools/clippy/tests/ui/crashes/ice-7126.rs index ca563ba097851..b2dc2248b5562 100644 --- a/src/tools/clippy/tests/ui/crashes/ice-7126.rs +++ b/src/tools/clippy/tests/ui/crashes/ice-7126.rs @@ -1,13 +1,13 @@ // This test requires a feature gated const fn and will stop working in the future. -#![feature(const_btree_new)] +#![feature(const_btree_len)] use std::collections::BTreeMap; -struct Foo(BTreeMap); +struct Foo(usize); impl Foo { fn new() -> Self { - Self(BTreeMap::new()) + Self(BTreeMap::len(&BTreeMap::::new())) } } From 66484c0a21b840b30f865e92fdd5b3bad877816f Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Fri, 23 Sep 2022 21:04:54 +0200 Subject: [PATCH 186/586] Fix clippy's const fn stability check for CURRENT_RUSTC_VERSION Since clippy can use a projects MSRV for its lints, it might not want to consider functions as const stable if they have been added lately. Functions that have been stabilized this version use CURRENT_RUSTC_VERSION as their version, which gets then turned into the current version, which might be something like `1.66.0-dev`. The version parser cannot deal with this version, so it has to be stripped off. --- .../clippy/clippy_utils/src/qualify_min_const_fn.rs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs index 405f022868395..f7ce719177268 100644 --- a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs +++ b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs @@ -367,10 +367,21 @@ fn is_const_fn(tcx: TyCtxt<'_>, def_id: DefId, msrv: Option) -> bo // Checking MSRV is manually necessary because `rustc` has no such concept. This entire // function could be removed if `rustc` provided a MSRV-aware version of `is_const_fn`. // as a part of an unimplemented MSRV check https://github.com/rust-lang/rust/issues/65262. + + // HACK(nilstrieb): CURRENT_RUSTC_VERSION can return versions like 1.66.0-dev. `rustc-semver` doesn't accept + // the `-dev` version number so we have to strip it off. + let short_version = since + .as_str() + .split('-') + .next() + .expect("rustc_attr::StabilityLevel::Stable::since` is empty"); + + let since = rustc_span::Symbol::intern(short_version); + crate::meets_msrv( msrv, RustcVersion::parse(since.as_str()) - .expect("`rustc_attr::StabilityLevel::Stable::since` is ill-formatted"), + .unwrap_or_else(|err| panic!("`rustc_attr::StabilityLevel::Stable::since` is ill-formatted: `{since}`, {err:?}")), ) } else { // Unstable const fn with the feature enabled. From 28e0c5aec8335d34cd84f3970d633860d6bd08a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Fri, 16 Sep 2022 00:06:25 +0200 Subject: [PATCH 187/586] Allow more !Copy impls --- .../rustc_typeck/src/coherence/builtin.rs | 18 ++++------ .../coherence-negative-impls-copy-bad.rs | 11 ++++++ .../coherence-negative-impls-copy-bad.stderr | 36 +++++++++++++++++++ .../coherence-negative-impls-copy.rs | 29 +++++++++++++++ .../ui/coherence/deep-bad-copy-reason.stderr | 4 +-- src/test/ui/opt-in-copy.stderr | 8 ++--- src/test/ui/span/E0204.stderr | 8 ++--- ...missing-bound-in-manual-copy-impl-2.stderr | 4 +-- .../missing-bound-in-manual-copy-impl.stderr | 4 +-- .../traits/copy-impl-cannot-normalize.stderr | 4 +-- src/test/ui/union/union-copy.stderr | 4 +-- 11 files changed, 100 insertions(+), 30 deletions(-) create mode 100644 src/test/ui/coherence/coherence-negative-impls-copy-bad.rs create mode 100644 src/test/ui/coherence/coherence-negative-impls-copy-bad.stderr create mode 100644 src/test/ui/coherence/coherence-negative-impls-copy.rs diff --git a/compiler/rustc_typeck/src/coherence/builtin.rs b/compiler/rustc_typeck/src/coherence/builtin.rs index d08c0d4dbb72a..d4eb826f0b4d3 100644 --- a/compiler/rustc_typeck/src/coherence/builtin.rs +++ b/compiler/rustc_typeck/src/coherence/builtin.rs @@ -70,23 +70,21 @@ fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) { let self_type = tcx.type_of(impl_did); debug!("visit_implementation_of_copy: self_type={:?} (bound)", self_type); - let span = tcx.hir().span(impl_hir_id); let param_env = tcx.param_env(impl_did); assert!(!self_type.has_escaping_bound_vars()); debug!("visit_implementation_of_copy: self_type={:?} (free)", self_type); + let span = match tcx.hir().expect_item(impl_did).kind { + ItemKind::Impl(hir::Impl { polarity: hir::ImplPolarity::Negative(_), .. }) => return, + ItemKind::Impl(impl_) => impl_.self_ty.span, + _ => bug!("expected Copy impl item"), + }; + let cause = traits::ObligationCause::misc(span, impl_hir_id); match can_type_implement_copy(tcx, param_env, self_type, cause) { Ok(()) => {} Err(CopyImplementationError::InfrigingFields(fields)) => { - let item = tcx.hir().expect_item(impl_did); - let span = if let ItemKind::Impl(hir::Impl { of_trait: Some(ref tr), .. }) = item.kind { - tr.path.span - } else { - span - }; - let mut err = struct_span_err!( tcx.sess, span, @@ -166,10 +164,6 @@ fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) { err.emit(); } Err(CopyImplementationError::NotAnAdt) => { - let item = tcx.hir().expect_item(impl_did); - let span = - if let ItemKind::Impl(ref impl_) = item.kind { impl_.self_ty.span } else { span }; - tcx.sess.emit_err(CopyImplOnNonAdt { span }); } Err(CopyImplementationError::HasDestructor) => { diff --git a/src/test/ui/coherence/coherence-negative-impls-copy-bad.rs b/src/test/ui/coherence/coherence-negative-impls-copy-bad.rs new file mode 100644 index 0000000000000..563f28e2291d4 --- /dev/null +++ b/src/test/ui/coherence/coherence-negative-impls-copy-bad.rs @@ -0,0 +1,11 @@ +#![feature(negative_impls)] +#![crate_type = "lib"] + +impl !Copy for str {} +//~^ ERROR only traits defined in the current crate can be implemented + +impl !Copy for fn() {} +//~^ ERROR only traits defined in the current crate can be implemented + +impl !Copy for () {} +//~^ ERROR only traits defined in the current crate can be implemented diff --git a/src/test/ui/coherence/coherence-negative-impls-copy-bad.stderr b/src/test/ui/coherence/coherence-negative-impls-copy-bad.stderr new file mode 100644 index 0000000000000..2295d6315d1c2 --- /dev/null +++ b/src/test/ui/coherence/coherence-negative-impls-copy-bad.stderr @@ -0,0 +1,36 @@ +error[E0117]: only traits defined in the current crate can be implemented for arbitrary types + --> $DIR/coherence-negative-impls-copy-bad.rs:4:1 + | +LL | impl !Copy for str {} + | ^^^^^^^^^^^^^^^--- + | | | + | | `str` is not defined in the current crate + | impl doesn't use only types from inside the current crate + | + = note: define and implement a trait or new type instead + +error[E0117]: only traits defined in the current crate can be implemented for arbitrary types + --> $DIR/coherence-negative-impls-copy-bad.rs:7:1 + | +LL | impl !Copy for fn() {} + | ^^^^^^^^^^^^^^^---- + | | | + | | `fn()` is not defined in the current crate + | impl doesn't use only types from inside the current crate + | + = note: define and implement a trait or new type instead + +error[E0117]: only traits defined in the current crate can be implemented for arbitrary types + --> $DIR/coherence-negative-impls-copy-bad.rs:10:1 + | +LL | impl !Copy for () {} + | ^^^^^^^^^^^^^^^-- + | | | + | | this is not defined in the current crate because tuples are always foreign + | impl doesn't use only types from inside the current crate + | + = note: define and implement a trait or new type instead + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0117`. diff --git a/src/test/ui/coherence/coherence-negative-impls-copy.rs b/src/test/ui/coherence/coherence-negative-impls-copy.rs new file mode 100644 index 0000000000000..7b29aade41335 --- /dev/null +++ b/src/test/ui/coherence/coherence-negative-impls-copy.rs @@ -0,0 +1,29 @@ +// check-pass +// regression test for issue #101836 + +#![feature(negative_impls, extern_types)] +#![crate_type = "lib"] + +struct NonCopy; +struct NeverCopy(NonCopy); + +impl !Copy for NeverCopy {} + + +struct WithDrop; +impl Drop for WithDrop { fn drop(&mut self) {} } + +impl !Copy for WithDrop {} + + +struct Type; +trait Trait {} +extern { + type ExternType; +} + +impl !Copy for &mut Type {} + +impl !Copy for dyn Trait {} + +impl !Copy for ExternType {} diff --git a/src/test/ui/coherence/deep-bad-copy-reason.stderr b/src/test/ui/coherence/deep-bad-copy-reason.stderr index 295538cee6096..168ee57263d2a 100644 --- a/src/test/ui/coherence/deep-bad-copy-reason.stderr +++ b/src/test/ui/coherence/deep-bad-copy-reason.stderr @@ -1,11 +1,11 @@ error[E0204]: the trait `Copy` may not be implemented for this type - --> $DIR/deep-bad-copy-reason.rs:33:15 + --> $DIR/deep-bad-copy-reason.rs:33:24 | LL | pub struct List<'tcx, T>(Interned<'tcx, ListS>); | ------------------------ this field does not implement `Copy` ... LL | impl<'tcx, T> Copy for List<'tcx, T> {} - | ^^^^ + | ^^^^^^^^^^^^^ | note: the `Copy` impl for `Interned<'tcx, ListS>` requires that `OpaqueListContents: Sized` --> $DIR/deep-bad-copy-reason.rs:23:26 diff --git a/src/test/ui/opt-in-copy.stderr b/src/test/ui/opt-in-copy.stderr index 0a275f1aa41d7..4461567df0a2a 100644 --- a/src/test/ui/opt-in-copy.stderr +++ b/src/test/ui/opt-in-copy.stderr @@ -1,20 +1,20 @@ error[E0204]: the trait `Copy` may not be implemented for this type - --> $DIR/opt-in-copy.rs:7:6 + --> $DIR/opt-in-copy.rs:7:15 | LL | but_i_cant: CantCopyThis, | ------------------------ this field does not implement `Copy` ... LL | impl Copy for IWantToCopyThis {} - | ^^^^ + | ^^^^^^^^^^^^^^^ error[E0204]: the trait `Copy` may not be implemented for this type - --> $DIR/opt-in-copy.rs:19:6 + --> $DIR/opt-in-copy.rs:19:15 | LL | ButICant(CantCopyThisEither), | ------------------ this field does not implement `Copy` ... LL | impl Copy for IWantToCopyThisToo {} - | ^^^^ + | ^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/span/E0204.stderr b/src/test/ui/span/E0204.stderr index 2575848435206..0b2166eed7ead 100644 --- a/src/test/ui/span/E0204.stderr +++ b/src/test/ui/span/E0204.stderr @@ -1,11 +1,11 @@ error[E0204]: the trait `Copy` may not be implemented for this type - --> $DIR/E0204.rs:5:6 + --> $DIR/E0204.rs:5:15 | LL | foo: Vec, | ------------- this field does not implement `Copy` ... LL | impl Copy for Foo { } - | ^^^^ + | ^^^ error[E0204]: the trait `Copy` may not be implemented for this type --> $DIR/E0204.rs:7:10 @@ -19,13 +19,13 @@ LL | ty: &'a mut bool, = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0204]: the trait `Copy` may not be implemented for this type - --> $DIR/E0204.rs:17:6 + --> $DIR/E0204.rs:17:15 | LL | Bar { x: Vec }, | ----------- this field does not implement `Copy` ... LL | impl Copy for EFoo { } - | ^^^^ + | ^^^^ error[E0204]: the trait `Copy` may not be implemented for this type --> $DIR/E0204.rs:19:10 diff --git a/src/test/ui/suggestions/missing-bound-in-manual-copy-impl-2.stderr b/src/test/ui/suggestions/missing-bound-in-manual-copy-impl-2.stderr index e0f405eedfa69..9e6f0d9ebbd27 100644 --- a/src/test/ui/suggestions/missing-bound-in-manual-copy-impl-2.stderr +++ b/src/test/ui/suggestions/missing-bound-in-manual-copy-impl-2.stderr @@ -1,11 +1,11 @@ error[E0204]: the trait `Copy` may not be implemented for this type - --> $DIR/missing-bound-in-manual-copy-impl-2.rs:16:9 + --> $DIR/missing-bound-in-manual-copy-impl-2.rs:16:18 | LL | struct Wrapper(T); | - this field does not implement `Copy` ... LL | impl Copy for Wrapper> {} - | ^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: the `Copy` impl for `OnlyCopyIfDisplay` requires that `S: std::fmt::Display` --> $DIR/missing-bound-in-manual-copy-impl-2.rs:4:19 diff --git a/src/test/ui/suggestions/missing-bound-in-manual-copy-impl.stderr b/src/test/ui/suggestions/missing-bound-in-manual-copy-impl.stderr index 218988511dbc3..fe2d133c8aa74 100644 --- a/src/test/ui/suggestions/missing-bound-in-manual-copy-impl.stderr +++ b/src/test/ui/suggestions/missing-bound-in-manual-copy-impl.stderr @@ -1,11 +1,11 @@ error[E0204]: the trait `Copy` may not be implemented for this type - --> $DIR/missing-bound-in-manual-copy-impl.rs:6:9 + --> $DIR/missing-bound-in-manual-copy-impl.rs:6:18 | LL | struct Wrapper(T); | - this field does not implement `Copy` LL | LL | impl Copy for Wrapper {} - | ^^^^ + | ^^^^^^^^^^ | help: consider restricting type parameter `S` | diff --git a/src/test/ui/traits/copy-impl-cannot-normalize.stderr b/src/test/ui/traits/copy-impl-cannot-normalize.stderr index afdad160919f9..68b95b42b3463 100644 --- a/src/test/ui/traits/copy-impl-cannot-normalize.stderr +++ b/src/test/ui/traits/copy-impl-cannot-normalize.stderr @@ -1,8 +1,8 @@ error[E0277]: the trait bound `T: TraitFoo` is not satisfied - --> $DIR/copy-impl-cannot-normalize.rs:22:1 + --> $DIR/copy-impl-cannot-normalize.rs:22:18 | LL | impl Copy for Foo {} - | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `TraitFoo` is not implemented for `T` + | ^^^^^^ the trait `TraitFoo` is not implemented for `T` | help: consider restricting type parameter `T` | diff --git a/src/test/ui/union/union-copy.stderr b/src/test/ui/union/union-copy.stderr index 8ecdafdde2045..53ee4dd2e5bdb 100644 --- a/src/test/ui/union/union-copy.stderr +++ b/src/test/ui/union/union-copy.stderr @@ -1,11 +1,11 @@ error[E0204]: the trait `Copy` may not be implemented for this type - --> $DIR/union-copy.rs:12:6 + --> $DIR/union-copy.rs:12:15 | LL | a: std::mem::ManuallyDrop | --------------------------------- this field does not implement `Copy` ... LL | impl Copy for W {} - | ^^^^ + | ^ | note: the `Copy` impl for `ManuallyDrop` requires that `String: Copy` --> $DIR/union-copy.rs:8:8 From ac06d9cca369b164ab522eba81d6b048309f058a Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Fri, 23 Sep 2022 13:24:35 -0700 Subject: [PATCH 188/586] diagnostics: avoid syntactically invalid suggestion in if conditionals Fixes #101065 --- compiler/rustc_typeck/src/check/demand.rs | 10 +++++++++ src/test/ui/suggestions/issue-101065.fixed | 14 +++++++++++++ src/test/ui/suggestions/issue-101065.rs | 14 +++++++++++++ src/test/ui/suggestions/issue-101065.stderr | 23 +++++++++++++++++++++ 4 files changed, 61 insertions(+) create mode 100644 src/test/ui/suggestions/issue-101065.fixed create mode 100644 src/test/ui/suggestions/issue-101065.rs create mode 100644 src/test/ui/suggestions/issue-101065.stderr diff --git a/compiler/rustc_typeck/src/check/demand.rs b/compiler/rustc_typeck/src/check/demand.rs index e1d55ff82cbad..2c07c333a6f98 100644 --- a/compiler/rustc_typeck/src/check/demand.rs +++ b/compiler/rustc_typeck/src/check/demand.rs @@ -417,6 +417,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { hir::def::CtorKind::Const => unreachable!(), }; + // Suggest constructor as deep into the block tree as possible. + // This fixes https://github.com/rust-lang/rust/issues/101065, + // and also just helps make the most minimal suggestions. + let mut expr = expr; + while let hir::ExprKind::Block(block, _) = &expr.kind + && let Some(expr_) = &block.expr + { + expr = expr_ + } + vec![ (expr.span.shrink_to_lo(), format!("{prefix}{variant}{open}")), (expr.span.shrink_to_hi(), close.to_owned()), diff --git a/src/test/ui/suggestions/issue-101065.fixed b/src/test/ui/suggestions/issue-101065.fixed new file mode 100644 index 0000000000000..88c716cc86ce8 --- /dev/null +++ b/src/test/ui/suggestions/issue-101065.fixed @@ -0,0 +1,14 @@ +// check-fail +// run-rustfix + +enum FakeResult { + Ok(T) +} + +fn main() { + let _x = if true { + FakeResult::Ok(FakeResult::Ok(())) + } else { + FakeResult::Ok(FakeResult::Ok(())) //~ERROR E0308 + }; +} diff --git a/src/test/ui/suggestions/issue-101065.rs b/src/test/ui/suggestions/issue-101065.rs new file mode 100644 index 0000000000000..2715f1027082f --- /dev/null +++ b/src/test/ui/suggestions/issue-101065.rs @@ -0,0 +1,14 @@ +// check-fail +// run-rustfix + +enum FakeResult { + Ok(T) +} + +fn main() { + let _x = if true { + FakeResult::Ok(FakeResult::Ok(())) + } else { + FakeResult::Ok(()) //~ERROR E0308 + }; +} diff --git a/src/test/ui/suggestions/issue-101065.stderr b/src/test/ui/suggestions/issue-101065.stderr new file mode 100644 index 0000000000000..6f7ecd24ca428 --- /dev/null +++ b/src/test/ui/suggestions/issue-101065.stderr @@ -0,0 +1,23 @@ +error[E0308]: `if` and `else` have incompatible types + --> $DIR/issue-101065.rs:12:9 + | +LL | let _x = if true { + | ______________- +LL | | FakeResult::Ok(FakeResult::Ok(())) + | | ---------------------------------- expected because of this +LL | | } else { +LL | | FakeResult::Ok(()) + | | ^^^^^^^^^^^^^^^^^^ expected enum `FakeResult`, found `()` +LL | | }; + | |_____- `if` and `else` have incompatible types + | + = note: expected enum `FakeResult>` + found enum `FakeResult<()>` +help: try wrapping the expression in `FakeResult::Ok` + | +LL | FakeResult::Ok(FakeResult::Ok(())) + | +++++++++++++++ + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. From eb1ddd2573fc41062c36d5ceb484f5a99364b3b8 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sat, 24 Sep 2022 00:10:28 +0200 Subject: [PATCH 189/586] Bless miri. --- .../miri/tests/fail/concurrency/windows_join_detached.stderr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri/tests/fail/concurrency/windows_join_detached.stderr b/src/tools/miri/tests/fail/concurrency/windows_join_detached.stderr index 78c75611d3333..20f34cf104d63 100644 --- a/src/tools/miri/tests/fail/concurrency/windows_join_detached.stderr +++ b/src/tools/miri/tests/fail/concurrency/windows_join_detached.stderr @@ -8,7 +8,7 @@ LL | let rc = unsafe { c::WaitForSingleObject(self.handle.as_raw_handle( = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information = note: BACKTRACE: = note: inside `std::sys::PLATFORM::thread::Thread::join` at RUSTLIB/std/src/sys/PLATFORM/thread.rs:LL:CC - = note: inside `std::thread::JoinInner::<()>::join` at RUSTLIB/std/src/thread/mod.rs:LL:CC + = note: inside `std::thread::JoinInner::<'_, ()>::join` at RUSTLIB/std/src/thread/mod.rs:LL:CC = note: inside `std::thread::JoinHandle::<()>::join` at RUSTLIB/std/src/thread/mod.rs:LL:CC note: inside `main` at $DIR/windows_join_detached.rs:LL:CC --> $DIR/windows_join_detached.rs:LL:CC From 7ad0ac75c90c56174483a6bac78bd523c49fb07b Mon Sep 17 00:00:00 2001 From: Chris Wailes Date: Fri, 23 Sep 2022 16:14:17 -0700 Subject: [PATCH 190/586] Respond to document review feedback --- src/doc/rustc/src/SUMMARY.md | 2 +- src/doc/rustc/src/platform-support/android.md | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md index 5b9e913116e50..ce120b99f997e 100644 --- a/src/doc/rustc/src/SUMMARY.md +++ b/src/doc/rustc/src/SUMMARY.md @@ -23,7 +23,7 @@ - [armv6k-nintendo-3ds](platform-support/armv6k-nintendo-3ds.md) - [armv7-unknown-linux-uclibceabi](platform-support/armv7-unknown-linux-uclibceabi.md) - [armv7-unknown-linux-uclibceabihf](platform-support/armv7-unknown-linux-uclibceabihf.md) - - [\*-android(eabi)?](platform-support/android.md) + - [\*-android and \*-androideabi](platform-support/android.md) - [\*-fuchsia](platform-support/fuchsia.md) - [\*-kmc-solid_\*](platform-support/kmc-solid.md) - [m68k-unknown-linux-gnu](platform-support/m68k-unknown-linux-gnu.md) diff --git a/src/doc/rustc/src/platform-support/android.md b/src/doc/rustc/src/platform-support/android.md index 752246db8d58f..b2c8e5d4df736 100644 --- a/src/doc/rustc/src/platform-support/android.md +++ b/src/doc/rustc/src/platform-support/android.md @@ -19,13 +19,13 @@ from the [source tree] or using the Android NDK. [source tree]: https://source.android.com/docs/setup/build/downloading -Android targets support std and generated binaries use the ELF file format. +Android targets support std. Generated binaries use the ELF file format. ## NDK/API Update Policy Rust will support the most recent Long Term Support (LTS) Android Native Development Kit (NDK). By default Rust will support all API levels supported -by the NDK but a higher minimum API level may be required if deemed necessary. +by the NDK, but a higher minimum API level may be required if deemed necessary. ## Building the target From ad05b32fee4d9ed08581fabb5c4554f00819b917 Mon Sep 17 00:00:00 2001 From: inquisitivecrystal <22333129+inquisitivecrystal@users.noreply.github.com> Date: Fri, 23 Sep 2022 03:09:16 -0700 Subject: [PATCH 191/586] Add regression test for issue #100878 --- src/test/ui/consts/const-eval/issue-100878.rs | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 src/test/ui/consts/const-eval/issue-100878.rs diff --git a/src/test/ui/consts/const-eval/issue-100878.rs b/src/test/ui/consts/const-eval/issue-100878.rs new file mode 100644 index 0000000000000..353ce5050359c --- /dev/null +++ b/src/test/ui/consts/const-eval/issue-100878.rs @@ -0,0 +1,8 @@ +// This checks that the const-eval ICE in issue #100878 does not recur. +// +// build-pass +pub fn bitshift_data(data: [u8; 1]) -> u8 { + data[0] << 8 +} + +fn main() {} From 3d01d43d488553d5fe8391564de36eed8659ca4c Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Fri, 23 Sep 2022 18:04:15 -0700 Subject: [PATCH 192/586] rustdoc: Stabilize --diagnostic-width --- src/librustdoc/lib.rs | 2 +- src/test/rustdoc-ui/diagnostic-width.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 14d695582b0f8..23ad0c30f21ed 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -461,7 +461,7 @@ fn opts() -> Vec { "human|json|short", ) }), - unstable("diagnostic-width", |o| { + stable("diagnostic-width", |o| { o.optopt( "", "diagnostic-width", diff --git a/src/test/rustdoc-ui/diagnostic-width.rs b/src/test/rustdoc-ui/diagnostic-width.rs index 61961d5ec710e..290d9db775b73 100644 --- a/src/test/rustdoc-ui/diagnostic-width.rs +++ b/src/test/rustdoc-ui/diagnostic-width.rs @@ -1,4 +1,4 @@ -// compile-flags: -Zunstable-options --diagnostic-width=10 +// compile-flags: --diagnostic-width=10 #![deny(rustdoc::bare_urls)] /// This is a long line that contains a http://link.com From f5f69bc0bbb1ac4e7c5e3a295392786bea80b22d Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Fri, 23 Sep 2022 19:02:59 -0700 Subject: [PATCH 193/586] Document some missing command-line arguments --- src/doc/rustc/src/command-line-arguments.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/doc/rustc/src/command-line-arguments.md b/src/doc/rustc/src/command-line-arguments.md index f05ff3f1b6b4e..79cdfb82e417e 100644 --- a/src/doc/rustc/src/command-line-arguments.md +++ b/src/doc/rustc/src/command-line-arguments.md @@ -270,6 +270,11 @@ This flag will set which lints should be set to the [warn level](lints/levels.md _Note:_ The order of these lint level arguments is taken into account, see [lint level via compiler flag](lints/levels.md#via-compiler-flag) for more information. + +## `--force-warn`: force a lint to warn + +This flag sets the given lint to the [forced warn level](lints/levels.md#force-warn) and the level cannot be overridden, even ignoring the [lint caps](lints/levels.md#capping-lints). + ## `-A`: set lint allowed @@ -381,6 +386,12 @@ are: - `always` — Always use colors. - `never` — Never colorize output. + +## `--diagnostic-width`: specify the terminal width for diagnostics + +This flag takes a number that specifies the width of the terminal in characters. +Formatting of diagnostics will take the width into consideration to make them better fit on the screen. + ## `--remap-path-prefix`: remap source names in output From f0dc35927becebf20730117a0bf00840ac1dd4ff Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Fri, 23 Sep 2022 00:02:49 -0700 Subject: [PATCH 194/586] Put back one of the `use`s for intra-doc mentions --- library/alloc/src/collections/vec_deque/mod.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/library/alloc/src/collections/vec_deque/mod.rs b/library/alloc/src/collections/vec_deque/mod.rs index 5546c9383de9c..2a57dad89a770 100644 --- a/library/alloc/src/collections/vec_deque/mod.rs +++ b/library/alloc/src/collections/vec_deque/mod.rs @@ -17,6 +17,12 @@ use core::ops::{Index, IndexMut, Range, RangeBounds}; use core::ptr::{self, NonNull}; use core::slice; +// This is used in a bunch of intra-doc links. +// FIXME: For some reason, `#[cfg(doc)]` wasn't sufficient, resulting in +// failures in linkchecker even though rustdoc built the docs just fine. +#[allow(unused_imports)] +use core::mem; + use crate::alloc::{Allocator, Global}; use crate::collections::TryReserveError; use crate::collections::TryReserveErrorKind; From a480ab6839ff88a770ca87faf4a4cadcb001bcbe Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Sat, 24 Sep 2022 06:02:49 +0000 Subject: [PATCH 195/586] Allow specializing on const trait bounds --- .../src/impl_wf_check/min_specialization.rs | 11 ++-- .../ui/specialization/const_trait_impl.rs | 55 +++++++++++++++++++ 2 files changed, 59 insertions(+), 7 deletions(-) create mode 100644 src/test/ui/specialization/const_trait_impl.rs diff --git a/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs b/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs index 2741d9f776ce2..5bebd7dee09b9 100644 --- a/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs +++ b/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs @@ -423,13 +423,10 @@ fn trait_predicate_kind<'tcx>( predicate: ty::Predicate<'tcx>, ) -> Option { match predicate.kind().skip_binder() { - ty::PredicateKind::Trait(ty::TraitPredicate { - trait_ref, - constness: ty::BoundConstness::NotConst, - polarity: _, - }) => Some(tcx.trait_def(trait_ref.def_id).specialization_kind), - ty::PredicateKind::Trait(_) - | ty::PredicateKind::RegionOutlives(_) + ty::PredicateKind::Trait(ty::TraitPredicate { trait_ref, constness: _, polarity: _ }) => { + Some(tcx.trait_def(trait_ref.def_id).specialization_kind) + } + ty::PredicateKind::RegionOutlives(_) | ty::PredicateKind::TypeOutlives(_) | ty::PredicateKind::Projection(_) | ty::PredicateKind::WellFormed(_) diff --git a/src/test/ui/specialization/const_trait_impl.rs b/src/test/ui/specialization/const_trait_impl.rs new file mode 100644 index 0000000000000..05ba4c8d45d5b --- /dev/null +++ b/src/test/ui/specialization/const_trait_impl.rs @@ -0,0 +1,55 @@ +// check-pass +#![feature(const_trait_impl, min_specialization, rustc_attrs)] + +#[rustc_specialization_trait] +#[const_trait] +pub unsafe trait Sup { + fn foo() -> u32; +} + +#[rustc_specialization_trait] +#[const_trait] +pub unsafe trait Sub: ~const Sup {} + +unsafe impl const Sup for u8 { + default fn foo() -> u32 { + 1 + } +} + +unsafe impl const Sup for () { + fn foo() -> u32 { + 42 + } +} + +unsafe impl const Sub for () {} + +#[const_trait] +pub trait A { + fn a() -> u32; +} + +impl const A for T { + default fn a() -> u32 { + 2 + } +} + +impl const A for T { + default fn a() -> u32 { + 3 + } +} + +impl const A for T { + fn a() -> u32 { + T::foo() + } +} + +const _: () = assert!(<()>::a() == 42); +const _: () = assert!(::a() == 3); +const _: () = assert!(::a() == 2); + +fn main() {} From 5f77ce029697dd9c91c5240f5b65372fb9d4c09a Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 24 Sep 2022 08:53:40 +0200 Subject: [PATCH 196/586] bootstrap/miri: switch to non-deprecated env var for setting the sysroot folder --- src/bootstrap/test.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index 1617875ec231c..01f4cacd771ff 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -520,7 +520,7 @@ impl Step for Miri { cargo.arg("--").arg("miri").arg("setup"); // Tell `cargo miri setup` where to find the sources. - cargo.env("XARGO_RUST_SRC", builder.src.join("library")); + cargo.env("MIRI_LIB_SRC", builder.src.join("library")); // Tell it where to find Miri. cargo.env("MIRI", &miri); // Debug things. From 8fe936099a3a2ea236d40212a340fc4a326eb506 Mon Sep 17 00:00:00 2001 From: Takayuki Maeda Date: Tue, 20 Sep 2022 14:11:23 +0900 Subject: [PATCH 197/586] separate definitions and `HIR` owners fix a ui test use `into` fix clippy ui test fix a run-make-fulldeps test implement `IntoQueryParam` for `OwnerId` use `OwnerId` for more queries change the type of `ParentOwnerIterator::Item` to `(OwnerId, OwnerNode)` --- compiler/rustc_ast_lowering/src/asm.rs | 2 +- compiler/rustc_ast_lowering/src/expr.rs | 2 +- compiler/rustc_ast_lowering/src/index.rs | 14 +-- compiler/rustc_ast_lowering/src/item.rs | 23 ++-- compiler/rustc_ast_lowering/src/lib.rs | 33 +++-- .../src/diagnostics/mutability_errors.rs | 4 +- .../src/diagnostics/region_errors.rs | 5 +- .../src/diagnostics/region_name.rs | 3 +- compiler/rustc_borrowck/src/lib.rs | 2 +- compiler/rustc_driver/src/pretty.rs | 2 +- compiler/rustc_hir/src/hir.rs | 36 +++--- compiler/rustc_hir/src/hir_id.rs | 60 +++++++-- compiler/rustc_hir/src/stable_hash_impls.rs | 10 +- .../src/persist/dirty_clean.rs | 8 +- .../src/infer/error_reporting/mod.rs | 2 +- .../nice_region_error/static_impl_trait.rs | 8 +- compiler/rustc_infer/src/infer/mod.rs | 5 +- .../rustc_infer/src/infer/opaque_types.rs | 2 +- .../rustc_interface/src/proc_macro_decls.rs | 5 +- compiler/rustc_lint/src/builtin.rs | 28 ++--- compiler/rustc_lint/src/context.rs | 2 +- compiler/rustc_metadata/src/native_libs.rs | 2 +- compiler/rustc_metadata/src/rmeta/encoder.rs | 10 +- .../rustc_middle/src/dep_graph/dep_node.rs | 24 +++- compiler/rustc_middle/src/hir/map/mod.rs | 59 ++++----- compiler/rustc_middle/src/hir/mod.rs | 36 +++--- .../src/middle/resolve_lifetime.rs | 8 +- compiler/rustc_middle/src/mir/mono.rs | 4 +- compiler/rustc_middle/src/query/mod.rs | 16 +-- compiler/rustc_middle/src/ty/context.rs | 17 +-- compiler/rustc_middle/src/ty/error.rs | 2 +- compiler/rustc_middle/src/ty/query.rs | 10 +- compiler/rustc_monomorphize/src/collector.rs | 4 +- compiler/rustc_passes/src/check_attr.rs | 14 ++- compiler/rustc_passes/src/dead.rs | 33 ++--- compiler/rustc_passes/src/diagnostic_items.rs | 8 +- compiler/rustc_passes/src/entry.rs | 8 +- compiler/rustc_passes/src/hir_id_validator.rs | 15 ++- compiler/rustc_passes/src/layout_test.rs | 2 +- compiler/rustc_passes/src/reachable.rs | 14 +-- compiler/rustc_passes/src/stability.rs | 24 ++-- compiler/rustc_privacy/src/lib.rs | 117 ++++++++++-------- compiler/rustc_query_impl/src/keys.rs | 14 +++ compiler/rustc_query_system/src/ich/hcx.rs | 7 +- compiler/rustc_resolve/src/late/lifetimes.rs | 32 ++--- .../rustc_save_analysis/src/dump_visitor.rs | 46 +++---- compiler/rustc_save_analysis/src/lib.rs | 4 +- compiler/rustc_symbol_mangling/src/test.rs | 8 +- .../src/traits/error_reporting/mod.rs | 4 +- .../src/traits/error_reporting/suggestions.rs | 4 +- compiler/rustc_ty_utils/src/assoc.rs | 2 +- compiler/rustc_typeck/src/astconv/mod.rs | 2 +- compiler/rustc_typeck/src/check/_match.rs | 4 +- compiler/rustc_typeck/src/check/check.rs | 20 +-- compiler/rustc_typeck/src/check/coercion.rs | 6 +- compiler/rustc_typeck/src/check/demand.rs | 2 +- compiler/rustc_typeck/src/check/expr.rs | 6 +- .../rustc_typeck/src/check/fn_ctxt/checks.rs | 4 +- .../rustc_typeck/src/check/method/suggest.rs | 2 +- compiler/rustc_typeck/src/check/mod.rs | 2 +- compiler/rustc_typeck/src/check/wfcheck.rs | 61 +++++---- .../src/coherence/inherent_impls.rs | 6 +- compiler/rustc_typeck/src/coherence/orphan.rs | 2 +- compiler/rustc_typeck/src/collect.rs | 33 ++--- compiler/rustc_typeck/src/collect/type_of.rs | 20 +-- compiler/rustc_typeck/src/impl_wf_check.rs | 6 +- src/librustdoc/clean/mod.rs | 8 +- src/librustdoc/passes/propagate_doc_cfg.rs | 2 +- src/librustdoc/scrape_examples.rs | 11 +- .../auxiliary/issue-40001-plugin.rs | 2 +- src/test/ui/thir-tree.stdout | 4 +- .../clippy/clippy_lints/src/dereference.rs | 2 +- src/tools/clippy/clippy_lints/src/doc.rs | 10 +- .../clippy/clippy_lints/src/enum_variants.rs | 2 +- src/tools/clippy/clippy_lints/src/escape.rs | 2 +- .../clippy_lints/src/exhaustive_items.rs | 2 +- src/tools/clippy/clippy_lints/src/exit.rs | 2 +- .../clippy_lints/src/fallible_impl_from.rs | 2 +- .../clippy_lints/src/functions/must_use.rs | 20 +-- .../src/functions/not_unsafe_ptr_arg_deref.rs | 2 +- .../clippy_lints/src/functions/result.rs | 14 +-- .../clippy_lints/src/implicit_hasher.rs | 2 +- .../clippy_lints/src/inherent_to_string.rs | 2 +- .../src/iter_not_returning_iterator.rs | 4 +- src/tools/clippy/clippy_lints/src/len_zero.rs | 4 +- .../clippy/clippy_lints/src/lifetimes.rs | 4 +- .../clippy_lints/src/loops/mut_range_bound.rs | 2 +- .../clippy_lints/src/manual_non_exhaustive.rs | 2 +- .../clippy/clippy_lints/src/methods/mod.rs | 8 +- .../clippy_lints/src/missing_const_for_fn.rs | 2 +- .../clippy/clippy_lints/src/missing_doc.rs | 2 +- .../clippy/clippy_lints/src/missing_inline.rs | 6 +- src/tools/clippy/clippy_lints/src/mut_key.rs | 2 +- .../clippy_lints/src/new_without_default.rs | 4 +- .../clippy/clippy_lints/src/non_copy_const.rs | 2 +- .../src/only_used_in_recursion.rs | 2 +- .../src/operators/assign_op_pattern.rs | 2 +- .../clippy_lints/src/pass_by_ref_or_value.rs | 2 +- .../clippy_lints/src/redundant_pub_crate.rs | 6 +- .../src/return_self_not_must_use.rs | 2 +- .../src/self_named_constructors.rs | 2 +- .../clippy_lints/src/suspicious_trait_impl.rs | 4 +- .../clippy_lints/src/transmute/utils.rs | 2 +- .../clippy_lints/src/types/borrowed_box.rs | 2 +- .../clippy/clippy_lints/src/types/mod.rs | 8 +- .../clippy/clippy_lints/src/unused_self.rs | 4 +- .../clippy_lints/src/unwrap_in_result.rs | 2 +- .../clippy_lints/src/upper_case_acronyms.rs | 2 +- src/tools/clippy/clippy_lints/src/use_self.rs | 2 +- .../clippy/clippy_lints/src/utils/author.rs | 2 +- .../clippy_lints/src/wildcard_imports.rs | 6 +- .../clippy_lints/src/zero_sized_map_values.rs | 2 +- src/tools/clippy/clippy_utils/src/lib.rs | 12 +- src/tools/clippy/clippy_utils/src/usage.rs | 2 +- 114 files changed, 659 insertions(+), 518 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/asm.rs b/compiler/rustc_ast_lowering/src/asm.rs index 24672efc63c55..85306d7184d89 100644 --- a/compiler/rustc_ast_lowering/src/asm.rs +++ b/compiler/rustc_ast_lowering/src/asm.rs @@ -237,7 +237,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // Wrap the expression in an AnonConst. let parent_def_id = self.current_hir_id_owner; let node_id = self.next_node_id(); - self.create_def(parent_def_id, node_id, DefPathData::AnonConst); + self.create_def(parent_def_id.def_id, node_id, DefPathData::AnonConst); let anon_const = AnonConst { id: node_id, value: P(expr) }; hir::InlineAsmOperand::SymFn { anon_const: self.lower_anon_const(&anon_const), diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 6c09269352cf2..94137391568c9 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -359,7 +359,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let node_id = self.next_node_id(); // Add a definition for the in-band const def. - self.create_def(parent_def_id, node_id, DefPathData::AnonConst); + self.create_def(parent_def_id.def_id, node_id, DefPathData::AnonConst); let anon_const = AnonConst { id: node_id, value: arg }; generic_args.push(AngleBracketedArg::Arg(GenericArg::Const(anon_const))); diff --git a/compiler/rustc_ast_lowering/src/index.rs b/compiler/rustc_ast_lowering/src/index.rs index 85846b56762e4..6d71679634331 100644 --- a/compiler/rustc_ast_lowering/src/index.rs +++ b/compiler/rustc_ast_lowering/src/index.rs @@ -24,7 +24,7 @@ pub(super) struct NodeCollector<'a, 'hir> { /// The parent of this node parent_node: hir::ItemLocalId, - owner: LocalDefId, + owner: OwnerId, definitions: &'a definitions::Definitions, } @@ -81,9 +81,9 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { current_dep_node_owner={} ({:?}), hir_id.owner={} ({:?})", self.source_map.span_to_diagnostic_string(span), node, - self.definitions.def_path(self.owner).to_string_no_crate_verbose(), + self.definitions.def_path(self.owner.def_id).to_string_no_crate_verbose(), self.owner, - self.definitions.def_path(hir_id.owner).to_string_no_crate_verbose(), + self.definitions.def_path(hir_id.owner.def_id).to_string_no_crate_verbose(), hir_id.owner, ) } @@ -112,19 +112,19 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { fn visit_nested_item(&mut self, item: ItemId) { debug!("visit_nested_item: {:?}", item); - self.insert_nested(item.def_id); + self.insert_nested(item.def_id.def_id); } fn visit_nested_trait_item(&mut self, item_id: TraitItemId) { - self.insert_nested(item_id.def_id); + self.insert_nested(item_id.def_id.def_id); } fn visit_nested_impl_item(&mut self, item_id: ImplItemId) { - self.insert_nested(item_id.def_id); + self.insert_nested(item_id.def_id.def_id); } fn visit_nested_foreign_item(&mut self, foreign_id: ForeignItemId) { - self.insert_nested(foreign_id.def_id); + self.insert_nested(foreign_id.def_id.def_id); } fn visit_nested_body(&mut self, id: BodyId) { diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index dfd04fe2974a9..1251702c1ff6b 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -68,7 +68,7 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> { bodies: Vec::new(), attrs: SortedMap::default(), children: FxHashMap::default(), - current_hir_id_owner: CRATE_DEF_ID, + current_hir_id_owner: hir::CRATE_OWNER_ID, item_local_id_counter: hir::ItemLocalId::new(0), node_id_to_local_id: Default::default(), local_id_to_def_id: SortedMap::new(), @@ -177,7 +177,8 @@ impl<'hir> LoweringContext<'_, 'hir> { } pub(super) fn lower_item_ref(&mut self, i: &Item) -> SmallVec<[hir::ItemId; 1]> { - let mut node_ids = smallvec![hir::ItemId { def_id: self.local_def_id(i.id) }]; + let mut node_ids = + smallvec![hir::ItemId { def_id: hir::OwnerId { def_id: self.local_def_id(i.id) } }]; if let ItemKind::Use(ref use_tree) = &i.kind { self.lower_item_id_use_tree(use_tree, i.id, &mut node_ids); } @@ -193,7 +194,9 @@ impl<'hir> LoweringContext<'_, 'hir> { match tree.kind { UseTreeKind::Nested(ref nested_vec) => { for &(ref nested, id) in nested_vec { - vec.push(hir::ItemId { def_id: self.local_def_id(id) }); + vec.push(hir::ItemId { + def_id: hir::OwnerId { def_id: self.local_def_id(id) }, + }); self.lower_item_id_use_tree(nested, id, vec); } } @@ -202,7 +205,9 @@ impl<'hir> LoweringContext<'_, 'hir> { for (_, &id) in iter::zip(self.expect_full_res_from_use(base_id).skip(1), &[id1, id2]) { - vec.push(hir::ItemId { def_id: self.local_def_id(id) }); + vec.push(hir::ItemId { + def_id: hir::OwnerId { def_id: self.local_def_id(id) }, + }); } } } @@ -553,7 +558,7 @@ impl<'hir> LoweringContext<'_, 'hir> { } let item = hir::Item { - def_id: new_id, + def_id: hir::OwnerId { def_id: new_id }, ident: this.lower_ident(ident), kind, vis_span, @@ -627,7 +632,7 @@ impl<'hir> LoweringContext<'_, 'hir> { } let item = hir::Item { - def_id: new_hir_id, + def_id: hir::OwnerId { def_id: new_hir_id }, ident: this.lower_ident(ident), kind, vis_span, @@ -689,7 +694,7 @@ impl<'hir> LoweringContext<'_, 'hir> { fn lower_foreign_item_ref(&mut self, i: &ForeignItem) -> hir::ForeignItemRef { hir::ForeignItemRef { - id: hir::ForeignItemId { def_id: self.local_def_id(i.id) }, + id: hir::ForeignItemId { def_id: hir::OwnerId { def_id: self.local_def_id(i.id) } }, ident: self.lower_ident(i.ident), span: self.lower_span(i.span), } @@ -851,7 +856,7 @@ impl<'hir> LoweringContext<'_, 'hir> { } AssocItemKind::MacCall(..) => unimplemented!(), }; - let id = hir::TraitItemId { def_id: self.local_def_id(i.id) }; + let id = hir::TraitItemId { def_id: hir::OwnerId { def_id: self.local_def_id(i.id) } }; hir::TraitItemRef { id, ident: self.lower_ident(i.ident), @@ -931,7 +936,7 @@ impl<'hir> LoweringContext<'_, 'hir> { fn lower_impl_item_ref(&mut self, i: &AssocItem) -> hir::ImplItemRef { hir::ImplItemRef { - id: hir::ImplItemId { def_id: self.local_def_id(i.id) }, + id: hir::ImplItemId { def_id: hir::OwnerId { def_id: self.local_def_id(i.id) } }, ident: self.lower_ident(i.ident), span: self.lower_span(i.span), kind: match &i.kind { diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index a11721ba0213a..186c10065f306 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -126,7 +126,7 @@ struct LoweringContext<'a, 'hir> { is_in_trait_impl: bool, is_in_dyn_type: bool, - current_hir_id_owner: LocalDefId, + current_hir_id_owner: hir::OwnerId, item_local_id_counter: hir::ItemLocalId, local_id_to_def_id: SortedMap, trait_map: FxHashMap>, @@ -572,7 +572,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let current_node_ids = std::mem::take(&mut self.node_id_to_local_id); let current_id_to_def_id = std::mem::take(&mut self.local_id_to_def_id); let current_trait_map = std::mem::take(&mut self.trait_map); - let current_owner = std::mem::replace(&mut self.current_hir_id_owner, def_id); + let current_owner = + std::mem::replace(&mut self.current_hir_id_owner, hir::OwnerId { def_id }); let current_local_counter = std::mem::replace(&mut self.item_local_id_counter, hir::ItemLocalId::new(1)); let current_impl_trait_defs = std::mem::take(&mut self.impl_trait_defs); @@ -587,7 +588,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { debug_assert_eq!(_old, None); let item = f(self); - debug_assert_eq!(def_id, item.def_id()); + debug_assert_eq!(def_id, item.def_id().def_id); // `f` should have consumed all the elements in these vectors when constructing `item`. debug_assert!(self.impl_trait_defs.is_empty()); debug_assert!(self.impl_trait_bounds.is_empty()); @@ -786,7 +787,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { /// Mark a span as relative to the current owning item. fn lower_span(&self, span: Span) -> Span { if self.tcx.sess.opts.unstable_opts.incremental_relative_spans { - span.with_parent(Some(self.current_hir_id_owner)) + span.with_parent(Some(self.current_hir_id_owner.def_id)) } else { // Do not make spans relative when not using incremental compilation. span @@ -812,7 +813,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { LifetimeRes::Fresh { param, .. } => { // Late resolution delegates to us the creation of the `LocalDefId`. let _def_id = self.create_def( - self.current_hir_id_owner, + self.current_hir_id_owner.def_id, param, DefPathData::LifetimeNs(kw::UnderscoreLifetime), ); @@ -1062,7 +1063,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let parent_def_id = self.current_hir_id_owner; let impl_trait_node_id = self.next_node_id(); - self.create_def(parent_def_id, impl_trait_node_id, DefPathData::ImplTrait); + self.create_def( + parent_def_id.def_id, + impl_trait_node_id, + DefPathData::ImplTrait, + ); self.with_dyn_type_scope(false, |this| { let node_id = this.next_node_id(); @@ -1154,7 +1159,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let node_id = self.next_node_id(); // Add a definition for the in-band const def. - self.create_def(parent_def_id, node_id, DefPathData::AnonConst); + self.create_def( + parent_def_id.def_id, + node_id, + DefPathData::AnonConst, + ); let span = self.lower_span(ty.span); let path_expr = Expr { @@ -1551,7 +1560,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { debug!(?lifetimes); // `impl Trait` now just becomes `Foo<'a, 'b, ..>`. - hir::TyKind::OpaqueDef(hir::ItemId { def_id: opaque_ty_def_id }, lifetimes, in_trait) + hir::TyKind::OpaqueDef( + hir::ItemId { def_id: hir::OwnerId { def_id: opaque_ty_def_id } }, + lifetimes, + in_trait, + ) } /// Registers a new opaque type with the proper `NodeId`s and @@ -1567,7 +1580,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // Generate an `type Foo = impl Trait;` declaration. trace!("registering opaque type with id {:#?}", opaque_ty_id); let opaque_ty_item = hir::Item { - def_id: opaque_ty_id, + def_id: hir::OwnerId { def_id: opaque_ty_id }, ident: Ident::empty(), kind: opaque_ty_item_kind, vis_span: self.lower_span(span.shrink_to_lo()), @@ -2018,7 +2031,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // async fn, so the *type parameters* are inherited. It's // only the lifetime parameters that we must supply. let opaque_ty_ref = hir::TyKind::OpaqueDef( - hir::ItemId { def_id: opaque_ty_def_id }, + hir::ItemId { def_id: hir::OwnerId { def_id: opaque_ty_def_id } }, generic_args, in_trait, ); diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs index 202729b4744d6..8ad40c0aa0a5d 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs @@ -932,7 +932,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { let opt_suggestions = self .infcx .tcx - .typeck(path_segment.hir_id.owner) + .typeck(path_segment.hir_id.owner.def_id) .type_dependent_def_id(*hir_id) .and_then(|def_id| self.infcx.tcx.impl_of_method(def_id)) .map(|def_id| self.infcx.tcx.associated_items(def_id)) @@ -1032,7 +1032,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { if look_at_return && hir.get_return_block(closure_id).is_some() { // ...otherwise we are probably in the tail expression of the function, point at the // return type. - match hir.get_by_def_id(hir.get_parent_item(fn_call_id)) { + match hir.get_by_def_id(hir.get_parent_item(fn_call_id).def_id) { hir::Node::Item(hir::Item { ident, kind: hir::ItemKind::Fn(sig, ..), .. }) | hir::Node::TraitItem(hir::TraitItem { ident, diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index 34be2874fcb73..43d67bfa72991 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -281,7 +281,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { let tcx = self.infcx.tcx; match tcx.hir().get_if_local(def_id) { Some(Node::ImplItem(impl_item)) => { - match tcx.hir().find_by_def_id(tcx.hir().get_parent_item(impl_item.hir_id())) { + match tcx.hir().find_by_def_id(tcx.hir().get_parent_item(impl_item.hir_id()).def_id) + { Some(Node::Item(Item { kind: ItemKind::Impl(hir::Impl { self_ty, .. }), .. @@ -291,7 +292,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { } Some(Node::TraitItem(trait_item)) => { let trait_did = tcx.hir().get_parent_item(trait_item.hir_id()); - match tcx.hir().find_by_def_id(trait_did) { + match tcx.hir().find_by_def_id(trait_did.def_id) { Some(Node::Item(Item { kind: ItemKind::Trait(..), .. })) => { // The method being called is defined in the `trait`, but the `'static` // obligation comes from the `impl`. Find that `impl` so that we can point diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs index 6c1eaa809c905..419e6c817915f 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs @@ -707,7 +707,8 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { hir::AsyncGeneratorKind::Block => " of async block", hir::AsyncGeneratorKind::Closure => " of async closure", hir::AsyncGeneratorKind::Fn => { - let parent_item = hir.get_by_def_id(hir.get_parent_item(mir_hir_id)); + let parent_item = + hir.get_by_def_id(hir.get_parent_item(mir_hir_id).def_id); let output = &parent_item .fn_decl() .expect("generator lowered from async fn should be in fn") diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index cb16bec57ee5a..6b90f2daeea3c 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -134,7 +134,7 @@ fn mir_borrowck<'tcx>( let opt_closure_req = tcx .infer_ctxt() - .with_opaque_type_inference(DefiningAnchor::Bind(hir_owner)) + .with_opaque_type_inference(DefiningAnchor::Bind(hir_owner.def_id)) .enter(|infcx| { let input_body: &Body<'_> = &input_body.borrow(); let promoted: &IndexVec<_, _> = &promoted.borrow(); diff --git a/compiler/rustc_driver/src/pretty.rs b/compiler/rustc_driver/src/pretty.rs index 2874fa0caff6f..e97da4322fa01 100644 --- a/compiler/rustc_driver/src/pretty.rs +++ b/compiler/rustc_driver/src/pretty.rs @@ -329,7 +329,7 @@ impl<'tcx> pprust_hir::PpAnn for TypedAnnotation<'tcx> { let typeck_results = self.maybe_typeck_results.get().or_else(|| { self.tcx .hir() - .maybe_body_owned_by(expr.hir_id.owner) + .maybe_body_owned_by(expr.hir_id.owner.def_id) .map(|body_id| self.tcx.typeck_body(body_id)) }); diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index a8436ea64f8d7..018b7cc5d9dfe 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -1,6 +1,6 @@ use crate::def::{CtorKind, DefKind, Res}; use crate::def_id::DefId; -pub(crate) use crate::hir_id::{HirId, ItemLocalId}; +pub(crate) use crate::hir_id::{HirId, ItemLocalId, OwnerId}; use crate::intravisit::FnKind; use crate::LangItem; @@ -2206,14 +2206,14 @@ pub struct FnSig<'hir> { // so it can fetched later. #[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Debug, HashStable_Generic)] pub struct TraitItemId { - pub def_id: LocalDefId, + pub def_id: OwnerId, } impl TraitItemId { #[inline] pub fn hir_id(&self) -> HirId { // Items are always HIR owners. - HirId::make_owner(self.def_id) + HirId::make_owner(self.def_id.def_id) } } @@ -2224,7 +2224,7 @@ impl TraitItemId { #[derive(Debug, HashStable_Generic)] pub struct TraitItem<'hir> { pub ident: Ident, - pub def_id: LocalDefId, + pub def_id: OwnerId, pub generics: &'hir Generics<'hir>, pub kind: TraitItemKind<'hir>, pub span: Span, @@ -2235,7 +2235,7 @@ impl TraitItem<'_> { #[inline] pub fn hir_id(&self) -> HirId { // Items are always HIR owners. - HirId::make_owner(self.def_id) + HirId::make_owner(self.def_id.def_id) } pub fn trait_item_id(&self) -> TraitItemId { @@ -2270,14 +2270,14 @@ pub enum TraitItemKind<'hir> { // so it can fetched later. #[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Debug, HashStable_Generic)] pub struct ImplItemId { - pub def_id: LocalDefId, + pub def_id: OwnerId, } impl ImplItemId { #[inline] pub fn hir_id(&self) -> HirId { // Items are always HIR owners. - HirId::make_owner(self.def_id) + HirId::make_owner(self.def_id.def_id) } } @@ -2285,7 +2285,7 @@ impl ImplItemId { #[derive(Debug, HashStable_Generic)] pub struct ImplItem<'hir> { pub ident: Ident, - pub def_id: LocalDefId, + pub def_id: OwnerId, pub generics: &'hir Generics<'hir>, pub kind: ImplItemKind<'hir>, pub defaultness: Defaultness, @@ -2297,7 +2297,7 @@ impl ImplItem<'_> { #[inline] pub fn hir_id(&self) -> HirId { // Items are always HIR owners. - HirId::make_owner(self.def_id) + HirId::make_owner(self.def_id.def_id) } pub fn impl_item_id(&self) -> ImplItemId { @@ -2888,14 +2888,14 @@ impl<'hir> VariantData<'hir> { // so it can fetched later. #[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Debug, Hash, HashStable_Generic)] pub struct ItemId { - pub def_id: LocalDefId, + pub def_id: OwnerId, } impl ItemId { #[inline] pub fn hir_id(&self) -> HirId { // Items are always HIR owners. - HirId::make_owner(self.def_id) + HirId::make_owner(self.def_id.def_id) } } @@ -2905,7 +2905,7 @@ impl ItemId { #[derive(Debug, HashStable_Generic)] pub struct Item<'hir> { pub ident: Ident, - pub def_id: LocalDefId, + pub def_id: OwnerId, pub kind: ItemKind<'hir>, pub span: Span, pub vis_span: Span, @@ -2915,7 +2915,7 @@ impl Item<'_> { #[inline] pub fn hir_id(&self) -> HirId { // Items are always HIR owners. - HirId::make_owner(self.def_id) + HirId::make_owner(self.def_id.def_id) } pub fn item_id(&self) -> ItemId { @@ -3132,14 +3132,14 @@ pub enum AssocItemKind { // so it can fetched later. #[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Debug, HashStable_Generic)] pub struct ForeignItemId { - pub def_id: LocalDefId, + pub def_id: OwnerId, } impl ForeignItemId { #[inline] pub fn hir_id(&self) -> HirId { // Items are always HIR owners. - HirId::make_owner(self.def_id) + HirId::make_owner(self.def_id.def_id) } } @@ -3160,7 +3160,7 @@ pub struct ForeignItemRef { pub struct ForeignItem<'hir> { pub ident: Ident, pub kind: ForeignItemKind<'hir>, - pub def_id: LocalDefId, + pub def_id: OwnerId, pub span: Span, pub vis_span: Span, } @@ -3169,7 +3169,7 @@ impl ForeignItem<'_> { #[inline] pub fn hir_id(&self) -> HirId { // Items are always HIR owners. - HirId::make_owner(self.def_id) + HirId::make_owner(self.def_id.def_id) } pub fn foreign_item_id(&self) -> ForeignItemId { @@ -3263,7 +3263,7 @@ impl<'hir> OwnerNode<'hir> { Node::generics(self.into()) } - pub fn def_id(self) -> LocalDefId { + pub fn def_id(self) -> OwnerId { match self { OwnerNode::Item(Item { def_id, .. }) | OwnerNode::TraitItem(TraitItem { def_id, .. }) diff --git a/compiler/rustc_hir/src/hir_id.rs b/compiler/rustc_hir/src/hir_id.rs index 84b0740c7b313..752f760ea9719 100644 --- a/compiler/rustc_hir/src/hir_id.rs +++ b/compiler/rustc_hir/src/hir_id.rs @@ -1,6 +1,43 @@ -use crate::def_id::{LocalDefId, CRATE_DEF_ID}; +use crate::def_id::{DefId, LocalDefId, CRATE_DEF_ID}; +use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey}; +use rustc_span::{def_id::DefPathHash, HashStableContext}; use std::fmt; +#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] +#[derive(Encodable, Decodable)] +pub struct OwnerId { + pub def_id: LocalDefId, +} + +impl From for HirId { + fn from(owner: OwnerId) -> HirId { + HirId { owner, local_id: ItemLocalId::from_u32(0) } + } +} + +impl OwnerId { + #[inline] + pub fn to_def_id(self) -> DefId { + self.def_id.to_def_id() + } +} + +impl HashStable for OwnerId { + #[inline] + fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) { + self.to_stable_hash_key(hcx).hash_stable(hcx, hasher); + } +} + +impl ToStableHashKey for OwnerId { + type KeyType = DefPathHash; + + #[inline] + fn to_stable_hash_key(&self, hcx: &CTX) -> DefPathHash { + hcx.def_path_hash(self.to_def_id()) + } +} + /// Uniquely identifies a node in the HIR of the current crate. It is /// composed of the `owner`, which is the `LocalDefId` of the directly enclosing /// `hir::Item`, `hir::TraitItem`, or `hir::ImplItem` (i.e., the closest "item-like"), @@ -15,22 +52,23 @@ use std::fmt; #[derive(Encodable, Decodable, HashStable_Generic)] #[rustc_pass_by_value] pub struct HirId { - pub owner: LocalDefId, + pub owner: OwnerId, pub local_id: ItemLocalId, } impl HirId { /// Signal local id which should never be used. - pub const INVALID: HirId = HirId { owner: CRATE_DEF_ID, local_id: ItemLocalId::INVALID }; + pub const INVALID: HirId = + HirId { owner: OwnerId { def_id: CRATE_DEF_ID }, local_id: ItemLocalId::INVALID }; #[inline] - pub fn expect_owner(self) -> LocalDefId { + pub fn expect_owner(self) -> OwnerId { assert_eq!(self.local_id.index(), 0); self.owner } #[inline] - pub fn as_owner(self) -> Option { + pub fn as_owner(self) -> Option { if self.local_id.index() == 0 { Some(self.owner) } else { None } } @@ -41,11 +79,14 @@ impl HirId { #[inline] pub fn make_owner(owner: LocalDefId) -> Self { - Self { owner, local_id: ItemLocalId::from_u32(0) } + Self { owner: OwnerId { def_id: owner }, local_id: ItemLocalId::from_u32(0) } } pub fn index(self) -> (usize, usize) { - (rustc_index::vec::Idx::index(self.owner), rustc_index::vec::Idx::index(self.local_id)) + ( + rustc_index::vec::Idx::index(self.owner.def_id), + rustc_index::vec::Idx::index(self.local_id), + ) } } @@ -94,4 +135,7 @@ impl ItemLocalId { } /// The `HirId` corresponding to `CRATE_NODE_ID` and `CRATE_DEF_ID`. -pub const CRATE_HIR_ID: HirId = HirId { owner: CRATE_DEF_ID, local_id: ItemLocalId::from_u32(0) }; +pub const CRATE_HIR_ID: HirId = + HirId { owner: OwnerId { def_id: CRATE_DEF_ID }, local_id: ItemLocalId::from_u32(0) }; + +pub const CRATE_OWNER_ID: OwnerId = OwnerId { def_id: CRATE_DEF_ID }; diff --git a/compiler/rustc_hir/src/stable_hash_impls.rs b/compiler/rustc_hir/src/stable_hash_impls.rs index 5b9c42686c344..06b7a65662e7c 100644 --- a/compiler/rustc_hir/src/stable_hash_impls.rs +++ b/compiler/rustc_hir/src/stable_hash_impls.rs @@ -20,7 +20,7 @@ impl ToStableHashKey for HirId { #[inline] fn to_stable_hash_key(&self, hcx: &HirCtx) -> (DefPathHash, ItemLocalId) { - let def_path_hash = self.owner.to_stable_hash_key(hcx); + let def_path_hash = self.owner.def_id.to_stable_hash_key(hcx); (def_path_hash, self.local_id) } } @@ -49,7 +49,7 @@ impl ToStableHashKey for ItemId { #[inline] fn to_stable_hash_key(&self, hcx: &HirCtx) -> DefPathHash { - self.def_id.to_stable_hash_key(hcx) + self.def_id.def_id.to_stable_hash_key(hcx) } } @@ -58,7 +58,7 @@ impl ToStableHashKey for TraitItemId { #[inline] fn to_stable_hash_key(&self, hcx: &HirCtx) -> DefPathHash { - self.def_id.to_stable_hash_key(hcx) + self.def_id.def_id.to_stable_hash_key(hcx) } } @@ -67,7 +67,7 @@ impl ToStableHashKey for ImplItemId { #[inline] fn to_stable_hash_key(&self, hcx: &HirCtx) -> DefPathHash { - self.def_id.to_stable_hash_key(hcx) + self.def_id.def_id.to_stable_hash_key(hcx) } } @@ -76,7 +76,7 @@ impl ToStableHashKey for ForeignItemId #[inline] fn to_stable_hash_key(&self, hcx: &HirCtx) -> DefPathHash { - self.def_id.to_stable_hash_key(hcx) + self.def_id.def_id.to_stable_hash_key(hcx) } } diff --git a/compiler/rustc_incremental/src/persist/dirty_clean.rs b/compiler/rustc_incremental/src/persist/dirty_clean.rs index 710c4a01b244f..09163e4f25f3c 100644 --- a/compiler/rustc_incremental/src/persist/dirty_clean.rs +++ b/compiler/rustc_incremental/src/persist/dirty_clean.rs @@ -149,19 +149,19 @@ pub fn check_dirty_clean_annotations(tcx: TyCtxt<'_>) { let crate_items = tcx.hir_crate_items(()); for id in crate_items.items() { - dirty_clean_visitor.check_item(id.def_id); + dirty_clean_visitor.check_item(id.def_id.def_id); } for id in crate_items.trait_items() { - dirty_clean_visitor.check_item(id.def_id); + dirty_clean_visitor.check_item(id.def_id.def_id); } for id in crate_items.impl_items() { - dirty_clean_visitor.check_item(id.def_id); + dirty_clean_visitor.check_item(id.def_id.def_id); } for id in crate_items.foreign_items() { - dirty_clean_visitor.check_item(id.def_id); + dirty_clean_visitor.check_item(id.def_id.def_id); } let mut all_attrs = FindAllAttrs { tcx, found_attrs: vec![] }; diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index 82099d9e3f345..0208c364e4388 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -2440,7 +2440,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { // We do this to avoid suggesting code that ends up as `T: 'a'b`, // instead we suggest `T: 'a + 'b` in that case. let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id); - let ast_generics = self.tcx.hir().get_generics(hir_id.owner); + let ast_generics = self.tcx.hir().get_generics(hir_id.owner.def_id); let bounds = ast_generics.and_then(|g| g.bounds_span_for_suggestions(def_id)); // `sp` only covers `T`, change it so that it covers diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs index ae56bea6f862d..2ccfcd51b1152 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs @@ -185,8 +185,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { | ObligationCauseCode::BlockTailExpression(hir_id) = cause.code() { let parent_id = tcx.hir().get_parent_item(*hir_id); - let parent_id = tcx.hir().local_def_id_to_hir_id(parent_id); - if let Some(fn_decl) = tcx.hir().fn_decl_by_hir_id(parent_id) { + if let Some(fn_decl) = tcx.hir().fn_decl_by_hir_id(parent_id.into()) { let mut span: MultiSpan = fn_decl.output.span().into(); let mut add_label = true; if let hir::FnRetTy::Return(ty) = fn_decl.output { @@ -415,7 +414,8 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { let tcx = self.tcx(); match tcx.hir().get_if_local(def_id) { Some(Node::ImplItem(impl_item)) => { - match tcx.hir().find_by_def_id(tcx.hir().get_parent_item(impl_item.hir_id())) { + match tcx.hir().find_by_def_id(tcx.hir().get_parent_item(impl_item.hir_id()).def_id) + { Some(Node::Item(Item { kind: ItemKind::Impl(hir::Impl { self_ty, .. }), .. @@ -425,7 +425,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { } Some(Node::TraitItem(trait_item)) => { let trait_did = tcx.hir().get_parent_item(trait_item.hir_id()); - match tcx.hir().find_by_def_id(trait_did) { + match tcx.hir().find_by_def_id(trait_did.def_id) { Some(Node::Item(Item { kind: ItemKind::Trait(..), .. })) => { // The method being called is defined in the `trait`, but the `'static` // obligation comes from the `impl`. Find that `impl` so that we can point diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 55cf9b7a2ea18..efc9c1ca46fe4 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -16,6 +16,7 @@ use rustc_data_structures::undo_log::Rollback; use rustc_data_structures::unify as ut; use rustc_errors::{DiagnosticBuilder, ErrorGuaranteed}; use rustc_hir::def_id::{DefId, LocalDefId}; +use rustc_hir::hir_id::OwnerId; use rustc_middle::infer::canonical::{Canonical, CanonicalVarValues}; use rustc_middle::infer::unify_key::{ConstVarValue, ConstVariableValue}; use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind, ToType}; @@ -583,9 +584,9 @@ impl<'tcx> InferCtxtBuilder<'tcx> { /// Used only by `rustc_typeck` during body type-checking/inference, /// will initialize `in_progress_typeck_results` with fresh `TypeckResults`. /// Will also change the scope for opaque type defining use checks to the given owner. - pub fn with_fresh_in_progress_typeck_results(mut self, table_owner: LocalDefId) -> Self { + pub fn with_fresh_in_progress_typeck_results(mut self, table_owner: OwnerId) -> Self { self.fresh_typeck_results = Some(RefCell::new(ty::TypeckResults::new(table_owner))); - self.with_opaque_type_inference(DefiningAnchor::Bind(table_owner)) + self.with_opaque_type_inference(DefiningAnchor::Bind(table_owner.def_id)) } /// Whenever the `InferCtxt` should be able to handle defining uses of opaque types, diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs index 76c340a5efae0..9bf92f08aa54b 100644 --- a/compiler/rustc_infer/src/infer/opaque_types.rs +++ b/compiler/rustc_infer/src/infer/opaque_types.rs @@ -616,7 +616,7 @@ fn may_define_opaque_type(tcx: TyCtxt<'_>, def_id: LocalDefId, opaque_hir_id: hi let scope = tcx.hir().get_defining_scope(opaque_hir_id); // We walk up the node tree until we hit the root or the scope of the opaque type. while hir_id != scope && hir_id != hir::CRATE_HIR_ID { - hir_id = tcx.hir().local_def_id_to_hir_id(tcx.hir().get_parent_item(hir_id)); + hir_id = tcx.hir().get_parent_item(hir_id).into(); } // Syntactically, we are allowed to define the concrete type if: let res = hir_id == scope; diff --git a/compiler/rustc_interface/src/proc_macro_decls.rs b/compiler/rustc_interface/src/proc_macro_decls.rs index 5371c513d2981..2b1b931b7326b 100644 --- a/compiler/rustc_interface/src/proc_macro_decls.rs +++ b/compiler/rustc_interface/src/proc_macro_decls.rs @@ -1,4 +1,3 @@ -use rustc_hir as hir; use rustc_hir::def_id::LocalDefId; use rustc_middle::ty::query::Providers; use rustc_middle::ty::TyCtxt; @@ -10,7 +9,7 @@ fn proc_macro_decls_static(tcx: TyCtxt<'_>, (): ()) -> Option { for id in tcx.hir().items() { let attrs = finder.tcx.hir().attrs(id.hir_id()); if finder.tcx.sess.contains_name(attrs, sym::rustc_proc_macro_decls) { - finder.decls = Some(id.def_id); + finder.decls = Some(id.def_id.def_id); } } @@ -19,7 +18,7 @@ fn proc_macro_decls_static(tcx: TyCtxt<'_>, (): ()) -> Option { struct Finder<'tcx> { tcx: TyCtxt<'tcx>, - decls: Option, + decls: Option, } pub(crate) fn provide(providers: &mut Providers) { diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 0ff2ef5cda391..5fba1d3d3c7ac 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -606,7 +606,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc { // Issue #11592: traits are always considered exported, even when private. if cx.tcx.visibility(it.def_id) == ty::Visibility::Restricted( - cx.tcx.parent_module_from_def_id(it.def_id).to_def_id(), + cx.tcx.parent_module_from_def_id(it.def_id.def_id).to_def_id(), ) { return; @@ -627,13 +627,13 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc { let (article, desc) = cx.tcx.article_and_description(it.def_id.to_def_id()); - self.check_missing_docs_attrs(cx, it.def_id, article, desc); + self.check_missing_docs_attrs(cx, it.def_id.def_id, article, desc); } fn check_trait_item(&mut self, cx: &LateContext<'_>, trait_item: &hir::TraitItem<'_>) { let (article, desc) = cx.tcx.article_and_description(trait_item.def_id.to_def_id()); - self.check_missing_docs_attrs(cx, trait_item.def_id, article, desc); + self.check_missing_docs_attrs(cx, trait_item.def_id.def_id, article, desc); } fn check_impl_item(&mut self, cx: &LateContext<'_>, impl_item: &hir::ImplItem<'_>) { @@ -661,12 +661,12 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc { } let (article, desc) = cx.tcx.article_and_description(impl_item.def_id.to_def_id()); - self.check_missing_docs_attrs(cx, impl_item.def_id, article, desc); + self.check_missing_docs_attrs(cx, impl_item.def_id.def_id, article, desc); } fn check_foreign_item(&mut self, cx: &LateContext<'_>, foreign_item: &hir::ForeignItem<'_>) { let (article, desc) = cx.tcx.article_and_description(foreign_item.def_id.to_def_id()); - self.check_missing_docs_attrs(cx, foreign_item.def_id, article, desc); + self.check_missing_docs_attrs(cx, foreign_item.def_id.def_id, article, desc); } fn check_field_def(&mut self, cx: &LateContext<'_>, sf: &hir::FieldDef<'_>) { @@ -719,7 +719,7 @@ declare_lint_pass!(MissingCopyImplementations => [MISSING_COPY_IMPLEMENTATIONS]) impl<'tcx> LateLintPass<'tcx> for MissingCopyImplementations { fn check_item(&mut self, cx: &LateContext<'_>, item: &hir::Item<'_>) { - if !cx.access_levels.is_reachable(item.def_id) { + if !cx.access_levels.is_reachable(item.def_id.def_id) { return; } let (def, ty) = match item.kind { @@ -809,7 +809,7 @@ impl_lint_pass!(MissingDebugImplementations => [MISSING_DEBUG_IMPLEMENTATIONS]); impl<'tcx> LateLintPass<'tcx> for MissingDebugImplementations { fn check_item(&mut self, cx: &LateContext<'_>, item: &hir::Item<'_>) { - if !cx.access_levels.is_reachable(item.def_id) { + if !cx.access_levels.is_reachable(item.def_id.def_id) { return; } @@ -836,7 +836,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingDebugImplementations { debug!("{:?}", self.impling_types); } - if !self.impling_types.as_ref().unwrap().contains(&item.def_id) { + if !self.impling_types.as_ref().unwrap().contains(&item.def_id.def_id) { cx.struct_span_lint(MISSING_DEBUG_IMPLEMENTATIONS, item.span, |lint| { lint.build(fluent::lint::builtin_missing_debug_impl) .set_arg("debug", cx.tcx.def_path_str(debug)) @@ -1206,7 +1206,7 @@ impl<'tcx> LateLintPass<'tcx> for InvalidNoMangleItems { check_no_mangle_on_generic_fn( no_mangle_attr, Some(generics), - cx.tcx.hir().get_generics(it.id.def_id).unwrap(), + cx.tcx.hir().get_generics(it.id.def_id.def_id).unwrap(), it.span, ); } @@ -1389,11 +1389,11 @@ impl<'tcx> LateLintPass<'tcx> for UnreachablePub { if let hir::ItemKind::Use(_, hir::UseKind::ListStem) = &item.kind { return; } - self.perform_lint(cx, "item", item.def_id, item.vis_span, true); + self.perform_lint(cx, "item", item.def_id.def_id, item.vis_span, true); } fn check_foreign_item(&mut self, cx: &LateContext<'_>, foreign_item: &hir::ForeignItem<'tcx>) { - self.perform_lint(cx, "item", foreign_item.def_id, foreign_item.vis_span, true); + self.perform_lint(cx, "item", foreign_item.def_id.def_id, foreign_item.vis_span, true); } fn check_field_def(&mut self, cx: &LateContext<'_>, field: &hir::FieldDef<'_>) { @@ -1404,7 +1404,7 @@ impl<'tcx> LateLintPass<'tcx> for UnreachablePub { fn check_impl_item(&mut self, cx: &LateContext<'_>, impl_item: &hir::ImplItem<'_>) { // Only lint inherent impl items. if cx.tcx.associated_item(impl_item.def_id).trait_item_def_id.is_none() { - self.perform_lint(cx, "item", impl_item.def_id, impl_item.vis_span, false); + self.perform_lint(cx, "item", impl_item.def_id.def_id, impl_item.vis_span, false); } } } @@ -1841,7 +1841,7 @@ declare_lint! { } pub struct UnnameableTestItems { - boundary: Option, // Id of the item under which things are not nameable + boundary: Option, // Id of the item under which things are not nameable items_nameable: bool, } @@ -2138,7 +2138,7 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) { use rustc_middle::middle::resolve_lifetime::Region; - let def_id = item.def_id; + let def_id = item.def_id.def_id; if let hir::ItemKind::Struct(_, ref hir_generics) | hir::ItemKind::Enum(_, ref hir_generics) | hir::ItemKind::Union(_, ref hir_generics) = item.kind diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index 7ca6ec5d96234..cbab56f2066f0 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -1048,7 +1048,7 @@ impl<'tcx> LateContext<'tcx> { .filter(|typeck_results| typeck_results.hir_owner == id.owner) .or_else(|| { if self.tcx.has_typeck_results(id.owner.to_def_id()) { - Some(self.tcx.typeck(id.owner)) + Some(self.tcx.typeck(id.owner.def_id)) } else { None } diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs index 2a986c41d72f0..9abb5c74895d0 100644 --- a/compiler/rustc_metadata/src/native_libs.rs +++ b/compiler/rustc_metadata/src/native_libs.rs @@ -382,7 +382,7 @@ impl<'tcx> Collector<'tcx> { let link_ordinal_attr = self .tcx .hir() - .attrs(self.tcx.hir().local_def_id_to_hir_id(child_item.id.def_id)) + .attrs(child_item.id.def_id.into()) .iter() .find(|a| a.has_name(sym::link_ordinal)) .unwrap(); diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 67c28461ce5cf..7cf00ca41fefb 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1217,14 +1217,14 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { // from name resolution point of view. hir::ItemKind::ForeignMod { items, .. } => { for foreign_item in items { - yield foreign_item.id.def_id.local_def_index; + yield foreign_item.id.def_id.def_id.local_def_index; } } // Only encode named non-reexport children, reexports are encoded // separately and unnamed items are not used by name resolution. hir::ItemKind::ExternCrate(..) => continue, _ if tcx.def_key(item_id.def_id.to_def_id()).get_opt_name().is_some() => { - yield item_id.def_id.local_def_index; + yield item_id.def_id.def_id.local_def_index; } _ => continue, } @@ -1446,7 +1446,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { record!(self.tables.macro_definition[def_id] <- &*macro_def.body); } hir::ItemKind::Mod(ref m) => { - return self.encode_info_for_mod(item.def_id, m); + return self.encode_info_for_mod(item.def_id.def_id, m); } hir::ItemKind::OpaqueTy(..) => { self.encode_explicit_item_bounds(def_id); @@ -1840,7 +1840,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { for id in tcx.hir().items() { if matches!(tcx.def_kind(id.def_id), DefKind::Impl) { - if let Some(trait_ref) = tcx.impl_trait_ref(id.def_id.to_def_id()) { + if let Some(trait_ref) = tcx.impl_trait_ref(id.def_id) { let simplified_self_ty = fast_reject::simplify_type( self.tcx, trait_ref.self_ty(), @@ -1850,7 +1850,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { fx_hash_map .entry(trait_ref.def_id) .or_default() - .push((id.def_id.local_def_index, simplified_self_ty)); + .push((id.def_id.def_id.local_def_index, simplified_self_ty)); } } } diff --git a/compiler/rustc_middle/src/dep_graph/dep_node.rs b/compiler/rustc_middle/src/dep_graph/dep_node.rs index 1fa0c6bababe4..ac106764c0217 100644 --- a/compiler/rustc_middle/src/dep_graph/dep_node.rs +++ b/compiler/rustc_middle/src/dep_graph/dep_node.rs @@ -62,7 +62,7 @@ use crate::ty::TyCtxt; use rustc_data_structures::fingerprint::Fingerprint; use rustc_hir::def_id::{CrateNum, DefId, LocalDefId}; use rustc_hir::definitions::DefPathHash; -use rustc_hir::HirId; +use rustc_hir::{HirId, OwnerId}; use rustc_query_system::dep_graph::FingerprintStyle; use rustc_span::symbol::Symbol; use std::hash::Hash; @@ -355,6 +355,28 @@ impl<'tcx> DepNodeParams> for LocalDefId { } } +impl<'tcx> DepNodeParams> for OwnerId { + #[inline(always)] + fn fingerprint_style() -> FingerprintStyle { + FingerprintStyle::DefPathHash + } + + #[inline(always)] + fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint { + self.to_def_id().to_fingerprint(tcx) + } + + #[inline(always)] + fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String { + self.to_def_id().to_debug_str(tcx) + } + + #[inline(always)] + fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option { + dep_node.extract_def_id(tcx).map(|id| OwnerId { def_id: id.expect_local() }) + } +} + impl<'tcx> DepNodeParams> for CrateNum { #[inline(always)] fn fingerprint_style() -> FingerprintStyle { diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index 30a23c342b356..b5f7b26ea7ab6 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -93,7 +93,7 @@ pub struct ParentOwnerIterator<'hir> { } impl<'hir> Iterator for ParentOwnerIterator<'hir> { - type Item = (LocalDefId, OwnerNode<'hir>); + type Item = (OwnerId, OwnerNode<'hir>); fn next(&mut self) -> Option { if self.current_id.local_id.index() != 0 { @@ -107,13 +107,13 @@ impl<'hir> Iterator for ParentOwnerIterator<'hir> { } loop { // There are nodes that do not have entries, so we need to skip them. - let parent_id = self.map.def_key(self.current_id.owner).parent; + let parent_id = self.map.def_key(self.current_id.owner.def_id).parent; - let parent_id = parent_id.map_or(CRATE_HIR_ID.owner, |local_def_index| { + let parent_id = parent_id.map_or(CRATE_OWNER_ID, |local_def_index| { let def_id = LocalDefId { local_def_index }; self.map.local_def_id_to_hir_id(def_id).owner }); - self.current_id = HirId::make_owner(parent_id); + self.current_id = HirId::make_owner(parent_id.def_id); // If this `HirId` doesn't have an entry, skip it and look for its `parent_id`. if let Some(node) = self.map.tcx.hir_owner(self.current_id.owner) { @@ -131,7 +131,7 @@ impl<'hir> Map<'hir> { #[inline] pub fn root_module(self) -> &'hir Mod<'hir> { - match self.tcx.hir_owner(CRATE_DEF_ID).map(|o| o.node) { + match self.tcx.hir_owner(CRATE_OWNER_ID).map(|o| o.node) { Some(OwnerNode::Crate(item)) => item, _ => bug!(), } @@ -186,7 +186,7 @@ impl<'hir> Map<'hir> { #[inline] pub fn opt_local_def_id(self, hir_id: HirId) -> Option { if hir_id.local_id == ItemLocalId::new(0) { - Some(hir_id.owner) + Some(hir_id.owner.def_id) } else { self.tcx .hir_owner_nodes(hir_id.owner) @@ -352,7 +352,7 @@ impl<'hir> Map<'hir> { } pub fn get_generics(self, id: LocalDefId) -> Option<&'hir Generics<'hir>> { - let node = self.tcx.hir_owner(id)?; + let node = self.tcx.hir_owner(OwnerId { def_id: id })?; node.node.generics() } @@ -532,7 +532,7 @@ impl<'hir> Map<'hir> { pub fn get_module(self, module: LocalDefId) -> (&'hir Mod<'hir>, Span, HirId) { let hir_id = HirId::make_owner(module); - match self.tcx.hir_owner(module).map(|o| o.node) { + match self.tcx.hir_owner(hir_id.owner).map(|o| o.node) { Some(OwnerNode::Item(&Item { span, kind: ItemKind::Mod(ref m), .. })) => { (m, span, hir_id) } @@ -622,14 +622,14 @@ impl<'hir> Map<'hir> { pub fn for_each_module(self, mut f: impl FnMut(LocalDefId)) { let crate_items = self.tcx.hir_crate_items(()); for module in crate_items.submodules.iter() { - f(*module) + f(module.def_id) } } #[inline] pub fn par_for_each_module(self, f: impl Fn(LocalDefId) + Sync + Send) { let crate_items = self.tcx.hir_crate_items(()); - par_for_each_in(&crate_items.submodules[..], |module| f(*module)) + par_for_each_in(&crate_items.submodules[..], |module| f(module.def_id)) } /// Returns an iterator for the nodes in the ancestor tree of the `current_id` @@ -721,27 +721,27 @@ impl<'hir> Map<'hir> { None } - /// Retrieves the `HirId` for `id`'s parent item, or `id` itself if no + /// Retrieves the `OwnerId` for `id`'s parent item, or `id` itself if no /// parent item is in this map. The "parent item" is the closest parent node /// in the HIR which is recorded by the map and is an item, either an item /// in a module, trait, or impl. - pub fn get_parent_item(self, hir_id: HirId) -> LocalDefId { + pub fn get_parent_item(self, hir_id: HirId) -> OwnerId { if let Some((def_id, _node)) = self.parent_owner_iter(hir_id).next() { def_id } else { - CRATE_DEF_ID + CRATE_OWNER_ID } } - /// Returns the `HirId` of `id`'s nearest module parent, or `id` itself if no + /// Returns the `OwnerId` of `id`'s nearest module parent, or `id` itself if no /// module parent is in this map. - pub(super) fn get_module_parent_node(self, hir_id: HirId) -> LocalDefId { + pub(super) fn get_module_parent_node(self, hir_id: HirId) -> OwnerId { for (def_id, node) in self.parent_owner_iter(hir_id) { if let OwnerNode::Item(&Item { kind: ItemKind::Mod(_), .. }) = node { return def_id; } } - CRATE_DEF_ID + CRATE_OWNER_ID } /// When on an if expression, a match arm tail expression or a match arm, give back @@ -814,30 +814,30 @@ impl<'hir> Map<'hir> { } bug!( "expected foreign mod or inlined parent, found {}", - self.node_to_string(HirId::make_owner(parent)) + self.node_to_string(HirId::make_owner(parent.def_id)) ) } - pub fn expect_owner(self, id: LocalDefId) -> OwnerNode<'hir> { + pub fn expect_owner(self, id: OwnerId) -> OwnerNode<'hir> { self.tcx.hir_owner(id).unwrap_or_else(|| bug!("expected owner for {:?}", id)).node } pub fn expect_item(self, id: LocalDefId) -> &'hir Item<'hir> { - match self.tcx.hir_owner(id) { + match self.tcx.hir_owner(OwnerId { def_id: id }) { Some(Owner { node: OwnerNode::Item(item), .. }) => item, _ => bug!("expected item, found {}", self.node_to_string(HirId::make_owner(id))), } } pub fn expect_impl_item(self, id: LocalDefId) -> &'hir ImplItem<'hir> { - match self.tcx.hir_owner(id) { + match self.tcx.hir_owner(OwnerId { def_id: id }) { Some(Owner { node: OwnerNode::ImplItem(item), .. }) => item, _ => bug!("expected impl item, found {}", self.node_to_string(HirId::make_owner(id))), } } pub fn expect_trait_item(self, id: LocalDefId) -> &'hir TraitItem<'hir> { - match self.tcx.hir_owner(id) { + match self.tcx.hir_owner(OwnerId { def_id: id }) { Some(Owner { node: OwnerNode::TraitItem(item), .. }) => item, _ => bug!("expected trait item, found {}", self.node_to_string(HirId::make_owner(id))), } @@ -850,11 +850,14 @@ impl<'hir> Map<'hir> { } } - pub fn expect_foreign_item(self, id: LocalDefId) -> &'hir ForeignItem<'hir> { + pub fn expect_foreign_item(self, id: OwnerId) -> &'hir ForeignItem<'hir> { match self.tcx.hir_owner(id) { Some(Owner { node: OwnerNode::ForeignItem(item), .. }) => item, _ => { - bug!("expected foreign item, found {}", self.node_to_string(HirId::make_owner(id))) + bug!( + "expected foreign item, found {}", + self.node_to_string(HirId::make_owner(id.def_id)) + ) } } } @@ -1290,7 +1293,7 @@ pub(crate) fn hir_crate_items(tcx: TyCtxt<'_>, _: ()) -> ModuleItems { // A "crate collector" and "module collector" start at a // module item (the former starts at the crate root) but only // the former needs to collect it. ItemCollector does not do this for us. - collector.submodules.push(CRATE_DEF_ID); + collector.submodules.push(CRATE_OWNER_ID); tcx.hir().walk_toplevel_module(&mut collector); let ItemCollector { @@ -1318,7 +1321,7 @@ struct ItemCollector<'tcx> { // otherwise it collects items in some module. crate_collector: bool, tcx: TyCtxt<'tcx>, - submodules: Vec, + submodules: Vec, items: Vec, trait_items: Vec, impl_items: Vec, @@ -1350,7 +1353,7 @@ impl<'hir> Visitor<'hir> for ItemCollector<'hir> { fn visit_item(&mut self, item: &'hir Item<'hir>) { if associated_body(Node::Item(item)).is_some() { - self.body_owners.push(item.def_id); + self.body_owners.push(item.def_id.def_id); } self.items.push(item.item_id()); @@ -1386,7 +1389,7 @@ impl<'hir> Visitor<'hir> for ItemCollector<'hir> { fn visit_trait_item(&mut self, item: &'hir TraitItem<'hir>) { if associated_body(Node::TraitItem(item)).is_some() { - self.body_owners.push(item.def_id); + self.body_owners.push(item.def_id.def_id); } self.trait_items.push(item.trait_item_id()); @@ -1395,7 +1398,7 @@ impl<'hir> Visitor<'hir> for ItemCollector<'hir> { fn visit_impl_item(&mut self, item: &'hir ImplItem<'hir>) { if associated_body(Node::ImplItem(item)).is_some() { - self.body_owners.push(item.def_id); + self.body_owners.push(item.def_id.def_id); } self.impl_items.push(item.impl_item_id()); diff --git a/compiler/rustc_middle/src/hir/mod.rs b/compiler/rustc_middle/src/hir/mod.rs index 211a614717f8b..1ce98a03c8a6c 100644 --- a/compiler/rustc_middle/src/hir/mod.rs +++ b/compiler/rustc_middle/src/hir/mod.rs @@ -39,7 +39,7 @@ impl<'a, 'tcx> HashStable> for Owner<'tcx> { /// bodies. The Ids are in visitor order. This is used to partition a pass between modules. #[derive(Debug, HashStable, Encodable, Decodable)] pub struct ModuleItems { - submodules: Box<[LocalDefId]>, + submodules: Box<[OwnerId]>, items: Box<[ItemId]>, trait_items: Box<[TraitItemId]>, impl_items: Box<[ImplItemId]>, @@ -67,10 +67,10 @@ impl ModuleItems { pub fn definitions(&self) -> impl Iterator + '_ { self.items .iter() - .map(|id| id.def_id) - .chain(self.trait_items.iter().map(|id| id.def_id)) - .chain(self.impl_items.iter().map(|id| id.def_id)) - .chain(self.foreign_items.iter().map(|id| id.def_id)) + .map(|id| id.def_id.def_id) + .chain(self.trait_items.iter().map(|id| id.def_id.def_id)) + .chain(self.impl_items.iter().map(|id| id.def_id.def_id)) + .chain(self.foreign_items.iter().map(|id| id.def_id.def_id)) } pub fn par_items(&self, f: impl Fn(ItemId) + Send + Sync) { @@ -97,7 +97,7 @@ impl<'tcx> TyCtxt<'tcx> { } pub fn parent_module(self, id: HirId) -> LocalDefId { - self.parent_module_from_def_id(id.owner) + self.parent_module_from_def_id(id.owner.def_id) } pub fn impl_subject(self, def_id: DefId) -> ImplSubject<'tcx> { @@ -110,13 +110,13 @@ impl<'tcx> TyCtxt<'tcx> { pub fn provide(providers: &mut Providers) { providers.parent_module_from_def_id = |tcx, id| { let hir = tcx.hir(); - hir.get_module_parent_node(hir.local_def_id_to_hir_id(id)) + hir.get_module_parent_node(hir.local_def_id_to_hir_id(id)).def_id }; providers.hir_crate_items = map::hir_crate_items; providers.crate_hash = map::crate_hash; providers.hir_module_items = map::hir_module_items; providers.hir_owner = |tcx, id| { - let owner = tcx.hir_crate(()).owners.get(id)?.as_owner()?; + let owner = tcx.hir_crate(()).owners.get(id.def_id)?.as_owner()?; let node = owner.node(); Some(Owner { node, hash_without_bodies: owner.nodes.hash_without_bodies }) }; @@ -128,21 +128,24 @@ pub fn provide(providers: &mut Providers) { MaybeOwner::NonOwner(hir_id) => hir_id, } }; - providers.hir_owner_nodes = |tcx, id| tcx.hir_crate(()).owners[id].map(|i| &i.nodes); + providers.hir_owner_nodes = |tcx, id| tcx.hir_crate(()).owners[id.def_id].map(|i| &i.nodes); providers.hir_owner_parent = |tcx, id| { // Accessing the local_parent is ok since its value is hashed as part of `id`'s DefPathHash. - tcx.opt_local_parent(id).map_or(CRATE_HIR_ID, |parent| { + tcx.opt_local_parent(id.def_id).map_or(CRATE_HIR_ID, |parent| { let mut parent_hir_id = tcx.hir().local_def_id_to_hir_id(parent); - if let Some(local_id) = - tcx.hir_crate(()).owners[parent_hir_id.owner].unwrap().parenting.get(&id) + if let Some(local_id) = tcx.hir_crate(()).owners[parent_hir_id.owner.def_id] + .unwrap() + .parenting + .get(&id.def_id) { parent_hir_id.local_id = *local_id; } parent_hir_id }) }; - providers.hir_attrs = - |tcx, id| tcx.hir_crate(()).owners[id].as_owner().map_or(AttributeMap::EMPTY, |o| &o.attrs); + providers.hir_attrs = |tcx, id| { + tcx.hir_crate(()).owners[id.def_id].as_owner().map_or(AttributeMap::EMPTY, |o| &o.attrs) + }; providers.source_span = |tcx, def_id| tcx.resolutions(()).source_span.get(def_id).copied().unwrap_or(DUMMY_SP); providers.def_span = |tcx, def_id| { @@ -177,6 +180,7 @@ pub fn provide(providers: &mut Providers) { let id = id.expect_local(); tcx.resolutions(()).expn_that_defined.get(&id).copied().unwrap_or(ExpnId::root()) }; - providers.in_scope_traits_map = - |tcx, id| tcx.hir_crate(()).owners[id].as_owner().map(|owner_info| &owner_info.trait_map); + providers.in_scope_traits_map = |tcx, id| { + tcx.hir_crate(()).owners[id.def_id].as_owner().map(|owner_info| &owner_info.trait_map) + }; } diff --git a/compiler/rustc_middle/src/middle/resolve_lifetime.rs b/compiler/rustc_middle/src/middle/resolve_lifetime.rs index 2a1a0bbe2aebe..c3bf1c717d9af 100644 --- a/compiler/rustc_middle/src/middle/resolve_lifetime.rs +++ b/compiler/rustc_middle/src/middle/resolve_lifetime.rs @@ -3,8 +3,8 @@ use crate::ty; use rustc_data_structures::fx::FxHashMap; -use rustc_hir::def_id::{DefId, LocalDefId}; -use rustc_hir::ItemLocalId; +use rustc_hir::def_id::DefId; +use rustc_hir::{ItemLocalId, OwnerId}; use rustc_macros::HashStable; #[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable, Debug, HashStable)] @@ -49,7 +49,7 @@ pub enum ObjectLifetimeDefault { pub struct ResolveLifetimes { /// Maps from every use of a named (not anonymous) lifetime to a /// `Region` describing how that region is bound - pub defs: FxHashMap>, + pub defs: FxHashMap>, - pub late_bound_vars: FxHashMap>>, + pub late_bound_vars: FxHashMap>>, } diff --git a/compiler/rustc_middle/src/mir/mono.rs b/compiler/rustc_middle/src/mir/mono.rs index 21ae121e1ce69..fdda62719ee10 100644 --- a/compiler/rustc_middle/src/mir/mono.rs +++ b/compiler/rustc_middle/src/mir/mono.rs @@ -182,7 +182,7 @@ impl<'tcx> MonoItem<'tcx> { match *self { MonoItem::Fn(Instance { def, .. }) => def.def_id().as_local(), MonoItem::Static(def_id) => def_id.as_local(), - MonoItem::GlobalAsm(item_id) => Some(item_id.def_id), + MonoItem::GlobalAsm(item_id) => Some(item_id.def_id.def_id), } .map(|def_id| tcx.def_span(def_id)) } @@ -373,7 +373,7 @@ impl<'tcx> CodegenUnit<'tcx> { } } MonoItem::Static(def_id) => def_id.as_local().map(Idx::index), - MonoItem::GlobalAsm(item_id) => Some(item_id.def_id.index()), + MonoItem::GlobalAsm(item_id) => Some(item_id.def_id.def_id.index()), }, item.symbol_name(tcx), ) diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 121a5b9f49227..eed44240f8357 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -73,7 +73,7 @@ rustc_queries! { /// /// This can be conveniently accessed by methods on `tcx.hir()`. /// Avoid calling this query directly. - query hir_owner(key: LocalDefId) -> Option> { + query hir_owner(key: hir::OwnerId) -> Option> { desc { |tcx| "HIR owner of `{}`", tcx.def_path_str(key.to_def_id()) } } @@ -89,7 +89,7 @@ rustc_queries! { /// /// This can be conveniently accessed by methods on `tcx.hir()`. /// Avoid calling this query directly. - query hir_owner_parent(key: LocalDefId) -> hir::HirId { + query hir_owner_parent(key: hir::OwnerId) -> hir::HirId { desc { |tcx| "HIR parent of `{}`", tcx.def_path_str(key.to_def_id()) } } @@ -97,7 +97,7 @@ rustc_queries! { /// /// This can be conveniently accessed by methods on `tcx.hir()`. /// Avoid calling this query directly. - query hir_owner_nodes(key: LocalDefId) -> hir::MaybeOwner<&'tcx hir::OwnerNodes<'tcx>> { + query hir_owner_nodes(key: hir::OwnerId) -> hir::MaybeOwner<&'tcx hir::OwnerNodes<'tcx>> { desc { |tcx| "HIR owner items in `{}`", tcx.def_path_str(key.to_def_id()) } } @@ -105,7 +105,7 @@ rustc_queries! { /// /// This can be conveniently accessed by methods on `tcx.hir()`. /// Avoid calling this query directly. - query hir_attrs(key: LocalDefId) -> &'tcx hir::AttributeMap<'tcx> { + query hir_attrs(key: hir::OwnerId) -> &'tcx hir::AttributeMap<'tcx> { desc { |tcx| "HIR owner attributes in `{}`", tcx.def_path_str(key.to_def_id()) } } @@ -1404,7 +1404,7 @@ rustc_queries! { query specializes(_: (DefId, DefId)) -> bool { desc { "computing whether impls specialize one another" } } - query in_scope_traits_map(_: LocalDefId) + query in_scope_traits_map(_: hir::OwnerId) -> Option<&'tcx FxHashMap>> { desc { "traits in scope at a block" } } @@ -1419,7 +1419,7 @@ rustc_queries! { separate_provide_extern } - query check_well_formed(key: LocalDefId) -> () { + query check_well_formed(key: hir::OwnerId) -> () { desc { |tcx| "checking that `{}` is well-formed", tcx.def_path_str(key.to_def_id()) } } @@ -1586,7 +1586,7 @@ rustc_queries! { arena_cache desc { "resolving lifetimes" } } - query named_region_map(_: LocalDefId) -> + query named_region_map(_: hir::OwnerId) -> Option<&'tcx FxHashMap> { desc { "looking up a named region" } } @@ -1602,7 +1602,7 @@ rustc_queries! { desc { "looking up lifetime defaults for generic parameter `{}`", tcx.def_path_str(key) } separate_provide_extern } - query late_bound_vars_map(_: LocalDefId) + query late_bound_vars_map(_: hir::OwnerId) -> Option<&'tcx FxHashMap>> { desc { "looking up late bound vars" } } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 8c44f4a98df5d..69bb9bb6fe04e 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -40,6 +40,7 @@ use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LOCAL_CRATE}; use rustc_hir::definitions::Definitions; +use rustc_hir::hir_id::OwnerId; use rustc_hir::intravisit::Visitor; use rustc_hir::lang_items::LangItem; use rustc_hir::{ @@ -289,7 +290,7 @@ pub struct CommonConsts<'tcx> { } pub struct LocalTableInContext<'a, V> { - hir_owner: LocalDefId, + hir_owner: OwnerId, data: &'a ItemLocalMap, } @@ -301,7 +302,7 @@ pub struct LocalTableInContext<'a, V> { /// would result in lookup errors, or worse, in silently wrong data being /// stored/returned. #[inline] -fn validate_hir_id_for_typeck_results(hir_owner: LocalDefId, hir_id: hir::HirId) { +fn validate_hir_id_for_typeck_results(hir_owner: OwnerId, hir_id: hir::HirId) { if hir_id.owner != hir_owner { invalid_hir_id_for_typeck_results(hir_owner, hir_id); } @@ -309,7 +310,7 @@ fn validate_hir_id_for_typeck_results(hir_owner: LocalDefId, hir_id: hir::HirId) #[cold] #[inline(never)] -fn invalid_hir_id_for_typeck_results(hir_owner: LocalDefId, hir_id: hir::HirId) { +fn invalid_hir_id_for_typeck_results(hir_owner: OwnerId, hir_id: hir::HirId) { ty::tls::with(|tcx| { bug!( "node {} with HirId::owner {:?} cannot be placed in TypeckResults with hir_owner {:?}", @@ -345,7 +346,7 @@ impl<'a, V> ::std::ops::Index for LocalTableInContext<'a, V> { } pub struct LocalTableInContextMut<'a, V> { - hir_owner: LocalDefId, + hir_owner: OwnerId, data: &'a mut ItemLocalMap, } @@ -417,7 +418,7 @@ pub struct GeneratorDiagnosticData<'tcx> { #[derive(TyEncodable, TyDecodable, Debug, HashStable)] pub struct TypeckResults<'tcx> { /// The `HirId::owner` all `ItemLocalId`s in this table are relative to. - pub hir_owner: LocalDefId, + pub hir_owner: OwnerId, /// Resolved definitions for `::X` associated paths and /// method calls, including those of overloaded operators. @@ -592,7 +593,7 @@ pub struct TypeckResults<'tcx> { } impl<'tcx> TypeckResults<'tcx> { - pub fn new(hir_owner: LocalDefId) -> TypeckResults<'tcx> { + pub fn new(hir_owner: OwnerId) -> TypeckResults<'tcx> { TypeckResults { hir_owner, type_dependent_defs: Default::default(), @@ -1726,7 +1727,7 @@ impl<'tcx> TyCtxt<'tcx> { #[inline] pub fn local_visibility(self, def_id: LocalDefId) -> Visibility { - self.visibility(def_id.to_def_id()).expect_local() + self.visibility(def_id).expect_local() } } @@ -2907,7 +2908,7 @@ impl<'tcx> TyCtxt<'tcx> { } pub fn is_late_bound(self, id: HirId) -> bool { - self.is_late_bound_map(id.owner).map_or(false, |set| { + self.is_late_bound_map(id.owner.def_id).map_or(false, |set| { let def_id = self.hir().local_def_id(id); set.contains(&def_id) }) diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs index 01e1e97b21a0b..52f16ad88f693 100644 --- a/compiler/rustc_middle/src/ty/error.rs +++ b/compiler/rustc_middle/src/ty/error.rs @@ -861,7 +861,7 @@ fn foo(&self) -> Self::T { String::new() } // When `body_owner` is an `impl` or `trait` item, look in its associated types for // `expected` and point at it. let parent_id = self.hir().get_parent_item(hir_id); - let item = self.hir().find_by_def_id(parent_id); + let item = self.hir().find_by_def_id(parent_id.def_id); debug!("expected_projection parent item {:?}", item); match item { Some(hir::Node::Item(hir::Item { kind: hir::ItemKind::Trait(.., items), .. })) => { diff --git a/compiler/rustc_middle/src/ty/query.rs b/compiler/rustc_middle/src/ty/query.rs index 00da260b1dc36..169da348a293a 100644 --- a/compiler/rustc_middle/src/ty/query.rs +++ b/compiler/rustc_middle/src/ty/query.rs @@ -44,6 +44,7 @@ use rustc_errors::ErrorGuaranteed; use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, DefIdSet, LocalDefId}; +use rustc_hir::hir_id::OwnerId; use rustc_hir::lang_items::{LangItem, LanguageItems}; use rustc_hir::{Crate, ItemLocalId, TraitCandidate}; use rustc_index::{bit_set::FiniteBitSet, vec::IndexVec}; @@ -336,7 +337,7 @@ macro_rules! define_callbacks { rustc_query_append! { define_callbacks! } mod sealed { - use super::{DefId, LocalDefId}; + use super::{DefId, LocalDefId, OwnerId}; /// An analogue of the `Into` trait that's intended only for query parameters. /// @@ -366,6 +367,13 @@ mod sealed { self.to_def_id() } } + + impl IntoQueryParam for OwnerId { + #[inline(always)] + fn into_query_param(self) -> DefId { + self.to_def_id() + } + } } use sealed::IntoQueryParam; diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index f1a25a60d5292..5cd7a7f760f5d 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -1246,7 +1246,7 @@ impl<'v> RootCollector<'_, 'v> { } } DefKind::Fn => { - self.push_if_root(id.def_id); + self.push_if_root(id.def_id.def_id); } _ => {} } @@ -1254,7 +1254,7 @@ impl<'v> RootCollector<'_, 'v> { fn process_impl_item(&mut self, id: hir::ImplItemId) { if matches!(self.tcx.def_kind(id.def_id), DefKind::AssocFn) { - self.push_if_root(id.def_id); + self.push_if_root(id.def_id.def_id); } } diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index f112f1274b8c7..a21521ff68b19 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -11,9 +11,11 @@ use rustc_errors::{fluent, struct_span_err, Applicability, MultiSpan}; use rustc_expand::base::resolve_path; use rustc_feature::{AttributeDuplicates, AttributeType, BuiltinAttribute, BUILTIN_ATTRIBUTE_MAP}; use rustc_hir as hir; -use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID}; +use rustc_hir::def_id::LocalDefId; use rustc_hir::intravisit::{self, Visitor}; -use rustc_hir::{self, FnSig, ForeignItem, HirId, Item, ItemKind, TraitItem, CRATE_HIR_ID}; +use rustc_hir::{ + self, FnSig, ForeignItem, HirId, Item, ItemKind, TraitItem, CRATE_HIR_ID, CRATE_OWNER_ID, +}; use rustc_hir::{MethodKind, Target}; use rustc_middle::hir::nested_filter; use rustc_middle::middle::resolve_lifetime::ObjectLifetimeDefault; @@ -35,7 +37,7 @@ pub(crate) fn target_from_impl_item<'tcx>( match impl_item.kind { hir::ImplItemKind::Const(..) => Target::AssocConst, hir::ImplItemKind::Fn(..) => { - let parent_def_id = tcx.hir().get_parent_item(impl_item.hir_id()); + let parent_def_id = tcx.hir().get_parent_item(impl_item.hir_id()).def_id; let containing_item = tcx.hir().expect_item(parent_def_id); let containing_impl_is_for_trait = match &containing_item.kind { hir::ItemKind::Impl(impl_) => impl_.of_trait.is_some(), @@ -640,7 +642,7 @@ impl CheckAttrVisitor<'_> { let span = meta.span(); if let Some(location) = match target { Target::AssocTy => { - let parent_def_id = self.tcx.hir().get_parent_item(hir_id); + let parent_def_id = self.tcx.hir().get_parent_item(hir_id).def_id; let containing_item = self.tcx.hir().expect_item(parent_def_id); if Target::from_item(containing_item) == Target::Impl { Some("type alias in implementation block") @@ -649,7 +651,7 @@ impl CheckAttrVisitor<'_> { } } Target::AssocConst => { - let parent_def_id = self.tcx.hir().get_parent_item(hir_id); + let parent_def_id = self.tcx.hir().get_parent_item(hir_id).def_id; let containing_item = self.tcx.hir().expect_item(parent_def_id); // We can't link to trait impl's consts. let err = "associated constant in trait implementation block"; @@ -878,7 +880,7 @@ impl CheckAttrVisitor<'_> { self.tcx.struct_span_lint_hir(INVALID_DOC_ATTRIBUTES, hir_id, meta.span(), |lint| { let mut err = lint.build(fluent::passes::attr_crate_level); if attr.style == AttrStyle::Outer - && self.tcx.hir().get_parent_item(hir_id) == CRATE_DEF_ID + && self.tcx.hir().get_parent_item(hir_id) == CRATE_OWNER_ID { if let Ok(mut src) = self.tcx.sess.source_map().span_to_snippet(attr.span) { src.insert(1, '!'); diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index 57f7c379d0490..e9d71bc93ac10 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -317,7 +317,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { intravisit::walk_trait_item(self, trait_item); } Node::ImplItem(impl_item) => { - let item = self.tcx.local_parent(impl_item.def_id); + let item = self.tcx.local_parent(impl_item.def_id.def_id); if self.tcx.impl_trait_ref(item).is_none() { //// If it's a type whose items are live, then it's live, too. //// This is done to handle the case where, for example, the static @@ -374,7 +374,7 @@ impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> { if has_repr_c || (f.is_positional() && has_repr_simd) { return Some(def_id); } - if !tcx.visibility(f.hir_id.owner).is_public() { + if !tcx.visibility(f.hir_id.owner.def_id).is_public() { return None; } if tcx.visibility(def_id).is_public() { Some(def_id) } else { None } @@ -528,7 +528,7 @@ fn check_item<'tcx>( ) { let allow_dead_code = has_allow_dead_code_or_lang_attr(tcx, id.hir_id()); if allow_dead_code { - worklist.push(id.def_id); + worklist.push(id.def_id.def_id); } match tcx.def_kind(id.def_id) { @@ -554,7 +554,7 @@ fn check_item<'tcx>( let of_trait = tcx.impl_trait_ref(id.def_id); if of_trait.is_some() { - worklist.push(id.def_id); + worklist.push(id.def_id.def_id); } // get DefIds from another query @@ -577,12 +577,12 @@ fn check_item<'tcx>( if let hir::ItemKind::Struct(ref variant_data, _) = item.kind && let Some(ctor_hir_id) = variant_data.ctor_hir_id() { - struct_constructors.insert(tcx.hir().local_def_id(ctor_hir_id), item.def_id); + struct_constructors.insert(tcx.hir().local_def_id(ctor_hir_id), item.def_id.def_id); } } DefKind::GlobalAsm => { // global_asm! is always live. - worklist.push(id.def_id); + worklist.push(id.def_id.def_id); } _ => {} } @@ -595,7 +595,7 @@ fn check_trait_item<'tcx>(tcx: TyCtxt<'tcx>, worklist: &mut Vec, id: if matches!(trait_item.kind, Const(_, Some(_)) | Fn(_, hir::TraitFn::Provided(_))) && has_allow_dead_code_or_lang_attr(tcx, trait_item.hir_id()) { - worklist.push(trait_item.def_id); + worklist.push(trait_item.def_id.def_id); } } } @@ -608,7 +608,7 @@ fn check_foreign_item<'tcx>( if matches!(tcx.def_kind(id.def_id), DefKind::Static(_) | DefKind::Fn) && has_allow_dead_code_or_lang_attr(tcx, id.hir_id()) { - worklist.push(id.def_id); + worklist.push(id.def_id.def_id); } } @@ -871,13 +871,13 @@ fn check_mod_deathness(tcx: TyCtxt<'_>, module: LocalDefId) { let module_items = tcx.hir_module_items(module); for item in module_items.items() { - if !live_symbols.contains(&item.def_id) { - let parent = tcx.local_parent(item.def_id); + if !live_symbols.contains(&item.def_id.def_id) { + let parent = tcx.local_parent(item.def_id.def_id); if parent != module && !live_symbols.contains(&parent) { // We already have diagnosed something. continue; } - visitor.check_definition(item.def_id); + visitor.check_definition(item.def_id.def_id); continue; } @@ -926,16 +926,21 @@ fn check_mod_deathness(tcx: TyCtxt<'_>, module: LocalDefId) { visitor.warn_dead_fields_and_variants(def_id, "read", dead_fields, is_positional) } - visitor.warn_dead_fields_and_variants(item.def_id, "constructed", dead_variants, false); + visitor.warn_dead_fields_and_variants( + item.def_id.def_id, + "constructed", + dead_variants, + false, + ); } } for impl_item in module_items.impl_items() { - visitor.check_definition(impl_item.def_id); + visitor.check_definition(impl_item.def_id.def_id); } for foreign_item in module_items.foreign_items() { - visitor.check_definition(foreign_item.def_id); + visitor.check_definition(foreign_item.def_id.def_id); } // We do not warn trait items. diff --git a/compiler/rustc_passes/src/diagnostic_items.rs b/compiler/rustc_passes/src/diagnostic_items.rs index e6b69d8986cf8..e428d9293db17 100644 --- a/compiler/rustc_passes/src/diagnostic_items.rs +++ b/compiler/rustc_passes/src/diagnostic_items.rs @@ -74,19 +74,19 @@ fn diagnostic_items<'tcx>(tcx: TyCtxt<'tcx>, cnum: CrateNum) -> DiagnosticItems let crate_items = tcx.hir_crate_items(()); for id in crate_items.items() { - observe_item(tcx, &mut diagnostic_items, id.def_id); + observe_item(tcx, &mut diagnostic_items, id.def_id.def_id); } for id in crate_items.trait_items() { - observe_item(tcx, &mut diagnostic_items, id.def_id); + observe_item(tcx, &mut diagnostic_items, id.def_id.def_id); } for id in crate_items.impl_items() { - observe_item(tcx, &mut diagnostic_items, id.def_id); + observe_item(tcx, &mut diagnostic_items, id.def_id.def_id); } for id in crate_items.foreign_items() { - observe_item(tcx, &mut diagnostic_items, id.def_id); + observe_item(tcx, &mut diagnostic_items, id.def_id.def_id); } diagnostic_items diff --git a/compiler/rustc_passes/src/entry.rs b/compiler/rustc_passes/src/entry.rs index cd10170d3ba58..eec37d19a8831 100644 --- a/compiler/rustc_passes/src/entry.rs +++ b/compiler/rustc_passes/src/entry.rs @@ -82,7 +82,7 @@ fn err_if_attr_found(ctxt: &EntryContext<'_>, id: ItemId, sym: Symbol, details: } fn find_item(id: ItemId, ctxt: &mut EntryContext<'_>) { - let at_root = ctxt.tcx.opt_local_parent(id.def_id) == Some(CRATE_DEF_ID); + let at_root = ctxt.tcx.opt_local_parent(id.def_id.def_id) == Some(CRATE_DEF_ID); match entry_point_type(ctxt, id, at_root) { EntryPointType::None => { @@ -99,7 +99,7 @@ fn find_item(id: ItemId, ctxt: &mut EntryContext<'_>) { } EntryPointType::RustcMainAttr => { if ctxt.attr_main_fn.is_none() { - ctxt.attr_main_fn = Some((id.def_id, ctxt.tcx.def_span(id.def_id.to_def_id()))); + ctxt.attr_main_fn = Some((id.def_id.def_id, ctxt.tcx.def_span(id.def_id))); } else { struct_span_err!( ctxt.tcx.sess, @@ -118,11 +118,11 @@ fn find_item(id: ItemId, ctxt: &mut EntryContext<'_>) { EntryPointType::Start => { err_if_attr_found(ctxt, id, sym::unix_sigpipe, "can only be used on `fn main()`"); if ctxt.start_fn.is_none() { - ctxt.start_fn = Some((id.def_id, ctxt.tcx.def_span(id.def_id.to_def_id()))); + ctxt.start_fn = Some((id.def_id.def_id, ctxt.tcx.def_span(id.def_id))); } else { struct_span_err!( ctxt.tcx.sess, - ctxt.tcx.def_span(id.def_id.to_def_id()), + ctxt.tcx.def_span(id.def_id), E0138, "multiple `start` functions" ) diff --git a/compiler/rustc_passes/src/hir_id_validator.rs b/compiler/rustc_passes/src/hir_id_validator.rs index 3bb8c0bb48c5f..3ee8c8bcb1dea 100644 --- a/compiler/rustc_passes/src/hir_id_validator.rs +++ b/compiler/rustc_passes/src/hir_id_validator.rs @@ -1,6 +1,5 @@ use rustc_data_structures::sync::Lock; use rustc_hir as hir; -use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID}; use rustc_hir::intravisit; use rustc_hir::{HirId, ItemLocalId}; use rustc_index::bit_set::GrowableBitSet; @@ -42,7 +41,7 @@ pub fn check_crate(tcx: TyCtxt<'_>) { struct HirIdValidator<'a, 'hir> { hir_map: Map<'hir>, - owner: Option, + owner: Option, hir_ids_seen: GrowableBitSet, errors: &'a Lock>, } @@ -63,12 +62,12 @@ impl<'a, 'hir> HirIdValidator<'a, 'hir> { self.errors.lock().push(f()); } - fn check)>(&mut self, owner: LocalDefId, walk: F) { + fn check)>(&mut self, owner: hir::OwnerId, walk: F) { assert!(self.owner.is_none()); self.owner = Some(owner); walk(self); - if owner == CRATE_DEF_ID { + if owner == hir::CRATE_OWNER_ID { return; } @@ -97,14 +96,14 @@ impl<'a, 'hir> HirIdValidator<'a, 'hir> { missing_items.push(format!( "[local_id: {}, owner: {}]", local_id, - self.hir_map.def_path(owner).to_string_no_crate_verbose() + self.hir_map.def_path(owner.def_id).to_string_no_crate_verbose() )); } self.error(|| { format!( "ItemLocalIds not assigned densely in {}. \ Max ItemLocalId = {}, missing IDs = {:#?}; seens IDs = {:#?}", - self.hir_map.def_path(owner).to_string_no_crate_verbose(), + self.hir_map.def_path(owner.def_id).to_string_no_crate_verbose(), max, missing_items, self.hir_ids_seen @@ -138,8 +137,8 @@ impl<'a, 'hir> intravisit::Visitor<'hir> for HirIdValidator<'a, 'hir> { format!( "HirIdValidator: The recorded owner of {} is {} instead of {}", self.hir_map.node_to_string(hir_id), - self.hir_map.def_path(hir_id.owner).to_string_no_crate_verbose(), - self.hir_map.def_path(owner).to_string_no_crate_verbose() + self.hir_map.def_path(hir_id.owner.def_id).to_string_no_crate_verbose(), + self.hir_map.def_path(owner.def_id).to_string_no_crate_verbose() ) }); } diff --git a/compiler/rustc_passes/src/layout_test.rs b/compiler/rustc_passes/src/layout_test.rs index fd03f657111d9..46c4a702fde95 100644 --- a/compiler/rustc_passes/src/layout_test.rs +++ b/compiler/rustc_passes/src/layout_test.rs @@ -16,7 +16,7 @@ pub fn test_layout(tcx: TyCtxt<'_>) { DefKind::TyAlias | DefKind::Enum | DefKind::Struct | DefKind::Union ) { for attr in tcx.get_attrs(id.def_id.to_def_id(), sym::rustc_layout) { - dump_layout_of(tcx, id.def_id, attr); + dump_layout_of(tcx, id.def_id.def_id, attr); } } } diff --git a/compiler/rustc_passes/src/reachable.rs b/compiler/rustc_passes/src/reachable.rs index 75244124e20ef..16055641aca9f 100644 --- a/compiler/rustc_passes/src/reachable.rs +++ b/compiler/rustc_passes/src/reachable.rs @@ -153,7 +153,7 @@ impl<'tcx> ReachableContext<'tcx> { hir::ImplItemKind::Fn(..) => { let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id); let impl_did = self.tcx.hir().get_parent_item(hir_id); - method_might_be_inlined(self.tcx, impl_item, impl_did) + method_might_be_inlined(self.tcx, impl_item, impl_did.def_id) } hir::ImplItemKind::TyAlias(_) => false, }, @@ -305,8 +305,8 @@ fn check_item<'tcx>( worklist: &mut Vec, access_levels: &privacy::AccessLevels, ) { - if has_custom_linkage(tcx, id.def_id) { - worklist.push(id.def_id); + if has_custom_linkage(tcx, id.def_id.def_id) { + worklist.push(id.def_id.def_id); } if !matches!(tcx.def_kind(id.def_id), DefKind::Impl) { @@ -318,8 +318,8 @@ fn check_item<'tcx>( if let hir::ItemKind::Impl(hir::Impl { of_trait: Some(ref trait_ref), ref items, .. }) = item.kind { - if !access_levels.is_reachable(item.def_id) { - worklist.extend(items.iter().map(|ii_ref| ii_ref.id.def_id)); + if !access_levels.is_reachable(item.def_id.def_id) { + worklist.extend(items.iter().map(|ii_ref| ii_ref.id.def_id.def_id)); let Res::Def(DefKind::Trait, trait_def_id) = trait_ref.path.res else { unreachable!(); @@ -403,8 +403,8 @@ fn reachable_set<'tcx>(tcx: TyCtxt<'tcx>, (): ()) -> FxHashSet { } for id in crate_items.impl_items() { - if has_custom_linkage(tcx, id.def_id) { - reachable_context.worklist.push(id.def_id); + if has_custom_linkage(tcx, id.def_id.def_id) { + reachable_context.worklist.push(id.def_id.def_id); } } } diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs index 3f23b027aef28..e50beb27d2a88 100644 --- a/compiler/rustc_passes/src/stability.rs +++ b/compiler/rustc_passes/src/stability.rs @@ -385,7 +385,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> { } self.annotate( - i.def_id, + i.def_id.def_id, i.span, fn_sig, kind, @@ -404,7 +404,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> { }; self.annotate( - ti.def_id, + ti.def_id.def_id, ti.span, fn_sig, AnnotationKind::Required, @@ -427,7 +427,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> { }; self.annotate( - ii.def_id, + ii.def_id.def_id, ii.span, fn_sig, kind, @@ -485,7 +485,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> { fn visit_foreign_item(&mut self, i: &'tcx hir::ForeignItem<'tcx>) { self.annotate( - i.def_id, + i.def_id.def_id, i.span, None, AnnotationKind::Required, @@ -573,25 +573,25 @@ impl<'tcx> Visitor<'tcx> for MissingStabilityAnnotations<'tcx> { hir::ItemKind::Impl(hir::Impl { of_trait: None, .. }) | hir::ItemKind::ForeignMod { .. } ) { - self.check_missing_stability(i.def_id, i.span); + self.check_missing_stability(i.def_id.def_id, i.span); } // Ensure stable `const fn` have a const stability attribute. - self.check_missing_const_stability(i.def_id, i.span); + self.check_missing_const_stability(i.def_id.def_id, i.span); intravisit::walk_item(self, i) } fn visit_trait_item(&mut self, ti: &'tcx hir::TraitItem<'tcx>) { - self.check_missing_stability(ti.def_id, ti.span); + self.check_missing_stability(ti.def_id.def_id, ti.span); intravisit::walk_trait_item(self, ti); } fn visit_impl_item(&mut self, ii: &'tcx hir::ImplItem<'tcx>) { let impl_def_id = self.tcx.hir().get_parent_item(ii.hir_id()); if self.tcx.impl_trait_ref(impl_def_id).is_none() { - self.check_missing_stability(ii.def_id, ii.span); - self.check_missing_const_stability(ii.def_id, ii.span); + self.check_missing_stability(ii.def_id.def_id, ii.span); + self.check_missing_const_stability(ii.def_id.def_id, ii.span); } intravisit::walk_impl_item(self, ii); } @@ -610,7 +610,7 @@ impl<'tcx> Visitor<'tcx> for MissingStabilityAnnotations<'tcx> { } fn visit_foreign_item(&mut self, i: &'tcx hir::ForeignItem<'tcx>) { - self.check_missing_stability(i.def_id, i.span); + self.check_missing_stability(i.def_id.def_id, i.span); intravisit::walk_foreign_item(self, i); } // Note that we don't need to `check_missing_stability` for default generic parameters, @@ -716,7 +716,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> { return; } - let Some(cnum) = self.tcx.extern_mod_stmt_cnum(item.def_id) else { + let Some(cnum) = self.tcx.extern_mod_stmt_cnum(item.def_id.def_id) else { return; }; let def_id = cnum.as_def_id(); @@ -869,7 +869,7 @@ fn is_unstable_reexport<'tcx>(tcx: TyCtxt<'tcx>, id: hir::HirId) -> bool { } // If this is a path that isn't a use, we don't need to do anything special - if !matches!(tcx.hir().item(hir::ItemId { def_id }).kind, ItemKind::Use(..)) { + if !matches!(tcx.hir().expect_item(def_id).kind, ItemKind::Use(..)) { return false; } diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 8f5ee51e6cfbb..728674472505c 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -506,8 +506,8 @@ impl<'tcx> EmbargoVisitor<'tcx> { let module = self.tcx.hir().get_module(module_def_id).0; for item_id in module.item_ids { let def_kind = self.tcx.def_kind(item_id.def_id); - let vis = self.tcx.local_visibility(item_id.def_id); - self.update_macro_reachable_def(item_id.def_id, def_kind, vis, defining_mod); + let vis = self.tcx.local_visibility(item_id.def_id.def_id); + self.update_macro_reachable_def(item_id.def_id.def_id, def_kind, vis, defining_mod); } if let Some(exports) = self.tcx.module_reexports(module_def_id) { for export in exports { @@ -627,11 +627,14 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> { fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) { let item_level = match item.kind { hir::ItemKind::Impl { .. } => { - let impl_level = - Option::::of_impl(item.def_id, self.tcx, &self.access_levels); - self.update(item.def_id, impl_level) + let impl_level = Option::::of_impl( + item.def_id.def_id, + self.tcx, + &self.access_levels, + ); + self.update(item.def_id.def_id, impl_level) } - _ => self.get(item.def_id), + _ => self.get(item.def_id.def_id), }; // Update levels of nested things. @@ -652,13 +655,13 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> { if impl_.of_trait.is_some() || self.tcx.visibility(impl_item_ref.id.def_id).is_public() { - self.update(impl_item_ref.id.def_id, item_level); + self.update(impl_item_ref.id.def_id.def_id, item_level); } } } hir::ItemKind::Trait(.., trait_item_refs) => { for trait_item_ref in trait_item_refs { - self.update(trait_item_ref.id.def_id, item_level); + self.update(trait_item_ref.id.def_id.def_id, item_level); } } hir::ItemKind::Struct(ref def, _) | hir::ItemKind::Union(ref def, _) => { @@ -674,12 +677,12 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> { } } hir::ItemKind::Macro(ref macro_def, _) => { - self.update_reachability_from_macro(item.def_id, macro_def); + self.update_reachability_from_macro(item.def_id.def_id, macro_def); } hir::ItemKind::ForeignMod { items, .. } => { for foreign_item in items { if self.tcx.visibility(foreign_item.id.def_id).is_public() { - self.update(foreign_item.id.def_id, item_level); + self.update(foreign_item.id.def_id.def_id, item_level); } } } @@ -717,7 +720,7 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> { // reachable if they are returned via `impl Trait`, even from private functions. let exist_level = cmp::max(item_level, Some(AccessLevel::ReachableFromImplTrait)); - self.reach(item.def_id, exist_level).generics().predicates().ty(); + self.reach(item.def_id.def_id, exist_level).generics().predicates().ty(); } } // Visit everything. @@ -726,16 +729,16 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> { | hir::ItemKind::Fn(..) | hir::ItemKind::TyAlias(..) => { if item_level.is_some() { - self.reach(item.def_id, item_level).generics().predicates().ty(); + self.reach(item.def_id.def_id, item_level).generics().predicates().ty(); } } hir::ItemKind::Trait(.., trait_item_refs) => { if item_level.is_some() { - self.reach(item.def_id, item_level).generics().predicates(); + self.reach(item.def_id.def_id, item_level).generics().predicates(); for trait_item_ref in trait_item_refs { let tcx = self.tcx; - let mut reach = self.reach(trait_item_ref.id.def_id, item_level); + let mut reach = self.reach(trait_item_ref.id.def_id.def_id, item_level); reach.generics().predicates(); if trait_item_ref.kind == AssocItemKind::Type @@ -750,18 +753,22 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> { } hir::ItemKind::TraitAlias(..) => { if item_level.is_some() { - self.reach(item.def_id, item_level).generics().predicates(); + self.reach(item.def_id.def_id, item_level).generics().predicates(); } } // Visit everything except for private impl items. hir::ItemKind::Impl(ref impl_) => { if item_level.is_some() { - self.reach(item.def_id, item_level).generics().predicates().ty().trait_ref(); + self.reach(item.def_id.def_id, item_level) + .generics() + .predicates() + .ty() + .trait_ref(); for impl_item_ref in impl_.items { - let impl_item_level = self.get(impl_item_ref.id.def_id); + let impl_item_level = self.get(impl_item_ref.id.def_id.def_id); if impl_item_level.is_some() { - self.reach(impl_item_ref.id.def_id, impl_item_level) + self.reach(impl_item_ref.id.def_id.def_id, impl_item_level) .generics() .predicates() .ty(); @@ -773,7 +780,7 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> { // Visit everything, but enum variants have their own levels. hir::ItemKind::Enum(ref def, _) => { if item_level.is_some() { - self.reach(item.def_id, item_level).generics().predicates(); + self.reach(item.def_id.def_id, item_level).generics().predicates(); } for variant in def.variants { let variant_level = self.get(self.tcx.hir().local_def_id(variant.id)); @@ -784,13 +791,13 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> { } // Corner case: if the variant is reachable, but its // enum is not, make the enum reachable as well. - self.reach(item.def_id, variant_level).ty(); + self.reach(item.def_id.def_id, variant_level).ty(); } if let Some(hir_id) = variant.data.ctor_hir_id() { let ctor_def_id = self.tcx.hir().local_def_id(hir_id); let ctor_level = self.get(ctor_def_id); if ctor_level.is_some() { - self.reach(item.def_id, ctor_level).ty(); + self.reach(item.def_id.def_id, ctor_level).ty(); } } } @@ -798,9 +805,9 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> { // Visit everything, but foreign items have their own levels. hir::ItemKind::ForeignMod { items, .. } => { for foreign_item in items { - let foreign_item_level = self.get(foreign_item.id.def_id); + let foreign_item_level = self.get(foreign_item.id.def_id.def_id); if foreign_item_level.is_some() { - self.reach(foreign_item.id.def_id, foreign_item_level) + self.reach(foreign_item.id.def_id.def_id, foreign_item_level) .generics() .predicates() .ty(); @@ -810,7 +817,7 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> { // Visit everything except for private fields. hir::ItemKind::Struct(ref struct_def, _) | hir::ItemKind::Union(ref struct_def, _) => { if item_level.is_some() { - self.reach(item.def_id, item_level).generics().predicates(); + self.reach(item.def_id.def_id, item_level).generics().predicates(); for field in struct_def.fields() { let def_id = self.tcx.hir().local_def_id(field.hir_id); let field_level = self.get(def_id); @@ -823,7 +830,7 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> { let ctor_def_id = self.tcx.hir().local_def_id(hir_id); let ctor_level = self.get(ctor_def_id); if ctor_level.is_some() { - self.reach(item.def_id, ctor_level).ty(); + self.reach(item.def_id.def_id, ctor_level).ty(); } } } @@ -945,7 +952,7 @@ impl<'tcx, 'a> TestReachabilityVisitor<'tcx, 'a> { impl<'tcx, 'a> Visitor<'tcx> for TestReachabilityVisitor<'tcx, 'a> { fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) { - self.access_level_diagnostic(item.def_id); + self.access_level_diagnostic(item.def_id.def_id); match item.kind { hir::ItemKind::Enum(ref def, _) => { @@ -969,13 +976,13 @@ impl<'tcx, 'a> Visitor<'tcx> for TestReachabilityVisitor<'tcx, 'a> { } fn visit_trait_item(&mut self, item: &'tcx hir::TraitItem<'tcx>) { - self.access_level_diagnostic(item.def_id); + self.access_level_diagnostic(item.def_id.def_id); } fn visit_impl_item(&mut self, item: &'tcx hir::ImplItem<'tcx>) { - self.access_level_diagnostic(item.def_id); + self.access_level_diagnostic(item.def_id.def_id); } fn visit_foreign_item(&mut self, item: &'tcx hir::ForeignItem<'tcx>) { - self.access_level_diagnostic(item.def_id); + self.access_level_diagnostic(item.def_id.def_id); } } @@ -1058,7 +1065,7 @@ impl<'tcx> Visitor<'tcx> for NamePrivacyVisitor<'tcx> { } fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) { - let orig_current_item = mem::replace(&mut self.current_item, item.def_id); + let orig_current_item = mem::replace(&mut self.current_item, item.def_id.def_id); intravisit::walk_item(self, item); self.current_item = orig_current_item; } @@ -1361,7 +1368,7 @@ impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> { // Check types in item interfaces. fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) { - let orig_current_item = mem::replace(&mut self.current_item, item.def_id); + let orig_current_item = mem::replace(&mut self.current_item, item.def_id.def_id); let old_maybe_typeck_results = self.maybe_typeck_results.take(); intravisit::walk_item(self, item); self.maybe_typeck_results = old_maybe_typeck_results; @@ -1503,7 +1510,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> { hir::ItemKind::ForeignMod { .. } => {} hir::ItemKind::Trait(.., bounds, _) => { - if !self.trait_is_public(item.def_id) { + if !self.trait_is_public(item.def_id.def_id) { return; } @@ -1564,7 +1571,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> { let impl_item = self.tcx.hir().impl_item(impl_item_ref.id); match impl_item.kind { hir::ImplItemKind::Const(..) | hir::ImplItemKind::Fn(..) => { - self.access_levels.is_reachable(impl_item_ref.id.def_id) + self.access_levels.is_reachable(impl_item_ref.id.def_id.def_id) } hir::ImplItemKind::TyAlias(_) => false, } @@ -1584,7 +1591,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> { let impl_item = self.tcx.hir().impl_item(impl_item_ref.id); match impl_item.kind { hir::ImplItemKind::Const(..) | hir::ImplItemKind::Fn(..) - if self.item_is_public(impl_item.def_id) => + if self.item_is_public(impl_item.def_id.def_id) => { intravisit::walk_impl_item(self, impl_item) } @@ -1625,7 +1632,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> { // methods will be visible as `Public::foo`. let mut found_pub_static = false; for impl_item_ref in impl_.items { - if self.access_levels.is_reachable(impl_item_ref.id.def_id) + if self.access_levels.is_reachable(impl_item_ref.id.def_id.def_id) || self.tcx.visibility(impl_item_ref.id.def_id).is_public() { let impl_item = self.tcx.hir().impl_item(impl_item_ref.id); @@ -1654,7 +1661,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> { hir::ItemKind::TyAlias(..) => return, // Not at all public, so we don't care. - _ if !self.item_is_public(item.def_id) => { + _ if !self.item_is_public(item.def_id.def_id) => { return; } @@ -1685,7 +1692,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> { } fn visit_foreign_item(&mut self, item: &'tcx hir::ForeignItem<'tcx>) { - if self.access_levels.is_reachable(item.def_id) { + if self.access_levels.is_reachable(item.def_id.def_id) { intravisit::walk_foreign_item(self, item) } } @@ -1922,43 +1929,44 @@ impl<'tcx> PrivateItemsInPublicInterfacesChecker<'tcx> { pub fn check_item(&mut self, id: ItemId) { let tcx = self.tcx; - let item_visibility = tcx.local_visibility(id.def_id); - let def_kind = tcx.def_kind(id.def_id); + let def_id = id.def_id.def_id; + let item_visibility = tcx.local_visibility(def_id); + let def_kind = tcx.def_kind(def_id); match def_kind { DefKind::Const | DefKind::Static(_) | DefKind::Fn | DefKind::TyAlias => { - self.check(id.def_id, item_visibility).generics().predicates().ty(); + self.check(def_id, item_visibility).generics().predicates().ty(); } DefKind::OpaqueTy => { // `ty()` for opaque types is the underlying type, // it's not a part of interface, so we skip it. - self.check(id.def_id, item_visibility).generics().bounds(); + self.check(def_id, item_visibility).generics().bounds(); } DefKind::Trait => { let item = tcx.hir().item(id); if let hir::ItemKind::Trait(.., trait_item_refs) = item.kind { - self.check(item.def_id, item_visibility).generics().predicates(); + self.check(item.def_id.def_id, item_visibility).generics().predicates(); for trait_item_ref in trait_item_refs { self.check_assoc_item( - trait_item_ref.id.def_id, + trait_item_ref.id.def_id.def_id, trait_item_ref.kind, item_visibility, ); if let AssocItemKind::Type = trait_item_ref.kind { - self.check(trait_item_ref.id.def_id, item_visibility).bounds(); + self.check(trait_item_ref.id.def_id.def_id, item_visibility).bounds(); } } } } DefKind::TraitAlias => { - self.check(id.def_id, item_visibility).generics().predicates(); + self.check(def_id, item_visibility).generics().predicates(); } DefKind::Enum => { let item = tcx.hir().item(id); if let hir::ItemKind::Enum(ref def, _) = item.kind { - self.check(item.def_id, item_visibility).generics().predicates(); + self.check(item.def_id.def_id, item_visibility).generics().predicates(); for variant in def.variants { for field in variant.data.fields() { @@ -1973,8 +1981,8 @@ impl<'tcx> PrivateItemsInPublicInterfacesChecker<'tcx> { let item = tcx.hir().item(id); if let hir::ItemKind::ForeignMod { items, .. } = item.kind { for foreign_item in items { - let vis = tcx.local_visibility(foreign_item.id.def_id); - self.check(foreign_item.id.def_id, vis).generics().predicates().ty(); + let vis = tcx.local_visibility(foreign_item.id.def_id.def_id); + self.check(foreign_item.id.def_id.def_id, vis).generics().predicates().ty(); } } } @@ -1984,7 +1992,7 @@ impl<'tcx> PrivateItemsInPublicInterfacesChecker<'tcx> { if let hir::ItemKind::Struct(ref struct_def, _) | hir::ItemKind::Union(ref struct_def, _) = item.kind { - self.check(item.def_id, item_visibility).generics().predicates(); + self.check(item.def_id.def_id, item_visibility).generics().predicates(); for field in struct_def.fields() { let def_id = tcx.hir().local_def_id(field.hir_id); @@ -2000,20 +2008,21 @@ impl<'tcx> PrivateItemsInPublicInterfacesChecker<'tcx> { DefKind::Impl => { let item = tcx.hir().item(id); if let hir::ItemKind::Impl(ref impl_) = item.kind { - let impl_vis = ty::Visibility::of_impl(item.def_id, tcx, &Default::default()); + let impl_vis = + ty::Visibility::of_impl(item.def_id.def_id, tcx, &Default::default()); // check that private components do not appear in the generics or predicates of inherent impls // this check is intentionally NOT performed for impls of traits, per #90586 if impl_.of_trait.is_none() { - self.check(item.def_id, impl_vis).generics().predicates(); + self.check(item.def_id.def_id, impl_vis).generics().predicates(); } for impl_item_ref in impl_.items { let impl_item_vis = if impl_.of_trait.is_none() { - min(tcx.local_visibility(impl_item_ref.id.def_id), impl_vis, tcx) + min(tcx.local_visibility(impl_item_ref.id.def_id.def_id), impl_vis, tcx) } else { impl_vis }; self.check_assoc_item( - impl_item_ref.id.def_id, + impl_item_ref.id.def_id.def_id, impl_item_ref.kind, impl_item_vis, ); @@ -2061,7 +2070,7 @@ fn local_visibility(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Visibility { // Visibilities of trait impl items are inherited from their traits // and are not filled in resolve. Node::ImplItem(impl_item) => { - match tcx.hir().get_by_def_id(tcx.hir().get_parent_item(hir_id)) { + match tcx.hir().get_by_def_id(tcx.hir().get_parent_item(hir_id).def_id) { Node::Item(hir::Item { kind: hir::ItemKind::Impl(hir::Impl { of_trait: Some(tr), .. }), .. diff --git a/compiler/rustc_query_impl/src/keys.rs b/compiler/rustc_query_impl/src/keys.rs index 2bb7a240faa60..47762440e290b 100644 --- a/compiler/rustc_query_impl/src/keys.rs +++ b/compiler/rustc_query_impl/src/keys.rs @@ -1,6 +1,7 @@ //! Defines the set of legal keys that can be used in queries. use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE}; +use rustc_hir::hir_id::OwnerId; use rustc_middle::infer::canonical::Canonical; use rustc_middle::mir; use rustc_middle::traits; @@ -104,6 +105,19 @@ impl Key for CrateNum { } } +impl Key for OwnerId { + #[inline(always)] + fn query_crate_is_local(&self) -> bool { + true + } + fn default_span(&self, tcx: TyCtxt<'_>) -> Span { + self.to_def_id().default_span(tcx) + } + fn key_as_def_id(&self) -> Option { + Some(self.to_def_id()) + } +} + impl Key for LocalDefId { #[inline(always)] fn query_crate_is_local(&self) -> bool { diff --git a/compiler/rustc_query_system/src/ich/hcx.rs b/compiler/rustc_query_system/src/ich/hcx.rs index a09b8ca30e138..8140c243453bd 100644 --- a/compiler/rustc_query_system/src/ich/hcx.rs +++ b/compiler/rustc_query_system/src/ich/hcx.rs @@ -41,7 +41,10 @@ pub struct StableHashingContext<'a> { pub(super) enum BodyResolver<'tcx> { Forbidden, Ignore, - Traverse { owner: LocalDefId, bodies: &'tcx SortedMap> }, + Traverse { + owner: hir::OwnerId, + bodies: &'tcx SortedMap>, + }, } impl<'a> StableHashingContext<'a> { @@ -103,7 +106,7 @@ impl<'a> StableHashingContext<'a> { #[inline] pub fn with_hir_bodies( &mut self, - owner: LocalDefId, + owner: hir::OwnerId, bodies: &SortedMap>, f: impl FnOnce(&mut StableHashingContext<'_>), ) { diff --git a/compiler/rustc_resolve/src/late/lifetimes.rs b/compiler/rustc_resolve/src/late/lifetimes.rs index 4d97046171231..9fb1af20ac976 100644 --- a/compiler/rustc_resolve/src/late/lifetimes.rs +++ b/compiler/rustc_resolve/src/late/lifetimes.rs @@ -339,24 +339,25 @@ fn convert_named_region_map(named_region_map: NamedRegionMap) -> ResolveLifetime /// This allows us to avoid cycles. Importantly, if we ask for lifetimes for lifetimes that have an owner /// other than the trait itself (like the trait methods or associated types), then we just use the regular /// `resolve_lifetimes`. -fn resolve_lifetimes_for<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &'tcx ResolveLifetimes { - let item_id = item_for(tcx, def_id); - if item_id == def_id { - let item = tcx.hir().item(hir::ItemId { def_id: item_id }); +fn resolve_lifetimes_for<'tcx>(tcx: TyCtxt<'tcx>, def_id: hir::OwnerId) -> &'tcx ResolveLifetimes { + let item_id = item_for(tcx, def_id.def_id); + let local_def_id = item_id.def_id.def_id; + if item_id.def_id == def_id { + let item = tcx.hir().item(item_id); match item.kind { - hir::ItemKind::Trait(..) => tcx.resolve_lifetimes_trait_definition(item_id), - _ => tcx.resolve_lifetimes(item_id), + hir::ItemKind::Trait(..) => tcx.resolve_lifetimes_trait_definition(local_def_id), + _ => tcx.resolve_lifetimes(local_def_id), } } else { - tcx.resolve_lifetimes(item_id) + tcx.resolve_lifetimes(local_def_id) } } /// Finds the `Item` that contains the given `LocalDefId` -fn item_for(tcx: TyCtxt<'_>, local_def_id: LocalDefId) -> LocalDefId { +fn item_for(tcx: TyCtxt<'_>, local_def_id: LocalDefId) -> hir::ItemId { match tcx.hir().find_by_def_id(local_def_id) { Some(Node::Item(item)) => { - return item.def_id; + return item.item_id(); } _ => {} } @@ -366,7 +367,7 @@ fn item_for(tcx: TyCtxt<'_>, local_def_id: LocalDefId) -> LocalDefId { loop { let node = parent_iter.next().map(|n| n.1); match node { - Some(hir::Node::Item(item)) => break item.def_id, + Some(hir::Node::Item(item)) => break item.item_id(), Some(hir::Node::Crate(_)) | None => bug!("Called `item_for` on an Item."), _ => {} } @@ -566,13 +567,12 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { // their owner, we can keep going until we find the Item that owns that. We then // conservatively add all resolved lifetimes. Otherwise we run into problems in // cases like `type Foo<'a> = impl Bar`. - for (_hir_id, node) in - self.tcx.hir().parent_iter(self.tcx.hir().local_def_id_to_hir_id(item.def_id)) - { + for (_hir_id, node) in self.tcx.hir().parent_iter(item.def_id.into()) { match node { hir::Node::Item(parent_item) => { - let resolved_lifetimes: &ResolveLifetimes = - self.tcx.resolve_lifetimes(item_for(self.tcx, parent_item.def_id)); + let resolved_lifetimes: &ResolveLifetimes = self.tcx.resolve_lifetimes( + item_for(self.tcx, parent_item.def_id.def_id).def_id.def_id, + ); // We need to add *all* deps, since opaque tys may want them from *us* for (&owner, defs) in resolved_lifetimes.defs.iter() { defs.iter().for_each(|(&local_id, region)| { @@ -1315,7 +1315,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { // regular fns. if let Some(hir::PredicateOrigin::ImplTrait) = where_bound_origin && let hir::LifetimeName::Param(_, hir::ParamName::Fresh) = lifetime_ref.name - && let hir::IsAsync::NotAsync = self.tcx.asyncness(lifetime_ref.hir_id.owner) + && let hir::IsAsync::NotAsync = self.tcx.asyncness(lifetime_ref.hir_id.owner.def_id) && !self.tcx.features().anonymous_lifetime_in_impl_trait { rustc_session::parse::feature_err( diff --git a/compiler/rustc_save_analysis/src/dump_visitor.rs b/compiler/rustc_save_analysis/src/dump_visitor.rs index 8bd42d8d21653..adbc119387dba 100644 --- a/compiler/rustc_save_analysis/src/dump_visitor.rs +++ b/compiler/rustc_save_analysis/src/dump_visitor.rs @@ -345,14 +345,14 @@ impl<'tcx> DumpVisitor<'tcx> { body: hir::BodyId, ) { let map = self.tcx.hir(); - self.nest_typeck_results(item.def_id, |v| { + self.nest_typeck_results(item.def_id.def_id, |v| { let body = map.body(body); if let Some(fn_data) = v.save_ctxt.get_item_data(item) { down_cast_data!(fn_data, DefData, item.span); v.process_formals(body.params, &fn_data.qualname); v.process_generic_params(ty_params, &fn_data.qualname, item.hir_id()); - v.dumper.dump_def(&access_from!(v.save_ctxt, item.def_id), fn_data); + v.dumper.dump_def(&access_from!(v.save_ctxt, item.def_id.def_id), fn_data); } for arg in decl.inputs { @@ -373,10 +373,10 @@ impl<'tcx> DumpVisitor<'tcx> { typ: &'tcx hir::Ty<'tcx>, expr: &'tcx hir::Expr<'tcx>, ) { - self.nest_typeck_results(item.def_id, |v| { + self.nest_typeck_results(item.def_id.def_id, |v| { if let Some(var_data) = v.save_ctxt.get_item_data(item) { down_cast_data!(var_data, DefData, item.span); - v.dumper.dump_def(&access_from!(v.save_ctxt, item.def_id), var_data); + v.dumper.dump_def(&access_from!(v.save_ctxt, item.def_id.def_id), var_data); } v.visit_ty(&typ); v.visit_expr(expr); @@ -473,7 +473,7 @@ impl<'tcx> DumpVisitor<'tcx> { let span = self.span_from_span(item.ident.span); let attrs = self.tcx.hir().attrs(item.hir_id()); self.dumper.dump_def( - &access_from!(self.save_ctxt, item.def_id), + &access_from!(self.save_ctxt, item.def_id.def_id), Def { kind, id: id_from_def_id(item.def_id.to_def_id()), @@ -491,7 +491,7 @@ impl<'tcx> DumpVisitor<'tcx> { ); } - self.nest_typeck_results(item.def_id, |v| { + self.nest_typeck_results(item.def_id.def_id, |v| { for field in def.fields() { v.process_struct_field_def(field, item.hir_id()); v.visit_ty(&field.ty); @@ -513,7 +513,7 @@ impl<'tcx> DumpVisitor<'tcx> { }; down_cast_data!(enum_data, DefData, item.span); - let access = access_from!(self.save_ctxt, item.def_id); + let access = access_from!(self.save_ctxt, item.def_id.def_id); for variant in enum_definition.variants { let name = variant.ident.name.to_string(); @@ -612,7 +612,7 @@ impl<'tcx> DumpVisitor<'tcx> { } let map = self.tcx.hir(); - self.nest_typeck_results(item.def_id, |v| { + self.nest_typeck_results(item.def_id.def_id, |v| { v.visit_ty(&impl_.self_ty); if let Some(trait_ref) = &impl_.of_trait { v.process_path(trait_ref.hir_ref_id, &hir::QPath::Resolved(None, &trait_ref.path)); @@ -648,7 +648,7 @@ impl<'tcx> DumpVisitor<'tcx> { methods.iter().map(|i| id_from_def_id(i.id.def_id.to_def_id())).collect(); let attrs = self.tcx.hir().attrs(item.hir_id()); self.dumper.dump_def( - &access_from!(self.save_ctxt, item.def_id), + &access_from!(self.save_ctxt, item.def_id.def_id), Def { kind: DefKind::Trait, id, @@ -710,7 +710,7 @@ impl<'tcx> DumpVisitor<'tcx> { fn process_mod(&mut self, item: &'tcx hir::Item<'tcx>) { if let Some(mod_data) = self.save_ctxt.get_item_data(item) { down_cast_data!(mod_data, DefData, item.span); - self.dumper.dump_def(&access_from!(self.save_ctxt, item.def_id), mod_data); + self.dumper.dump_def(&access_from!(self.save_ctxt, item.def_id.def_id), mod_data); } } @@ -980,7 +980,7 @@ impl<'tcx> DumpVisitor<'tcx> { let body = body.map(|b| self.tcx.hir().body(b).value); let attrs = self.tcx.hir().attrs(trait_item.hir_id()); self.process_assoc_const( - trait_item.def_id, + trait_item.def_id.def_id, trait_item.ident, &ty, body, @@ -994,7 +994,7 @@ impl<'tcx> DumpVisitor<'tcx> { self.process_method( sig, body, - trait_item.def_id, + trait_item.def_id.def_id, trait_item.ident, &trait_item.generics, trait_item.span, @@ -1050,7 +1050,7 @@ impl<'tcx> DumpVisitor<'tcx> { let body = self.tcx.hir().body(body); let attrs = self.tcx.hir().attrs(impl_item.hir_id()); self.process_assoc_const( - impl_item.def_id, + impl_item.def_id.def_id, impl_item.ident, &ty, Some(&body.value), @@ -1062,7 +1062,7 @@ impl<'tcx> DumpVisitor<'tcx> { self.process_method( sig, Some(body), - impl_item.def_id, + impl_item.def_id.def_id, impl_item.ident, &impl_item.generics, impl_item.span, @@ -1136,10 +1136,10 @@ impl<'tcx> Visitor<'tcx> for DumpVisitor<'tcx> { hir::ItemKind::Use(path, hir::UseKind::Single) => { let sub_span = path.segments.last().unwrap().ident.span; if !self.span.filter_generated(sub_span) { - let access = access_from!(self.save_ctxt, item.def_id); + let access = access_from!(self.save_ctxt, item.def_id.def_id); let ref_id = self.lookup_def_id(item.hir_id()).map(id_from_def_id); let span = self.span_from_span(sub_span); - let parent = self.save_ctxt.tcx.local_parent(item.def_id); + let parent = self.save_ctxt.tcx.local_parent(item.def_id.def_id); self.dumper.import( &access, Import { @@ -1157,16 +1157,16 @@ impl<'tcx> Visitor<'tcx> for DumpVisitor<'tcx> { } hir::ItemKind::Use(path, hir::UseKind::Glob) => { // Make a comma-separated list of names of imported modules. - let names = self.tcx.names_imported_by_glob_use(item.def_id); + let names = self.tcx.names_imported_by_glob_use(item.def_id.def_id); let names: Vec<_> = names.iter().map(|n| n.to_string()).collect(); // Otherwise it's a span with wrong macro expansion info, which // we don't want to track anyway, since it's probably macro-internal `use` if let Some(sub_span) = self.span.sub_span_of_star(item.span) { if !self.span.filter_generated(item.span) { - let access = access_from!(self.save_ctxt, item.def_id); + let access = access_from!(self.save_ctxt, item.def_id.def_id); let span = self.span_from_span(sub_span); - let parent = self.save_ctxt.tcx.local_parent(item.def_id); + let parent = self.save_ctxt.tcx.local_parent(item.def_id.def_id); self.dumper.import( &access, Import { @@ -1187,7 +1187,7 @@ impl<'tcx> Visitor<'tcx> for DumpVisitor<'tcx> { let name_span = item.ident.span; if !self.span.filter_generated(name_span) { let span = self.span_from_span(name_span); - let parent = self.save_ctxt.tcx.local_parent(item.def_id); + let parent = self.save_ctxt.tcx.local_parent(item.def_id.def_id); self.dumper.import( &Access { public: false, reachable: false }, Import { @@ -1235,7 +1235,7 @@ impl<'tcx> Visitor<'tcx> for DumpVisitor<'tcx> { let attrs = self.tcx.hir().attrs(item.hir_id()); self.dumper.dump_def( - &access_from!(self.save_ctxt, item.def_id), + &access_from!(self.save_ctxt, item.def_id.def_id), Def { kind: DefKind::Type, id, @@ -1323,7 +1323,7 @@ impl<'tcx> Visitor<'tcx> for DumpVisitor<'tcx> { } hir::TyKind::OpaqueDef(item_id, _, _) => { let item = self.tcx.hir().item(item_id); - self.nest_typeck_results(item_id.def_id, |v| v.visit_item(item)); + self.nest_typeck_results(item_id.def_id.def_id, |v| v.visit_item(item)); } _ => intravisit::walk_ty(self, t), } @@ -1430,7 +1430,7 @@ impl<'tcx> Visitor<'tcx> for DumpVisitor<'tcx> { } fn visit_foreign_item(&mut self, item: &'tcx hir::ForeignItem<'tcx>) { - let access = access_from!(self.save_ctxt, item.def_id); + let access = access_from!(self.save_ctxt, item.def_id.def_id); match item.kind { hir::ForeignItemKind::Fn(decl, _, ref generics) => { diff --git a/compiler/rustc_save_analysis/src/lib.rs b/compiler/rustc_save_analysis/src/lib.rs index ce03c2a8ad05f..1a3511a1dc8bc 100644 --- a/compiler/rustc_save_analysis/src/lib.rs +++ b/compiler/rustc_save_analysis/src/lib.rs @@ -622,7 +622,7 @@ impl<'tcx> SaveContext<'tcx> { hir::QPath::TypeRelative(..) | hir::QPath::LangItem(..) => { // #75962: `self.typeck_results` may be different from the `hir_id`'s result. if self.tcx.has_typeck_results(hir_id.owner.to_def_id()) { - self.tcx.typeck(hir_id.owner).qpath_res(qpath, hir_id) + self.tcx.typeck(hir_id.owner.def_id).qpath_res(qpath, hir_id) } else { Res::Err } @@ -1041,7 +1041,7 @@ fn id_from_hir_id(id: hir::HirId, scx: &SaveContext<'_>) -> rls_data::Id { // crate (very unlikely to actually happen). rls_data::Id { krate: LOCAL_CRATE.as_u32(), - index: id.owner.local_def_index.as_u32() | id.local_id.as_u32().reverse_bits(), + index: id.owner.def_id.local_def_index.as_u32() | id.local_id.as_u32().reverse_bits(), } }) } diff --git a/compiler/rustc_symbol_mangling/src/test.rs b/compiler/rustc_symbol_mangling/src/test.rs index 9d89c9c52b20e..c8c6fe2bf8526 100644 --- a/compiler/rustc_symbol_mangling/src/test.rs +++ b/compiler/rustc_symbol_mangling/src/test.rs @@ -26,19 +26,19 @@ pub fn report_symbol_names(tcx: TyCtxt<'_>) { let crate_items = tcx.hir_crate_items(()); for id in crate_items.items() { - symbol_names.process_attrs(id.def_id); + symbol_names.process_attrs(id.def_id.def_id); } for id in crate_items.trait_items() { - symbol_names.process_attrs(id.def_id); + symbol_names.process_attrs(id.def_id.def_id); } for id in crate_items.impl_items() { - symbol_names.process_attrs(id.def_id); + symbol_names.process_attrs(id.def_id.def_id); } for id in crate_items.foreign_items() { - symbol_names.process_attrs(id.def_id); + symbol_names.process_attrs(id.def_id.def_id); } }) } diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index d62b399c1b562..b0cabc6275f5a 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -1898,7 +1898,9 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> { // FIXME(compiler-errors): This could be generalized, both to // be more granular, and probably look past other `#[fundamental]` // types, too. - self.tcx.visibility(def.did()).is_accessible_from(body_id.owner, self.tcx) + self.tcx + .visibility(def.did()) + .is_accessible_from(body_id.owner.def_id, self.tcx) } else { true } diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index d90b77fc55682..fff26547be075 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -659,7 +659,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { _ => {} } - hir_id = self.tcx.hir().local_def_id_to_hir_id(self.tcx.hir().get_parent_item(hir_id)); + hir_id = self.tcx.hir().get_parent_item(hir_id).into(); } } @@ -2712,7 +2712,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { let parent_id = hir.get_parent_item(arg_hir_id); let typeck_results: &TypeckResults<'tcx> = match &in_progress_typeck_results { Some(t) if t.hir_owner == parent_id => t, - _ => self.tcx.typeck(parent_id), + _ => self.tcx.typeck(parent_id.def_id), }; let expr = expr.peel_blocks(); let ty = typeck_results.expr_ty_adjusted_opt(expr).unwrap_or(tcx.ty_error()); diff --git a/compiler/rustc_ty_utils/src/assoc.rs b/compiler/rustc_ty_utils/src/assoc.rs index 515a73ead777a..3e2553c425edd 100644 --- a/compiler/rustc_ty_utils/src/assoc.rs +++ b/compiler/rustc_ty_utils/src/assoc.rs @@ -42,7 +42,7 @@ fn impl_item_implementor_ids(tcx: TyCtxt<'_>, impl_id: DefId) -> FxHashMap, def_id: DefId) -> ty::AssocItem { let id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local()); let parent_def_id = tcx.hir().get_parent_item(id); - let parent_item = tcx.hir().expect_item(parent_def_id); + let parent_item = tcx.hir().expect_item(parent_def_id.def_id); match parent_item.kind { hir::ItemKind::Impl(ref impl_) => { if let Some(impl_item_ref) = diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs index 5432fdbb5e8e3..2c06ac2e13939 100644 --- a/compiler/rustc_typeck/src/astconv/mod.rs +++ b/compiler/rustc_typeck/src/astconv/mod.rs @@ -3003,7 +3003,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { /// Make sure that we are in the condition to suggest the blanket implementation. fn maybe_lint_blanket_trait_impl(&self, self_ty: &hir::Ty<'_>, diag: &mut Diagnostic) { let tcx = self.tcx(); - let parent_id = tcx.hir().get_parent_item(self_ty.hir_id); + let parent_id = tcx.hir().get_parent_item(self_ty.hir_id).def_id; if let hir::Node::Item(hir::Item { kind: hir::ItemKind::Impl(hir::Impl { diff --git a/compiler/rustc_typeck/src/check/_match.rs b/compiler/rustc_typeck/src/check/_match.rs index 27329f8eab42e..201927091a60a 100644 --- a/compiler/rustc_typeck/src/check/_match.rs +++ b/compiler/rustc_typeck/src/check/_match.rs @@ -140,7 +140,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let Some(ret) = self .tcx .hir() - .find_by_def_id(self.body_id.owner) + .find_by_def_id(self.body_id.owner.def_id) .and_then(|owner| owner.fn_decl()) .map(|decl| decl.output.span()) else { return; }; @@ -495,7 +495,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .typeck_results .borrow() .liberated_fn_sigs() - .get(hir::HirId::make_owner(self.body_id.owner))?; + .get(hir::HirId::make_owner(self.body_id.owner.def_id))?; let substs = sig.output().walk().find_map(|arg| { if let ty::GenericArgKind::Type(ty) = arg.unpack() diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs index d6fa74c87309c..d82ee8f48c52b 100644 --- a/compiler/rustc_typeck/src/check/check.rs +++ b/compiler/rustc_typeck/src/check/check.rs @@ -782,19 +782,19 @@ fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, id: hir::ItemId) { let _indenter = indenter(); match tcx.def_kind(id.def_id) { DefKind::Static(..) => { - tcx.ensure().typeck(id.def_id); - maybe_check_static_with_link_section(tcx, id.def_id); - check_static_inhabited(tcx, id.def_id); + tcx.ensure().typeck(id.def_id.def_id); + maybe_check_static_with_link_section(tcx, id.def_id.def_id); + check_static_inhabited(tcx, id.def_id.def_id); } DefKind::Const => { - tcx.ensure().typeck(id.def_id); + tcx.ensure().typeck(id.def_id.def_id); } DefKind::Enum => { let item = tcx.hir().item(id); let hir::ItemKind::Enum(ref enum_definition, _) = item.kind else { return; }; - check_enum(tcx, &enum_definition.variants, item.def_id); + check_enum(tcx, &enum_definition.variants, item.def_id.def_id); } DefKind::Fn => {} // entirely within check_item_body DefKind::Impl => { @@ -807,7 +807,7 @@ fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, id: hir::ItemId) { check_impl_items_against_trait( tcx, it.span, - it.def_id, + it.def_id.def_id, impl_trait_ref, &impl_.items, ); @@ -845,10 +845,10 @@ fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, id: hir::ItemId) { } } DefKind::Struct => { - check_struct(tcx, id.def_id); + check_struct(tcx, id.def_id.def_id); } DefKind::Union => { - check_union(tcx, id.def_id); + check_union(tcx, id.def_id.def_id); } DefKind::OpaqueTy => { let item = tcx.hir().item(id); @@ -861,7 +861,7 @@ fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, id: hir::ItemId) { // See https://github.com/rust-lang/rust/issues/75100 if !tcx.sess.opts.actually_rustdoc { let substs = InternalSubsts::identity_for_item(tcx, item.def_id.to_def_id()); - check_opaque(tcx, item.def_id, substs, &origin); + check_opaque(tcx, item.def_id.def_id, substs, &origin); } } DefKind::TyAlias => { @@ -888,7 +888,7 @@ fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, id: hir::ItemId) { } } else { for item in items { - let def_id = item.id.def_id; + let def_id = item.id.def_id.def_id; let generics = tcx.generics_of(def_id); let own_counts = generics.own_counts(); if generics.params.len() - own_counts.lifetimes != 0 { diff --git a/compiler/rustc_typeck/src/check/coercion.rs b/compiler/rustc_typeck/src/check/coercion.rs index def592c46c2e5..d738e56325613 100644 --- a/compiler/rustc_typeck/src/check/coercion.rs +++ b/compiler/rustc_typeck/src/check/coercion.rs @@ -1683,7 +1683,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { expected, found, can_suggest, - fcx.tcx.hir().local_def_id_to_hir_id(fcx.tcx.hir().get_parent_item(id)), + fcx.tcx.hir().get_parent_item(id).into(), ); } if !pointing_at_return_type { @@ -1692,7 +1692,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { } let parent_id = fcx.tcx.hir().get_parent_item(id); - let parent_item = fcx.tcx.hir().get_by_def_id(parent_id); + let parent_item = fcx.tcx.hir().get_by_def_id(parent_id.def_id); if let (Some(expr), Some(_), Some((fn_decl, _, _))) = (expression, blk_id, fcx.get_node_fn_decl(parent_item)) @@ -1704,7 +1704,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { expected, found, id, - fcx.tcx.hir().local_def_id_to_hir_id(parent_id), + parent_id.into(), ); } diff --git a/compiler/rustc_typeck/src/check/demand.rs b/compiler/rustc_typeck/src/check/demand.rs index e1d55ff82cbad..222082497ef68 100644 --- a/compiler/rustc_typeck/src/check/demand.rs +++ b/compiler/rustc_typeck/src/check/demand.rs @@ -375,7 +375,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let field_is_local = sole_field.did.is_local(); let field_is_accessible = - sole_field.vis.is_accessible_from(expr.hir_id.owner, self.tcx) + sole_field.vis.is_accessible_from(expr.hir_id.owner.def_id, self.tcx) // Skip suggestions for unstable public fields (for example `Pin::pointer`) && matches!(self.tcx.eval_stability(sole_field.did, None, expr.span, None), EvalResult::Allow | EvalResult::Unmarked); diff --git a/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_typeck/src/check/expr.rs index 23fadff3248c8..48a4f40780bf4 100644 --- a/compiler/rustc_typeck/src/check/expr.rs +++ b/compiler/rustc_typeck/src/check/expr.rs @@ -752,7 +752,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { kind: hir::ImplItemKind::Fn(..), span: encl_fn_span, .. - })) = self.tcx.hir().find_by_def_id(encl_item_id) + })) = self.tcx.hir().find_by_def_id(encl_item_id.def_id) { // We are inside a function body, so reporting "return statement // outside of function body" needs an explanation. @@ -761,7 +761,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // If this didn't hold, we would not have to report an error in // the first place. - assert_ne!(encl_item_id, encl_body_owner_id); + assert_ne!(encl_item_id.def_id, encl_body_owner_id); let encl_body_id = self.tcx.hir().body_owned_by(encl_body_owner_id); let encl_body = self.tcx.hir().body(encl_body_id); @@ -2338,7 +2338,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if let ty::Adt(def, _) = output_ty.kind() && !def.is_enum() { def.non_enum_variant().fields.iter().any(|field| { field.ident(self.tcx) == ident - && field.vis.is_accessible_from(expr.hir_id.owner, self.tcx) + && field.vis.is_accessible_from(expr.hir_id.owner.def_id, self.tcx) }) } else if let ty::Tuple(tys) = output_ty.kind() && let Ok(idx) = ident.as_str().parse::() diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs index 311fcaadaa98b..64e7fa1a42bf7 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs @@ -1543,7 +1543,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } fn parent_item_span(&self, id: hir::HirId) -> Option { - let node = self.tcx.hir().get_by_def_id(self.tcx.hir().get_parent_item(id)); + let node = self.tcx.hir().get_by_def_id(self.tcx.hir().get_parent_item(id).def_id); match node { Node::Item(&hir::Item { kind: hir::ItemKind::Fn(_, _, body_id), .. }) | Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Fn(_, body_id), .. }) => { @@ -1559,7 +1559,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// Given a function block's `HirId`, returns its `FnDecl` if it exists, or `None` otherwise. fn get_parent_fn_decl(&self, blk_id: hir::HirId) -> Option<(&'tcx hir::FnDecl<'tcx>, Ident)> { - let parent = self.tcx.hir().get_by_def_id(self.tcx.hir().get_parent_item(blk_id)); + let parent = self.tcx.hir().get_by_def_id(self.tcx.hir().get_parent_item(blk_id).def_id); self.get_node_fn_decl(parent).map(|(fn_decl, ident, _)| (fn_decl, ident)) } diff --git a/compiler/rustc_typeck/src/check/method/suggest.rs b/compiler/rustc_typeck/src/check/method/suggest.rs index 2d459b2cc0e32..0e77ed0a4fe28 100644 --- a/compiler/rustc_typeck/src/check/method/suggest.rs +++ b/compiler/rustc_typeck/src/check/method/suggest.rs @@ -2077,7 +2077,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Colon, Nothing, } - let ast_generics = hir.get_generics(id.owner).unwrap(); + let ast_generics = hir.get_generics(id.owner.def_id).unwrap(); let (sp, mut introducer) = if let Some(span) = ast_generics.bounds_span_for_suggestions(def_id) { diff --git a/compiler/rustc_typeck/src/check/mod.rs b/compiler/rustc_typeck/src/check/mod.rs index 1a4c888a5a494..593a9776bde30 100644 --- a/compiler/rustc_typeck/src/check/mod.rs +++ b/compiler/rustc_typeck/src/check/mod.rs @@ -519,7 +519,7 @@ fn get_owner_return_paths<'tcx>( def_id: LocalDefId, ) -> Option<(LocalDefId, ReturnsVisitor<'tcx>)> { let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); - let parent_id = tcx.hir().get_parent_item(hir_id); + let parent_id = tcx.hir().get_parent_item(hir_id).def_id; tcx.hir().find_by_def_id(parent_id).and_then(|node| node.body_id()).map(|body_id| { let body = tcx.hir().body(body_id); let mut visitor = ReturnsVisitor::default(); diff --git a/compiler/rustc_typeck/src/check/wfcheck.rs b/compiler/rustc_typeck/src/check/wfcheck.rs index e4124185d153d..7965ec1b43f41 100644 --- a/compiler/rustc_typeck/src/check/wfcheck.rs +++ b/compiler/rustc_typeck/src/check/wfcheck.rs @@ -116,7 +116,7 @@ pub(super) fn enter_wf_checking_ctxt<'tcx, F>( }) } -fn check_well_formed(tcx: TyCtxt<'_>, def_id: LocalDefId) { +fn check_well_formed(tcx: TyCtxt<'_>, def_id: hir::OwnerId) { let node = tcx.hir().expect_owner(def_id); match node { hir::OwnerNode::Crate(_) => {} @@ -148,7 +148,7 @@ fn check_well_formed(tcx: TyCtxt<'_>, def_id: LocalDefId) { /// the types first. #[instrument(skip(tcx), level = "debug")] fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) { - let def_id = item.def_id; + let def_id = item.def_id.def_id; debug!( ?item.def_id, @@ -175,7 +175,7 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) { // for `T` hir::ItemKind::Impl(ref impl_) => { let is_auto = tcx - .impl_trait_ref(item.def_id) + .impl_trait_ref(def_id) .map_or(false, |trait_ref| tcx.trait_is_auto(trait_ref.def_id)); if let (hir::Defaultness::Default { .. }, true) = (impl_.defaultness, is_auto) { let sp = impl_.of_trait.as_ref().map_or(item.span, |t| t.path.span); @@ -211,13 +211,13 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) { } } hir::ItemKind::Fn(ref sig, ..) => { - check_item_fn(tcx, item.def_id, item.ident, item.span, sig.decl); + check_item_fn(tcx, def_id, item.ident, item.span, sig.decl); } hir::ItemKind::Static(ty, ..) => { - check_item_type(tcx, item.def_id, ty.span, false); + check_item_type(tcx, def_id, ty.span, false); } hir::ItemKind::Const(ty, ..) => { - check_item_type(tcx, item.def_id, ty.span, false); + check_item_type(tcx, def_id, ty.span, false); } hir::ItemKind::Struct(ref struct_def, ref ast_generics) => { check_type_defn(tcx, item, false, |wfcx| vec![wfcx.non_enum_variant(struct_def)]); @@ -247,7 +247,7 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) { } fn check_foreign_item(tcx: TyCtxt<'_>, item: &hir::ForeignItem<'_>) { - let def_id = item.def_id; + let def_id = item.def_id.def_id; debug!( ?item.def_id, @@ -256,15 +256,15 @@ fn check_foreign_item(tcx: TyCtxt<'_>, item: &hir::ForeignItem<'_>) { match item.kind { hir::ForeignItemKind::Fn(decl, ..) => { - check_item_fn(tcx, item.def_id, item.ident, item.span, decl) + check_item_fn(tcx, def_id, item.ident, item.span, decl) } - hir::ForeignItemKind::Static(ty, ..) => check_item_type(tcx, item.def_id, ty.span, true), + hir::ForeignItemKind::Static(ty, ..) => check_item_type(tcx, def_id, ty.span, true), hir::ForeignItemKind::Type => (), } } fn check_trait_item(tcx: TyCtxt<'_>, trait_item: &hir::TraitItem<'_>) { - let def_id = trait_item.def_id; + let def_id = trait_item.def_id.def_id; let (method_sig, span) = match trait_item.kind { hir::TraitItemKind::Fn(ref sig, _) => (Some(sig), trait_item.span), @@ -272,7 +272,7 @@ fn check_trait_item(tcx: TyCtxt<'_>, trait_item: &hir::TraitItem<'_>) { _ => (None, trait_item.span), }; check_object_unsafe_self_trait_by_name(tcx, trait_item); - check_associated_item(tcx, trait_item.def_id, span, method_sig); + check_associated_item(tcx, def_id, span, method_sig); let encl_trait_def_id = tcx.local_parent(def_id); let encl_trait = tcx.hir().expect_item(encl_trait_def_id); @@ -393,7 +393,7 @@ fn check_gat_where_clauses(tcx: TyCtxt<'_>, associated_items: &[hir::TraitItemRe // We also assume that all of the function signature's parameter types // are well formed. &sig.inputs().iter().copied().collect(), - gat_def_id, + gat_def_id.def_id, gat_generics, ) } @@ -416,7 +416,7 @@ fn check_gat_where_clauses(tcx: TyCtxt<'_>, associated_items: &[hir::TraitItemRe .copied() .collect::>(), &FxHashSet::default(), - gat_def_id, + gat_def_id.def_id, gat_generics, ) } @@ -456,7 +456,7 @@ fn check_gat_where_clauses(tcx: TyCtxt<'_>, associated_items: &[hir::TraitItemRe } for (gat_def_id, required_bounds) in required_bounds_by_item { - let gat_item_hir = tcx.hir().expect_trait_item(gat_def_id); + let gat_item_hir = tcx.hir().expect_trait_item(gat_def_id.def_id); debug!(?required_bounds); let param_env = tcx.param_env(gat_def_id); let gat_hir = gat_item_hir.hir_id(); @@ -786,7 +786,7 @@ fn could_be_self(trait_def_id: LocalDefId, ty: &hir::Ty<'_>) -> bool { /// When this is done, suggest using `Self` instead. fn check_object_unsafe_self_trait_by_name(tcx: TyCtxt<'_>, item: &hir::TraitItem<'_>) { let (trait_name, trait_def_id) = - match tcx.hir().get_by_def_id(tcx.hir().get_parent_item(item.hir_id())) { + match tcx.hir().get_by_def_id(tcx.hir().get_parent_item(item.hir_id()).def_id) { hir::Node::Item(item) => match item.kind { hir::ItemKind::Trait(..) => (item.ident, item.def_id), _ => return, @@ -796,18 +796,18 @@ fn check_object_unsafe_self_trait_by_name(tcx: TyCtxt<'_>, item: &hir::TraitItem let mut trait_should_be_self = vec![]; match &item.kind { hir::TraitItemKind::Const(ty, _) | hir::TraitItemKind::Type(_, Some(ty)) - if could_be_self(trait_def_id, ty) => + if could_be_self(trait_def_id.def_id, ty) => { trait_should_be_self.push(ty.span) } hir::TraitItemKind::Fn(sig, _) => { for ty in sig.decl.inputs { - if could_be_self(trait_def_id, ty) { + if could_be_self(trait_def_id.def_id, ty) { trait_should_be_self.push(ty.span); } } match sig.decl.output { - hir::FnRetTy::Return(ty) if could_be_self(trait_def_id, ty) => { + hir::FnRetTy::Return(ty) if could_be_self(trait_def_id.def_id, ty) => { trait_should_be_self.push(ty.span); } _ => {} @@ -836,8 +836,6 @@ fn check_object_unsafe_self_trait_by_name(tcx: TyCtxt<'_>, item: &hir::TraitItem } fn check_impl_item(tcx: TyCtxt<'_>, impl_item: &hir::ImplItem<'_>) { - let def_id = impl_item.def_id; - let (method_sig, span) = match impl_item.kind { hir::ImplItemKind::Fn(ref sig, _) => (Some(sig), impl_item.span), // Constrain binding and overflow error spans to `` in `type foo = `. @@ -845,7 +843,7 @@ fn check_impl_item(tcx: TyCtxt<'_>, impl_item: &hir::ImplItem<'_>) { _ => (None, impl_item.span), }; - check_associated_item(tcx, def_id, span, method_sig); + check_associated_item(tcx, impl_item.def_id.def_id, span, method_sig); } fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) { @@ -1045,7 +1043,7 @@ fn check_type_defn<'tcx, F>( ) where F: FnMut(&WfCheckingCtxt<'_, 'tcx>) -> Vec>, { - enter_wf_checking_ctxt(tcx, item.span, item.def_id, |wfcx| { + enter_wf_checking_ctxt(tcx, item.span, item.def_id.def_id, |wfcx| { let variants = lookup_fields(wfcx); let packed = tcx.adt_def(item.def_id).repr().packed(); @@ -1124,7 +1122,7 @@ fn check_type_defn<'tcx, F>( } } - check_where_clauses(wfcx, item.span, item.def_id); + check_where_clauses(wfcx, item.span, item.def_id.def_id); }); } @@ -1132,11 +1130,12 @@ fn check_type_defn<'tcx, F>( fn check_trait(tcx: TyCtxt<'_>, item: &hir::Item<'_>) { debug!(?item.def_id); - let trait_def = tcx.trait_def(item.def_id); + let def_id = item.def_id.def_id; + let trait_def = tcx.trait_def(def_id); if trait_def.is_marker || matches!(trait_def.specialization_kind, TraitSpecializationKind::Marker) { - for associated_def_id in &*tcx.associated_item_def_ids(item.def_id) { + for associated_def_id in &*tcx.associated_item_def_ids(def_id) { struct_span_err!( tcx.sess, tcx.def_span(*associated_def_id), @@ -1147,8 +1146,8 @@ fn check_trait(tcx: TyCtxt<'_>, item: &hir::Item<'_>) { } } - enter_wf_checking_ctxt(tcx, item.span, item.def_id, |wfcx| { - check_where_clauses(wfcx, item.span, item.def_id) + enter_wf_checking_ctxt(tcx, item.span, def_id, |wfcx| { + check_where_clauses(wfcx, item.span, def_id) }); // Only check traits, don't check trait aliases @@ -1242,7 +1241,7 @@ fn check_impl<'tcx>( ast_trait_ref: &Option>, constness: hir::Constness, ) { - enter_wf_checking_ctxt(tcx, item.span, item.def_id, |wfcx| { + enter_wf_checking_ctxt(tcx, item.span, item.def_id.def_id, |wfcx| { match *ast_trait_ref { Some(ref ast_trait_ref) => { // `#[rustc_reservation_impl]` impls are not real impls and @@ -1273,18 +1272,18 @@ fn check_impl<'tcx>( let self_ty = tcx.type_of(item.def_id); let self_ty = wfcx.normalize( item.span, - Some(WellFormedLoc::Ty(item.hir_id().expect_owner())), + Some(WellFormedLoc::Ty(item.hir_id().expect_owner().def_id)), self_ty, ); wfcx.register_wf_obligation( ast_self_ty.span, - Some(WellFormedLoc::Ty(item.hir_id().expect_owner())), + Some(WellFormedLoc::Ty(item.hir_id().expect_owner().def_id)), self_ty.into(), ); } } - check_where_clauses(wfcx, item.span, item.def_id); + check_where_clauses(wfcx, item.span, item.def_id.def_id); }); } diff --git a/compiler/rustc_typeck/src/coherence/inherent_impls.rs b/compiler/rustc_typeck/src/coherence/inherent_impls.rs index 52aad636fd88a..308ad5d5fc2c2 100644 --- a/compiler/rustc_typeck/src/coherence/inherent_impls.rs +++ b/compiler/rustc_typeck/src/coherence/inherent_impls.rs @@ -105,7 +105,7 @@ impl<'tcx> InherentCollect<'tcx> { } if let Some(simp) = simplify_type(self.tcx, self_ty, TreatParams::AsInfer) { - self.impls_map.incoherent_impls.entry(simp).or_default().push(impl_def_id); + self.impls_map.incoherent_impls.entry(simp).or_default().push(impl_def_id.def_id); } else { bug!("unexpected self type: {:?}", self_ty); } @@ -220,7 +220,9 @@ impl<'tcx> InherentCollect<'tcx> { | ty::Ref(..) | ty::Never | ty::FnPtr(_) - | ty::Tuple(..) => self.check_primitive_impl(item.def_id, self_ty, items, ty.span), + | ty::Tuple(..) => { + self.check_primitive_impl(item.def_id.def_id, self_ty, items, ty.span) + } ty::Projection(..) | ty::Opaque(..) | ty::Param(_) => { let mut err = struct_span_err!( self.tcx.sess, diff --git a/compiler/rustc_typeck/src/coherence/orphan.rs b/compiler/rustc_typeck/src/coherence/orphan.rs index 87961890f53e5..7d15e5a7f3c22 100644 --- a/compiler/rustc_typeck/src/coherence/orphan.rs +++ b/compiler/rustc_typeck/src/coherence/orphan.rs @@ -42,7 +42,7 @@ fn do_orphan_check_impl<'tcx>( ) -> Result<(), ErrorGuaranteed> { let trait_def_id = trait_ref.def_id; - let item = tcx.hir().item(hir::ItemId { def_id }); + let item = tcx.hir().expect_item(def_id); let hir::ItemKind::Impl(ref impl_) = item.kind else { bug!("{:?} is not an impl: {:?}", def_id, item); }; diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index 359a79e9979ed..23369b2f1b43e 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -28,7 +28,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet}; use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed, StashKey}; use rustc_hir as hir; use rustc_hir::def::{CtorKind, DefKind}; -use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID, LOCAL_CRATE}; +use rustc_hir::def_id::{DefId, LocalDefId, LOCAL_CRATE}; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::weak_lang_items; use rustc_hir::{GenericParamKind, HirId, Node}; @@ -449,8 +449,10 @@ impl<'tcx> AstConv<'tcx> for ItemCtxt<'tcx> { match self.node() { hir::Node::Field(_) | hir::Node::Ctor(_) | hir::Node::Variant(_) => { - let item = - self.tcx.hir().expect_item(self.tcx.hir().get_parent_item(self.hir_id())); + let item = self + .tcx + .hir() + .expect_item(self.tcx.hir().get_parent_item(self.hir_id()).def_id); match &item.kind { hir::ItemKind::Enum(_, generics) | hir::ItemKind::Struct(_, generics) @@ -728,7 +730,7 @@ impl<'tcx> ItemCtxt<'tcx> { fn convert_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) { let it = tcx.hir().item(item_id); debug!("convert: item {} with id {}", it.ident, it.hir_id()); - let def_id = item_id.def_id; + let def_id = item_id.def_id.def_id; match it.kind { // These don't define types. @@ -840,20 +842,21 @@ fn convert_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) { fn convert_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::TraitItemId) { let trait_item = tcx.hir().trait_item(trait_item_id); - tcx.ensure().generics_of(trait_item_id.def_id); + let def_id = trait_item_id.def_id; + tcx.ensure().generics_of(def_id); match trait_item.kind { hir::TraitItemKind::Fn(..) => { - tcx.ensure().type_of(trait_item_id.def_id); - tcx.ensure().fn_sig(trait_item_id.def_id); + tcx.ensure().type_of(def_id); + tcx.ensure().fn_sig(def_id); } hir::TraitItemKind::Const(.., Some(_)) => { - tcx.ensure().type_of(trait_item_id.def_id); + tcx.ensure().type_of(def_id); } hir::TraitItemKind::Const(hir_ty, _) => { - tcx.ensure().type_of(trait_item_id.def_id); + tcx.ensure().type_of(def_id); // Account for `const C: _;`. let mut visitor = HirPlaceholderCollector::default(); visitor.visit_trait_item(trait_item); @@ -863,8 +866,8 @@ fn convert_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::TraitItemId) { } hir::TraitItemKind::Type(_, Some(_)) => { - tcx.ensure().item_bounds(trait_item_id.def_id); - tcx.ensure().type_of(trait_item_id.def_id); + tcx.ensure().item_bounds(def_id); + tcx.ensure().type_of(def_id); // Account for `type T = _;`. let mut visitor = HirPlaceholderCollector::default(); visitor.visit_trait_item(trait_item); @@ -872,7 +875,7 @@ fn convert_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::TraitItemId) { } hir::TraitItemKind::Type(_, None) => { - tcx.ensure().item_bounds(trait_item_id.def_id); + tcx.ensure().item_bounds(def_id); // #74612: Visit and try to find bad placeholders // even if there is no concrete type. let mut visitor = HirPlaceholderCollector::default(); @@ -882,7 +885,7 @@ fn convert_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::TraitItemId) { } }; - tcx.ensure().predicates_of(trait_item_id.def_id); + tcx.ensure().predicates_of(def_id); } fn convert_impl_item(tcx: TyCtxt<'_>, impl_item_id: hir::ImplItemId) { @@ -1595,7 +1598,7 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics { } ItemKind::OpaqueTy(hir::OpaqueTy { origin: hir::OpaqueTyOrigin::TyAlias, .. }) => { let parent_id = tcx.hir().get_parent_item(hir_id); - assert_ne!(parent_id, CRATE_DEF_ID); + assert_ne!(parent_id, hir::CRATE_OWNER_ID); debug!("generics_of: parent of opaque ty {:?} is {:?}", def_id, parent_id); // Opaque types are always nested within another item, and // inherit the generics of the item. @@ -3386,7 +3389,7 @@ fn check_target_feature_trait_unsafe(tcx: TyCtxt<'_>, id: LocalDefId, attr_span: let node = tcx.hir().get(hir_id); if let Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Fn(..), .. }) = node { let parent_id = tcx.hir().get_parent_item(hir_id); - let parent_item = tcx.hir().expect_item(parent_id); + let parent_item = tcx.hir().expect_item(parent_id.def_id); if let hir::ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }) = parent_item.kind { tcx.sess .struct_span_err( diff --git a/compiler/rustc_typeck/src/collect/type_of.rs b/compiler/rustc_typeck/src/collect/type_of.rs index 70e259b46bf20..24fb0b1fd26b5 100644 --- a/compiler/rustc_typeck/src/collect/type_of.rs +++ b/compiler/rustc_typeck/src/collect/type_of.rs @@ -569,22 +569,22 @@ fn find_opaque_ty_constraints_for_tait(tcx: TyCtxt<'_>, def_id: LocalDefId) -> T fn visit_item(&mut self, it: &'tcx Item<'tcx>) { trace!(?it.def_id); // The opaque type itself or its children are not within its reveal scope. - if it.def_id != self.def_id { - self.check(it.def_id); + if it.def_id.def_id != self.def_id { + self.check(it.def_id.def_id); intravisit::walk_item(self, it); } } fn visit_impl_item(&mut self, it: &'tcx ImplItem<'tcx>) { trace!(?it.def_id); // The opaque type itself or its children are not within its reveal scope. - if it.def_id != self.def_id { - self.check(it.def_id); + if it.def_id.def_id != self.def_id { + self.check(it.def_id.def_id); intravisit::walk_impl_item(self, it); } } fn visit_trait_item(&mut self, it: &'tcx TraitItem<'tcx>) { trace!(?it.def_id); - self.check(it.def_id); + self.check(it.def_id.def_id); intravisit::walk_trait_item(self, it); } } @@ -688,22 +688,22 @@ fn find_opaque_ty_constraints_for_rpit( fn visit_item(&mut self, it: &'tcx Item<'tcx>) { trace!(?it.def_id); // The opaque type itself or its children are not within its reveal scope. - if it.def_id != self.def_id { - self.check(it.def_id); + if it.def_id.def_id != self.def_id { + self.check(it.def_id.def_id); intravisit::walk_item(self, it); } } fn visit_impl_item(&mut self, it: &'tcx ImplItem<'tcx>) { trace!(?it.def_id); // The opaque type itself or its children are not within its reveal scope. - if it.def_id != self.def_id { - self.check(it.def_id); + if it.def_id.def_id != self.def_id { + self.check(it.def_id.def_id); intravisit::walk_impl_item(self, it); } } fn visit_trait_item(&mut self, it: &'tcx TraitItem<'tcx>) { trace!(?it.def_id); - self.check(it.def_id); + self.check(it.def_id.def_id); intravisit::walk_trait_item(self, it); } } diff --git a/compiler/rustc_typeck/src/impl_wf_check.rs b/compiler/rustc_typeck/src/impl_wf_check.rs index 9fee1eaaec983..c499364056ff9 100644 --- a/compiler/rustc_typeck/src/impl_wf_check.rs +++ b/compiler/rustc_typeck/src/impl_wf_check.rs @@ -58,10 +58,10 @@ fn check_mod_impl_wf(tcx: TyCtxt<'_>, module_def_id: LocalDefId) { let module = tcx.hir_module_items(module_def_id); for id in module.items() { if matches!(tcx.def_kind(id.def_id), DefKind::Impl) { - enforce_impl_params_are_constrained(tcx, id.def_id); - enforce_impl_items_are_distinct(tcx, id.def_id); + enforce_impl_params_are_constrained(tcx, id.def_id.def_id); + enforce_impl_items_are_distinct(tcx, id.def_id.def_id); if min_specialization { - check_min_specialization(tcx, id.def_id); + check_min_specialization(tcx, id.def_id.def_id); } } } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 375737e9bc4ea..bd68dffb823d1 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1080,7 +1080,7 @@ pub(crate) fn clean_impl_item<'tcx>( let mut what_rustc_thinks = Item::from_def_id_and_parts(local_did, Some(impl_.ident.name), inner, cx); - let impl_ref = cx.tcx.impl_trait_ref(cx.tcx.local_parent(impl_.def_id)); + let impl_ref = cx.tcx.impl_trait_ref(cx.tcx.local_parent(impl_.def_id.def_id)); // Trait impl items always inherit the impl's visibility -- // we don't want to show `pub`. @@ -1325,7 +1325,7 @@ fn clean_qpath<'tcx>(hir_ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> Type segments: trait_segments.iter().map(|x| clean_path_segment(x, cx)).collect(), }; register_res(cx, trait_.res); - let self_def_id = DefId::local(qself.hir_id.owner.local_def_index); + let self_def_id = DefId::local(qself.hir_id.owner.def_id.local_def_index); let self_type = clean_ty(qself, cx); let should_show_cast = compute_should_show_cast(Some(self_def_id), &trait_, &self_type); Type::QPath(Box::new(QPathData { @@ -2037,7 +2037,7 @@ fn clean_extern_crate<'tcx>( cx: &mut DocContext<'tcx>, ) -> Vec { // this is the ID of the `extern crate` statement - let cnum = cx.tcx.extern_mod_stmt_cnum(krate.def_id).unwrap_or(LOCAL_CRATE); + let cnum = cx.tcx.extern_mod_stmt_cnum(krate.def_id.def_id).unwrap_or(LOCAL_CRATE); // this is the ID of the crate itself let crate_def_id = cnum.as_def_id(); let attrs = cx.tcx.hir().attrs(krate.hir_id()); @@ -2099,7 +2099,7 @@ fn clean_use_statement<'tcx>( let attrs = cx.tcx.hir().attrs(import.hir_id()); let inline_attr = attrs.lists(sym::doc).get_word_attr(sym::inline); let pub_underscore = visibility.is_public() && name == kw::Underscore; - let current_mod = cx.tcx.parent_module_from_def_id(import.def_id); + let current_mod = cx.tcx.parent_module_from_def_id(import.def_id.def_id); // The parent of the module in which this import resides. This // is the same as `current_mod` if that's already the top diff --git a/src/librustdoc/passes/propagate_doc_cfg.rs b/src/librustdoc/passes/propagate_doc_cfg.rs index 765f7c61bd392..de3a4b3390595 100644 --- a/src/librustdoc/passes/propagate_doc_cfg.rs +++ b/src/librustdoc/passes/propagate_doc_cfg.rs @@ -48,7 +48,7 @@ impl<'a, 'tcx> CfgPropagator<'a, 'tcx> { let expected_parent = hir.get_parent_item(hir_id); // If parents are different, it means that `item` is a reexport and we need // to compute the actual `cfg` by iterating through its "real" parents. - if self.parent == Some(expected_parent) { + if self.parent == Some(expected_parent.def_id) { return; } } diff --git a/src/librustdoc/scrape_examples.rs b/src/librustdoc/scrape_examples.rs index ca86ac89e8583..dfa6ba38b883b 100644 --- a/src/librustdoc/scrape_examples.rs +++ b/src/librustdoc/scrape_examples.rs @@ -143,14 +143,14 @@ where // then we need to exit before calling typeck (which will panic). See // test/run-make/rustdoc-scrape-examples-invalid-expr for an example. let hir = tcx.hir(); - if hir.maybe_body_owned_by(ex.hir_id.owner).is_none() { + if hir.maybe_body_owned_by(ex.hir_id.owner.def_id).is_none() { return; } // Get type of function if expression is a function call let (ty, call_span, ident_span) = match ex.kind { hir::ExprKind::Call(f, _) => { - let types = tcx.typeck(ex.hir_id.owner); + let types = tcx.typeck(ex.hir_id.owner.def_id); if let Some(ty) = types.node_type_opt(f.hir_id) { (ty, ex.span, f.span) @@ -160,7 +160,7 @@ where } } hir::ExprKind::MethodCall(path, _, _, call_span) => { - let types = tcx.typeck(ex.hir_id.owner); + let types = tcx.typeck(ex.hir_id.owner.def_id); let Some(def_id) = types.type_dependent_def_id(ex.hir_id) else { trace!("type_dependent_def_id({}) = None", ex.hir_id); return; @@ -183,9 +183,8 @@ where // If the enclosing item has a span coming from a proc macro, then we also don't want to include // the example. - let enclosing_item_span = tcx - .hir() - .span_with_body(tcx.hir().local_def_id_to_hir_id(tcx.hir().get_parent_item(ex.hir_id))); + let enclosing_item_span = + tcx.hir().span_with_body(tcx.hir().get_parent_item(ex.hir_id).into()); if enclosing_item_span.from_expansion() { trace!("Rejecting expr ({call_span:?}) from macro item: {enclosing_item_span:?}"); return; diff --git a/src/test/ui-fulldeps/auxiliary/issue-40001-plugin.rs b/src/test/ui-fulldeps/auxiliary/issue-40001-plugin.rs index 03ad3ca826146..03da804bd1c1f 100644 --- a/src/test/ui-fulldeps/auxiliary/issue-40001-plugin.rs +++ b/src/test/ui-fulldeps/auxiliary/issue-40001-plugin.rs @@ -44,7 +44,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingAllowedAttrPass { ) { let item = match cx.tcx.hir().get(id) { Node::Item(item) => item, - _ => cx.tcx.hir().expect_item(cx.tcx.hir().get_parent_item(id)), + _ => cx.tcx.hir().expect_item(cx.tcx.hir().get_parent_item(id).def_id), }; let allowed = |attr| pprust::attribute_to_string(attr).contains("allowed_attr"); diff --git a/src/test/ui/thir-tree.stdout b/src/test/ui/thir-tree.stdout index 5fcdfca18d69e..7fb90581f8a8f 100644 --- a/src/test/ui/thir-tree.stdout +++ b/src/test/ui/thir-tree.stdout @@ -33,7 +33,9 @@ Thir { region_scope: Node(2), lint_level: Explicit( HirId { - owner: DefId(0:3 ~ thir_tree[8f1d]::main), + owner: OwnerId { + def_id: DefId(0:3 ~ thir_tree[8f1d]::main), + }, local_id: 2, }, ), diff --git a/src/tools/clippy/clippy_lints/src/dereference.rs b/src/tools/clippy/clippy_lints/src/dereference.rs index 501f9ef78aebe..e54d71fc8e417 100644 --- a/src/tools/clippy/clippy_lints/src/dereference.rs +++ b/src/tools/clippy/clippy_lints/src/dereference.rs @@ -704,7 +704,7 @@ fn walk_parents<'tcx>( span, .. }) if span.ctxt() == ctxt => { - let ty = cx.tcx.type_of(def_id); + let ty = cx.tcx.type_of(def_id.def_id); Some(ty_auto_deref_stability(cx, ty, precedence).position_for_result(cx)) }, diff --git a/src/tools/clippy/clippy_lints/src/doc.rs b/src/tools/clippy/clippy_lints/src/doc.rs index eb158d850fa72..f48ba526d51e1 100644 --- a/src/tools/clippy/clippy_lints/src/doc.rs +++ b/src/tools/clippy/clippy_lints/src/doc.rs @@ -233,11 +233,11 @@ impl<'tcx> LateLintPass<'tcx> for DocMarkdown { let body = cx.tcx.hir().body(body_id); let mut fpu = FindPanicUnwrap { cx, - typeck_results: cx.tcx.typeck(item.def_id), + typeck_results: cx.tcx.typeck(item.def_id.def_id), panic_span: None, }; fpu.visit_expr(body.value); - lint_for_missing_headers(cx, item.def_id, item.span, sig, headers, Some(body_id), fpu.panic_span); + lint_for_missing_headers(cx, item.def_id.def_id, item.span, sig, headers, Some(body_id), fpu.panic_span); } }, hir::ItemKind::Impl(impl_) => { @@ -268,7 +268,7 @@ impl<'tcx> LateLintPass<'tcx> for DocMarkdown { let headers = check_attrs(cx, &self.valid_idents, attrs); if let hir::TraitItemKind::Fn(ref sig, ..) = item.kind { if !in_external_macro(cx.tcx.sess, item.span) { - lint_for_missing_headers(cx, item.def_id, item.span, sig, headers, None, None); + lint_for_missing_headers(cx, item.def_id.def_id, item.span, sig, headers, None, None); } } } @@ -283,11 +283,11 @@ impl<'tcx> LateLintPass<'tcx> for DocMarkdown { let body = cx.tcx.hir().body(body_id); let mut fpu = FindPanicUnwrap { cx, - typeck_results: cx.tcx.typeck(item.def_id), + typeck_results: cx.tcx.typeck(item.def_id.def_id), panic_span: None, }; fpu.visit_expr(body.value); - lint_for_missing_headers(cx, item.def_id, item.span, sig, headers, Some(body_id), fpu.panic_span); + lint_for_missing_headers(cx, item.def_id.def_id, item.span, sig, headers, Some(body_id), fpu.panic_span); } } } diff --git a/src/tools/clippy/clippy_lints/src/enum_variants.rs b/src/tools/clippy/clippy_lints/src/enum_variants.rs index cd36f9fcd729e..c39a909b3ccb9 100644 --- a/src/tools/clippy/clippy_lints/src/enum_variants.rs +++ b/src/tools/clippy/clippy_lints/src/enum_variants.rs @@ -297,7 +297,7 @@ impl LateLintPass<'_> for EnumVariantNames { } } if let ItemKind::Enum(ref def, _) = item.kind { - if !(self.avoid_breaking_exported_api && cx.access_levels.is_exported(item.def_id)) { + if !(self.avoid_breaking_exported_api && cx.access_levels.is_exported(item.def_id.def_id)) { check_variant(cx, self.threshold, def, item_name, item.span); } } diff --git a/src/tools/clippy/clippy_lints/src/escape.rs b/src/tools/clippy/clippy_lints/src/escape.rs index 327865e4c858a..a6ddb26e2dee3 100644 --- a/src/tools/clippy/clippy_lints/src/escape.rs +++ b/src/tools/clippy/clippy_lints/src/escape.rs @@ -71,7 +71,7 @@ impl<'tcx> LateLintPass<'tcx> for BoxedLocal { } } - let parent_id = cx.tcx.hir().get_parent_item(hir_id); + let parent_id = cx.tcx.hir().get_parent_item(hir_id).def_id; let parent_node = cx.tcx.hir().find_by_def_id(parent_id); let mut trait_self_ty = None; diff --git a/src/tools/clippy/clippy_lints/src/exhaustive_items.rs b/src/tools/clippy/clippy_lints/src/exhaustive_items.rs index 173d41b4b0506..f3d9ebc5f12de 100644 --- a/src/tools/clippy/clippy_lints/src/exhaustive_items.rs +++ b/src/tools/clippy/clippy_lints/src/exhaustive_items.rs @@ -73,7 +73,7 @@ impl LateLintPass<'_> for ExhaustiveItems { fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) { if_chain! { if let ItemKind::Enum(..) | ItemKind::Struct(..) = item.kind; - if cx.access_levels.is_exported(item.def_id); + if cx.access_levels.is_exported(item.def_id.def_id); let attrs = cx.tcx.hir().attrs(item.hir_id()); if !attrs.iter().any(|a| a.has_name(sym::non_exhaustive)); then { diff --git a/src/tools/clippy/clippy_lints/src/exit.rs b/src/tools/clippy/clippy_lints/src/exit.rs index cbf52d19334c0..407dd1b39575f 100644 --- a/src/tools/clippy/clippy_lints/src/exit.rs +++ b/src/tools/clippy/clippy_lints/src/exit.rs @@ -33,7 +33,7 @@ impl<'tcx> LateLintPass<'tcx> for Exit { if let ExprKind::Path(ref path) = path_expr.kind; if let Some(def_id) = cx.qpath_res(path, path_expr.hir_id).opt_def_id(); if match_def_path(cx, def_id, &paths::EXIT); - let parent = cx.tcx.hir().get_parent_item(e.hir_id); + let parent = cx.tcx.hir().get_parent_item(e.hir_id).def_id; if let Some(Node::Item(Item{kind: ItemKind::Fn(..), ..})) = cx.tcx.hir().find_by_def_id(parent); // If the next item up is a function we check if it is an entry point // and only then emit a linter warning diff --git a/src/tools/clippy/clippy_lints/src/fallible_impl_from.rs b/src/tools/clippy/clippy_lints/src/fallible_impl_from.rs index 1f69f34a229df..ef24a5d06ad0b 100644 --- a/src/tools/clippy/clippy_lints/src/fallible_impl_from.rs +++ b/src/tools/clippy/clippy_lints/src/fallible_impl_from.rs @@ -107,7 +107,7 @@ fn lint_impl_body<'tcx>(cx: &LateContext<'tcx>, impl_span: Span, impl_items: &[h let body = cx.tcx.hir().body(body_id); let mut fpu = FindPanicUnwrap { lcx: cx, - typeck_results: cx.tcx.typeck(impl_item.id.def_id), + typeck_results: cx.tcx.typeck(impl_item.id.def_id.def_id), result: Vec::new(), }; fpu.visit_expr(body.value); diff --git a/src/tools/clippy/clippy_lints/src/functions/must_use.rs b/src/tools/clippy/clippy_lints/src/functions/must_use.rs index 00a4937763eb5..d6d33bda17381 100644 --- a/src/tools/clippy/clippy_lints/src/functions/must_use.rs +++ b/src/tools/clippy/clippy_lints/src/functions/must_use.rs @@ -21,7 +21,7 @@ pub(super) fn check_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_> let attrs = cx.tcx.hir().attrs(item.hir_id()); let attr = cx.tcx.get_attr(item.def_id.to_def_id(), sym::must_use); if let hir::ItemKind::Fn(ref sig, _generics, ref body_id) = item.kind { - let is_public = cx.access_levels.is_exported(item.def_id); + let is_public = cx.access_levels.is_exported(item.def_id.def_id); let fn_header_span = item.span.with_hi(sig.decl.output.span().hi()); if let Some(attr) = attr { check_needless_must_use(cx, sig.decl, item.hir_id(), item.span, fn_header_span, attr); @@ -31,7 +31,7 @@ pub(super) fn check_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_> sig.decl, cx.tcx.hir().body(*body_id), item.span, - item.def_id, + item.def_id.def_id, item.span.with_hi(sig.decl.output.span().hi()), "this function could have a `#[must_use]` attribute", ); @@ -41,19 +41,19 @@ pub(super) fn check_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_> pub(super) fn check_impl_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::ImplItem<'_>) { if let hir::ImplItemKind::Fn(ref sig, ref body_id) = item.kind { - let is_public = cx.access_levels.is_exported(item.def_id); + let is_public = cx.access_levels.is_exported(item.def_id.def_id); let fn_header_span = item.span.with_hi(sig.decl.output.span().hi()); let attrs = cx.tcx.hir().attrs(item.hir_id()); let attr = cx.tcx.get_attr(item.def_id.to_def_id(), sym::must_use); if let Some(attr) = attr { check_needless_must_use(cx, sig.decl, item.hir_id(), item.span, fn_header_span, attr); - } else if is_public && !is_proc_macro(cx.sess(), attrs) && trait_ref_of_method(cx, item.def_id).is_none() { + } else if is_public && !is_proc_macro(cx.sess(), attrs) && trait_ref_of_method(cx, item.def_id.def_id).is_none() { check_must_use_candidate( cx, sig.decl, cx.tcx.hir().body(*body_id), item.span, - item.def_id, + item.def_id.def_id, item.span.with_hi(sig.decl.output.span().hi()), "this method could have a `#[must_use]` attribute", ); @@ -63,7 +63,7 @@ pub(super) fn check_impl_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Imp pub(super) fn check_trait_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::TraitItem<'_>) { if let hir::TraitItemKind::Fn(ref sig, ref eid) = item.kind { - let is_public = cx.access_levels.is_exported(item.def_id); + let is_public = cx.access_levels.is_exported(item.def_id.def_id); let fn_header_span = item.span.with_hi(sig.decl.output.span().hi()); let attrs = cx.tcx.hir().attrs(item.hir_id()); @@ -78,7 +78,7 @@ pub(super) fn check_trait_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Tr sig.decl, body, item.span, - item.def_id, + item.def_id.def_id, item.span.with_hi(sig.decl.output.span().hi()), "this method could have a `#[must_use]` attribute", ); @@ -171,7 +171,7 @@ fn is_mutable_pat(cx: &LateContext<'_>, pat: &hir::Pat<'_>, tys: &mut DefIdSet) return false; // ignore `_` patterns } if cx.tcx.has_typeck_results(pat.hir_id.owner.to_def_id()) { - is_mutable_ty(cx, cx.tcx.typeck(pat.hir_id.owner).pat_ty(pat), pat.span, tys) + is_mutable_ty(cx, cx.tcx.typeck(pat.hir_id.owner.def_id).pat_ty(pat), pat.span, tys) } else { false } @@ -218,7 +218,7 @@ impl<'a, 'tcx> intravisit::Visitor<'tcx> for StaticMutVisitor<'a, 'tcx> { if self.cx.tcx.has_typeck_results(arg.hir_id.owner.to_def_id()) && is_mutable_ty( self.cx, - self.cx.tcx.typeck(arg.hir_id.owner).expr_ty(arg), + self.cx.tcx.typeck(arg.hir_id.owner.def_id).expr_ty(arg), arg.span, &mut tys, ) @@ -236,7 +236,7 @@ impl<'a, 'tcx> intravisit::Visitor<'tcx> for StaticMutVisitor<'a, 'tcx> { if self.cx.tcx.has_typeck_results(arg.hir_id.owner.to_def_id()) && is_mutable_ty( self.cx, - self.cx.tcx.typeck(arg.hir_id.owner).expr_ty(arg), + self.cx.tcx.typeck(arg.hir_id.owner.def_id).expr_ty(arg), arg.span, &mut tys, ) diff --git a/src/tools/clippy/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs b/src/tools/clippy/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs index 3bbfa52e81039..0b50431fbaaba 100644 --- a/src/tools/clippy/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs +++ b/src/tools/clippy/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs @@ -28,7 +28,7 @@ pub(super) fn check_fn<'tcx>( pub(super) fn check_trait_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::TraitItem<'_>) { if let hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Provided(eid)) = item.kind { let body = cx.tcx.hir().body(eid); - check_raw_ptr(cx, sig.header.unsafety, sig.decl, body, item.def_id); + check_raw_ptr(cx, sig.header.unsafety, sig.decl, body, item.def_id.def_id); } } diff --git a/src/tools/clippy/clippy_lints/src/functions/result.rs b/src/tools/clippy/clippy_lints/src/functions/result.rs index 9591405cb06f7..113c4e9f50910 100644 --- a/src/tools/clippy/clippy_lints/src/functions/result.rs +++ b/src/tools/clippy/clippy_lints/src/functions/result.rs @@ -34,9 +34,9 @@ fn result_err_ty<'tcx>( pub(super) fn check_item<'tcx>(cx: &LateContext<'tcx>, item: &hir::Item<'tcx>, large_err_threshold: u64) { if let hir::ItemKind::Fn(ref sig, _generics, _) = item.kind - && let Some((hir_ty, err_ty)) = result_err_ty(cx, sig.decl, item.def_id, item.span) + && let Some((hir_ty, err_ty)) = result_err_ty(cx, sig.decl, item.def_id.def_id, item.span) { - if cx.access_levels.is_exported(item.def_id) { + if cx.access_levels.is_exported(item.def_id.def_id) { let fn_header_span = item.span.with_hi(sig.decl.output.span().hi()); check_result_unit_err(cx, err_ty, fn_header_span); } @@ -47,10 +47,10 @@ pub(super) fn check_item<'tcx>(cx: &LateContext<'tcx>, item: &hir::Item<'tcx>, l pub(super) fn check_impl_item<'tcx>(cx: &LateContext<'tcx>, item: &hir::ImplItem<'tcx>, large_err_threshold: u64) { // Don't lint if method is a trait's implementation, we can't do anything about those if let hir::ImplItemKind::Fn(ref sig, _) = item.kind - && let Some((hir_ty, err_ty)) = result_err_ty(cx, sig.decl, item.def_id, item.span) - && trait_ref_of_method(cx, item.def_id).is_none() + && let Some((hir_ty, err_ty)) = result_err_ty(cx, sig.decl, item.def_id.def_id, item.span) + && trait_ref_of_method(cx, item.def_id.def_id).is_none() { - if cx.access_levels.is_exported(item.def_id) { + if cx.access_levels.is_exported(item.def_id.def_id) { let fn_header_span = item.span.with_hi(sig.decl.output.span().hi()); check_result_unit_err(cx, err_ty, fn_header_span); } @@ -61,8 +61,8 @@ pub(super) fn check_impl_item<'tcx>(cx: &LateContext<'tcx>, item: &hir::ImplItem pub(super) fn check_trait_item<'tcx>(cx: &LateContext<'tcx>, item: &hir::TraitItem<'tcx>, large_err_threshold: u64) { if let hir::TraitItemKind::Fn(ref sig, _) = item.kind { let fn_header_span = item.span.with_hi(sig.decl.output.span().hi()); - if let Some((hir_ty, err_ty)) = result_err_ty(cx, sig.decl, item.def_id, item.span) { - if cx.access_levels.is_exported(item.def_id) { + if let Some((hir_ty, err_ty)) = result_err_ty(cx, sig.decl, item.def_id.def_id, item.span) { + if cx.access_levels.is_exported(item.def_id.def_id) { check_result_unit_err(cx, err_ty, fn_header_span); } check_result_large_err(cx, err_ty, hir_ty.span, large_err_threshold); diff --git a/src/tools/clippy/clippy_lints/src/implicit_hasher.rs b/src/tools/clippy/clippy_lints/src/implicit_hasher.rs index 4f9680f60fe8b..804fdc2da0889 100644 --- a/src/tools/clippy/clippy_lints/src/implicit_hasher.rs +++ b/src/tools/clippy/clippy_lints/src/implicit_hasher.rs @@ -112,7 +112,7 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitHasher { } } - if !cx.access_levels.is_exported(item.def_id) { + if !cx.access_levels.is_exported(item.def_id.def_id) { return; } diff --git a/src/tools/clippy/clippy_lints/src/inherent_to_string.rs b/src/tools/clippy/clippy_lints/src/inherent_to_string.rs index 17d867aacb533..cb6c2ec0fb985 100644 --- a/src/tools/clippy/clippy_lints/src/inherent_to_string.rs +++ b/src/tools/clippy/clippy_lints/src/inherent_to_string.rs @@ -108,7 +108,7 @@ impl<'tcx> LateLintPass<'tcx> for InherentToString { if is_type_diagnostic_item(cx, return_ty(cx, impl_item.hir_id()), sym::String); // Filters instances of to_string which are required by a trait - if trait_ref_of_method(cx, impl_item.def_id).is_none(); + if trait_ref_of_method(cx, impl_item.def_id.def_id).is_none(); then { show_lint(cx, impl_item); diff --git a/src/tools/clippy/clippy_lints/src/iter_not_returning_iterator.rs b/src/tools/clippy/clippy_lints/src/iter_not_returning_iterator.rs index b56d87c5348c2..2027c23d328c9 100644 --- a/src/tools/clippy/clippy_lints/src/iter_not_returning_iterator.rs +++ b/src/tools/clippy/clippy_lints/src/iter_not_returning_iterator.rs @@ -44,7 +44,7 @@ impl<'tcx> LateLintPass<'tcx> for IterNotReturningIterator { let name = item.ident.name.as_str(); if matches!(name, "iter" | "iter_mut") { if let TraitItemKind::Fn(fn_sig, _) = &item.kind { - check_sig(cx, name, fn_sig, item.def_id); + check_sig(cx, name, fn_sig, item.def_id.def_id); } } } @@ -58,7 +58,7 @@ impl<'tcx> LateLintPass<'tcx> for IterNotReturningIterator { ) { if let ImplItemKind::Fn(fn_sig, _) = &item.kind { - check_sig(cx, name, fn_sig, item.def_id); + check_sig(cx, name, fn_sig, item.def_id.def_id); } } } diff --git a/src/tools/clippy/clippy_lints/src/len_zero.rs b/src/tools/clippy/clippy_lints/src/len_zero.rs index 7ae8ef830faea..7d15dd4cb2164 100644 --- a/src/tools/clippy/clippy_lints/src/len_zero.rs +++ b/src/tools/clippy/clippy_lints/src/len_zero.rs @@ -134,7 +134,7 @@ impl<'tcx> LateLintPass<'tcx> for LenZero { if item.ident.name == sym::len; if let ImplItemKind::Fn(sig, _) = &item.kind; if sig.decl.implicit_self.has_implicit_self(); - if cx.access_levels.is_exported(item.def_id); + if cx.access_levels.is_exported(item.def_id.def_id); if matches!(sig.decl.output, FnRetTy::Return(_)); if let Some(imp) = get_parent_as_impl(cx.tcx, item.hir_id()); if imp.of_trait.is_none(); @@ -210,7 +210,7 @@ fn check_trait_items(cx: &LateContext<'_>, visited_trait: &Item<'_>, trait_items } } - if cx.access_levels.is_exported(visited_trait.def_id) && trait_items.iter().any(|i| is_named_self(cx, i, sym::len)) + if cx.access_levels.is_exported(visited_trait.def_id.def_id) && trait_items.iter().any(|i| is_named_self(cx, i, sym::len)) { let mut current_and_super_traits = DefIdSet::default(); fill_trait_set(visited_trait.def_id.to_def_id(), &mut current_and_super_traits, cx); diff --git a/src/tools/clippy/clippy_lints/src/lifetimes.rs b/src/tools/clippy/clippy_lints/src/lifetimes.rs index 643a7cfd577b7..399a03187d993 100644 --- a/src/tools/clippy/clippy_lints/src/lifetimes.rs +++ b/src/tools/clippy/clippy_lints/src/lifetimes.rs @@ -102,7 +102,7 @@ impl<'tcx> LateLintPass<'tcx> for Lifetimes { fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx ImplItem<'_>) { if let ImplItemKind::Fn(ref sig, id) = item.kind { - let report_extra_lifetimes = trait_ref_of_method(cx, item.def_id).is_none(); + let report_extra_lifetimes = trait_ref_of_method(cx, item.def_id.def_id).is_none(); check_fn_inner( cx, sig.decl, @@ -276,7 +276,7 @@ fn could_use_elision<'tcx>( let mut checker = BodyLifetimeChecker { lifetimes_used_in_body: false, }; - checker.visit_expr(body.value); + checker.visit_expr(&body.value); if checker.lifetimes_used_in_body { return false; } diff --git a/src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs b/src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs index fce2d54639cbf..be7f96e9bb077 100644 --- a/src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs +++ b/src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs @@ -69,7 +69,7 @@ fn check_for_mutation<'tcx>( ExprUseVisitor::new( &mut delegate, &infcx, - body.hir_id.owner, + body.hir_id.owner.def_id, cx.param_env, cx.typeck_results(), ) diff --git a/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs b/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs index 2b04475c7a9de..53e7565bd33f3 100644 --- a/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs +++ b/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs @@ -166,7 +166,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualNonExhaustiveEnum { if let Some((id, span)) = iter.next() && iter.next().is_none() { - self.potential_enums.push((item.def_id, id, item.span, span)); + self.potential_enums.push((item.def_id.def_id, id, item.span, span)); } } } diff --git a/src/tools/clippy/clippy_lints/src/methods/mod.rs b/src/tools/clippy/clippy_lints/src/methods/mod.rs index cdde4c54d6378..ddb6d1ca26c91 100644 --- a/src/tools/clippy/clippy_lints/src/methods/mod.rs +++ b/src/tools/clippy/clippy_lints/src/methods/mod.rs @@ -3250,7 +3250,7 @@ impl<'tcx> LateLintPass<'tcx> for Methods { return; } let name = impl_item.ident.name.as_str(); - let parent = cx.tcx.hir().get_parent_item(impl_item.hir_id()); + let parent = cx.tcx.hir().get_parent_item(impl_item.hir_id()).def_id; let item = cx.tcx.hir().expect_item(parent); let self_ty = cx.tcx.type_of(item.def_id); @@ -3259,7 +3259,7 @@ impl<'tcx> LateLintPass<'tcx> for Methods { if let hir::ImplItemKind::Fn(ref sig, id) = impl_item.kind; if let Some(first_arg) = iter_input_pats(sig.decl, cx.tcx.hir().body(id)).next(); - let method_sig = cx.tcx.fn_sig(impl_item.def_id); + let method_sig = cx.tcx.fn_sig(impl_item.def_id.def_id); let method_sig = cx.tcx.erase_late_bound_regions(method_sig); let first_arg_ty = method_sig.inputs().iter().next(); @@ -3269,7 +3269,7 @@ impl<'tcx> LateLintPass<'tcx> for Methods { then { // if this impl block implements a trait, lint in trait definition instead - if !implements_trait && cx.access_levels.is_exported(impl_item.def_id) { + if !implements_trait && cx.access_levels.is_exported(impl_item.def_id.def_id) { // check missing trait implementations for method_config in &TRAIT_METHODS { if name == method_config.method_name && @@ -3301,7 +3301,7 @@ impl<'tcx> LateLintPass<'tcx> for Methods { if sig.decl.implicit_self.has_implicit_self() && !(self.avoid_breaking_exported_api - && cx.access_levels.is_exported(impl_item.def_id)) + && cx.access_levels.is_exported(impl_item.def_id.def_id)) { wrong_self_convention::check( cx, diff --git a/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs b/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs index bc304c081b906..f24b41411c816 100644 --- a/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs +++ b/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs @@ -136,7 +136,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingConstForFn { // Const fns are not allowed as methods in a trait. { - let parent = cx.tcx.hir().get_parent_item(hir_id); + let parent = cx.tcx.hir().get_parent_item(hir_id).def_id; if parent != CRATE_DEF_ID { if let hir::Node::Item(item) = cx.tcx.hir().get_by_def_id(parent) { if let hir::ItemKind::Trait(..) = &item.kind { diff --git a/src/tools/clippy/clippy_lints/src/missing_doc.rs b/src/tools/clippy/clippy_lints/src/missing_doc.rs index 3701fdb4adbff..4721955667688 100644 --- a/src/tools/clippy/clippy_lints/src/missing_doc.rs +++ b/src/tools/clippy/clippy_lints/src/missing_doc.rs @@ -131,7 +131,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc { hir::ItemKind::Fn(..) => { // ignore main() if it.ident.name == sym::main { - let at_root = cx.tcx.local_parent(it.def_id) == CRATE_DEF_ID; + let at_root = cx.tcx.local_parent(it.def_id.def_id) == CRATE_DEF_ID; if at_root { return; } diff --git a/src/tools/clippy/clippy_lints/src/missing_inline.rs b/src/tools/clippy/clippy_lints/src/missing_inline.rs index 07bc2ca5d3cd2..9d5764ac09260 100644 --- a/src/tools/clippy/clippy_lints/src/missing_inline.rs +++ b/src/tools/clippy/clippy_lints/src/missing_inline.rs @@ -88,7 +88,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingInline { return; } - if !cx.access_levels.is_exported(it.def_id) { + if !cx.access_levels.is_exported(it.def_id.def_id) { return; } match it.kind { @@ -142,7 +142,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingInline { } // If the item being implemented is not exported, then we don't need #[inline] - if !cx.access_levels.is_exported(impl_item.def_id) { + if !cx.access_levels.is_exported(impl_item.def_id.def_id) { return; } @@ -159,7 +159,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingInline { }; if let Some(trait_def_id) = trait_def_id { - if trait_def_id.is_local() && !cx.access_levels.is_exported(impl_item.def_id) { + if trait_def_id.is_local() && !cx.access_levels.is_exported(impl_item.def_id.def_id) { // If a trait is being implemented for an item, and the // trait is not exported, we don't need #[inline] return; diff --git a/src/tools/clippy/clippy_lints/src/mut_key.rs b/src/tools/clippy/clippy_lints/src/mut_key.rs index 4db103bbc1305..25d6ca83a94bc 100644 --- a/src/tools/clippy/clippy_lints/src/mut_key.rs +++ b/src/tools/clippy/clippy_lints/src/mut_key.rs @@ -89,7 +89,7 @@ impl<'tcx> LateLintPass<'tcx> for MutableKeyType { fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::ImplItem<'tcx>) { if let hir::ImplItemKind::Fn(ref sig, ..) = item.kind { - if trait_ref_of_method(cx, item.def_id).is_none() { + if trait_ref_of_method(cx, item.def_id.def_id).is_none() { check_sig(cx, item.hir_id(), sig.decl); } } diff --git a/src/tools/clippy/clippy_lints/src/new_without_default.rs b/src/tools/clippy/clippy_lints/src/new_without_default.rs index 5c45ee6d94ad3..357a71693d2c3 100644 --- a/src/tools/clippy/clippy_lints/src/new_without_default.rs +++ b/src/tools/clippy/clippy_lints/src/new_without_default.rs @@ -84,7 +84,7 @@ impl<'tcx> LateLintPass<'tcx> for NewWithoutDefault { // can't be implemented for unsafe new return; } - if cx.tcx.is_doc_hidden(impl_item.def_id) { + if cx.tcx.is_doc_hidden(impl_item.def_id.def_id) { // shouldn't be implemented when it is hidden in docs return; } @@ -96,7 +96,7 @@ impl<'tcx> LateLintPass<'tcx> for NewWithoutDefault { if_chain! { if sig.decl.inputs.is_empty(); if name == sym::new; - if cx.access_levels.is_reachable(impl_item.def_id); + if cx.access_levels.is_reachable(impl_item.def_id.def_id); let self_def_id = cx.tcx.hir().get_parent_item(id); let self_ty = cx.tcx.type_of(self_def_id); if self_ty == return_ty(cx, id); diff --git a/src/tools/clippy/clippy_lints/src/non_copy_const.rs b/src/tools/clippy/clippy_lints/src/non_copy_const.rs index b15884527321c..616ef9e2f867f 100644 --- a/src/tools/clippy/clippy_lints/src/non_copy_const.rs +++ b/src/tools/clippy/clippy_lints/src/non_copy_const.rs @@ -286,7 +286,7 @@ impl<'tcx> LateLintPass<'tcx> for NonCopyConst { fn check_impl_item(&mut self, cx: &LateContext<'tcx>, impl_item: &'tcx ImplItem<'_>) { if let ImplItemKind::Const(hir_ty, body_id) = &impl_item.kind { - let item_def_id = cx.tcx.hir().get_parent_item(impl_item.hir_id()); + let item_def_id = cx.tcx.hir().get_parent_item(impl_item.hir_id()).def_id; let item = cx.tcx.hir().expect_item(item_def_id); match &item.kind { diff --git a/src/tools/clippy/clippy_lints/src/only_used_in_recursion.rs b/src/tools/clippy/clippy_lints/src/only_used_in_recursion.rs index 6217110a1f3ae..d64a9cf71e17a 100644 --- a/src/tools/clippy/clippy_lints/src/only_used_in_recursion.rs +++ b/src/tools/clippy/clippy_lints/src/only_used_in_recursion.rs @@ -243,7 +243,7 @@ impl<'tcx> LateLintPass<'tcx> for OnlyUsedInRecursion { .. })) => { #[allow(trivial_casts)] - if let Some(Node::Item(item)) = get_parent_node(cx.tcx, cx.tcx.hir().local_def_id_to_hir_id(def_id)) + if let Some(Node::Item(item)) = get_parent_node(cx.tcx, def_id.into()) && let Some(trait_ref) = cx.tcx.impl_trait_ref(item.def_id) && let Some(trait_item_id) = cx.tcx.associated_item(def_id).trait_item_def_id { diff --git a/src/tools/clippy/clippy_lints/src/operators/assign_op_pattern.rs b/src/tools/clippy/clippy_lints/src/operators/assign_op_pattern.rs index 945a09a647c41..2c22c8b3d0819 100644 --- a/src/tools/clippy/clippy_lints/src/operators/assign_op_pattern.rs +++ b/src/tools/clippy/clippy_lints/src/operators/assign_op_pattern.rs @@ -28,7 +28,7 @@ pub(super) fn check<'tcx>( if_chain! { if let Some((_, lang_item)) = binop_traits(op.node); if let Ok(trait_id) = cx.tcx.lang_items().require(lang_item); - let parent_fn = cx.tcx.hir().get_parent_item(e.hir_id); + let parent_fn = cx.tcx.hir().get_parent_item(e.hir_id).def_id; if trait_ref_of_method(cx, parent_fn) .map_or(true, |t| t.path.res.def_id() != trait_id); if implements_trait(cx, ty, trait_id, &[rty.into()]); diff --git a/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs b/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs index 0960b050c240e..6b2eea4893225 100644 --- a/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs +++ b/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs @@ -261,7 +261,7 @@ impl<'tcx> LateLintPass<'tcx> for PassByRefOrValue { } if let hir::TraitItemKind::Fn(method_sig, _) = &item.kind { - self.check_poly_fn(cx, item.def_id, method_sig.decl, None); + self.check_poly_fn(cx, item.def_id.def_id, method_sig.decl, None); } } diff --git a/src/tools/clippy/clippy_lints/src/redundant_pub_crate.rs b/src/tools/clippy/clippy_lints/src/redundant_pub_crate.rs index 323326381d407..3c6ca9d98975d 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_pub_crate.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_pub_crate.rs @@ -46,8 +46,8 @@ impl_lint_pass!(RedundantPubCrate => [REDUNDANT_PUB_CRATE]); impl<'tcx> LateLintPass<'tcx> for RedundantPubCrate { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) { if_chain! { - if cx.tcx.visibility(item.def_id) == ty::Visibility::Restricted(CRATE_DEF_ID.to_def_id()); - if !cx.access_levels.is_exported(item.def_id) && self.is_exported.last() == Some(&false); + if cx.tcx.visibility(item.def_id.def_id) == ty::Visibility::Restricted(CRATE_DEF_ID.to_def_id()); + if !cx.access_levels.is_exported(item.def_id.def_id) && self.is_exported.last() == Some(&false); if is_not_macro_export(item); then { let span = item.span.with_hi(item.ident.span.hi()); @@ -70,7 +70,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantPubCrate { } if let ItemKind::Mod { .. } = item.kind { - self.is_exported.push(cx.access_levels.is_exported(item.def_id)); + self.is_exported.push(cx.access_levels.is_exported(item.def_id.def_id)); } } diff --git a/src/tools/clippy/clippy_lints/src/return_self_not_must_use.rs b/src/tools/clippy/clippy_lints/src/return_self_not_must_use.rs index 60be6bd335f68..16d702a3868d1 100644 --- a/src/tools/clippy/clippy_lints/src/return_self_not_must_use.rs +++ b/src/tools/clippy/clippy_lints/src/return_self_not_must_use.rs @@ -128,7 +128,7 @@ impl<'tcx> LateLintPass<'tcx> for ReturnSelfNotMustUse { fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx TraitItem<'tcx>) { if let TraitItemKind::Fn(ref sig, _) = item.kind { - check_method(cx, sig.decl, item.def_id, item.span, item.hir_id()); + check_method(cx, sig.decl, item.def_id.def_id, item.span, item.hir_id()); } } } diff --git a/src/tools/clippy/clippy_lints/src/self_named_constructors.rs b/src/tools/clippy/clippy_lints/src/self_named_constructors.rs index 9cea4d8806710..1ac538f4c7c07 100644 --- a/src/tools/clippy/clippy_lints/src/self_named_constructors.rs +++ b/src/tools/clippy/clippy_lints/src/self_named_constructors.rs @@ -51,7 +51,7 @@ impl<'tcx> LateLintPass<'tcx> for SelfNamedConstructors { _ => return, } - let parent = cx.tcx.hir().get_parent_item(impl_item.hir_id()); + let parent = cx.tcx.hir().get_parent_item(impl_item.hir_id()).def_id; let item = cx.tcx.hir().expect_item(parent); let self_ty = cx.tcx.type_of(item.def_id); let ret_ty = return_ty(cx, impl_item.hir_id()); diff --git a/src/tools/clippy/clippy_lints/src/suspicious_trait_impl.rs b/src/tools/clippy/clippy_lints/src/suspicious_trait_impl.rs index 6add20c1fb712..d47ed459387ef 100644 --- a/src/tools/clippy/clippy_lints/src/suspicious_trait_impl.rs +++ b/src/tools/clippy/clippy_lints/src/suspicious_trait_impl.rs @@ -64,11 +64,11 @@ impl<'tcx> LateLintPass<'tcx> for SuspiciousImpl { // Check for more than one binary operation in the implemented function // Linting when multiple operations are involved can result in false positives - let parent_fn = cx.tcx.hir().get_parent_item(expr.hir_id); + let parent_fn = cx.tcx.hir().get_parent_item(expr.hir_id).def_id; if let hir::Node::ImplItem(impl_item) = cx.tcx.hir().get_by_def_id(parent_fn); if let hir::ImplItemKind::Fn(_, body_id) = impl_item.kind; let body = cx.tcx.hir().body(body_id); - let parent_fn = cx.tcx.hir().get_parent_item(expr.hir_id); + let parent_fn = cx.tcx.hir().get_parent_item(expr.hir_id).def_id; if let Some(trait_ref) = trait_ref_of_method(cx, parent_fn); let trait_id = trait_ref.path.res.def_id(); if ![binop_trait_id, op_assign_trait_id].contains(&trait_id); diff --git a/src/tools/clippy/clippy_lints/src/transmute/utils.rs b/src/tools/clippy/clippy_lints/src/transmute/utils.rs index 8bdadf2440231..8e90d20265ce1 100644 --- a/src/tools/clippy/clippy_lints/src/transmute/utils.rs +++ b/src/tools/clippy/clippy_lints/src/transmute/utils.rs @@ -42,7 +42,7 @@ pub(super) fn can_be_expressed_as_pointer_cast<'tcx>( /// messages. This function will panic if that occurs. fn check_cast<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>, from_ty: Ty<'tcx>, to_ty: Ty<'tcx>) -> Option { let hir_id = e.hir_id; - let local_def_id = hir_id.owner; + let local_def_id = hir_id.owner.def_id; Inherited::build(cx.tcx, local_def_id).enter(|inherited| { let fn_ctxt = FnCtxt::new(&inherited, cx.param_env, hir_id); diff --git a/src/tools/clippy/clippy_lints/src/types/borrowed_box.rs b/src/tools/clippy/clippy_lints/src/types/borrowed_box.rs index 94945b2e1a9e2..1268c23206a6f 100644 --- a/src/tools/clippy/clippy_lints/src/types/borrowed_box.rs +++ b/src/tools/clippy/clippy_lints/src/types/borrowed_box.rs @@ -104,7 +104,7 @@ fn get_bounds_if_impl_trait<'tcx>(cx: &LateContext<'tcx>, qpath: &QPath<'_>, id: if let Some(Node::GenericParam(generic_param)) = cx.tcx.hir().get_if_local(did); if let GenericParamKind::Type { synthetic, .. } = generic_param.kind; if synthetic; - if let Some(generics) = cx.tcx.hir().get_generics(id.owner); + if let Some(generics) = cx.tcx.hir().get_generics(id.owner.def_id); if let Some(pred) = generics.bounds_for_param(did.expect_local()).next(); then { Some(pred.bounds) diff --git a/src/tools/clippy/clippy_lints/src/types/mod.rs b/src/tools/clippy/clippy_lints/src/types/mod.rs index 353a6f6b899ea..aca55817c5250 100644 --- a/src/tools/clippy/clippy_lints/src/types/mod.rs +++ b/src/tools/clippy/clippy_lints/src/types/mod.rs @@ -313,7 +313,7 @@ impl_lint_pass!(Types => [BOX_COLLECTION, VEC_BOX, OPTION_OPTION, LINKEDLIST, BO impl<'tcx> LateLintPass<'tcx> for Types { fn check_fn(&mut self, cx: &LateContext<'_>, _: FnKind<'_>, decl: &FnDecl<'_>, _: &Body<'_>, _: Span, id: HirId) { let is_in_trait_impl = - if let Some(hir::Node::Item(item)) = cx.tcx.hir().find_by_def_id(cx.tcx.hir().get_parent_item(id)) { + if let Some(hir::Node::Item(item)) = cx.tcx.hir().find_by_def_id(cx.tcx.hir().get_parent_item(id).def_id) { matches!(item.kind, ItemKind::Impl(hir::Impl { of_trait: Some(_), .. })) } else { false @@ -333,7 +333,7 @@ impl<'tcx> LateLintPass<'tcx> for Types { } fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) { - let is_exported = cx.access_levels.is_exported(item.def_id); + let is_exported = cx.access_levels.is_exported(item.def_id.def_id); match item.kind { ItemKind::Static(ty, _, _) | ItemKind::Const(ty, _) => self.check_ty( @@ -353,7 +353,7 @@ impl<'tcx> LateLintPass<'tcx> for Types { match item.kind { ImplItemKind::Const(ty, _) => { let is_in_trait_impl = if let Some(hir::Node::Item(item)) = - cx.tcx.hir().find_by_def_id(cx.tcx.hir().get_parent_item(item.hir_id())) + cx.tcx.hir().find_by_def_id(cx.tcx.hir().get_parent_item(item.hir_id()).def_id) { matches!(item.kind, ItemKind::Impl(hir::Impl { of_trait: Some(_), .. })) } else { @@ -390,7 +390,7 @@ impl<'tcx> LateLintPass<'tcx> for Types { } fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &TraitItem<'_>) { - let is_exported = cx.access_levels.is_exported(item.def_id); + let is_exported = cx.access_levels.is_exported(item.def_id.def_id); let context = CheckTyContext { is_exported, diff --git a/src/tools/clippy/clippy_lints/src/unused_self.rs b/src/tools/clippy/clippy_lints/src/unused_self.rs index 51c65d898cf5f..713fe06bad436 100644 --- a/src/tools/clippy/clippy_lints/src/unused_self.rs +++ b/src/tools/clippy/clippy_lints/src/unused_self.rs @@ -54,14 +54,14 @@ impl<'tcx> LateLintPass<'tcx> for UnusedSelf { if impl_item.span.from_expansion() { return; } - let parent = cx.tcx.hir().get_parent_item(impl_item.hir_id()); + let parent = cx.tcx.hir().get_parent_item(impl_item.hir_id()).def_id; let parent_item = cx.tcx.hir().expect_item(parent); let assoc_item = cx.tcx.associated_item(impl_item.def_id); if_chain! { if let ItemKind::Impl(Impl { of_trait: None, .. }) = parent_item.kind; if assoc_item.fn_has_self_parameter; if let ImplItemKind::Fn(.., body_id) = &impl_item.kind; - if !cx.access_levels.is_exported(impl_item.def_id) || !self.avoid_breaking_exported_api; + if !cx.access_levels.is_exported(impl_item.def_id.def_id) || !self.avoid_breaking_exported_api; let body = cx.tcx.hir().body(*body_id); if let [self_param, ..] = body.params; if !is_local_used(cx, body, self_param.pat.hir_id); diff --git a/src/tools/clippy/clippy_lints/src/unwrap_in_result.rs b/src/tools/clippy/clippy_lints/src/unwrap_in_result.rs index 46020adcaa2ca..baa53ba664f69 100644 --- a/src/tools/clippy/clippy_lints/src/unwrap_in_result.rs +++ b/src/tools/clippy/clippy_lints/src/unwrap_in_result.rs @@ -111,7 +111,7 @@ fn lint_impl_body<'tcx>(cx: &LateContext<'tcx>, impl_span: Span, impl_item: &'tc let body = cx.tcx.hir().body(body_id); let mut fpu = FindExpectUnwrap { lcx: cx, - typeck_results: cx.tcx.typeck(impl_item.def_id), + typeck_results: cx.tcx.typeck(impl_item.def_id.def_id), result: Vec::new(), }; fpu.visit_expr(body.value); diff --git a/src/tools/clippy/clippy_lints/src/upper_case_acronyms.rs b/src/tools/clippy/clippy_lints/src/upper_case_acronyms.rs index 02bf09ed5068c..2c71f35d490cb 100644 --- a/src/tools/clippy/clippy_lints/src/upper_case_acronyms.rs +++ b/src/tools/clippy/clippy_lints/src/upper_case_acronyms.rs @@ -105,7 +105,7 @@ impl LateLintPass<'_> for UpperCaseAcronyms { fn check_item(&mut self, cx: &LateContext<'_>, it: &Item<'_>) { // do not lint public items or in macros if in_external_macro(cx.sess(), it.span) - || (self.avoid_breaking_exported_api && cx.access_levels.is_exported(it.def_id)) + || (self.avoid_breaking_exported_api && cx.access_levels.is_exported(it.def_id.def_id)) { return; } diff --git a/src/tools/clippy/clippy_lints/src/use_self.rs b/src/tools/clippy/clippy_lints/src/use_self.rs index 44ab9bca79596..ce51cb693fc02 100644 --- a/src/tools/clippy/clippy_lints/src/use_self.rs +++ b/src/tools/clippy/clippy_lints/src/use_self.rs @@ -106,7 +106,7 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf { if !is_from_proc_macro(cx, item); // expensive, should be last check then { StackItem::Check { - impl_id: item.def_id, + impl_id: item.def_id.def_id, in_body: 0, types_to_skip: std::iter::once(self_ty.hir_id).collect(), } diff --git a/src/tools/clippy/clippy_lints/src/utils/author.rs b/src/tools/clippy/clippy_lints/src/utils/author.rs index 4003fff27c006..1df3135c962d1 100644 --- a/src/tools/clippy/clippy_lints/src/utils/author.rs +++ b/src/tools/clippy/clippy_lints/src/utils/author.rs @@ -140,7 +140,7 @@ impl<'tcx> LateLintPass<'tcx> for Author { fn check_item(cx: &LateContext<'_>, hir_id: HirId) { let hir = cx.tcx.hir(); - if let Some(body_id) = hir.maybe_body_owned_by(hir_id.expect_owner()) { + if let Some(body_id) = hir.maybe_body_owned_by(hir_id.expect_owner().def_id) { check_node(cx, hir_id, |v| { v.expr(&v.bind("expr", hir.body(body_id).value)); }); diff --git a/src/tools/clippy/clippy_lints/src/wildcard_imports.rs b/src/tools/clippy/clippy_lints/src/wildcard_imports.rs index 5418eca382da0..2604b1ee7c56a 100644 --- a/src/tools/clippy/clippy_lints/src/wildcard_imports.rs +++ b/src/tools/clippy/clippy_lints/src/wildcard_imports.rs @@ -120,14 +120,14 @@ impl LateLintPass<'_> for WildcardImports { if is_test_module_or_function(cx.tcx, item) { self.test_modules_deep = self.test_modules_deep.saturating_add(1); } - let module = cx.tcx.parent_module_from_def_id(item.def_id); - if cx.tcx.visibility(item.def_id) != ty::Visibility::Restricted(module.to_def_id()) { + let module = cx.tcx.parent_module_from_def_id(item.def_id.def_id); + if cx.tcx.visibility(item.def_id.def_id) != ty::Visibility::Restricted(module.to_def_id()) { return; } if_chain! { if let ItemKind::Use(use_path, UseKind::Glob) = &item.kind; if self.warn_on_all || !self.check_exceptions(item, use_path.segments); - let used_imports = cx.tcx.names_imported_by_glob_use(item.def_id); + let used_imports = cx.tcx.names_imported_by_glob_use(item.def_id.def_id); if !used_imports.is_empty(); // Already handled by `unused_imports` then { let mut applicability = Applicability::MachineApplicable; diff --git a/src/tools/clippy/clippy_lints/src/zero_sized_map_values.rs b/src/tools/clippy/clippy_lints/src/zero_sized_map_values.rs index 8dc43c0e29436..386f3c527f174 100644 --- a/src/tools/clippy/clippy_lints/src/zero_sized_map_values.rs +++ b/src/tools/clippy/clippy_lints/src/zero_sized_map_values.rs @@ -72,7 +72,7 @@ fn in_trait_impl(cx: &LateContext<'_>, hir_id: HirId) -> bool { let second_parent_id = cx .tcx .hir() - .get_parent_item(cx.tcx.hir().local_def_id_to_hir_id(parent_id)); + .get_parent_item(parent_id.into()).def_id; if let Some(Node::Item(item)) = cx.tcx.hir().find_by_def_id(second_parent_id) { if let ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }) = item.kind { return true; diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index 62da850a15e70..9343cf457b341 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -78,7 +78,7 @@ use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::unhash::UnhashMap; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; -use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, CRATE_DEF_ID}; +use rustc_hir::def_id::{CrateNum, DefId, LocalDefId}; use rustc_hir::hir_id::{HirIdMap, HirIdSet}; use rustc_hir::intravisit::{walk_expr, FnKind, Visitor}; use rustc_hir::LangItem::{OptionNone, ResultErr, ResultOk}; @@ -212,7 +212,7 @@ pub fn find_binding_init<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId) -> Option< /// } /// ``` pub fn in_constant(cx: &LateContext<'_>, id: HirId) -> bool { - let parent_id = cx.tcx.hir().get_parent_item(id); + let parent_id = cx.tcx.hir().get_parent_item(id).def_id; match cx.tcx.hir().get_by_def_id(parent_id) { Node::Item(&Item { kind: ItemKind::Const(..) | ItemKind::Static(..), @@ -597,8 +597,8 @@ pub fn trait_ref_of_method<'tcx>(cx: &LateContext<'tcx>, def_id: LocalDefId) -> let hir_id = cx.tcx.hir().local_def_id_to_hir_id(def_id); let parent_impl = cx.tcx.hir().get_parent_item(hir_id); if_chain! { - if parent_impl != CRATE_DEF_ID; - if let hir::Node::Item(item) = cx.tcx.hir().get_by_def_id(parent_impl); + if parent_impl != hir::CRATE_OWNER_ID; + if let hir::Node::Item(item) = cx.tcx.hir().get_by_def_id(parent_impl.def_id); if let hir::ItemKind::Impl(impl_) = &item.kind; then { return impl_.of_trait.as_ref(); @@ -1104,7 +1104,7 @@ pub fn is_in_panic_handler(cx: &LateContext<'_>, e: &Expr<'_>) -> bool { /// Gets the name of the item the expression is in, if available. pub fn get_item_name(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option { - let parent_id = cx.tcx.hir().get_parent_item(expr.hir_id); + let parent_id = cx.tcx.hir().get_parent_item(expr.hir_id).def_id; match cx.tcx.hir().find_by_def_id(parent_id) { Some( Node::Item(Item { ident, .. }) @@ -1648,7 +1648,7 @@ pub fn any_parent_has_attr(tcx: TyCtxt<'_>, node: HirId, symbol: Symbol) -> bool return true; } prev_enclosing_node = Some(enclosing_node); - enclosing_node = map.local_def_id_to_hir_id(map.get_parent_item(enclosing_node)); + enclosing_node = map.get_parent_item(enclosing_node).into(); } false diff --git a/src/tools/clippy/clippy_utils/src/usage.rs b/src/tools/clippy/clippy_utils/src/usage.rs index 3af5dfb62f97e..a7c08839f5241 100644 --- a/src/tools/clippy/clippy_utils/src/usage.rs +++ b/src/tools/clippy/clippy_utils/src/usage.rs @@ -21,7 +21,7 @@ pub fn mutated_variables<'tcx>(expr: &'tcx Expr<'_>, cx: &LateContext<'tcx>) -> ExprUseVisitor::new( &mut delegate, &infcx, - expr.hir_id.owner, + expr.hir_id.owner.def_id, cx.param_env, cx.typeck_results(), ) From 9363f0fda5a699b48ea87ad7007dcb811e04a60d Mon Sep 17 00:00:00 2001 From: Ellis Hoag Date: Fri, 26 Aug 2022 19:32:04 -0700 Subject: [PATCH 198/586] Add RanlibFailure --- compiler/rustc_codegen_gcc/src/archive.rs | 4 +++- compiler/rustc_codegen_gcc/src/errors.rs | 7 +++++++ compiler/rustc_codegen_gcc/src/lib.rs | 2 ++ .../rustc_error_messages/locales/en-US/codegen_gcc.ftl | 2 ++ compiler/rustc_error_messages/src/lib.rs | 1 + compiler/rustc_errors/src/diagnostic.rs | 9 +++++++++ 6 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 compiler/rustc_codegen_gcc/src/errors.rs create mode 100644 compiler/rustc_error_messages/locales/en-US/codegen_gcc.ftl diff --git a/compiler/rustc_codegen_gcc/src/archive.rs b/compiler/rustc_codegen_gcc/src/archive.rs index f863abdcc97ec..14a69c194e4e4 100644 --- a/compiler/rustc_codegen_gcc/src/archive.rs +++ b/compiler/rustc_codegen_gcc/src/archive.rs @@ -1,6 +1,8 @@ use std::fs::File; use std::path::{Path, PathBuf}; +use crate::errors::RanlibFailure; + use rustc_codegen_ssa::back::archive::{ArchiveBuilder, ArchiveBuilderBuilder}; use rustc_session::Session; @@ -181,7 +183,7 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> { std::process::Command::new("ranlib").arg(output).status().expect("Couldn't run ranlib"); if !status.success() { - self.config.sess.fatal(&format!("Ranlib exited with code {:?}", status.code())); + self.config.sess.emit_fatal(RanlibFailure { exit_code: status.code() }); } any_members diff --git a/compiler/rustc_codegen_gcc/src/errors.rs b/compiler/rustc_codegen_gcc/src/errors.rs new file mode 100644 index 0000000000000..1a0e38fc0bb29 --- /dev/null +++ b/compiler/rustc_codegen_gcc/src/errors.rs @@ -0,0 +1,7 @@ +use rustc_macros::SessionDiagnostic; + +#[derive(SessionDiagnostic)] +#[diag(codegen_gcc::ranlib_failure)] +pub(crate) struct RanlibFailure { + pub exit_code: Option +} diff --git a/compiler/rustc_codegen_gcc/src/lib.rs b/compiler/rustc_codegen_gcc/src/lib.rs index 223466fb9b51f..fc10112e55ef9 100644 --- a/compiler/rustc_codegen_gcc/src/lib.rs +++ b/compiler/rustc_codegen_gcc/src/lib.rs @@ -25,6 +25,7 @@ extern crate rustc_codegen_ssa; extern crate rustc_data_structures; extern crate rustc_errors; extern crate rustc_hir; +extern crate rustc_macros; extern crate rustc_metadata; extern crate rustc_middle; extern crate rustc_session; @@ -50,6 +51,7 @@ mod context; mod coverageinfo; mod debuginfo; mod declare; +mod errors; mod int; mod intrinsic; mod mono_item; diff --git a/compiler/rustc_error_messages/locales/en-US/codegen_gcc.ftl b/compiler/rustc_error_messages/locales/en-US/codegen_gcc.ftl new file mode 100644 index 0000000000000..a093fa18a61bd --- /dev/null +++ b/compiler/rustc_error_messages/locales/en-US/codegen_gcc.ftl @@ -0,0 +1,2 @@ +codegen_gcc_ranlib_failure = + Ranlib exited with code {$exit_code} diff --git a/compiler/rustc_error_messages/src/lib.rs b/compiler/rustc_error_messages/src/lib.rs index ff33ae7e8f224..abf98a9621e78 100644 --- a/compiler/rustc_error_messages/src/lib.rs +++ b/compiler/rustc_error_messages/src/lib.rs @@ -41,6 +41,7 @@ fluent_messages! { borrowck => "../locales/en-US/borrowck.ftl", builtin_macros => "../locales/en-US/builtin_macros.ftl", const_eval => "../locales/en-US/const_eval.ftl", + codegen_gcc => "../locales/en-US/codegen_gcc.ftl", driver => "../locales/en-US/driver.ftl", expand => "../locales/en-US/expand.ftl", session => "../locales/en-US/session.ftl", diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index 1c440a0a07efc..f6af0f879ca57 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -114,6 +114,15 @@ impl IntoDiagnosticArg for char { } } +impl IntoDiagnosticArg for Option { + fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { + match self { + Some(t) => t.into_diagnostic_arg(), + None => DiagnosticArgValue::Str(Cow::Borrowed("None")), + } + } +} + impl IntoDiagnosticArg for Symbol { fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { self.to_ident_string().into_diagnostic_arg() From 7e00a4830520eb01dfb547726a0705a63227e8b7 Mon Sep 17 00:00:00 2001 From: Ellis Hoag Date: Fri, 26 Aug 2022 20:23:50 -0700 Subject: [PATCH 199/586] Add LinkageConstOrMutType --- compiler/rustc_codegen_gcc/src/consts.rs | 6 ++---- compiler/rustc_codegen_gcc/src/errors.rs | 8 ++++++++ .../rustc_error_messages/locales/en-US/codegen_gcc.ftl | 3 +++ 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_codegen_gcc/src/consts.rs b/compiler/rustc_codegen_gcc/src/consts.rs index 356c03ee3c189..81f533288677a 100644 --- a/compiler/rustc_codegen_gcc/src/consts.rs +++ b/compiler/rustc_codegen_gcc/src/consts.rs @@ -14,6 +14,7 @@ use rustc_target::abi::{self, Align, HasDataLayout, Primitive, Size, WrappingRan use crate::base; use crate::context::CodegenCx; +use crate::errors::LinkageConstOrMutType; use crate::type_of::LayoutGccExt; impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { @@ -368,10 +369,7 @@ fn check_and_apply_linkage<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, attrs: &Codeg cx.layout_of(mt.ty).gcc_type(cx, true) } else { - cx.sess().span_fatal( - span, - "must have type `*const T` or `*mut T` due to `#[linkage]` attribute", - ) + cx.sess().emit_fatal(LinkageConstOrMutType { span: span }) }; // Declare a symbol `foo` with the desired linkage. let global1 = cx.declare_global_with_linkage(&sym, llty2, base::global_linkage_to_gcc(linkage)); diff --git a/compiler/rustc_codegen_gcc/src/errors.rs b/compiler/rustc_codegen_gcc/src/errors.rs index 1a0e38fc0bb29..456a60c6f90ba 100644 --- a/compiler/rustc_codegen_gcc/src/errors.rs +++ b/compiler/rustc_codegen_gcc/src/errors.rs @@ -1,7 +1,15 @@ use rustc_macros::SessionDiagnostic; +use rustc_span::Span; #[derive(SessionDiagnostic)] #[diag(codegen_gcc::ranlib_failure)] pub(crate) struct RanlibFailure { pub exit_code: Option } + +#[derive(SessionDiagnostic)] +#[diag(codegen_gcc::linkage_const_or_mut_type)] +pub(crate) struct LinkageConstOrMutType { + #[primary_span] + pub span: Span +} diff --git a/compiler/rustc_error_messages/locales/en-US/codegen_gcc.ftl b/compiler/rustc_error_messages/locales/en-US/codegen_gcc.ftl index a093fa18a61bd..80af7232c0622 100644 --- a/compiler/rustc_error_messages/locales/en-US/codegen_gcc.ftl +++ b/compiler/rustc_error_messages/locales/en-US/codegen_gcc.ftl @@ -1,2 +1,5 @@ codegen_gcc_ranlib_failure = Ranlib exited with code {$exit_code} + +codegen_gcc_linkage_const_or_mut_type = + must have type `*const T` or `*mut T` due to `#[linkage]` attribute \ No newline at end of file From d9aa635969b1fa3a00899ecc58a5c7076fd16f9d Mon Sep 17 00:00:00 2001 From: Ellis Hoag Date: Fri, 26 Aug 2022 20:44:44 -0700 Subject: [PATCH 200/586] Add UnwindingInlineAsm --- compiler/rustc_codegen_gcc/src/asm.rs | 3 ++- compiler/rustc_codegen_gcc/src/errors.rs | 7 +++++++ .../rustc_error_messages/locales/en-US/codegen_gcc.ftl | 5 ++++- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_codegen_gcc/src/asm.rs b/compiler/rustc_codegen_gcc/src/asm.rs index 52fd66af0659d..007b001f213f8 100644 --- a/compiler/rustc_codegen_gcc/src/asm.rs +++ b/compiler/rustc_codegen_gcc/src/asm.rs @@ -12,6 +12,7 @@ use std::borrow::Cow; use crate::builder::Builder; use crate::context::CodegenCx; +use crate::errors::UnwindingInlineAsm; use crate::type_of::LayoutGccExt; use crate::callee::get_fn; @@ -109,7 +110,7 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { fn codegen_inline_asm(&mut self, template: &[InlineAsmTemplatePiece], rust_operands: &[InlineAsmOperandRef<'tcx, Self>], options: InlineAsmOptions, span: &[Span], _instance: Instance<'_>, _dest_catch_funclet: Option<(Self::BasicBlock, Self::BasicBlock, Option<&Self::Funclet>)>) { if options.contains(InlineAsmOptions::MAY_UNWIND) { self.sess() - .struct_span_err(span[0], "GCC backend does not support unwinding from inline asm") + .create_err(UnwindingInlineAsm { span: span[0] }) .emit(); return; } diff --git a/compiler/rustc_codegen_gcc/src/errors.rs b/compiler/rustc_codegen_gcc/src/errors.rs index 456a60c6f90ba..e0c7dca8e3241 100644 --- a/compiler/rustc_codegen_gcc/src/errors.rs +++ b/compiler/rustc_codegen_gcc/src/errors.rs @@ -13,3 +13,10 @@ pub(crate) struct LinkageConstOrMutType { #[primary_span] pub span: Span } + +#[derive(SessionDiagnostic)] +#[diag(codegen_gcc::unwinding_inline_asm)] +pub(crate) struct UnwindingInlineAsm { + #[primary_span] + pub span: Span +} diff --git a/compiler/rustc_error_messages/locales/en-US/codegen_gcc.ftl b/compiler/rustc_error_messages/locales/en-US/codegen_gcc.ftl index 80af7232c0622..1920cf0fff13d 100644 --- a/compiler/rustc_error_messages/locales/en-US/codegen_gcc.ftl +++ b/compiler/rustc_error_messages/locales/en-US/codegen_gcc.ftl @@ -2,4 +2,7 @@ codegen_gcc_ranlib_failure = Ranlib exited with code {$exit_code} codegen_gcc_linkage_const_or_mut_type = - must have type `*const T` or `*mut T` due to `#[linkage]` attribute \ No newline at end of file + must have type `*const T` or `*mut T` due to `#[linkage]` attribute + +codegen_gcc_unwinding_inline_asm = + GCC backend does not support unwinding from inline asm From d0b7e7191850258979be7518b9ddce7c7cb555f0 Mon Sep 17 00:00:00 2001 From: Ellis Hoag Date: Fri, 26 Aug 2022 20:50:37 -0700 Subject: [PATCH 201/586] Add LTONotSupported --- compiler/rustc_codegen_gcc/src/errors.rs | 4 ++++ compiler/rustc_codegen_gcc/src/lib.rs | 3 ++- compiler/rustc_error_messages/locales/en-US/codegen_gcc.ftl | 3 +++ 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_codegen_gcc/src/errors.rs b/compiler/rustc_codegen_gcc/src/errors.rs index e0c7dca8e3241..1b2953952ef75 100644 --- a/compiler/rustc_codegen_gcc/src/errors.rs +++ b/compiler/rustc_codegen_gcc/src/errors.rs @@ -14,6 +14,10 @@ pub(crate) struct LinkageConstOrMutType { pub span: Span } +#[derive(SessionDiagnostic)] +#[diag(codegen_gcc::lto_not_supported)] +pub(crate) struct LTONotSupported {} + #[derive(SessionDiagnostic)] #[diag(codegen_gcc::unwinding_inline_asm)] pub(crate) struct UnwindingInlineAsm { diff --git a/compiler/rustc_codegen_gcc/src/lib.rs b/compiler/rustc_codegen_gcc/src/lib.rs index fc10112e55ef9..03f41d197b8f7 100644 --- a/compiler/rustc_codegen_gcc/src/lib.rs +++ b/compiler/rustc_codegen_gcc/src/lib.rs @@ -61,6 +61,7 @@ mod type_of; use std::any::Any; use std::sync::{Arc, Mutex}; +use crate::errors::LTONotSupported; use gccjit::{Context, OptimizationLevel, CType}; use rustc_ast::expand::allocator::AllocatorKind; use rustc_codegen_ssa::{CodegenResults, CompiledModule, ModuleCodegen}; @@ -99,7 +100,7 @@ pub struct GccCodegenBackend { impl CodegenBackend for GccCodegenBackend { fn init(&self, sess: &Session) { if sess.lto() != Lto::No { - sess.warn("LTO is not supported. You may get a linker error."); + sess.emit_warning(LTONotSupported {}); } let temp_dir = TempDir::new().expect("cannot create temporary directory"); diff --git a/compiler/rustc_error_messages/locales/en-US/codegen_gcc.ftl b/compiler/rustc_error_messages/locales/en-US/codegen_gcc.ftl index 1920cf0fff13d..189c948c4fae7 100644 --- a/compiler/rustc_error_messages/locales/en-US/codegen_gcc.ftl +++ b/compiler/rustc_error_messages/locales/en-US/codegen_gcc.ftl @@ -6,3 +6,6 @@ codegen_gcc_linkage_const_or_mut_type = codegen_gcc_unwinding_inline_asm = GCC backend does not support unwinding from inline asm + +codegen_gcc_lto_not_supported = + LTO is not supported. You may get a linker error. From 5e0c53a679bb81dea64cb498e7ea2626d8acc3c8 Mon Sep 17 00:00:00 2001 From: Ellis Hoag Date: Sat, 27 Aug 2022 15:19:16 -0700 Subject: [PATCH 202/586] Add LayoutSizeOverflow --- compiler/rustc_codegen_gcc/src/context.rs | 5 +++-- compiler/rustc_codegen_gcc/src/errors.rs | 8 ++++++++ .../rustc_error_messages/locales/en-US/codegen_gcc.ftl | 3 +++ 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_codegen_gcc/src/context.rs b/compiler/rustc_codegen_gcc/src/context.rs index 478f6d893dd0f..187e4c689ec47 100644 --- a/compiler/rustc_codegen_gcc/src/context.rs +++ b/compiler/rustc_codegen_gcc/src/context.rs @@ -18,6 +18,7 @@ use rustc_target::abi::{call::FnAbi, HasDataLayout, PointeeInfo, Size, TargetDat use rustc_target::spec::{HasTargetSpec, Target, TlsModel}; use crate::callee::get_fn; +use crate::errors::LayoutSizeOverflow; #[derive(Clone)] pub struct FuncSig<'gcc> { @@ -477,7 +478,7 @@ impl<'gcc, 'tcx> LayoutOfHelpers<'tcx> for CodegenCx<'gcc, 'tcx> { #[inline] fn handle_layout_err(&self, err: LayoutError<'tcx>, span: Span, ty: Ty<'tcx>) -> ! { if let LayoutError::SizeOverflow(_) = err { - self.sess().span_fatal(span, &err.to_string()) + self.sess().emit_fatal(LayoutSizeOverflow { span, error: err.to_string() }) } else { span_bug!(span, "failed to get layout for `{}`: {}", ty, err) } @@ -495,7 +496,7 @@ impl<'gcc, 'tcx> FnAbiOfHelpers<'tcx> for CodegenCx<'gcc, 'tcx> { fn_abi_request: FnAbiRequest<'tcx>, ) -> ! { if let FnAbiError::Layout(LayoutError::SizeOverflow(_)) = err { - self.sess().span_fatal(span, &err.to_string()) + self.sess().emit_fatal(LayoutSizeOverflow { span, error: err.to_string() }) } else { match fn_abi_request { FnAbiRequest::OfFnPtr { sig, extra_args } => { diff --git a/compiler/rustc_codegen_gcc/src/errors.rs b/compiler/rustc_codegen_gcc/src/errors.rs index 1b2953952ef75..490a209ead05f 100644 --- a/compiler/rustc_codegen_gcc/src/errors.rs +++ b/compiler/rustc_codegen_gcc/src/errors.rs @@ -7,6 +7,14 @@ pub(crate) struct RanlibFailure { pub exit_code: Option } +#[derive(SessionDiagnostic)] +#[diag(codegen_gcc::layout_size_overflow)] +pub(crate) struct LayoutSizeOverflow { + #[primary_span] + pub span: Span, + pub error: String, +} + #[derive(SessionDiagnostic)] #[diag(codegen_gcc::linkage_const_or_mut_type)] pub(crate) struct LinkageConstOrMutType { diff --git a/compiler/rustc_error_messages/locales/en-US/codegen_gcc.ftl b/compiler/rustc_error_messages/locales/en-US/codegen_gcc.ftl index 189c948c4fae7..70072a073cd1d 100644 --- a/compiler/rustc_error_messages/locales/en-US/codegen_gcc.ftl +++ b/compiler/rustc_error_messages/locales/en-US/codegen_gcc.ftl @@ -1,6 +1,9 @@ codegen_gcc_ranlib_failure = Ranlib exited with code {$exit_code} +codegen_gcc_layout_size_overflow = + {$error} + codegen_gcc_linkage_const_or_mut_type = must have type `*const T` or `*mut T` due to `#[linkage]` attribute From 1ce482adda7f5b18ff6b107351565e31056fd8f3 Mon Sep 17 00:00:00 2001 From: Ellis Hoag Date: Sat, 27 Aug 2022 15:21:46 -0700 Subject: [PATCH 203/586] Lint against untranslatable diagnostics in rustc_codegen_gcc --- compiler/rustc_codegen_gcc/src/lib.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/compiler/rustc_codegen_gcc/src/lib.rs b/compiler/rustc_codegen_gcc/src/lib.rs index 03f41d197b8f7..007d61ed51de8 100644 --- a/compiler/rustc_codegen_gcc/src/lib.rs +++ b/compiler/rustc_codegen_gcc/src/lib.rs @@ -18,6 +18,8 @@ #![recursion_limit="256"] #![warn(rust_2018_idioms)] #![warn(unused_lifetimes)] +#![deny(rustc::untranslatable_diagnostic)] +#![deny(rustc::diagnostic_outside_of_impl)] extern crate rustc_apfloat; extern crate rustc_ast; From fb488ad36605093d17ea22e9e533b2103559e376 Mon Sep 17 00:00:00 2001 From: Ellis Hoag Date: Mon, 29 Aug 2022 20:22:03 -0700 Subject: [PATCH 204/586] remove IntoDiagnosticArg impl for Option --- compiler/rustc_codegen_gcc/src/archive.rs | 2 +- compiler/rustc_codegen_gcc/src/errors.rs | 2 +- compiler/rustc_errors/src/diagnostic.rs | 9 --------- 3 files changed, 2 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_codegen_gcc/src/archive.rs b/compiler/rustc_codegen_gcc/src/archive.rs index 14a69c194e4e4..77fbb2c500e81 100644 --- a/compiler/rustc_codegen_gcc/src/archive.rs +++ b/compiler/rustc_codegen_gcc/src/archive.rs @@ -183,7 +183,7 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> { std::process::Command::new("ranlib").arg(output).status().expect("Couldn't run ranlib"); if !status.success() { - self.config.sess.emit_fatal(RanlibFailure { exit_code: status.code() }); + self.config.sess.emit_fatal(RanlibFailure { exit_code: format!("{:?}", status.code()) }); } any_members diff --git a/compiler/rustc_codegen_gcc/src/errors.rs b/compiler/rustc_codegen_gcc/src/errors.rs index 490a209ead05f..01de75976a323 100644 --- a/compiler/rustc_codegen_gcc/src/errors.rs +++ b/compiler/rustc_codegen_gcc/src/errors.rs @@ -4,7 +4,7 @@ use rustc_span::Span; #[derive(SessionDiagnostic)] #[diag(codegen_gcc::ranlib_failure)] pub(crate) struct RanlibFailure { - pub exit_code: Option + pub exit_code: String, } #[derive(SessionDiagnostic)] diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index f6af0f879ca57..1c440a0a07efc 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -114,15 +114,6 @@ impl IntoDiagnosticArg for char { } } -impl IntoDiagnosticArg for Option { - fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { - match self { - Some(t) => t.into_diagnostic_arg(), - None => DiagnosticArgValue::Str(Cow::Borrowed("None")), - } - } -} - impl IntoDiagnosticArg for Symbol { fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { self.to_ident_string().into_diagnostic_arg() From e906ea80fef37b17ac7b3630f6b248fbb0927c49 Mon Sep 17 00:00:00 2001 From: Ellis Hoag Date: Wed, 31 Aug 2022 22:02:35 -0700 Subject: [PATCH 205/586] Add wrapper type for ExitCode for use in RanlibFailure --- compiler/rustc_codegen_gcc/src/archive.rs | 2 +- compiler/rustc_codegen_gcc/src/errors.rs | 24 ++++++++++++++++++++++- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_codegen_gcc/src/archive.rs b/compiler/rustc_codegen_gcc/src/archive.rs index 77fbb2c500e81..ac0342f6b80a0 100644 --- a/compiler/rustc_codegen_gcc/src/archive.rs +++ b/compiler/rustc_codegen_gcc/src/archive.rs @@ -183,7 +183,7 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> { std::process::Command::new("ranlib").arg(output).status().expect("Couldn't run ranlib"); if !status.success() { - self.config.sess.emit_fatal(RanlibFailure { exit_code: format!("{:?}", status.code()) }); + self.config.sess.emit_fatal(RanlibFailure::new(status.code())); } any_members diff --git a/compiler/rustc_codegen_gcc/src/errors.rs b/compiler/rustc_codegen_gcc/src/errors.rs index 01de75976a323..b5fc789c27918 100644 --- a/compiler/rustc_codegen_gcc/src/errors.rs +++ b/compiler/rustc_codegen_gcc/src/errors.rs @@ -1,10 +1,32 @@ +use rustc_errors::{DiagnosticArgValue, IntoDiagnosticArg}; use rustc_macros::SessionDiagnostic; use rustc_span::Span; +use std::borrow::Cow; + +struct ExitCode { + pub exit_code: Option, +} + +impl IntoDiagnosticArg for ExitCode { + fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { + match self.exit_code { + Some(t) => t.into_diagnostic_arg(), + None => DiagnosticArgValue::Str(Cow::Borrowed("None")), + } + } +} #[derive(SessionDiagnostic)] #[diag(codegen_gcc::ranlib_failure)] pub(crate) struct RanlibFailure { - pub exit_code: String, + exit_code: ExitCode, +} + +impl RanlibFailure { + pub fn new(exit_code: Option) -> Self { + let exit_code = ExitCode{ exit_code }; + RanlibFailure { exit_code } + } } #[derive(SessionDiagnostic)] From 6fdfcb35471e2b8a90aeb668b34e1fe5c7250c4c Mon Sep 17 00:00:00 2001 From: Ellis Hoag Date: Wed, 31 Aug 2022 22:03:05 -0700 Subject: [PATCH 206/586] lint type --- compiler/rustc_codegen_gcc/src/errors.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_codegen_gcc/src/errors.rs b/compiler/rustc_codegen_gcc/src/errors.rs index b5fc789c27918..938c0a74af38a 100644 --- a/compiler/rustc_codegen_gcc/src/errors.rs +++ b/compiler/rustc_codegen_gcc/src/errors.rs @@ -46,7 +46,7 @@ pub(crate) struct LinkageConstOrMutType { #[derive(SessionDiagnostic)] #[diag(codegen_gcc::lto_not_supported)] -pub(crate) struct LTONotSupported {} +pub(crate) struct LTONotSupported; #[derive(SessionDiagnostic)] #[diag(codegen_gcc::unwinding_inline_asm)] From 249e46bfbae66d18a96771dd2c3bdaf0f8fc25b4 Mon Sep 17 00:00:00 2001 From: Ellis Hoag Date: Sun, 11 Sep 2022 16:43:18 -0700 Subject: [PATCH 207/586] Add monomorphization errors --- compiler/rustc_codegen_gcc/src/errors.rs | 198 ++++++++++++++++- .../rustc_codegen_gcc/src/intrinsic/mod.rs | 13 +- .../rustc_codegen_gcc/src/intrinsic/simd.rs | 203 ++++++------------ .../locales/en-US/codegen_gcc.ftl | 57 +++++ 4 files changed, 318 insertions(+), 153 deletions(-) diff --git a/compiler/rustc_codegen_gcc/src/errors.rs b/compiler/rustc_codegen_gcc/src/errors.rs index 938c0a74af38a..a70ebf62da3e9 100644 --- a/compiler/rustc_codegen_gcc/src/errors.rs +++ b/compiler/rustc_codegen_gcc/src/errors.rs @@ -1,6 +1,7 @@ use rustc_errors::{DiagnosticArgValue, IntoDiagnosticArg}; use rustc_macros::SessionDiagnostic; -use rustc_span::Span; +use rustc_middle::ty::Ty; +use rustc_span::{Span, Symbol}; use std::borrow::Cow; struct ExitCode { @@ -29,6 +30,201 @@ impl RanlibFailure { } } +#[derive(SessionDiagnostic)] +#[diag(codegen_gcc::invalid_monomorphization_basic_integer, code = "E0511")] +pub(crate) struct InvalidMonomorphizationBasicInteger<'a> { + #[primary_span] + pub span: Span, + pub name: Symbol, + pub ty: Ty<'a>, +} + +#[derive(SessionDiagnostic)] +#[diag(codegen_gcc::invalid_monomorphization_invalid_float_vector, code = "E0511")] +pub(crate) struct InvalidMonomorphizationInvalidFloatVector<'a> { + #[primary_span] + pub span: Span, + pub name: Symbol, + pub elem_ty: &'a str, + pub vec_ty: Ty<'a>, +} + +#[derive(SessionDiagnostic)] +#[diag(codegen_gcc::invalid_monomorphization_not_float, code = "E0511")] +pub(crate) struct InvalidMonomorphizationNotFloat<'a> { + #[primary_span] + pub span: Span, + pub name: Symbol, + pub ty: Ty<'a>, +} + +#[derive(SessionDiagnostic)] +#[diag(codegen_gcc::invalid_monomorphization_unrecognized, code = "E0511")] +pub(crate) struct InvalidMonomorphizationUnrecognized { + #[primary_span] + pub span: Span, + pub name: Symbol, +} + +#[derive(SessionDiagnostic)] +#[diag(codegen_gcc::invalid_monomorphization_expected_signed_unsigned, code = "E0511")] +pub(crate) struct InvalidMonomorphizationExpectedSignedUnsigned<'a> { + #[primary_span] + pub span: Span, + pub name: Symbol, + pub elem_ty: Ty<'a>, + pub vec_ty: Ty<'a>, +} + +#[derive(SessionDiagnostic)] +#[diag(codegen_gcc::invalid_monomorphization_unsupported_element, code = "E0511")] +pub(crate) struct InvalidMonomorphizationUnsupportedElement<'a> { + #[primary_span] + pub span: Span, + pub name: Symbol, + pub in_ty: Ty<'a>, + pub elem_ty: Ty<'a>, + pub ret_ty: Ty<'a>, +} + +#[derive(SessionDiagnostic)] +#[diag(codegen_gcc::invalid_monomorphization_invalid_bitmask, code = "E0511")] +pub(crate) struct InvalidMonomorphizationInvalidBitmask<'a> { + #[primary_span] + pub span: Span, + pub name: Symbol, + pub ty: Ty<'a>, + pub expected_int_bits: u64, + pub expected_bytes: u64, +} + +#[derive(SessionDiagnostic)] +#[diag(codegen_gcc::invalid_monomorphization_simd_shuffle, code = "E0511")] +pub(crate) struct InvalidMonomorphizationSimdShuffle<'a> { + #[primary_span] + pub span: Span, + pub name: Symbol, + pub ty: Ty<'a>, +} + +#[derive(SessionDiagnostic)] +#[diag(codegen_gcc::invalid_monomorphization_expected_simd, code = "E0511")] +pub(crate) struct InvalidMonomorphizationExpectedSimd<'a> { + #[primary_span] + pub span: Span, + pub name: Symbol, + pub position: &'a str, + pub found_ty: Ty<'a>, +} + +#[derive(SessionDiagnostic)] +#[diag(codegen_gcc::invalid_monomorphization_mask_type, code = "E0511")] +pub(crate) struct InvalidMonomorphizationMaskType<'a> { + #[primary_span] + pub span: Span, + pub name: Symbol, + pub ty: Ty<'a>, +} + +#[derive(SessionDiagnostic)] +#[diag(codegen_gcc::invalid_monomorphization_return_length, code = "E0511")] +pub(crate) struct InvalidMonomorphizationReturnLength<'a> { + #[primary_span] + pub span: Span, + pub name: Symbol, + pub in_len: u64, + pub ret_ty: Ty<'a>, + pub out_len: u64, +} + +#[derive(SessionDiagnostic)] +#[diag(codegen_gcc::invalid_monomorphization_return_length_input_type, code = "E0511")] +pub(crate) struct InvalidMonomorphizationReturnLengthInputType<'a> { + #[primary_span] + pub span: Span, + pub name: Symbol, + pub in_len: u64, + pub in_ty: Ty<'a>, + pub ret_ty: Ty<'a>, + pub out_len: u64, +} + +#[derive(SessionDiagnostic)] +#[diag(codegen_gcc::invalid_monomorphization_return_element, code = "E0511")] +pub(crate) struct InvalidMonomorphizationReturnElement<'a> { + #[primary_span] + pub span: Span, + pub name: Symbol, + pub in_elem: Ty<'a>, + pub in_ty: Ty<'a>, + pub ret_ty: Ty<'a>, + pub out_ty: Ty<'a>, +} + +#[derive(SessionDiagnostic)] +#[diag(codegen_gcc::invalid_monomorphization_return_type, code = "E0511")] +pub(crate) struct InvalidMonomorphizationReturnType<'a> { + #[primary_span] + pub span: Span, + pub name: Symbol, + pub in_elem: Ty<'a>, + pub in_ty: Ty<'a>, + pub ret_ty: Ty<'a>, +} + +#[derive(SessionDiagnostic)] +#[diag(codegen_gcc::invalid_monomorphization_inserted_type, code = "E0511")] +pub(crate) struct InvalidMonomorphizationInsertedType<'a> { + #[primary_span] + pub span: Span, + pub name: Symbol, + pub in_elem: Ty<'a>, + pub in_ty: Ty<'a>, + pub out_ty: Ty<'a>, +} + +#[derive(SessionDiagnostic)] +#[diag(codegen_gcc::invalid_monomorphization_return_integer_type, code = "E0511")] +pub(crate) struct InvalidMonomorphizationReturnIntegerType<'a> { + #[primary_span] + pub span: Span, + pub name: Symbol, + pub ret_ty: Ty<'a>, + pub out_ty: Ty<'a>, +} + +#[derive(SessionDiagnostic)] +#[diag(codegen_gcc::invalid_monomorphization_mismatched_lengths, code = "E0511")] +pub(crate) struct InvalidMonomorphizationMismatchedLengths { + #[primary_span] + pub span: Span, + pub name: Symbol, + pub m_len: u64, + pub v_len: u64, +} + +#[derive(SessionDiagnostic)] +#[diag(codegen_gcc::invalid_monomorphization_unsupported_cast, code = "E0511")] +pub(crate) struct InvalidMonomorphizationUnsupportedCast<'a> { + #[primary_span] + pub span: Span, + pub name: Symbol, + pub in_ty: Ty<'a>, + pub in_elem: Ty<'a>, + pub ret_ty: Ty<'a>, + pub out_elem: Ty<'a>, +} + +#[derive(SessionDiagnostic)] +#[diag(codegen_gcc::invalid_monomorphization_unsupported_operation, code = "E0511")] +pub(crate) struct InvalidMonomorphizationUnsupportedOperation<'a> { + #[primary_span] + pub span: Span, + pub name: Symbol, + pub in_ty: Ty<'a>, + pub in_elem: Ty<'a>, +} + #[derive(SessionDiagnostic)] #[diag(codegen_gcc::layout_size_overflow)] pub(crate) struct LayoutSizeOverflow { diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs index 02cedd4646bbd..cc9c90c242709 100644 --- a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs +++ b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs @@ -4,7 +4,7 @@ mod simd; use gccjit::{ComparisonOp, Function, RValue, ToRValue, Type, UnaryOp, FunctionType}; use rustc_codegen_ssa::MemFlags; use rustc_codegen_ssa::base::wants_msvc_seh; -use rustc_codegen_ssa::common::{IntPredicate, span_invalid_monomorphization_error}; +use rustc_codegen_ssa::common::IntPredicate; use rustc_codegen_ssa::mir::operand::{OperandRef, OperandValue}; use rustc_codegen_ssa::mir::place::PlaceRef; use rustc_codegen_ssa::traits::{ArgAbiMethods, BaseTypeMethods, BuilderMethods, ConstMethods, IntrinsicCallMethods}; @@ -20,6 +20,7 @@ use crate::abi::GccType; use crate::builder::Builder; use crate::common::{SignType, TypeReflection}; use crate::context::CodegenCx; +use crate::errors::InvalidMonomorphizationBasicInteger; use crate::type_of::LayoutGccExt; use crate::intrinsic::simd::generic_simd_intrinsic; @@ -242,15 +243,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { _ => bug!(), }, None => { - span_invalid_monomorphization_error( - tcx.sess, - span, - &format!( - "invalid monomorphization of `{}` intrinsic: \ - expected basic integer type, found `{}`", - name, ty - ), - ); + tcx.sess.emit_err(InvalidMonomorphizationBasicInteger { span, name, ty }); return; } } diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs b/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs index 2401f3350186e..22bd0a1de8230 100644 --- a/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs +++ b/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs @@ -2,7 +2,7 @@ use std::cmp::Ordering; use gccjit::{BinaryOp, RValue, Type, ToRValue}; use rustc_codegen_ssa::base::compare_simd_types; -use rustc_codegen_ssa::common::{TypeKind, span_invalid_monomorphization_error}; +use rustc_codegen_ssa::common::TypeKind; use rustc_codegen_ssa::mir::operand::OperandRef; use rustc_codegen_ssa::mir::place::PlaceRef; use rustc_codegen_ssa::traits::{BaseTypeMethods, BuilderMethods}; @@ -14,43 +14,48 @@ use rustc_span::{Span, Symbol, sym}; use rustc_target::abi::Align; use crate::builder::Builder; +use crate::errors::{ + InvalidMonomorphizationInvalidFloatVector, + InvalidMonomorphizationNotFloat, + InvalidMonomorphizationUnrecognized, + InvalidMonomorphizationExpectedSignedUnsigned, + InvalidMonomorphizationUnsupportedElement, + InvalidMonomorphizationInvalidBitmask, + InvalidMonomorphizationSimdShuffle, + InvalidMonomorphizationExpectedSimd, + InvalidMonomorphizationMaskType, + InvalidMonomorphizationReturnLength, + InvalidMonomorphizationReturnLengthInputType, + InvalidMonomorphizationReturnElement, + InvalidMonomorphizationReturnType, + InvalidMonomorphizationInsertedType, + InvalidMonomorphizationReturnIntegerType, + InvalidMonomorphizationMismatchedLengths, + InvalidMonomorphizationUnsupportedCast, + InvalidMonomorphizationUnsupportedOperation +}; use crate::intrinsic; pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>, name: Symbol, callee_ty: Ty<'tcx>, args: &[OperandRef<'tcx, RValue<'gcc>>], ret_ty: Ty<'tcx>, llret_ty: Type<'gcc>, span: Span) -> Result, ()> { // macros for error handling: - #[allow(unused_macro_rules)] - macro_rules! emit_error { - ($msg: tt) => { - emit_error!($msg, ) - }; - ($msg: tt, $($fmt: tt)*) => { - span_invalid_monomorphization_error( - bx.sess(), span, - &format!(concat!("invalid monomorphization of `{}` intrinsic: ", $msg), - name, $($fmt)*)); - } - } - macro_rules! return_error { - ($($fmt: tt)*) => { + ($err:expr) => { { - emit_error!($($fmt)*); + bx.sess().emit_err($err); return Err(()); } } } - macro_rules! require { - ($cond: expr, $($fmt: tt)*) => { + ($cond:expr, $err:expr) => { if !$cond { - return_error!($($fmt)*); + return_error!($err); } - }; + } } - macro_rules! require_simd { ($ty: expr, $position: expr) => { - require!($ty.is_simd(), "expected SIMD {} type, found non-SIMD `{}`", $position, $ty) + require!($ty.is_simd(), InvalidMonomorphizationExpectedSimd { span, name, position: $position, found_ty: $ty }) }; } @@ -82,10 +87,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>, bx.load(int_ty, ptr, Align::ONE) } _ => return_error!( - "invalid bitmask `{}`, expected `u{}` or `[u8; {}]`", - mask_ty, - expected_int_bits, - expected_bytes + InvalidMonomorphizationInvalidBitmask { span, name, ty: mask_ty, expected_int_bits, expected_bytes } ), }; @@ -127,18 +129,11 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>, let (out_len, out_ty) = ret_ty.simd_size_and_type(bx.tcx()); require!( in_len == out_len, - "expected return type with length {} (same as input type `{}`), \ - found `{}` with length {}", - in_len, - in_ty, - ret_ty, - out_len + InvalidMonomorphizationReturnLengthInputType { span, name, in_len, in_ty, ret_ty, out_len } ); require!( bx.type_kind(bx.element_type(llret_ty)) == TypeKind::Integer, - "expected return type with integer elements, found `{}` with non-integer `{}`", - ret_ty, - out_ty + InvalidMonomorphizationReturnIntegerType {span, name, ret_ty, out_ty} ); return Ok(compare_simd_types( @@ -163,8 +158,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>, }) } _ => return_error!( - "simd_shuffle index must be an array of `u32`, got `{}`", - args[2].layout.ty + InvalidMonomorphizationSimdShuffle { span, name, ty: args[2].layout.ty } ), } } @@ -179,19 +173,11 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>, let (out_len, out_ty) = ret_ty.simd_size_and_type(bx.tcx()); require!( out_len == n, - "expected return type of length {}, found `{}` with length {}", - n, - ret_ty, - out_len + InvalidMonomorphizationReturnLength { span, name, in_len: n, ret_ty, out_len } ); require!( in_elem == out_ty, - "expected return element type `{}` (element of input `{}`), \ - found `{}` with element type `{}`", - in_elem, - in_ty, - ret_ty, - out_ty + InvalidMonomorphizationReturnElement { span, name, in_elem, in_ty, ret_ty, out_ty } ); let vector = args[2].immediate(); @@ -207,10 +193,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>, if name == sym::simd_insert { require!( in_elem == arg_tys[2], - "expected inserted type `{}` (element of input `{}`), found `{}`", - in_elem, - in_ty, - arg_tys[2] + InvalidMonomorphizationInsertedType { span, name, in_elem, in_ty, out_ty: arg_tys[2] } ); let vector = args[0].immediate(); let index = args[1].immediate(); @@ -263,10 +246,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>, if name == sym::simd_extract { require!( ret_ty == in_elem, - "expected return type `{}` (element of input `{}`), found `{}`", - in_elem, - in_ty, - ret_ty + InvalidMonomorphizationReturnType { span, name, in_elem, in_ty, ret_ty } ); let vector = args[0].immediate(); return Ok(bx.context.new_vector_access(None, vector, args[1].immediate()).to_rvalue()); @@ -279,13 +259,11 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>, let (v_len, _) = arg_tys[1].simd_size_and_type(bx.tcx()); require!( m_len == v_len, - "mismatched lengths: mask length `{}` != other vector length `{}`", - m_len, - v_len + InvalidMonomorphizationMismatchedLengths { span, name, m_len, v_len } ); match m_elem_ty.kind() { ty::Int(_) => {} - _ => return_error!("mask element type is `{}`, expected `i_`", m_elem_ty), + _ => return_error!(InvalidMonomorphizationMaskType { span, name, ty: m_elem_ty }), } return Ok(bx.vector_select(args[0].immediate(), args[1].immediate(), args[2].immediate())); } @@ -295,12 +273,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>, let (out_len, out_elem) = ret_ty.simd_size_and_type(bx.tcx()); require!( in_len == out_len, - "expected return type with length {} (same as input type `{}`), \ - found `{}` with length {}", - in_len, - in_ty, - ret_ty, - out_len + InvalidMonomorphizationReturnLengthInputType { span, name, in_len, in_ty, ret_ty, out_len } ); // casting cares about nominal type, not just structural type if in_elem == out_elem { @@ -412,13 +385,8 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>, } _ => { /* Unsupported. Fallthrough. */ } } - require!( - false, - "unsupported cast from `{}` with element `{}` to `{}` with element `{}`", - in_ty, - in_elem, - ret_ty, - out_elem + return_error!( + InvalidMonomorphizationUnsupportedCast { span, name, in_ty, in_elem, ret_ty, out_elem } ); } @@ -431,10 +399,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>, })* _ => {}, } - require!(false, - "unsupported operation on `{}` with element `{}`", - in_ty, - in_elem) + return_error!(InvalidMonomorphizationUnsupportedOperation { span, name, in_ty, in_elem }) })* } } @@ -448,23 +413,14 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>, span: Span, args: &[OperandRef<'tcx, RValue<'gcc>>], ) -> Result, ()> { - macro_rules! emit_error { - ($msg: tt, $($fmt: tt)*) => { - span_invalid_monomorphization_error( - bx.sess(), span, - &format!(concat!("invalid monomorphization of `{}` intrinsic: ", $msg), - name, $($fmt)*)); - } - } macro_rules! return_error { - ($($fmt: tt)*) => { + ($err:expr) => { { - emit_error!($($fmt)*); + bx.sess().emit_err($err); return Err(()); } } } - let (elem_ty_str, elem_ty) = if let ty::Float(f) = in_elem.kind() { let elem_ty = bx.cx.type_float_from_ty(*f); @@ -472,16 +428,13 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>, 32 => ("f32", elem_ty), 64 => ("f64", elem_ty), _ => { - return_error!( - "unsupported element type `{}` of floating-point vector `{}`", - f.name_str(), - in_ty - ); + // Can we pass elem_ty directly? + return_error!(InvalidMonomorphizationInvalidFloatVector { span, name, elem_ty: f.name_str(), vec_ty: in_ty }); } } } else { - return_error!("`{}` is not a floating-point type", in_ty); + return_error!(InvalidMonomorphizationNotFloat { span, name, ty: in_ty }); }; let vec_ty = bx.cx.type_vector(elem_ty, in_len); @@ -504,7 +457,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>, sym::simd_fsqrt => ("sqrt", bx.type_func(&[vec_ty], vec_ty)), sym::simd_round => ("round", bx.type_func(&[vec_ty], vec_ty)), sym::simd_trunc => ("trunc", bx.type_func(&[vec_ty], vec_ty)), - _ => return_error!("unrecognized intrinsic `{}`", name), + _ => return_error!(InvalidMonomorphizationUnrecognized { span, name }) }; let llvm_name = &format!("llvm.{0}.v{1}{2}", intr_name, in_len, elem_ty_str); let function = intrinsic::llvm::intrinsic(llvm_name, &bx.cx); @@ -557,10 +510,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>, })* _ => {}, } - require!(false, - "unsupported operation on `{}` with element `{}`", - in_ty, - in_elem) + return_error!(InvalidMonomorphizationUnsupportedOperation { span, name, in_ty, in_elem }) })* } } @@ -579,12 +529,12 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>, ty::Int(i) => (true, i.bit_width().unwrap_or(ptr_bits), bx.cx.type_int_from_ty(i)), ty::Uint(i) => (false, i.bit_width().unwrap_or(ptr_bits), bx.cx.type_uint_from_ty(i)), _ => { - return_error!( - "expected element type `{}` of vector type `{}` \ - to be a signed or unsigned integer type", - arg_tys[0].simd_size_and_type(bx.tcx()).1, - arg_tys[0] - ); + return_error!(InvalidMonomorphizationExpectedSignedUnsigned { + span, + name, + elem_ty: arg_tys[0].simd_size_and_type(bx.tcx()).1, + vec_ty: arg_tys[0], + }); } }; let builtin_name = @@ -617,10 +567,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>, if name == sym::$name { require!( ret_ty == in_elem, - "expected return type `{}` (element of input `{}`), found `{}`", - in_elem, - in_ty, - ret_ty + InvalidMonomorphizationReturnType { span, name, in_elem, in_ty, ret_ty } ); return match in_elem.kind() { ty::Int(_) | ty::Uint(_) => { @@ -644,13 +591,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>, Ok(bx.vector_reduce_op(args[0].immediate(), $vec_op)) } } - _ => return_error!( - "unsupported {} from `{}` with element `{}` to `{}`", - sym::$name, - in_ty, - in_elem, - ret_ty - ), + _ => return_error!(InvalidMonomorphizationUnsupportedElement { span, name, in_ty, elem_ty: in_elem, ret_ty }), }; } }; @@ -676,20 +617,11 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>, if name == sym::$name { require!( ret_ty == in_elem, - "expected return type `{}` (element of input `{}`), found `{}`", - in_elem, - in_ty, - ret_ty + InvalidMonomorphizationReturnType { span, name, in_elem, in_ty, ret_ty } ); return match in_elem.kind() { ty::Int(_) | ty::Uint(_) | ty::Float(_) => Ok(bx.$reduction(args[0].immediate())), - _ => return_error!( - "unsupported {} from `{}` with element `{}` to `{}`", - sym::$name, - in_ty, - in_elem, - ret_ty - ), + _ => return_error!(InvalidMonomorphizationUnsupportedElement { span, name, in_ty, elem_ty: in_elem, ret_ty }), }; } }; @@ -704,22 +636,13 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>, let input = if !$boolean { require!( ret_ty == in_elem, - "expected return type `{}` (element of input `{}`), found `{}`", - in_elem, - in_ty, - ret_ty + InvalidMonomorphizationReturnType { span, name, in_elem, in_ty, ret_ty } ); args[0].immediate() } else { match in_elem.kind() { ty::Int(_) | ty::Uint(_) => {} - _ => return_error!( - "unsupported {} from `{}` with element `{}` to `{}`", - sym::$name, - in_ty, - in_elem, - ret_ty - ), + _ => return_error!(InvalidMonomorphizationUnsupportedElement { span, name, in_ty, elem_ty: in_elem, ret_ty }), } // boolean reductions operate on vectors of i1s: @@ -733,11 +656,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>, Ok(if !$boolean { r } else { bx.zext(r, bx.type_bool()) }) } _ => return_error!( - "unsupported {} from `{}` with element `{}` to `{}`", - sym::$name, - in_ty, - in_elem, - ret_ty + InvalidMonomorphizationUnsupportedElement { span, name, in_ty, elem_ty: in_elem, ret_ty } ), }; } diff --git a/compiler/rustc_error_messages/locales/en-US/codegen_gcc.ftl b/compiler/rustc_error_messages/locales/en-US/codegen_gcc.ftl index 70072a073cd1d..2497d55032396 100644 --- a/compiler/rustc_error_messages/locales/en-US/codegen_gcc.ftl +++ b/compiler/rustc_error_messages/locales/en-US/codegen_gcc.ftl @@ -12,3 +12,60 @@ codegen_gcc_unwinding_inline_asm = codegen_gcc_lto_not_supported = LTO is not supported. You may get a linker error. + +codegen_gcc_invalid_monomorphization_basic_integer = + invalid monomorphization of `{$name}` intrinsic: expected basic integer type, found `{$ty}` + +codegen_gcc_invalid_monomorphization_invalid_float_vector = + invalid monomorphization of `{$name}` intrinsic: unsupported element type `{$elem_ty}` of floating-point vector `{$vec_ty}` + +codegen_gcc_invalid_monomorphization_not_float = + invalid monomorphization of `{$name}` intrinsic: `{$ty}` is not a floating-point type + +codegen_gcc_invalid_monomorphization_unrecognized = + invalid monomorphization of `{$name}` intrinsic: unrecognized intrinsic `{$name}` + +codegen_gcc_invalid_monomorphization_expected_signed_unsigned = + invalid monomorphization of `{$name}` intrinsic: expected element type `{$elem_ty}` of vector type `{$vec_ty}` to be a signed or unsigned integer type + +codegen_gcc_invalid_monomorphization_unsupported_element = + invalid monomorphization of `{$name}` intrinsic: unsupported {$name} from `{$in_ty}` with element `{$elem_ty}` to `{$ret_ty}` + +codegen_gcc_invalid_monomorphization_invalid_bitmask = + invalid monomorphization of `{$name}` intrinsic: invalid bitmask `{ty}`, expected `u{$expected_int_bits}` or `[u8; {$expected_bytes}]` + +codegen_gcc_invalid_monomorphization_simd_shuffle = + invalid monomorphization of `{$name}` intrinsic: simd_shuffle index must be an array of `u32`, got `{$ty}` + +codegen_gcc_invalid_monomorphization_expected_simd = + invalid monomorphization of `{$name}` intrinsic: expected SIMD {$expected_ty} type, found non-SIMD `{$found_ty}` + +codegen_gcc_invalid_monomorphization_mask_type = + invalid monomorphization of `{$name}` intrinsic: mask element type is `{$ty}`, expected `i_` + +codegen_gcc_invalid_monomorphization_return_length = + invalid monomorphization of `{$name}` intrinsic: expected return type of length {$in_len}, found `{$ret_ty}` with length {$out_len} + +codegen_gcc_invalid_monomorphization_return_length_input_type = + invalid monomorphization of `{$name}` intrinsic: expected return type with length {$in_len} (same as input type `{$in_ty}`), found `{$ret_ty}` with length {$out_len} + +codegen_gcc_invalid_monomorphization_return_element = + invalid monomorphization of `{$name}` intrinsic: expected return element type `{$in_elem}` (element of input `{$in_ty}`), found `{$ret_ty}` with element type `{$out_ty}` + +codegen_gcc_invalid_monomorphization_return_type = + invalid monomorphization of `{$name}` intrinsic: expected return type `{$in_elem}` (element of input `{$in_ty}`), found `{$ret_ty}` + +codegen_gcc_invalid_monomorphization_inserted_type = + invalid monomorphization of `{$name}` intrinsic: expected inserted type `{$in_elem}` (element of input `{$in_ty}`), found `{$out_ty}` + +codegen_gcc_invalid_monomorphization_return_integer_type = + invalid monomorphization of `{$name}` intrinsic: expected return type with integer elements, found `{$ret_ty}` with non-integer `{$out_ty}` + +codegen_gcc_invalid_monomorphization_mismatched_lengths = + invalid monomorphization of `{$name}` intrinsic: mismatched lengths: mask length `{$m_len}` != other vector length `{$v_len}` + +codegen_gcc_invalid_monomorphization_unsupported_cast = + invalid monomorphization of `{$name}` intrinsic: unsupported cast from `{$in_ty}` with element `{$in_elem}` to `{$ret_ty}` with element `{$out_elem}` + +codegen_gcc_invalid_monomorphization_unsupported_operation = + invalid monomorphization of `{$name}` intrinsic: unsupported operation on `{$in_ty}` with element `{$in_elem}` From 6e22c0a8e1799e0d14f4845060f6857d8921b283 Mon Sep 17 00:00:00 2001 From: Ellis Hoag Date: Sun, 11 Sep 2022 17:34:51 -0700 Subject: [PATCH 208/586] impl SessionDiagnostic for LayoutError and Spanned --- compiler/rustc_codegen_gcc/src/context.rs | 19 ++++++++++++++++++- compiler/rustc_middle/src/ty/layout.rs | 11 ++++++++++- compiler/rustc_session/src/session.rs | 23 ++++++++++++++++++++++- 3 files changed, 50 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_codegen_gcc/src/context.rs b/compiler/rustc_codegen_gcc/src/context.rs index 187e4c689ec47..14de0cee28e9d 100644 --- a/compiler/rustc_codegen_gcc/src/context.rs +++ b/compiler/rustc_codegen_gcc/src/context.rs @@ -13,7 +13,7 @@ use rustc_middle::mir::mono::CodegenUnit; use rustc_middle::ty::{self, Instance, ParamEnv, PolyExistentialTraitRef, Ty, TyCtxt}; use rustc_middle::ty::layout::{FnAbiError, FnAbiOfHelpers, FnAbiRequest, HasParamEnv, HasTyCtxt, LayoutError, TyAndLayout, LayoutOfHelpers}; use rustc_session::Session; -use rustc_span::Span; +use rustc_span::{Span, source_map::respan}; use rustc_target::abi::{call::FnAbi, HasDataLayout, PointeeInfo, Size, TargetDataLayout, VariantIdx}; use rustc_target::spec::{HasTargetSpec, Target, TlsModel}; @@ -478,6 +478,23 @@ impl<'gcc, 'tcx> LayoutOfHelpers<'tcx> for CodegenCx<'gcc, 'tcx> { #[inline] fn handle_layout_err(&self, err: LayoutError<'tcx>, span: Span, ty: Ty<'tcx>) -> ! { if let LayoutError::SizeOverflow(_) = err { + let _ = respan(span, err); + // error: lifetime may not live long enough + // --> src/context.rs:483:13 + // | + // 475 | impl<'gcc, 'tcx> LayoutOfHelpers<'tcx> for CodegenCx<'gcc, 'tcx> { + // | ---- ---- lifetime `'tcx` defined here + // | | + // | lifetime `'gcc` defined here + // ... + // 483 | self.sess().emit_fatal(respan(span, err)) + // | ^^^^^^^^^^^ argument requires that `'gcc` must outlive `'tcx` + // | + // = help: consider adding the following bound: `'gcc: 'tcx` + // = note: requirement occurs because of the type `CodegenCx<'_, '_>`, which makes the generic argument `'_` invariant + // = note: the struct `CodegenCx<'gcc, 'tcx>` is invariant over the parameter `'gcc` + // = help: see for more information about variance + // self.sess().emit_fatal(respan(span, err)) self.sess().emit_fatal(LayoutSizeOverflow { span, error: err.to_string() }) } else { span_bug!(span, "failed to get layout for `{}`: {}", ty, err) diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index cc820d9eb2d9e..322841888889d 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -7,12 +7,15 @@ use crate::ty::{ }; use rustc_ast as ast; use rustc_attr as attr; +use rustc_errors::Handler; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_hir::lang_items::LangItem; use rustc_index::bit_set::BitSet; use rustc_index::vec::{Idx, IndexVec}; -use rustc_session::{config::OptLevel, DataTypeKind, FieldInfo, SizeKind, VariantInfo}; +use rustc_session::{ + config::OptLevel, DataTypeKind, FieldInfo, SessionDiagnostic, SizeKind, VariantInfo, +}; use rustc_span::symbol::Symbol; use rustc_span::{Span, DUMMY_SP}; use rustc_target::abi::call::{ @@ -206,6 +209,12 @@ pub enum LayoutError<'tcx> { NormalizationFailure(Ty<'tcx>, NormalizationError<'tcx>), } +impl<'a> SessionDiagnostic<'a, !> for LayoutError<'a> { + fn into_diagnostic(self, handler: &'a Handler) -> rustc_errors::DiagnosticBuilder<'a, !> { + handler.struct_fatal(self.to_string()) + } +} + impl<'tcx> fmt::Display for LayoutError<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match *self { diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 0142e98176633..21c1ff999f665 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -33,7 +33,7 @@ use rustc_errors::{ use rustc_macros::HashStable_Generic; pub use rustc_span::def_id::StableCrateId; use rustc_span::edition::Edition; -use rustc_span::source_map::{FileLoader, RealFileLoader, SourceMap, Span}; +use rustc_span::source_map::{FileLoader, RealFileLoader, SourceMap, Span, Spanned}; use rustc_span::{sym, SourceFileHashAlgorithm, Symbol}; use rustc_target::asm::InlineAsmArch; use rustc_target::spec::{CodeModel, PanicStrategy, RelocModel, RelroLevel}; @@ -223,6 +223,27 @@ pub struct PerfStats { pub normalize_projection_ty: AtomicUsize, } +/// Trait implemented by error types. This should not be implemented manually. Instead, use +/// `#[derive(SessionDiagnostic)]` -- see [rustc_macros::SessionDiagnostic]. +#[rustc_diagnostic_item = "SessionDiagnostic"] +pub trait SessionDiagnostic<'a, T: EmissionGuarantee = ErrorGuaranteed> { + /// Write out as a diagnostic out of `Handler`. + #[must_use] + fn into_diagnostic(self, handler: &'a Handler) -> DiagnosticBuilder<'a, T>; +} + +impl<'a, T, E> SessionDiagnostic<'a, E> for Spanned +where + T: SessionDiagnostic<'a, E>, + E: EmissionGuarantee, +{ + fn into_diagnostic(self, handler: &'a Handler) -> rustc_errors::DiagnosticBuilder<'a, E> { + let mut diag = self.node.into_diagnostic(handler); + diag.set_span(self.span); + diag + } +} + impl Session { pub fn miri_unleashed_feature(&self, span: Span, feature_gate: Option) { self.miri_unleashed_features.lock().push((span, feature_gate)); From a0be6c49c89556c9d596c9f430ced9d61c16e6d2 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Sat, 24 Sep 2022 10:03:59 -0700 Subject: [PATCH 209/586] rustdoc: remove unused CSS `#main-content > .line-numbers` This selector was added in 10b937028660e079cf15735cfb5c4d58892fb10e. It became unreachable when 09150f81930e035254e58ee56f5905c2eb421617 made it so that `.line-numbers` are always nested below `.example-wrap`, even on source pages. --- src/librustdoc/html/static/css/rustdoc.css | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index 4136cb6cab33a..8691d60821504 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -1917,10 +1917,6 @@ in storage.js plus the media query with (min-width: 701px) border-bottom: 1px solid; } - #main-content > .line-numbers { - margin-top: 0; - } - .notable-traits .notable-traits-tooltiptext { left: 0; top: 100%; From 55b11cf15cfac6798bf87191c30406486f20d642 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Sat, 24 Sep 2022 10:51:37 -0700 Subject: [PATCH 210/586] rustdoc: remove unused CSS `.summary` It was added in 4d16de01d0beb84dc4a351022ea5cb587b4ab557 as part of a stability dashboard that was removed in 0a46933c4d81573e78ce16cd215ba155a3114fce. --- src/librustdoc/html/static/css/rustdoc.css | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index 4136cb6cab33a..645f0454aa27d 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -1130,10 +1130,6 @@ so that we can apply CSS-filters to change the arrow color in themes */ font-size: 1rem; } -.summary { - padding-right: 0px; -} - pre.rust .question-mark { font-weight: bold; } From 5c7e629b6378a25d3575c56a803fa1de0b2641e5 Mon Sep 17 00:00:00 2001 From: Ellis Hoag Date: Sat, 24 Sep 2022 11:05:37 -0700 Subject: [PATCH 211/586] rebase and update trait names --- compiler/rustc_codegen_gcc/src/errors.rs | 50 +++++++++---------- .../rustc_errors/src/diagnostic_builder.rs | 13 +++++ compiler/rustc_middle/src/ty/layout.rs | 8 ++- compiler/rustc_session/src/session.rs | 23 +-------- 4 files changed, 42 insertions(+), 52 deletions(-) diff --git a/compiler/rustc_codegen_gcc/src/errors.rs b/compiler/rustc_codegen_gcc/src/errors.rs index a70ebf62da3e9..a1c95e7a7f450 100644 --- a/compiler/rustc_codegen_gcc/src/errors.rs +++ b/compiler/rustc_codegen_gcc/src/errors.rs @@ -1,5 +1,5 @@ use rustc_errors::{DiagnosticArgValue, IntoDiagnosticArg}; -use rustc_macros::SessionDiagnostic; +use rustc_macros::Diagnostic; use rustc_middle::ty::Ty; use rustc_span::{Span, Symbol}; use std::borrow::Cow; @@ -17,7 +17,7 @@ impl IntoDiagnosticArg for ExitCode { } } -#[derive(SessionDiagnostic)] +#[derive(Diagnostic)] #[diag(codegen_gcc::ranlib_failure)] pub(crate) struct RanlibFailure { exit_code: ExitCode, @@ -30,7 +30,7 @@ impl RanlibFailure { } } -#[derive(SessionDiagnostic)] +#[derive(Diagnostic)] #[diag(codegen_gcc::invalid_monomorphization_basic_integer, code = "E0511")] pub(crate) struct InvalidMonomorphizationBasicInteger<'a> { #[primary_span] @@ -39,7 +39,7 @@ pub(crate) struct InvalidMonomorphizationBasicInteger<'a> { pub ty: Ty<'a>, } -#[derive(SessionDiagnostic)] +#[derive(Diagnostic)] #[diag(codegen_gcc::invalid_monomorphization_invalid_float_vector, code = "E0511")] pub(crate) struct InvalidMonomorphizationInvalidFloatVector<'a> { #[primary_span] @@ -49,7 +49,7 @@ pub(crate) struct InvalidMonomorphizationInvalidFloatVector<'a> { pub vec_ty: Ty<'a>, } -#[derive(SessionDiagnostic)] +#[derive(Diagnostic)] #[diag(codegen_gcc::invalid_monomorphization_not_float, code = "E0511")] pub(crate) struct InvalidMonomorphizationNotFloat<'a> { #[primary_span] @@ -58,7 +58,7 @@ pub(crate) struct InvalidMonomorphizationNotFloat<'a> { pub ty: Ty<'a>, } -#[derive(SessionDiagnostic)] +#[derive(Diagnostic)] #[diag(codegen_gcc::invalid_monomorphization_unrecognized, code = "E0511")] pub(crate) struct InvalidMonomorphizationUnrecognized { #[primary_span] @@ -66,7 +66,7 @@ pub(crate) struct InvalidMonomorphizationUnrecognized { pub name: Symbol, } -#[derive(SessionDiagnostic)] +#[derive(Diagnostic)] #[diag(codegen_gcc::invalid_monomorphization_expected_signed_unsigned, code = "E0511")] pub(crate) struct InvalidMonomorphizationExpectedSignedUnsigned<'a> { #[primary_span] @@ -76,7 +76,7 @@ pub(crate) struct InvalidMonomorphizationExpectedSignedUnsigned<'a> { pub vec_ty: Ty<'a>, } -#[derive(SessionDiagnostic)] +#[derive(Diagnostic)] #[diag(codegen_gcc::invalid_monomorphization_unsupported_element, code = "E0511")] pub(crate) struct InvalidMonomorphizationUnsupportedElement<'a> { #[primary_span] @@ -87,7 +87,7 @@ pub(crate) struct InvalidMonomorphizationUnsupportedElement<'a> { pub ret_ty: Ty<'a>, } -#[derive(SessionDiagnostic)] +#[derive(Diagnostic)] #[diag(codegen_gcc::invalid_monomorphization_invalid_bitmask, code = "E0511")] pub(crate) struct InvalidMonomorphizationInvalidBitmask<'a> { #[primary_span] @@ -98,7 +98,7 @@ pub(crate) struct InvalidMonomorphizationInvalidBitmask<'a> { pub expected_bytes: u64, } -#[derive(SessionDiagnostic)] +#[derive(Diagnostic)] #[diag(codegen_gcc::invalid_monomorphization_simd_shuffle, code = "E0511")] pub(crate) struct InvalidMonomorphizationSimdShuffle<'a> { #[primary_span] @@ -107,7 +107,7 @@ pub(crate) struct InvalidMonomorphizationSimdShuffle<'a> { pub ty: Ty<'a>, } -#[derive(SessionDiagnostic)] +#[derive(Diagnostic)] #[diag(codegen_gcc::invalid_monomorphization_expected_simd, code = "E0511")] pub(crate) struct InvalidMonomorphizationExpectedSimd<'a> { #[primary_span] @@ -117,7 +117,7 @@ pub(crate) struct InvalidMonomorphizationExpectedSimd<'a> { pub found_ty: Ty<'a>, } -#[derive(SessionDiagnostic)] +#[derive(Diagnostic)] #[diag(codegen_gcc::invalid_monomorphization_mask_type, code = "E0511")] pub(crate) struct InvalidMonomorphizationMaskType<'a> { #[primary_span] @@ -126,7 +126,7 @@ pub(crate) struct InvalidMonomorphizationMaskType<'a> { pub ty: Ty<'a>, } -#[derive(SessionDiagnostic)] +#[derive(Diagnostic)] #[diag(codegen_gcc::invalid_monomorphization_return_length, code = "E0511")] pub(crate) struct InvalidMonomorphizationReturnLength<'a> { #[primary_span] @@ -137,7 +137,7 @@ pub(crate) struct InvalidMonomorphizationReturnLength<'a> { pub out_len: u64, } -#[derive(SessionDiagnostic)] +#[derive(Diagnostic)] #[diag(codegen_gcc::invalid_monomorphization_return_length_input_type, code = "E0511")] pub(crate) struct InvalidMonomorphizationReturnLengthInputType<'a> { #[primary_span] @@ -149,7 +149,7 @@ pub(crate) struct InvalidMonomorphizationReturnLengthInputType<'a> { pub out_len: u64, } -#[derive(SessionDiagnostic)] +#[derive(Diagnostic)] #[diag(codegen_gcc::invalid_monomorphization_return_element, code = "E0511")] pub(crate) struct InvalidMonomorphizationReturnElement<'a> { #[primary_span] @@ -161,7 +161,7 @@ pub(crate) struct InvalidMonomorphizationReturnElement<'a> { pub out_ty: Ty<'a>, } -#[derive(SessionDiagnostic)] +#[derive(Diagnostic)] #[diag(codegen_gcc::invalid_monomorphization_return_type, code = "E0511")] pub(crate) struct InvalidMonomorphizationReturnType<'a> { #[primary_span] @@ -172,7 +172,7 @@ pub(crate) struct InvalidMonomorphizationReturnType<'a> { pub ret_ty: Ty<'a>, } -#[derive(SessionDiagnostic)] +#[derive(Diagnostic)] #[diag(codegen_gcc::invalid_monomorphization_inserted_type, code = "E0511")] pub(crate) struct InvalidMonomorphizationInsertedType<'a> { #[primary_span] @@ -183,7 +183,7 @@ pub(crate) struct InvalidMonomorphizationInsertedType<'a> { pub out_ty: Ty<'a>, } -#[derive(SessionDiagnostic)] +#[derive(Diagnostic)] #[diag(codegen_gcc::invalid_monomorphization_return_integer_type, code = "E0511")] pub(crate) struct InvalidMonomorphizationReturnIntegerType<'a> { #[primary_span] @@ -193,7 +193,7 @@ pub(crate) struct InvalidMonomorphizationReturnIntegerType<'a> { pub out_ty: Ty<'a>, } -#[derive(SessionDiagnostic)] +#[derive(Diagnostic)] #[diag(codegen_gcc::invalid_monomorphization_mismatched_lengths, code = "E0511")] pub(crate) struct InvalidMonomorphizationMismatchedLengths { #[primary_span] @@ -203,7 +203,7 @@ pub(crate) struct InvalidMonomorphizationMismatchedLengths { pub v_len: u64, } -#[derive(SessionDiagnostic)] +#[derive(Diagnostic)] #[diag(codegen_gcc::invalid_monomorphization_unsupported_cast, code = "E0511")] pub(crate) struct InvalidMonomorphizationUnsupportedCast<'a> { #[primary_span] @@ -215,7 +215,7 @@ pub(crate) struct InvalidMonomorphizationUnsupportedCast<'a> { pub out_elem: Ty<'a>, } -#[derive(SessionDiagnostic)] +#[derive(Diagnostic)] #[diag(codegen_gcc::invalid_monomorphization_unsupported_operation, code = "E0511")] pub(crate) struct InvalidMonomorphizationUnsupportedOperation<'a> { #[primary_span] @@ -225,7 +225,7 @@ pub(crate) struct InvalidMonomorphizationUnsupportedOperation<'a> { pub in_elem: Ty<'a>, } -#[derive(SessionDiagnostic)] +#[derive(Diagnostic)] #[diag(codegen_gcc::layout_size_overflow)] pub(crate) struct LayoutSizeOverflow { #[primary_span] @@ -233,18 +233,18 @@ pub(crate) struct LayoutSizeOverflow { pub error: String, } -#[derive(SessionDiagnostic)] +#[derive(Diagnostic)] #[diag(codegen_gcc::linkage_const_or_mut_type)] pub(crate) struct LinkageConstOrMutType { #[primary_span] pub span: Span } -#[derive(SessionDiagnostic)] +#[derive(Diagnostic)] #[diag(codegen_gcc::lto_not_supported)] pub(crate) struct LTONotSupported; -#[derive(SessionDiagnostic)] +#[derive(Diagnostic)] #[diag(codegen_gcc::unwinding_inline_asm)] pub(crate) struct UnwindingInlineAsm { #[primary_span] diff --git a/compiler/rustc_errors/src/diagnostic_builder.rs b/compiler/rustc_errors/src/diagnostic_builder.rs index b4ba65ca96d3b..092a77f944c09 100644 --- a/compiler/rustc_errors/src/diagnostic_builder.rs +++ b/compiler/rustc_errors/src/diagnostic_builder.rs @@ -5,6 +5,7 @@ use crate::{ }; use crate::{Handler, Level, MultiSpan, StashKey}; use rustc_lint_defs::Applicability; +use rustc_span::source_map::Spanned; use rustc_span::Span; use std::borrow::Cow; @@ -23,6 +24,18 @@ pub trait IntoDiagnostic<'a, T: EmissionGuarantee = ErrorGuaranteed> { fn into_diagnostic(self, handler: &'a Handler) -> DiagnosticBuilder<'a, T>; } +impl<'a, T, E> IntoDiagnostic<'a, E> for Spanned +where + T: IntoDiagnostic<'a, E>, + E: EmissionGuarantee, +{ + fn into_diagnostic(self, handler: &'a Handler) -> DiagnosticBuilder<'a, E> { + let mut diag = self.node.into_diagnostic(handler); + diag.set_span(self.span); + diag + } +} + /// Used for emitting structured error messages and other diagnostic information. /// /// If there is some state in a downstream crate you would like to diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 322841888889d..a0b7cf1feb5fd 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -7,15 +7,13 @@ use crate::ty::{ }; use rustc_ast as ast; use rustc_attr as attr; -use rustc_errors::Handler; +use rustc_errors::{Handler, IntoDiagnostic}; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_hir::lang_items::LangItem; use rustc_index::bit_set::BitSet; use rustc_index::vec::{Idx, IndexVec}; -use rustc_session::{ - config::OptLevel, DataTypeKind, FieldInfo, SessionDiagnostic, SizeKind, VariantInfo, -}; +use rustc_session::{config::OptLevel, DataTypeKind, FieldInfo, SizeKind, VariantInfo}; use rustc_span::symbol::Symbol; use rustc_span::{Span, DUMMY_SP}; use rustc_target::abi::call::{ @@ -209,7 +207,7 @@ pub enum LayoutError<'tcx> { NormalizationFailure(Ty<'tcx>, NormalizationError<'tcx>), } -impl<'a> SessionDiagnostic<'a, !> for LayoutError<'a> { +impl<'a> IntoDiagnostic<'a, !> for LayoutError<'a> { fn into_diagnostic(self, handler: &'a Handler) -> rustc_errors::DiagnosticBuilder<'a, !> { handler.struct_fatal(self.to_string()) } diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 21c1ff999f665..0142e98176633 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -33,7 +33,7 @@ use rustc_errors::{ use rustc_macros::HashStable_Generic; pub use rustc_span::def_id::StableCrateId; use rustc_span::edition::Edition; -use rustc_span::source_map::{FileLoader, RealFileLoader, SourceMap, Span, Spanned}; +use rustc_span::source_map::{FileLoader, RealFileLoader, SourceMap, Span}; use rustc_span::{sym, SourceFileHashAlgorithm, Symbol}; use rustc_target::asm::InlineAsmArch; use rustc_target::spec::{CodeModel, PanicStrategy, RelocModel, RelroLevel}; @@ -223,27 +223,6 @@ pub struct PerfStats { pub normalize_projection_ty: AtomicUsize, } -/// Trait implemented by error types. This should not be implemented manually. Instead, use -/// `#[derive(SessionDiagnostic)]` -- see [rustc_macros::SessionDiagnostic]. -#[rustc_diagnostic_item = "SessionDiagnostic"] -pub trait SessionDiagnostic<'a, T: EmissionGuarantee = ErrorGuaranteed> { - /// Write out as a diagnostic out of `Handler`. - #[must_use] - fn into_diagnostic(self, handler: &'a Handler) -> DiagnosticBuilder<'a, T>; -} - -impl<'a, T, E> SessionDiagnostic<'a, E> for Spanned -where - T: SessionDiagnostic<'a, E>, - E: EmissionGuarantee, -{ - fn into_diagnostic(self, handler: &'a Handler) -> rustc_errors::DiagnosticBuilder<'a, E> { - let mut diag = self.node.into_diagnostic(handler); - diag.set_span(self.span); - diag - } -} - impl Session { pub fn miri_unleashed_feature(&self, span: Span, feature_gate: Option) { self.miri_unleashed_features.lock().push((span, feature_gate)); From 2ef3d172c4c574bd58abca0e8bbe7548c313c60b Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Sat, 24 Sep 2022 13:32:19 -0500 Subject: [PATCH 212/586] Copy `bootstrap.exe` on Windows, not `bootstrap` --- src/bootstrap/dist.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index 3d03a056c1540..e02031d09bccf 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -2078,7 +2078,7 @@ impl Step for Bootstrap { let bootstrap_outdir = &builder.bootstrap_out; for file in &["bootstrap", "llvm-config-wrapper", "rustc", "rustdoc", "sccache-plus-cl"] { - tarball.add_file(bootstrap_outdir.join(file), "bootstrap/bin", 0o755); + tarball.add_file(bootstrap_outdir.join(exe(file, target)), "bootstrap/bin", 0o755); } Some(tarball.generate()) From ac97487645fdf018724f17ed1e764f2dbb4b04ba Mon Sep 17 00:00:00 2001 From: Ellis Hoag Date: Sat, 24 Sep 2022 11:36:16 -0700 Subject: [PATCH 213/586] fix lifetime error --- compiler/rustc_codegen_gcc/src/context.rs | 24 +++-------------------- compiler/rustc_codegen_gcc/src/errors.rs | 8 -------- compiler/rustc_middle/src/ty/layout.rs | 10 ++++++++-- 3 files changed, 11 insertions(+), 31 deletions(-) diff --git a/compiler/rustc_codegen_gcc/src/context.rs b/compiler/rustc_codegen_gcc/src/context.rs index 14de0cee28e9d..46ade33eb01cb 100644 --- a/compiler/rustc_codegen_gcc/src/context.rs +++ b/compiler/rustc_codegen_gcc/src/context.rs @@ -18,7 +18,6 @@ use rustc_target::abi::{call::FnAbi, HasDataLayout, PointeeInfo, Size, TargetDat use rustc_target::spec::{HasTargetSpec, Target, TlsModel}; use crate::callee::get_fn; -use crate::errors::LayoutSizeOverflow; #[derive(Clone)] pub struct FuncSig<'gcc> { @@ -294,7 +293,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { self.is_native_int_type(typ) || self.is_non_native_int_type(typ) || typ.is_compatible_with(self.bool_type) } - pub fn sess(&self) -> &Session { + pub fn sess(&self) -> &'tcx Session { &self.tcx.sess } @@ -478,24 +477,7 @@ impl<'gcc, 'tcx> LayoutOfHelpers<'tcx> for CodegenCx<'gcc, 'tcx> { #[inline] fn handle_layout_err(&self, err: LayoutError<'tcx>, span: Span, ty: Ty<'tcx>) -> ! { if let LayoutError::SizeOverflow(_) = err { - let _ = respan(span, err); - // error: lifetime may not live long enough - // --> src/context.rs:483:13 - // | - // 475 | impl<'gcc, 'tcx> LayoutOfHelpers<'tcx> for CodegenCx<'gcc, 'tcx> { - // | ---- ---- lifetime `'tcx` defined here - // | | - // | lifetime `'gcc` defined here - // ... - // 483 | self.sess().emit_fatal(respan(span, err)) - // | ^^^^^^^^^^^ argument requires that `'gcc` must outlive `'tcx` - // | - // = help: consider adding the following bound: `'gcc: 'tcx` - // = note: requirement occurs because of the type `CodegenCx<'_, '_>`, which makes the generic argument `'_` invariant - // = note: the struct `CodegenCx<'gcc, 'tcx>` is invariant over the parameter `'gcc` - // = help: see for more information about variance - // self.sess().emit_fatal(respan(span, err)) - self.sess().emit_fatal(LayoutSizeOverflow { span, error: err.to_string() }) + self.sess().emit_fatal(respan(span, err)) } else { span_bug!(span, "failed to get layout for `{}`: {}", ty, err) } @@ -513,7 +495,7 @@ impl<'gcc, 'tcx> FnAbiOfHelpers<'tcx> for CodegenCx<'gcc, 'tcx> { fn_abi_request: FnAbiRequest<'tcx>, ) -> ! { if let FnAbiError::Layout(LayoutError::SizeOverflow(_)) = err { - self.sess().emit_fatal(LayoutSizeOverflow { span, error: err.to_string() }) + self.sess().emit_fatal(respan(span, err)) } else { match fn_abi_request { FnAbiRequest::OfFnPtr { sig, extra_args } => { diff --git a/compiler/rustc_codegen_gcc/src/errors.rs b/compiler/rustc_codegen_gcc/src/errors.rs index a1c95e7a7f450..eb8528104fac3 100644 --- a/compiler/rustc_codegen_gcc/src/errors.rs +++ b/compiler/rustc_codegen_gcc/src/errors.rs @@ -225,14 +225,6 @@ pub(crate) struct InvalidMonomorphizationUnsupportedOperation<'a> { pub in_elem: Ty<'a>, } -#[derive(Diagnostic)] -#[diag(codegen_gcc::layout_size_overflow)] -pub(crate) struct LayoutSizeOverflow { - #[primary_span] - pub span: Span, - pub error: String, -} - #[derive(Diagnostic)] #[diag(codegen_gcc::linkage_const_or_mut_type)] pub(crate) struct LinkageConstOrMutType { diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index a0b7cf1feb5fd..3c523659df74e 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -7,7 +7,7 @@ use crate::ty::{ }; use rustc_ast as ast; use rustc_attr as attr; -use rustc_errors::{Handler, IntoDiagnostic}; +use rustc_errors::{DiagnosticBuilder, Handler, IntoDiagnostic}; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_hir::lang_items::LangItem; @@ -208,7 +208,7 @@ pub enum LayoutError<'tcx> { } impl<'a> IntoDiagnostic<'a, !> for LayoutError<'a> { - fn into_diagnostic(self, handler: &'a Handler) -> rustc_errors::DiagnosticBuilder<'a, !> { + fn into_diagnostic(self, handler: &'a Handler) -> DiagnosticBuilder<'a, !> { handler.struct_fatal(self.to_string()) } } @@ -3072,6 +3072,12 @@ impl<'tcx> fmt::Display for FnAbiError<'tcx> { } } +impl<'tcx> IntoDiagnostic<'tcx, !> for FnAbiError<'tcx> { + fn into_diagnostic(self, handler: &'tcx Handler) -> DiagnosticBuilder<'tcx, !> { + handler.struct_fatal(self.to_string()) + } +} + // FIXME(eddyb) maybe use something like this for an unified `fn_abi_of`, not // just for error handling. #[derive(Debug)] From ed16dbf65e55c54a6cb5eb2596a46a6639428370 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Sat, 24 Sep 2022 12:12:41 -0700 Subject: [PATCH 214/586] Add some more documentation --- library/core/src/mem/mod.rs | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs index cd92ea24b6171..66fca2fd28141 100644 --- a/library/core/src/mem/mod.rs +++ b/library/core/src/mem/mod.rs @@ -1179,6 +1179,9 @@ pub const fn variant_count() -> usize { intrinsics::variant_count::() } +/// Provides associated constants for various useful properties of types, +/// to give them a canonical form in our code and make them easier to read. +/// /// This is here only to simplify all the ZST checks we need in the library. /// It's not on a stabilization track right now. #[doc(hidden)] @@ -1186,6 +1189,29 @@ pub const fn variant_count() -> usize { pub trait SizedTypeProperties: Sized { /// `true` if this type requires no storage. /// `false` if its [size](size_of) is greater than zero. + /// + /// # Examples + /// + /// ``` + /// #![feature(sized_type_properties)] + /// use core::mem::SizedTypeProperties; + /// + /// fn do_something_with() { + /// if T::IS_ZST { + /// // ... special approach ... + /// } else { + /// // ... the normal thing ... + /// } + /// } + /// + /// struct MyUnit; + /// assert!(MyUnit::IS_ZST); + /// + /// // For negative checks, consider using UFCS to emphasize the negation + /// assert!(!::IS_ZST); + /// // As it can sometimes hide in the type otherwise + /// assert!(!String::IS_ZST); + /// ``` #[doc(hidden)] #[unstable(feature = "sized_type_properties", issue = "none")] const IS_ZST: bool = size_of::() == 0; From 59c4a92bafaf19e2d9039436294aa805d748ce0f Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 22 Sep 2022 22:53:32 +0000 Subject: [PATCH 215/586] Resolve async fn signature even without body (in trait) --- compiler/rustc_resolve/src/late.rs | 5 +- .../ui/async-await/in-trait/issue-102138.rs | 46 +++++++++++++++++++ src/test/ui/async-await/issue-102138.rs | 46 +++++++++++++++++++ .../issue-69401-trait-fn-no-body-ty-local.rs | 2 +- ...sue-69401-trait-fn-no-body-ty-local.stderr | 6 +-- 5 files changed, 98 insertions(+), 7 deletions(-) create mode 100644 src/test/ui/async-await/in-trait/issue-102138.rs create mode 100644 src/test/ui/async-await/issue-102138.rs diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 0aea90bb5aaf3..d38eca23ade10 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -789,9 +789,8 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> { let previous_value = self.diagnostic_metadata.current_function; match fn_kind { // Bail if the function is foreign, and thus cannot validly have - // a body, or if there's no body for some other reason. - FnKind::Fn(FnCtxt::Foreign, _, sig, _, generics, _) - | FnKind::Fn(_, _, sig, _, generics, None) => { + // a body. + FnKind::Fn(FnCtxt::Foreign, _, sig, _, generics, _) => { self.visit_fn_header(&sig.header); self.visit_generics(generics); self.with_lifetime_rib( diff --git a/src/test/ui/async-await/in-trait/issue-102138.rs b/src/test/ui/async-await/in-trait/issue-102138.rs new file mode 100644 index 0000000000000..f61b34ed99e00 --- /dev/null +++ b/src/test/ui/async-await/in-trait/issue-102138.rs @@ -0,0 +1,46 @@ +// check-pass +// edition:2021 + +#![feature(async_fn_in_trait)] +#![allow(incomplete_features)] + +use std::future::Future; + +async fn yield_now() {} + +trait AsyncIterator { + type Item; + async fn next(&mut self) -> Option; +} + +struct YieldingRange { + counter: u32, + stop: u32, +} + +impl AsyncIterator for YieldingRange { + type Item = u32; + + async fn next(&mut self) -> Option { + if self.counter == self.stop { + None + } else { + let c = self.counter; + self.counter += 1; + yield_now().await; + Some(c) + } + } +} + +async fn async_main() { + let mut x = YieldingRange { counter: 0, stop: 10 }; + + while let Some(v) = x.next().await { + println!("Hi: {v}"); + } +} + +fn main() { + let _ = async_main(); +} diff --git a/src/test/ui/async-await/issue-102138.rs b/src/test/ui/async-await/issue-102138.rs new file mode 100644 index 0000000000000..91a14523c63b2 --- /dev/null +++ b/src/test/ui/async-await/issue-102138.rs @@ -0,0 +1,46 @@ +// check-pass +// edition:2021 + +#![feature(return_position_impl_trait_in_trait)] +#![allow(incomplete_features)] + +use std::future::Future; + +async fn yield_now() {} + +trait AsyncIterator { + type Item; + async fn next(&mut self) -> Option; +} + +struct YieldingRange { + counter: u32, + stop: u32, +} + +impl AsyncIterator for YieldingRange { + type Item = u32; + + async fn next(&mut self) -> Option { + if self.counter == self.stop { + None + } else { + let c = self.counter; + self.counter += 1; + yield_now().await; + Some(c) + } + } +} + +async fn async_main() { + let mut x = YieldingRange { counter: 0, stop: 10 }; + + while let Some(v) = x.next().await { + println!("Hi: {v}"); + } +} + +fn main() { + let _ = async_main(); +} diff --git a/src/test/ui/resolve/issue-69401-trait-fn-no-body-ty-local.rs b/src/test/ui/resolve/issue-69401-trait-fn-no-body-ty-local.rs index c377ecea94d0c..4ec4472cc9aea 100644 --- a/src/test/ui/resolve/issue-69401-trait-fn-no-body-ty-local.rs +++ b/src/test/ui/resolve/issue-69401-trait-fn-no-body-ty-local.rs @@ -2,5 +2,5 @@ fn main() {} trait Foo { fn fn_with_type_named_same_as_local_in_param(b: b); - //~^ ERROR cannot find type `b` in this scope [E0412] + //~^ ERROR expected type, found local variable `b` } diff --git a/src/test/ui/resolve/issue-69401-trait-fn-no-body-ty-local.stderr b/src/test/ui/resolve/issue-69401-trait-fn-no-body-ty-local.stderr index 109409d2731c5..c53028e9b2ad7 100644 --- a/src/test/ui/resolve/issue-69401-trait-fn-no-body-ty-local.stderr +++ b/src/test/ui/resolve/issue-69401-trait-fn-no-body-ty-local.stderr @@ -1,9 +1,9 @@ -error[E0412]: cannot find type `b` in this scope +error[E0573]: expected type, found local variable `b` --> $DIR/issue-69401-trait-fn-no-body-ty-local.rs:4:53 | LL | fn fn_with_type_named_same_as_local_in_param(b: b); - | ^ not found in this scope + | ^ not a type error: aborting due to previous error -For more information about this error, try `rustc --explain E0412`. +For more information about this error, try `rustc --explain E0573`. From 3d7e9a7b27c735a8eb2fe05781bb7b4331572983 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 23 Sep 2022 00:49:25 +0000 Subject: [PATCH 216/586] Only record extra lifetime params for async trait fn with no body --- compiler/rustc_resolve/src/late.rs | 78 ++++++++++--------- src/test/ui/async-await/issue-102138.rs | 46 ----------- .../issue-69401-trait-fn-no-body-ty-local.rs | 2 +- ...sue-69401-trait-fn-no-body-ty-local.stderr | 6 +- 4 files changed, 44 insertions(+), 88 deletions(-) delete mode 100644 src/test/ui/async-await/issue-102138.rs diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index d38eca23ade10..558db003867d2 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -789,8 +789,9 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> { let previous_value = self.diagnostic_metadata.current_function; match fn_kind { // Bail if the function is foreign, and thus cannot validly have - // a body. - FnKind::Fn(FnCtxt::Foreign, _, sig, _, generics, _) => { + // a body, or if there's no body for some other reason. + FnKind::Fn(FnCtxt::Foreign, _, sig, _, generics, _) + | FnKind::Fn(_, _, sig, _, generics, None) => { self.visit_fn_header(&sig.header); self.visit_generics(generics); self.with_lifetime_rib( @@ -804,7 +805,12 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> { sig.decl.has_self(), sig.decl.inputs.iter().map(|Param { ty, .. }| (None, &**ty)), &sig.decl.output, - ) + ); + + this.record_lifetime_params_for_async( + fn_id, + sig.header.asyncness.opt_return_id(), + ); }, ); return; @@ -846,41 +852,7 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> { }, ); - // Construct the list of in-scope lifetime parameters for async lowering. - // We include all lifetime parameters, either named or "Fresh". - // The order of those parameters does not matter, as long as it is - // deterministic. - if let Some((async_node_id, _)) = async_node_id { - let mut extra_lifetime_params = this - .r - .extra_lifetime_params_map - .get(&fn_id) - .cloned() - .unwrap_or_default(); - for rib in this.lifetime_ribs.iter().rev() { - extra_lifetime_params.extend( - rib.bindings - .iter() - .map(|(&ident, &(node_id, res))| (ident, node_id, res)), - ); - match rib.kind { - LifetimeRibKind::Item => break, - LifetimeRibKind::AnonymousCreateParameter { - binder, .. - } => { - if let Some(earlier_fresh) = - this.r.extra_lifetime_params_map.get(&binder) - { - extra_lifetime_params.extend(earlier_fresh); - } - } - _ => {} - } - } - this.r - .extra_lifetime_params_map - .insert(async_node_id, extra_lifetime_params); - } + this.record_lifetime_params_for_async(fn_id, async_node_id); if let Some(body) = body { // Ignore errors in function bodies if this is rustdoc @@ -3925,6 +3897,36 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { Some((ident.name, ns)), ) } + + /// Construct the list of in-scope lifetime parameters for async lowering. + /// We include all lifetime parameters, either named or "Fresh". + /// The order of those parameters does not matter, as long as it is + /// deterministic. + fn record_lifetime_params_for_async( + &mut self, + fn_id: NodeId, + async_node_id: Option<(NodeId, Span)>, + ) { + if let Some((async_node_id, _)) = async_node_id { + let mut extra_lifetime_params = + self.r.extra_lifetime_params_map.get(&fn_id).cloned().unwrap_or_default(); + for rib in self.lifetime_ribs.iter().rev() { + extra_lifetime_params.extend( + rib.bindings.iter().map(|(&ident, &(node_id, res))| (ident, node_id, res)), + ); + match rib.kind { + LifetimeRibKind::Item => break, + LifetimeRibKind::AnonymousCreateParameter { binder, .. } => { + if let Some(earlier_fresh) = self.r.extra_lifetime_params_map.get(&binder) { + extra_lifetime_params.extend(earlier_fresh); + } + } + _ => {} + } + } + self.r.extra_lifetime_params_map.insert(async_node_id, extra_lifetime_params); + } + } } struct LifetimeCountVisitor<'a, 'b> { diff --git a/src/test/ui/async-await/issue-102138.rs b/src/test/ui/async-await/issue-102138.rs deleted file mode 100644 index 91a14523c63b2..0000000000000 --- a/src/test/ui/async-await/issue-102138.rs +++ /dev/null @@ -1,46 +0,0 @@ -// check-pass -// edition:2021 - -#![feature(return_position_impl_trait_in_trait)] -#![allow(incomplete_features)] - -use std::future::Future; - -async fn yield_now() {} - -trait AsyncIterator { - type Item; - async fn next(&mut self) -> Option; -} - -struct YieldingRange { - counter: u32, - stop: u32, -} - -impl AsyncIterator for YieldingRange { - type Item = u32; - - async fn next(&mut self) -> Option { - if self.counter == self.stop { - None - } else { - let c = self.counter; - self.counter += 1; - yield_now().await; - Some(c) - } - } -} - -async fn async_main() { - let mut x = YieldingRange { counter: 0, stop: 10 }; - - while let Some(v) = x.next().await { - println!("Hi: {v}"); - } -} - -fn main() { - let _ = async_main(); -} diff --git a/src/test/ui/resolve/issue-69401-trait-fn-no-body-ty-local.rs b/src/test/ui/resolve/issue-69401-trait-fn-no-body-ty-local.rs index 4ec4472cc9aea..c377ecea94d0c 100644 --- a/src/test/ui/resolve/issue-69401-trait-fn-no-body-ty-local.rs +++ b/src/test/ui/resolve/issue-69401-trait-fn-no-body-ty-local.rs @@ -2,5 +2,5 @@ fn main() {} trait Foo { fn fn_with_type_named_same_as_local_in_param(b: b); - //~^ ERROR expected type, found local variable `b` + //~^ ERROR cannot find type `b` in this scope [E0412] } diff --git a/src/test/ui/resolve/issue-69401-trait-fn-no-body-ty-local.stderr b/src/test/ui/resolve/issue-69401-trait-fn-no-body-ty-local.stderr index c53028e9b2ad7..109409d2731c5 100644 --- a/src/test/ui/resolve/issue-69401-trait-fn-no-body-ty-local.stderr +++ b/src/test/ui/resolve/issue-69401-trait-fn-no-body-ty-local.stderr @@ -1,9 +1,9 @@ -error[E0573]: expected type, found local variable `b` +error[E0412]: cannot find type `b` in this scope --> $DIR/issue-69401-trait-fn-no-body-ty-local.rs:4:53 | LL | fn fn_with_type_named_same_as_local_in_param(b: b); - | ^ not a type + | ^ not found in this scope error: aborting due to previous error -For more information about this error, try `rustc --explain E0573`. +For more information about this error, try `rustc --explain E0412`. From e87fcc026b4e31ffd352a035e58d78142c577dea Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 24 Sep 2022 19:04:25 +0000 Subject: [PATCH 217/586] Add test --- src/test/ui/resolve/name-collision-in-trait-fn-sig.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 src/test/ui/resolve/name-collision-in-trait-fn-sig.rs diff --git a/src/test/ui/resolve/name-collision-in-trait-fn-sig.rs b/src/test/ui/resolve/name-collision-in-trait-fn-sig.rs new file mode 100644 index 0000000000000..fba4ffa1c6ed2 --- /dev/null +++ b/src/test/ui/resolve/name-collision-in-trait-fn-sig.rs @@ -0,0 +1,11 @@ +// check-pass +// This is currently stable behavior, which was almost accidentally made an +// error in #102161 since there is no test exercising it. I am not sure if +// this _should_ be the desired behavior, but at least we should know if it +// changes. + +fn main() {} + +trait Foo { + fn fn_with_type_named_same_as_local_in_param(b: i32, b: i32); +} From 2e7a201d2e9e73477f1e69240711bfe09aefdc18 Mon Sep 17 00:00:00 2001 From: onestacked Date: Fri, 23 Sep 2022 18:47:47 +0200 Subject: [PATCH 218/586] Constify cmp_min_max_by --- library/core/src/cmp.rs | 55 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 49 insertions(+), 6 deletions(-) diff --git a/library/core/src/cmp.rs b/library/core/src/cmp.rs index 50b8264bac72a..f0fa2e1d2c190 100644 --- a/library/core/src/cmp.rs +++ b/library/core/src/cmp.rs @@ -22,6 +22,7 @@ #![stable(feature = "rust1", since = "1.0.0")] +use crate::const_closure::ConstFnMutClosure; use crate::marker::Destruct; use crate::marker::StructuralPartialEq; @@ -1222,7 +1223,12 @@ pub const fn min(v1: T, v2: T) -> T { #[inline] #[must_use] #[stable(feature = "cmp_min_max_by", since = "1.53.0")] -pub fn min_by Ordering>(v1: T, v2: T, compare: F) -> T { +#[rustc_const_unstable(feature = "const_cmp", issue = "92391")] +pub const fn min_by Ordering>(v1: T, v2: T, compare: F) -> T +where + T: ~const Destruct, + F: ~const Destruct, +{ match compare(&v1, &v2) { Ordering::Less | Ordering::Equal => v1, Ordering::Greater => v2, @@ -1244,8 +1250,24 @@ pub fn min_by Ordering>(v1: T, v2: T, compare: F) -> T { #[inline] #[must_use] #[stable(feature = "cmp_min_max_by", since = "1.53.0")] -pub fn min_by_key K, K: Ord>(v1: T, v2: T, mut f: F) -> T { - min_by(v1, v2, |v1, v2| f(v1).cmp(&f(v2))) +#[rustc_const_unstable(feature = "const_cmp", issue = "92391")] +pub const fn min_by_key K, K: ~const Ord>(v1: T, v2: T, mut f: F) -> T +where + T: ~const Destruct, + F: ~const Destruct, + K: ~const Destruct, +{ + const fn imp K, K: ~const Ord>( + f: &mut F, + (v1, v2): (&T, &T), + ) -> Ordering + where + T: ~const Destruct, + K: ~const Destruct, + { + f(v1).cmp(&f(v2)) + } + min_by(v1, v2, ConstFnMutClosure::new(&mut f, imp)) } /// Compares and returns the maximum of two values. @@ -1286,7 +1308,12 @@ pub const fn max(v1: T, v2: T) -> T { #[inline] #[must_use] #[stable(feature = "cmp_min_max_by", since = "1.53.0")] -pub fn max_by Ordering>(v1: T, v2: T, compare: F) -> T { +#[rustc_const_unstable(feature = "const_cmp", issue = "92391")] +pub const fn max_by Ordering>(v1: T, v2: T, compare: F) -> T +where + T: ~const Destruct, + F: ~const Destruct, +{ match compare(&v1, &v2) { Ordering::Less | Ordering::Equal => v2, Ordering::Greater => v1, @@ -1308,8 +1335,24 @@ pub fn max_by Ordering>(v1: T, v2: T, compare: F) -> T { #[inline] #[must_use] #[stable(feature = "cmp_min_max_by", since = "1.53.0")] -pub fn max_by_key K, K: Ord>(v1: T, v2: T, mut f: F) -> T { - max_by(v1, v2, |v1, v2| f(v1).cmp(&f(v2))) +#[rustc_const_unstable(feature = "const_cmp", issue = "92391")] +pub const fn max_by_key K, K: ~const Ord>(v1: T, v2: T, mut f: F) -> T +where + T: ~const Destruct, + F: ~const Destruct, + K: ~const Destruct, +{ + const fn imp K, K: ~const Ord>( + f: &mut F, + (v1, v2): (&T, &T), + ) -> Ordering + where + T: ~const Destruct, + K: ~const Destruct, + { + f(v1).cmp(&f(v2)) + } + max_by(v1, v2, ConstFnMutClosure::new(&mut f, imp)) } // Implementation of PartialEq, Eq, PartialOrd and Ord for primitive types From 36e8c113f67bb793cb231cbf0d29c29c02819b85 Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Sat, 24 Sep 2022 20:15:19 +0000 Subject: [PATCH 219/586] added tests --- .../specializing-constness-2.rs | 31 +++++++++++++++++++ .../specializing-constness-2.stderr | 19 ++++++++++++ .../specializing-constness.rs | 26 ++++++++++++++++ .../specializing-constness.stderr | 8 +++++ 4 files changed, 84 insertions(+) create mode 100644 src/test/ui/rfc-2632-const-trait-impl/specializing-constness-2.rs create mode 100644 src/test/ui/rfc-2632-const-trait-impl/specializing-constness-2.stderr create mode 100644 src/test/ui/rfc-2632-const-trait-impl/specializing-constness.rs create mode 100644 src/test/ui/rfc-2632-const-trait-impl/specializing-constness.stderr diff --git a/src/test/ui/rfc-2632-const-trait-impl/specializing-constness-2.rs b/src/test/ui/rfc-2632-const-trait-impl/specializing-constness-2.rs new file mode 100644 index 0000000000000..633543700d2ec --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/specializing-constness-2.rs @@ -0,0 +1,31 @@ +#![feature(const_trait_impl, min_specialization, rustc_attrs)] + +#[rustc_specialization_trait] +#[const_trait] +pub trait Sup {} + +impl const Sup for () {} + +#[const_trait] +pub trait A { + fn a() -> u32; +} + +impl A for T { + default fn a() -> u32 { + 2 + } +} + +impl const A for T { + fn a() -> u32 { + 3 + } +} + +const fn generic() { + ::a(); + //~^ ERROR: the trait bound `T: ~const Sup` is not satisfied +} + +fn main() {} diff --git a/src/test/ui/rfc-2632-const-trait-impl/specializing-constness-2.stderr b/src/test/ui/rfc-2632-const-trait-impl/specializing-constness-2.stderr new file mode 100644 index 0000000000000..c554671e18d82 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/specializing-constness-2.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `T: ~const Sup` is not satisfied + --> $DIR/specializing-constness-2.rs:27:5 + | +LL | ::a(); + | ^^^^^^^^^^^^^ the trait `~const Sup` is not implemented for `T` + | +note: required for `T` to implement `~const A` + --> $DIR/specializing-constness-2.rs:20:37 + | +LL | impl const A for T { + | ^ ^ +help: consider further restricting this bound + | +LL | const fn generic() { + | ++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/rfc-2632-const-trait-impl/specializing-constness.rs b/src/test/ui/rfc-2632-const-trait-impl/specializing-constness.rs new file mode 100644 index 0000000000000..ff0cd489d4744 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/specializing-constness.rs @@ -0,0 +1,26 @@ +#![feature(const_trait_impl, min_specialization, rustc_attrs)] + +#[rustc_specialization_trait] +#[const_trait] +pub trait Sup {} + +impl const Sup for () {} + +#[const_trait] +pub trait A { + fn a() -> u32; +} + +impl const A for T { + default fn a() -> u32 { + 2 + } +} + +impl A for T { //~ ERROR: cannot specialize + fn a() -> u32 { + 3 + } +} + +fn main() {} diff --git a/src/test/ui/rfc-2632-const-trait-impl/specializing-constness.stderr b/src/test/ui/rfc-2632-const-trait-impl/specializing-constness.stderr new file mode 100644 index 0000000000000..3296c109c4e73 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/specializing-constness.stderr @@ -0,0 +1,8 @@ +error: cannot specialize on trait `Default` + --> $DIR/specializing-constness.rs:20:9 + | +LL | impl A for T { + | ^^^^^^^ + +error: aborting due to previous error + From 2ce1cd511f0d1152054936def739184b20c0e64f Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Fri, 23 Sep 2022 14:22:36 +0000 Subject: [PATCH 220/586] Note the type when unable to drop values in compile time --- .../src/transform/check_consts/check.rs | 5 ++- .../src/transform/check_consts/ops.rs | 13 ++++--- .../check_consts/post_drop_elaboration.rs | 12 +++---- .../ui/check-static-values-constraints.rs | 2 +- .../ui/check-static-values-constraints.stderr | 4 +-- src/test/ui/consts/const-eval/const_let.rs | 8 ++--- .../ui/consts/const-eval/const_let.stderr | 16 ++++----- src/test/ui/consts/const-eval/issue-65394.rs | 2 +- .../ui/consts/const-eval/issue-65394.stderr | 4 +-- src/test/ui/consts/const-eval/livedrop.rs | 2 +- src/test/ui/consts/const-eval/livedrop.stderr | 4 +-- .../control-flow/drop-fail.precise.stderr | 8 ++--- src/test/ui/consts/control-flow/drop-fail.rs | 8 ++--- .../control-flow/drop-fail.stock.stderr | 16 ++++----- src/test/ui/consts/drop_box.rs | 2 +- src/test/ui/consts/drop_box.stderr | 4 +-- src/test/ui/consts/drop_zst.stderr | 4 +-- .../ui/consts/min_const_fn/min_const_fn.rs | 6 ++-- .../consts/min_const_fn/min_const_fn.stderr | 20 +++++------ ...ure-gate-unleash_the_miri_inside_of_you.rs | 2 +- ...gate-unleash_the_miri_inside_of_you.stderr | 4 +-- .../consts/qualif-indirect-mutation-fail.rs | 18 +++++----- .../qualif-indirect-mutation-fail.stderr | 36 +++++++++---------- .../stable-precise-live-drops-in-libcore.rs | 2 +- ...table-precise-live-drops-in-libcore.stderr | 4 +-- .../ui/consts/unstable-const-fn-in-libcore.rs | 4 +-- .../unstable-const-fn-in-libcore.stderr | 8 ++--- src/test/ui/drop/repeat-drop-2.rs | 2 +- src/test/ui/drop/repeat-drop-2.stderr | 4 +-- src/test/ui/impl-trait/issues/issue-78722.rs | 2 +- .../ui/impl-trait/issues/issue-78722.stderr | 4 +-- .../drop-elaboration-after-borrowck-error.rs | 8 ++--- ...op-elaboration-after-borrowck-error.stderr | 16 ++++----- src/test/ui/span/E0493.rs | 2 +- src/test/ui/span/E0493.stderr | 4 +-- src/test/ui/static/static-drop-scope.rs | 16 ++++----- src/test/ui/static/static-drop-scope.stderr | 32 ++++++++--------- 37 files changed, 158 insertions(+), 150 deletions(-) diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs index fb35399fa3aec..b0dcbf76b01b0 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs @@ -1009,7 +1009,10 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { if needs_non_const_drop { self.check_op_spanned( - ops::LiveDrop { dropped_at: Some(terminator.source_info.span) }, + ops::LiveDrop { + dropped_at: Some(terminator.source_info.span), + dropped_ty: ty_of_dropped_place, + }, err_span, ); } diff --git a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs index 5fb4bf638b342..b56b230201ed4 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs @@ -422,10 +422,11 @@ impl<'tcx> NonConstOp<'tcx> for InlineAsm { } #[derive(Debug)] -pub struct LiveDrop { +pub struct LiveDrop<'tcx> { pub dropped_at: Option, + pub dropped_ty: Ty<'tcx>, } -impl<'tcx> NonConstOp<'tcx> for LiveDrop { +impl<'tcx> NonConstOp<'tcx> for LiveDrop<'tcx> { fn build_error( &self, ccx: &ConstCx<'_, 'tcx>, @@ -435,9 +436,13 @@ impl<'tcx> NonConstOp<'tcx> for LiveDrop { ccx.tcx.sess, span, E0493, - "destructors cannot be evaluated at compile-time" + "destructor of `{}` cannot be evaluated at compile-time", + self.dropped_ty, + ); + err.span_label( + span, + format!("the destructor for this type cannot be evaluated in {}s", ccx.const_kind()), ); - err.span_label(span, format!("{}s cannot evaluate destructors", ccx.const_kind())); if let Some(span) = self.dropped_at { err.span_label(span, "value is dropped here"); } diff --git a/compiler/rustc_const_eval/src/transform/check_consts/post_drop_elaboration.rs b/compiler/rustc_const_eval/src/transform/check_consts/post_drop_elaboration.rs index 4e210f66353f3..d4570c5988914 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/post_drop_elaboration.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/post_drop_elaboration.rs @@ -1,6 +1,6 @@ use rustc_middle::mir::visit::Visitor; use rustc_middle::mir::{self, BasicBlock, Location}; -use rustc_middle::ty::TyCtxt; +use rustc_middle::ty::{Ty, TyCtxt}; use rustc_span::{symbol::sym, Span}; use super::check::Qualifs; @@ -58,9 +58,9 @@ impl<'mir, 'tcx> std::ops::Deref for CheckLiveDrops<'mir, 'tcx> { } } -impl CheckLiveDrops<'_, '_> { - fn check_live_drop(&self, span: Span) { - ops::LiveDrop { dropped_at: None }.build_error(self.ccx, span).emit(); +impl<'tcx> CheckLiveDrops<'_, 'tcx> { + fn check_live_drop(&self, span: Span, dropped_ty: Ty<'tcx>) { + ops::LiveDrop { dropped_at: None, dropped_ty }.build_error(self.ccx, span).emit(); } } @@ -90,7 +90,7 @@ impl<'tcx> Visitor<'tcx> for CheckLiveDrops<'_, 'tcx> { } if dropped_place.is_indirect() { - self.check_live_drop(terminator.source_info.span); + self.check_live_drop(terminator.source_info.span, dropped_ty); return; } @@ -101,7 +101,7 @@ impl<'tcx> Visitor<'tcx> for CheckLiveDrops<'_, 'tcx> { if self.qualifs.needs_non_const_drop(self.ccx, dropped_place.local, location) { // Use the span where the dropped local was declared for the error. let span = self.body.local_decls[dropped_place.local].source_info.span; - self.check_live_drop(span); + self.check_live_drop(span, dropped_ty); } } diff --git a/src/test/ui/check-static-values-constraints.rs b/src/test/ui/check-static-values-constraints.rs index eb4ecd8baca96..f6a577d0d9c93 100644 --- a/src/test/ui/check-static-values-constraints.rs +++ b/src/test/ui/check-static-values-constraints.rs @@ -63,7 +63,7 @@ static STATIC8: SafeStruct = SafeStruct{field1: SafeEnum::Variant1, // This example should fail because field1 in the base struct is not safe static STATIC9: SafeStruct = SafeStruct{field1: SafeEnum::Variant1, ..SafeStruct{field1: SafeEnum::Variant3(WithDtor), -//~^ ERROR destructors cannot be evaluated at compile-time +//~^ ERROR destructor of field2: SafeEnum::Variant1}}; struct UnsafeStruct; diff --git a/src/test/ui/check-static-values-constraints.stderr b/src/test/ui/check-static-values-constraints.stderr index 3c193ca34acce..31939f7f6db5d 100644 --- a/src/test/ui/check-static-values-constraints.stderr +++ b/src/test/ui/check-static-values-constraints.stderr @@ -1,4 +1,4 @@ -error[E0493]: destructors cannot be evaluated at compile-time +error[E0493]: destructor of `SafeStruct` cannot be evaluated at compile-time --> $DIR/check-static-values-constraints.rs:65:43 | LL | ..SafeStruct{field1: SafeEnum::Variant3(WithDtor), @@ -7,7 +7,7 @@ LL | | LL | | field2: SafeEnum::Variant1}}; | | ^- value is dropped here | |________________________________________________________________________________| - | statics cannot evaluate destructors + | the destructor for this type cannot be evaluated in statics error[E0010]: allocations are not allowed in statics --> $DIR/check-static-values-constraints.rs:79:33 diff --git a/src/test/ui/consts/const-eval/const_let.rs b/src/test/ui/consts/const-eval/const_let.rs index 18692dbced679..1e2bcc55b6b10 100644 --- a/src/test/ui/consts/const-eval/const_let.rs +++ b/src/test/ui/consts/const-eval/const_let.rs @@ -14,16 +14,16 @@ const X2: FakeNeedsDrop = { let x; x = FakeNeedsDrop; x }; // error const Y: FakeNeedsDrop = { let mut x = FakeNeedsDrop; x = FakeNeedsDrop; x }; -//~^ ERROR destructors cannot be evaluated at compile-time +//~^ ERROR destructor of // error const Y2: FakeNeedsDrop = { let mut x; x = FakeNeedsDrop; x = FakeNeedsDrop; x }; -//~^ ERROR destructors cannot be evaluated at compile-time +//~^ ERROR destructor of // error const Z: () = { let mut x = None; x = Some(FakeNeedsDrop); }; -//~^ ERROR destructors cannot be evaluated at compile-time +//~^ ERROR destructor of // error const Z2: () = { let mut x; x = None; x = Some(FakeNeedsDrop); }; -//~^ ERROR destructors cannot be evaluated at compile-time +//~^ ERROR destructor of diff --git a/src/test/ui/consts/const-eval/const_let.stderr b/src/test/ui/consts/const-eval/const_let.stderr index 47f39b703e460..63442f55718cb 100644 --- a/src/test/ui/consts/const-eval/const_let.stderr +++ b/src/test/ui/consts/const-eval/const_let.stderr @@ -1,34 +1,34 @@ -error[E0493]: destructors cannot be evaluated at compile-time +error[E0493]: destructor of `FakeNeedsDrop` cannot be evaluated at compile-time --> $DIR/const_let.rs:16:32 | LL | const Y: FakeNeedsDrop = { let mut x = FakeNeedsDrop; x = FakeNeedsDrop; x }; | ^^^^^ - value is dropped here | | - | constants cannot evaluate destructors + | the destructor for this type cannot be evaluated in constants -error[E0493]: destructors cannot be evaluated at compile-time +error[E0493]: destructor of `FakeNeedsDrop` cannot be evaluated at compile-time --> $DIR/const_let.rs:20:33 | LL | const Y2: FakeNeedsDrop = { let mut x; x = FakeNeedsDrop; x = FakeNeedsDrop; x }; | ^^^^^ - value is dropped here | | - | constants cannot evaluate destructors + | the destructor for this type cannot be evaluated in constants -error[E0493]: destructors cannot be evaluated at compile-time +error[E0493]: destructor of `Option` cannot be evaluated at compile-time --> $DIR/const_let.rs:24:21 | LL | const Z: () = { let mut x = None; x = Some(FakeNeedsDrop); }; | ^^^^^ - value is dropped here | | - | constants cannot evaluate destructors + | the destructor for this type cannot be evaluated in constants -error[E0493]: destructors cannot be evaluated at compile-time +error[E0493]: destructor of `Option` cannot be evaluated at compile-time --> $DIR/const_let.rs:28:22 | LL | const Z2: () = { let mut x; x = None; x = Some(FakeNeedsDrop); }; | ^^^^^ - value is dropped here | | - | constants cannot evaluate destructors + | the destructor for this type cannot be evaluated in constants error: aborting due to 4 previous errors diff --git a/src/test/ui/consts/const-eval/issue-65394.rs b/src/test/ui/consts/const-eval/issue-65394.rs index 2518e4ed40b30..e6639826cb26a 100644 --- a/src/test/ui/consts/const-eval/issue-65394.rs +++ b/src/test/ui/consts/const-eval/issue-65394.rs @@ -4,7 +4,7 @@ // We will likely have to change this behavior before we allow `&mut` in a `const`. const _: Vec = { - let mut x = Vec::::new(); //~ ERROR destructors cannot be evaluated at compile-time + let mut x = Vec::::new(); //~ ERROR destructor of let r = &mut x; //~ ERROR mutable references are not allowed in constants let y = x; y diff --git a/src/test/ui/consts/const-eval/issue-65394.stderr b/src/test/ui/consts/const-eval/issue-65394.stderr index ec229d7f53a0f..ae6f0e9371680 100644 --- a/src/test/ui/consts/const-eval/issue-65394.stderr +++ b/src/test/ui/consts/const-eval/issue-65394.stderr @@ -7,11 +7,11 @@ LL | let r = &mut x; = note: see issue #57349 for more information = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable -error[E0493]: destructors cannot be evaluated at compile-time +error[E0493]: destructor of `Vec` cannot be evaluated at compile-time --> $DIR/issue-65394.rs:7:9 | LL | let mut x = Vec::::new(); - | ^^^^^ constants cannot evaluate destructors + | ^^^^^ the destructor for this type cannot be evaluated in constants ... LL | }; | - value is dropped here diff --git a/src/test/ui/consts/const-eval/livedrop.rs b/src/test/ui/consts/const-eval/livedrop.rs index 66b7d05808084..543f1f0ecee24 100644 --- a/src/test/ui/consts/const-eval/livedrop.rs +++ b/src/test/ui/consts/const-eval/livedrop.rs @@ -1,6 +1,6 @@ const _: Option> = { let mut never_returned = Some(Vec::new()); - let mut always_returned = None; //~ ERROR destructors cannot be evaluated at compile-time + let mut always_returned = None; //~ ERROR destructor of let mut i = 0; loop { diff --git a/src/test/ui/consts/const-eval/livedrop.stderr b/src/test/ui/consts/const-eval/livedrop.stderr index 1e8b4230c6f11..d04fdb70ed30b 100644 --- a/src/test/ui/consts/const-eval/livedrop.stderr +++ b/src/test/ui/consts/const-eval/livedrop.stderr @@ -1,8 +1,8 @@ -error[E0493]: destructors cannot be evaluated at compile-time +error[E0493]: destructor of `Option>` cannot be evaluated at compile-time --> $DIR/livedrop.rs:3:9 | LL | let mut always_returned = None; - | ^^^^^^^^^^^^^^^^^^^ constants cannot evaluate destructors + | ^^^^^^^^^^^^^^^^^^^ the destructor for this type cannot be evaluated in constants ... LL | always_returned = never_returned; | --------------- value is dropped here diff --git a/src/test/ui/consts/control-flow/drop-fail.precise.stderr b/src/test/ui/consts/control-flow/drop-fail.precise.stderr index 0b0b2443a4a46..93b5f257efb77 100644 --- a/src/test/ui/consts/control-flow/drop-fail.precise.stderr +++ b/src/test/ui/consts/control-flow/drop-fail.precise.stderr @@ -1,14 +1,14 @@ -error[E0493]: destructors cannot be evaluated at compile-time +error[E0493]: destructor of `Option>` cannot be evaluated at compile-time --> $DIR/drop-fail.rs:8:9 | LL | let x = Some(Vec::new()); - | ^ constants cannot evaluate destructors + | ^ the destructor for this type cannot be evaluated in constants -error[E0493]: destructors cannot be evaluated at compile-time +error[E0493]: destructor of `Option>` cannot be evaluated at compile-time --> $DIR/drop-fail.rs:39:9 | LL | let mut tmp = None; - | ^^^^^^^ constants cannot evaluate destructors + | ^^^^^^^ the destructor for this type cannot be evaluated in constants error: aborting due to 2 previous errors diff --git a/src/test/ui/consts/control-flow/drop-fail.rs b/src/test/ui/consts/control-flow/drop-fail.rs index efa5a11c941e9..41341f3121e2b 100644 --- a/src/test/ui/consts/control-flow/drop-fail.rs +++ b/src/test/ui/consts/control-flow/drop-fail.rs @@ -6,7 +6,7 @@ const _: Option> = { let y: Option> = None; let x = Some(Vec::new()); - //[stock,precise]~^ ERROR destructors cannot be evaluated at compile-time + //[stock,precise]~^ ERROR destructor of if true { x @@ -19,7 +19,7 @@ const _: Option> = { // existing analysis. const _: Vec = { let vec_tuple = (Vec::new(),); - //[stock]~^ ERROR destructors cannot be evaluated at compile-time + //[stock]~^ ERROR destructor of vec_tuple.0 }; @@ -27,7 +27,7 @@ const _: Vec = { // This applies to single-field enum variants as well. const _: Vec = { let x: Result<_, Vec> = Ok(Vec::new()); - //[stock]~^ ERROR destructors cannot be evaluated at compile-time + //[stock]~^ ERROR destructor of match x { Ok(x) | Err(x) => x, @@ -37,7 +37,7 @@ const _: Vec = { const _: Option> = { let mut some = Some(Vec::new()); let mut tmp = None; - //[stock,precise]~^ ERROR destructors cannot be evaluated at compile-time + //[stock,precise]~^ ERROR destructor of let mut i = 0; while i < 10 { diff --git a/src/test/ui/consts/control-flow/drop-fail.stock.stderr b/src/test/ui/consts/control-flow/drop-fail.stock.stderr index 72ca4fa08bc4e..2cc8568026eb5 100644 --- a/src/test/ui/consts/control-flow/drop-fail.stock.stderr +++ b/src/test/ui/consts/control-flow/drop-fail.stock.stderr @@ -1,35 +1,35 @@ -error[E0493]: destructors cannot be evaluated at compile-time +error[E0493]: destructor of `Option>` cannot be evaluated at compile-time --> $DIR/drop-fail.rs:8:9 | LL | let x = Some(Vec::new()); - | ^ constants cannot evaluate destructors + | ^ the destructor for this type cannot be evaluated in constants ... LL | }; | - value is dropped here -error[E0493]: destructors cannot be evaluated at compile-time +error[E0493]: destructor of `(Vec,)` cannot be evaluated at compile-time --> $DIR/drop-fail.rs:21:9 | LL | let vec_tuple = (Vec::new(),); - | ^^^^^^^^^ constants cannot evaluate destructors + | ^^^^^^^^^ the destructor for this type cannot be evaluated in constants ... LL | }; | - value is dropped here -error[E0493]: destructors cannot be evaluated at compile-time +error[E0493]: destructor of `Result, Vec>` cannot be evaluated at compile-time --> $DIR/drop-fail.rs:29:9 | LL | let x: Result<_, Vec> = Ok(Vec::new()); - | ^ constants cannot evaluate destructors + | ^ the destructor for this type cannot be evaluated in constants ... LL | }; | - value is dropped here -error[E0493]: destructors cannot be evaluated at compile-time +error[E0493]: destructor of `Option>` cannot be evaluated at compile-time --> $DIR/drop-fail.rs:39:9 | LL | let mut tmp = None; - | ^^^^^^^ constants cannot evaluate destructors + | ^^^^^^^ the destructor for this type cannot be evaluated in constants ... LL | }; | - value is dropped here diff --git a/src/test/ui/consts/drop_box.rs b/src/test/ui/consts/drop_box.rs index 58a373a967388..6799741307869 100644 --- a/src/test/ui/consts/drop_box.rs +++ b/src/test/ui/consts/drop_box.rs @@ -1,4 +1,4 @@ const fn f(_: Box) {} -//~^ ERROR destructors cannot be evaluated at compile-time +//~^ ERROR destructor of fn main() {} diff --git a/src/test/ui/consts/drop_box.stderr b/src/test/ui/consts/drop_box.stderr index b9d6581e8ecc8..62324939b08af 100644 --- a/src/test/ui/consts/drop_box.stderr +++ b/src/test/ui/consts/drop_box.stderr @@ -1,10 +1,10 @@ -error[E0493]: destructors cannot be evaluated at compile-time +error[E0493]: destructor of `Box` cannot be evaluated at compile-time --> $DIR/drop_box.rs:1:15 | LL | const fn f(_: Box) {} | ^ - value is dropped here | | - | constant functions cannot evaluate destructors + | the destructor for this type cannot be evaluated in constant functions error: aborting due to previous error diff --git a/src/test/ui/consts/drop_zst.stderr b/src/test/ui/consts/drop_zst.stderr index d4be5aa56d9af..37758a4cbda64 100644 --- a/src/test/ui/consts/drop_zst.stderr +++ b/src/test/ui/consts/drop_zst.stderr @@ -1,8 +1,8 @@ -error[E0493]: destructors cannot be evaluated at compile-time +error[E0493]: destructor of `S` cannot be evaluated at compile-time --> $DIR/drop_zst.rs:14:9 | LL | let s = S; - | ^ constant functions cannot evaluate destructors + | ^ the destructor for this type cannot be evaluated in constant functions error: aborting due to previous error diff --git a/src/test/ui/consts/min_const_fn/min_const_fn.rs b/src/test/ui/consts/min_const_fn/min_const_fn.rs index 0bafaf2e81f73..c2891488c7f1b 100644 --- a/src/test/ui/consts/min_const_fn/min_const_fn.rs +++ b/src/test/ui/consts/min_const_fn/min_const_fn.rs @@ -34,7 +34,7 @@ const fn foo35(a: bool, b: bool) -> bool { a ^ b } struct Foo(T); impl Foo { const fn new(t: T) -> Self { Foo(t) } - const fn into_inner(self) -> T { self.0 } //~ destructors cannot be evaluated + const fn into_inner(self) -> T { self.0 } //~ destructor of const fn get(&self) -> &T { &self.0 } const fn get_mut(&mut self) -> &mut T { &mut self.0 } //~^ mutable references @@ -43,7 +43,7 @@ impl Foo { } impl<'a, T> Foo { const fn new_lt(t: T) -> Self { Foo(t) } - const fn into_inner_lt(self) -> T { self.0 } //~ destructors cannot be evaluated + const fn into_inner_lt(self) -> T { self.0 } //~ destructor of const fn get_lt(&'a self) -> &T { &self.0 } const fn get_mut_lt(&'a mut self) -> &mut T { &mut self.0 } //~^ mutable references @@ -52,7 +52,7 @@ impl<'a, T> Foo { } impl Foo { const fn new_s(t: T) -> Self { Foo(t) } - const fn into_inner_s(self) -> T { self.0 } //~ ERROR destructors + const fn into_inner_s(self) -> T { self.0 } //~ ERROR destructor const fn get_s(&self) -> &T { &self.0 } const fn get_mut_s(&mut self) -> &mut T { &mut self.0 } //~^ mutable references diff --git a/src/test/ui/consts/min_const_fn/min_const_fn.stderr b/src/test/ui/consts/min_const_fn/min_const_fn.stderr index 4ad17602c8452..11c79e8e2d6a9 100644 --- a/src/test/ui/consts/min_const_fn/min_const_fn.stderr +++ b/src/test/ui/consts/min_const_fn/min_const_fn.stderr @@ -1,10 +1,10 @@ -error[E0493]: destructors cannot be evaluated at compile-time +error[E0493]: destructor of `Foo` cannot be evaluated at compile-time --> $DIR/min_const_fn.rs:37:25 | LL | const fn into_inner(self) -> T { self.0 } | ^^^^ - value is dropped here | | - | constant functions cannot evaluate destructors + | the destructor for this type cannot be evaluated in constant functions error[E0658]: mutable references are not allowed in constant functions --> $DIR/min_const_fn.rs:39:22 @@ -33,13 +33,13 @@ LL | const fn get_mut(&mut self) -> &mut T { &mut self.0 } = note: see issue #57349 for more information = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable -error[E0493]: destructors cannot be evaluated at compile-time +error[E0493]: destructor of `Foo` cannot be evaluated at compile-time --> $DIR/min_const_fn.rs:46:28 | LL | const fn into_inner_lt(self) -> T { self.0 } | ^^^^ - value is dropped here | | - | constant functions cannot evaluate destructors + | the destructor for this type cannot be evaluated in constant functions error[E0658]: mutable references are not allowed in constant functions --> $DIR/min_const_fn.rs:48:25 @@ -68,13 +68,13 @@ LL | const fn get_mut_lt(&'a mut self) -> &mut T { &mut self.0 } = note: see issue #57349 for more information = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable -error[E0493]: destructors cannot be evaluated at compile-time +error[E0493]: destructor of `Foo` cannot be evaluated at compile-time --> $DIR/min_const_fn.rs:55:27 | LL | const fn into_inner_s(self) -> T { self.0 } | ^^^^ - value is dropped here | | - | constant functions cannot evaluate destructors + | the destructor for this type cannot be evaluated in constant functions error[E0658]: mutable references are not allowed in constant functions --> $DIR/min_const_fn.rs:57:24 @@ -191,21 +191,21 @@ LL | const fn inc(x: &mut i32) { *x += 1 } = note: see issue #57349 for more information = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable -error[E0493]: destructors cannot be evaluated at compile-time +error[E0493]: destructor of `AlanTuring` cannot be evaluated at compile-time --> $DIR/min_const_fn.rs:122:19 | LL | const fn no_apit2(_x: AlanTuring) {} | ^^ - value is dropped here | | - | constant functions cannot evaluate destructors + | the destructor for this type cannot be evaluated in constant functions -error[E0493]: destructors cannot be evaluated at compile-time +error[E0493]: destructor of `impl std::fmt::Debug` cannot be evaluated at compile-time --> $DIR/min_const_fn.rs:124:18 | LL | const fn no_apit(_x: impl std::fmt::Debug) {} | ^^ - value is dropped here | | - | constant functions cannot evaluate destructors + | the destructor for this type cannot be evaluated in constant functions error: aborting due to 24 previous errors diff --git a/src/test/ui/consts/miri_unleashed/feature-gate-unleash_the_miri_inside_of_you.rs b/src/test/ui/consts/miri_unleashed/feature-gate-unleash_the_miri_inside_of_you.rs index 8b17f6885ad3e..4466f097ef4a1 100644 --- a/src/test/ui/consts/miri_unleashed/feature-gate-unleash_the_miri_inside_of_you.rs +++ b/src/test/ui/consts/miri_unleashed/feature-gate-unleash_the_miri_inside_of_you.rs @@ -8,7 +8,7 @@ trait Foo { } trait Bar> { - const F: u32 = (U::X, 42).1; //~ ERROR destructors cannot be evaluated at compile-time + const F: u32 = (U::X, 42).1; //~ ERROR destructor of } impl Foo for () { diff --git a/src/test/ui/consts/miri_unleashed/feature-gate-unleash_the_miri_inside_of_you.stderr b/src/test/ui/consts/miri_unleashed/feature-gate-unleash_the_miri_inside_of_you.stderr index 0b6cb2fab46f1..c91c72d1fbf16 100644 --- a/src/test/ui/consts/miri_unleashed/feature-gate-unleash_the_miri_inside_of_you.stderr +++ b/src/test/ui/consts/miri_unleashed/feature-gate-unleash_the_miri_inside_of_you.stderr @@ -1,10 +1,10 @@ -error[E0493]: destructors cannot be evaluated at compile-time +error[E0493]: destructor of `(T, u32)` cannot be evaluated at compile-time --> $DIR/feature-gate-unleash_the_miri_inside_of_you.rs:11:20 | LL | const F: u32 = (U::X, 42).1; | ^^^^^^^^^^ - value is dropped here | | - | constants cannot evaluate destructors + | the destructor for this type cannot be evaluated in constants error: aborting due to previous error diff --git a/src/test/ui/consts/qualif-indirect-mutation-fail.rs b/src/test/ui/consts/qualif-indirect-mutation-fail.rs index f74a25a346fda..a6d2934044ac7 100644 --- a/src/test/ui/consts/qualif-indirect-mutation-fail.rs +++ b/src/test/ui/consts/qualif-indirect-mutation-fail.rs @@ -6,13 +6,13 @@ // Mutable borrow of a field with drop impl. pub const fn f() { - let mut a: (u32, Option) = (0, None); //~ ERROR destructors cannot be evaluated + let mut a: (u32, Option) = (0, None); //~ ERROR destructor of let _ = &mut a.1; } // Mutable borrow of a type with drop impl. pub const A1: () = { - let mut x = None; //~ ERROR destructors cannot be evaluated + let mut x = None; //~ ERROR destructor of let mut y = Some(String::new()); let a = &mut x; let b = &mut y; @@ -28,12 +28,12 @@ pub const A2: () = { let b = &mut y; std::mem::swap(a, b); std::mem::forget(y); - let _z = x; //~ ERROR destructors cannot be evaluated + let _z = x; //~ ERROR destructor of }; // Shared borrow of a type that might be !Freeze and Drop. pub const fn g1() { - let x: Option = None; //~ ERROR destructors cannot be evaluated + let x: Option = None; //~ ERROR destructor of let _ = x.is_some(); } @@ -41,24 +41,24 @@ pub const fn g1() { pub const fn g2() { let x: Option = None; let _ = x.is_some(); - let _y = x; //~ ERROR destructors cannot be evaluated + let _y = x; //~ ERROR destructor of } // Mutable raw reference to a Drop type. pub const fn address_of_mut() { - let mut x: Option = None; //~ ERROR destructors cannot be evaluated + let mut x: Option = None; //~ ERROR destructor of &raw mut x; - let mut y: Option = None; //~ ERROR destructors cannot be evaluated + let mut y: Option = None; //~ ERROR destructor of std::ptr::addr_of_mut!(y); } // Const raw reference to a Drop type. Conservatively assumed to allow mutation // until resolution of https://github.com/rust-lang/rust/issues/56604. pub const fn address_of_const() { - let x: Option = None; //~ ERROR destructors cannot be evaluated + let x: Option = None; //~ ERROR destructor of &raw const x; - let y: Option = None; //~ ERROR destructors cannot be evaluated + let y: Option = None; //~ ERROR destructor of std::ptr::addr_of!(y); } diff --git a/src/test/ui/consts/qualif-indirect-mutation-fail.stderr b/src/test/ui/consts/qualif-indirect-mutation-fail.stderr index 713df12b7a55f..6379c00e4b434 100644 --- a/src/test/ui/consts/qualif-indirect-mutation-fail.stderr +++ b/src/test/ui/consts/qualif-indirect-mutation-fail.stderr @@ -1,56 +1,56 @@ -error[E0493]: destructors cannot be evaluated at compile-time +error[E0493]: destructor of `(u32, Option)` cannot be evaluated at compile-time --> $DIR/qualif-indirect-mutation-fail.rs:9:9 | LL | let mut a: (u32, Option) = (0, None); - | ^^^^^ constant functions cannot evaluate destructors + | ^^^^^ the destructor for this type cannot be evaluated in constant functions -error[E0493]: destructors cannot be evaluated at compile-time +error[E0493]: destructor of `Option` cannot be evaluated at compile-time --> $DIR/qualif-indirect-mutation-fail.rs:15:9 | LL | let mut x = None; - | ^^^^^ constants cannot evaluate destructors + | ^^^^^ the destructor for this type cannot be evaluated in constants -error[E0493]: destructors cannot be evaluated at compile-time +error[E0493]: destructor of `Option` cannot be evaluated at compile-time --> $DIR/qualif-indirect-mutation-fail.rs:31:9 | LL | let _z = x; - | ^^ constants cannot evaluate destructors + | ^^ the destructor for this type cannot be evaluated in constants -error[E0493]: destructors cannot be evaluated at compile-time +error[E0493]: destructor of `Option` cannot be evaluated at compile-time --> $DIR/qualif-indirect-mutation-fail.rs:36:9 | LL | let x: Option = None; - | ^ constant functions cannot evaluate destructors + | ^ the destructor for this type cannot be evaluated in constant functions -error[E0493]: destructors cannot be evaluated at compile-time +error[E0493]: destructor of `Option` cannot be evaluated at compile-time --> $DIR/qualif-indirect-mutation-fail.rs:44:9 | LL | let _y = x; - | ^^ constant functions cannot evaluate destructors + | ^^ the destructor for this type cannot be evaluated in constant functions -error[E0493]: destructors cannot be evaluated at compile-time +error[E0493]: destructor of `Option` cannot be evaluated at compile-time --> $DIR/qualif-indirect-mutation-fail.rs:52:9 | LL | let mut y: Option = None; - | ^^^^^ constant functions cannot evaluate destructors + | ^^^^^ the destructor for this type cannot be evaluated in constant functions -error[E0493]: destructors cannot be evaluated at compile-time +error[E0493]: destructor of `Option` cannot be evaluated at compile-time --> $DIR/qualif-indirect-mutation-fail.rs:49:9 | LL | let mut x: Option = None; - | ^^^^^ constant functions cannot evaluate destructors + | ^^^^^ the destructor for this type cannot be evaluated in constant functions -error[E0493]: destructors cannot be evaluated at compile-time +error[E0493]: destructor of `Option` cannot be evaluated at compile-time --> $DIR/qualif-indirect-mutation-fail.rs:62:9 | LL | let y: Option = None; - | ^ constant functions cannot evaluate destructors + | ^ the destructor for this type cannot be evaluated in constant functions -error[E0493]: destructors cannot be evaluated at compile-time +error[E0493]: destructor of `Option` cannot be evaluated at compile-time --> $DIR/qualif-indirect-mutation-fail.rs:59:9 | LL | let x: Option = None; - | ^ constant functions cannot evaluate destructors + | ^ the destructor for this type cannot be evaluated in constant functions error: aborting due to 9 previous errors diff --git a/src/test/ui/consts/stable-precise-live-drops-in-libcore.rs b/src/test/ui/consts/stable-precise-live-drops-in-libcore.rs index 2b970390f03c3..7cd3dbec93149 100644 --- a/src/test/ui/consts/stable-precise-live-drops-in-libcore.rs +++ b/src/test/ui/consts/stable-precise-live-drops-in-libcore.rs @@ -11,7 +11,7 @@ impl Either { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "foo", since = "1.0.0")] pub const fn unwrap(self) -> T { - //~^ ERROR destructors cannot be evaluated at compile-time + //~^ ERROR destructor of match self { Self::Left(t) => t, Self::Right(t) => t, diff --git a/src/test/ui/consts/stable-precise-live-drops-in-libcore.stderr b/src/test/ui/consts/stable-precise-live-drops-in-libcore.stderr index a3f513541dd6a..5f70391eec248 100644 --- a/src/test/ui/consts/stable-precise-live-drops-in-libcore.stderr +++ b/src/test/ui/consts/stable-precise-live-drops-in-libcore.stderr @@ -1,8 +1,8 @@ -error[E0493]: destructors cannot be evaluated at compile-time +error[E0493]: destructor of `Either` cannot be evaluated at compile-time --> $DIR/stable-precise-live-drops-in-libcore.rs:13:25 | LL | pub const fn unwrap(self) -> T { - | ^^^^ constant functions cannot evaluate destructors + | ^^^^ the destructor for this type cannot be evaluated in constant functions ... LL | } | - value is dropped here diff --git a/src/test/ui/consts/unstable-const-fn-in-libcore.rs b/src/test/ui/consts/unstable-const-fn-in-libcore.rs index b9e7e1405f949..ca4ed8f0b471c 100644 --- a/src/test/ui/consts/unstable-const-fn-in-libcore.rs +++ b/src/test/ui/consts/unstable-const-fn-in-libcore.rs @@ -15,8 +15,8 @@ impl Opt { #[rustc_const_unstable(feature = "foo", issue = "none")] #[stable(feature = "rust1", since = "1.0.0")] const fn unwrap_or_else T>(self, f: F) -> T { - //~^ ERROR destructors cannot be evaluated at compile-time - //~| ERROR destructors cannot be evaluated at compile-time + //~^ ERROR destructor of + //~| ERROR destructor of match self { Opt::Some(t) => t, Opt::None => f(), diff --git a/src/test/ui/consts/unstable-const-fn-in-libcore.stderr b/src/test/ui/consts/unstable-const-fn-in-libcore.stderr index fee74bd0a6cfe..e5b00dd07abee 100644 --- a/src/test/ui/consts/unstable-const-fn-in-libcore.stderr +++ b/src/test/ui/consts/unstable-const-fn-in-libcore.stderr @@ -1,17 +1,17 @@ -error[E0493]: destructors cannot be evaluated at compile-time +error[E0493]: destructor of `F` cannot be evaluated at compile-time --> $DIR/unstable-const-fn-in-libcore.rs:17:60 | LL | const fn unwrap_or_else T>(self, f: F) -> T { - | ^ constant functions cannot evaluate destructors + | ^ the destructor for this type cannot be evaluated in constant functions ... LL | } | - value is dropped here -error[E0493]: destructors cannot be evaluated at compile-time +error[E0493]: destructor of `Opt` cannot be evaluated at compile-time --> $DIR/unstable-const-fn-in-libcore.rs:17:54 | LL | const fn unwrap_or_else T>(self, f: F) -> T { - | ^^^^ constant functions cannot evaluate destructors + | ^^^^ the destructor for this type cannot be evaluated in constant functions ... LL | } | - value is dropped here diff --git a/src/test/ui/drop/repeat-drop-2.rs b/src/test/ui/drop/repeat-drop-2.rs index 59d5ef202051a..3cfacea5e17f4 100644 --- a/src/test/ui/drop/repeat-drop-2.rs +++ b/src/test/ui/drop/repeat-drop-2.rs @@ -5,7 +5,7 @@ fn borrowck_catch() { } const _: [String; 0] = [String::new(); 0]; -//~^ ERROR destructors cannot be evaluated at compile-time [E0493] +//~^ ERROR destructor of `String` cannot be evaluated at compile-time [E0493] fn must_be_init() { let x: u8; diff --git a/src/test/ui/drop/repeat-drop-2.stderr b/src/test/ui/drop/repeat-drop-2.stderr index 48fa2bfa975c0..adfaed739735b 100644 --- a/src/test/ui/drop/repeat-drop-2.stderr +++ b/src/test/ui/drop/repeat-drop-2.stderr @@ -8,13 +8,13 @@ LL | let _bar = foo; LL | let _baz = [foo; 0]; | ^^^ value used here after move -error[E0493]: destructors cannot be evaluated at compile-time +error[E0493]: destructor of `String` cannot be evaluated at compile-time --> $DIR/repeat-drop-2.rs:7:25 | LL | const _: [String; 0] = [String::new(); 0]; | -^^^^^^^^^^^^^---- | || - | |constants cannot evaluate destructors + | |the destructor for this type cannot be evaluated in constants | value is dropped here error[E0381]: used binding `x` isn't initialized diff --git a/src/test/ui/impl-trait/issues/issue-78722.rs b/src/test/ui/impl-trait/issues/issue-78722.rs index 90d1cd3798a83..9ee1ba3d3b486 100644 --- a/src/test/ui/impl-trait/issues/issue-78722.rs +++ b/src/test/ui/impl-trait/issues/issue-78722.rs @@ -12,7 +12,7 @@ struct Bug { } let f: F = async { 1 }; //~^ ERROR `async` blocks are not allowed in constants - //~| ERROR destructors cannot be evaluated at compile-time + //~| ERROR destructor of 1 }], } diff --git a/src/test/ui/impl-trait/issues/issue-78722.stderr b/src/test/ui/impl-trait/issues/issue-78722.stderr index 9a0ffbc89d92e..a96994f5a7fb8 100644 --- a/src/test/ui/impl-trait/issues/issue-78722.stderr +++ b/src/test/ui/impl-trait/issues/issue-78722.stderr @@ -7,11 +7,11 @@ LL | let f: F = async { 1 }; = note: see issue #85368 for more information = help: add `#![feature(const_async_blocks)]` to the crate attributes to enable -error[E0493]: destructors cannot be evaluated at compile-time +error[E0493]: destructor of `F` cannot be evaluated at compile-time --> $DIR/issue-78722.rs:13:13 | LL | let f: F = async { 1 }; - | ^ constants cannot evaluate destructors + | ^ the destructor for this type cannot be evaluated in constants ... LL | }], | - value is dropped here diff --git a/src/test/ui/mir/drop-elaboration-after-borrowck-error.rs b/src/test/ui/mir/drop-elaboration-after-borrowck-error.rs index fc7341a563bb2..624b464ecef25 100644 --- a/src/test/ui/mir/drop-elaboration-after-borrowck-error.rs +++ b/src/test/ui/mir/drop-elaboration-after-borrowck-error.rs @@ -3,9 +3,9 @@ static A: () = { let a: [String; 1]; - //~^ ERROR destructors cannot be evaluated at compile-time + //~^ ERROR destructor of a[0] = String::new(); - //~^ ERROR destructors cannot be evaluated at compile-time + //~^ ERROR destructor of //~| ERROR binding `a` isn't initialized }; @@ -14,9 +14,9 @@ struct B([T; 1]); impl B { pub const fn f(mut self, other: T) -> Self { let _this = self; - //~^ ERROR destructors cannot be evaluated at compile-time + //~^ ERROR destructor of self.0[0] = other; - //~^ ERROR destructors cannot be evaluated at compile-time + //~^ ERROR destructor of //~| ERROR use of moved value self } diff --git a/src/test/ui/mir/drop-elaboration-after-borrowck-error.stderr b/src/test/ui/mir/drop-elaboration-after-borrowck-error.stderr index d8154f8d2cbc4..c06a6238a9026 100644 --- a/src/test/ui/mir/drop-elaboration-after-borrowck-error.stderr +++ b/src/test/ui/mir/drop-elaboration-after-borrowck-error.stderr @@ -1,17 +1,17 @@ -error[E0493]: destructors cannot be evaluated at compile-time +error[E0493]: destructor of `String` cannot be evaluated at compile-time --> $DIR/drop-elaboration-after-borrowck-error.rs:7:5 | LL | a[0] = String::new(); | ^^^^ | | - | statics cannot evaluate destructors + | the destructor for this type cannot be evaluated in statics | value is dropped here -error[E0493]: destructors cannot be evaluated at compile-time +error[E0493]: destructor of `[String; 1]` cannot be evaluated at compile-time --> $DIR/drop-elaboration-after-borrowck-error.rs:5:9 | LL | let a: [String; 1]; - | ^ statics cannot evaluate destructors + | ^ the destructor for this type cannot be evaluated in statics ... LL | }; | - value is dropped here @@ -25,20 +25,20 @@ LL | LL | a[0] = String::new(); | ^^^^ `a` used here but it isn't initialized -error[E0493]: destructors cannot be evaluated at compile-time +error[E0493]: destructor of `T` cannot be evaluated at compile-time --> $DIR/drop-elaboration-after-borrowck-error.rs:18:9 | LL | self.0[0] = other; | ^^^^^^^^^ | | - | constant functions cannot evaluate destructors + | the destructor for this type cannot be evaluated in constant functions | value is dropped here -error[E0493]: destructors cannot be evaluated at compile-time +error[E0493]: destructor of `B` cannot be evaluated at compile-time --> $DIR/drop-elaboration-after-borrowck-error.rs:16:13 | LL | let _this = self; - | ^^^^^ constant functions cannot evaluate destructors + | ^^^^^ the destructor for this type cannot be evaluated in constant functions ... LL | } | - value is dropped here diff --git a/src/test/ui/span/E0493.rs b/src/test/ui/span/E0493.rs index ad4100205f273..625da25a7c2ca 100644 --- a/src/test/ui/span/E0493.rs +++ b/src/test/ui/span/E0493.rs @@ -15,7 +15,7 @@ impl Drop for Bar { } const F : Foo = (Foo { a : 0 }, Foo { a : 1 }).1; -//~^ destructors cannot be evaluated at compile-time +//~^ ERROR destructor of fn main() { } diff --git a/src/test/ui/span/E0493.stderr b/src/test/ui/span/E0493.stderr index 29d1b00094321..9db627562d6eb 100644 --- a/src/test/ui/span/E0493.stderr +++ b/src/test/ui/span/E0493.stderr @@ -1,10 +1,10 @@ -error[E0493]: destructors cannot be evaluated at compile-time +error[E0493]: destructor of `(Foo, Foo)` cannot be evaluated at compile-time --> $DIR/E0493.rs:17:17 | LL | const F : Foo = (Foo { a : 0 }, Foo { a : 1 }).1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - value is dropped here | | - | constants cannot evaluate destructors + | the destructor for this type cannot be evaluated in constants error: aborting due to previous error diff --git a/src/test/ui/static/static-drop-scope.rs b/src/test/ui/static/static-drop-scope.rs index e7ea8663d5af8..34afa9873a388 100644 --- a/src/test/ui/static/static-drop-scope.rs +++ b/src/test/ui/static/static-drop-scope.rs @@ -5,33 +5,33 @@ impl Drop for WithDtor { } static PROMOTION_FAIL_S: Option<&'static WithDtor> = Some(&WithDtor); -//~^ ERROR destructors cannot be evaluated at compile-time +//~^ ERROR destructor of //~| ERROR temporary value dropped while borrowed const PROMOTION_FAIL_C: Option<&'static WithDtor> = Some(&WithDtor); -//~^ ERROR destructors cannot be evaluated at compile-time +//~^ ERROR destructor of //~| ERROR temporary value dropped while borrowed static EARLY_DROP_S: i32 = (WithDtor, 0).1; -//~^ ERROR destructors cannot be evaluated at compile-time +//~^ ERROR destructor of const EARLY_DROP_C: i32 = (WithDtor, 0).1; -//~^ ERROR destructors cannot be evaluated at compile-time +//~^ ERROR destructor of const fn const_drop(_: T) {} -//~^ ERROR destructors cannot be evaluated at compile-time +//~^ ERROR destructor of const fn const_drop2(x: T) { (x, ()).1 - //~^ ERROR destructors cannot be evaluated at compile-time + //~^ ERROR destructor of } const EARLY_DROP_C_OPTION: i32 = (Some(WithDtor), 0).1; -//~^ ERROR destructors cannot be evaluated at compile-time +//~^ ERROR destructor of const HELPER: Option = Some(WithDtor); const EARLY_DROP_C_OPTION_CONSTANT: i32 = (HELPER, 0).1; -//~^ ERROR destructors cannot be evaluated at compile-time +//~^ ERROR destructor of fn main () {} diff --git a/src/test/ui/static/static-drop-scope.stderr b/src/test/ui/static/static-drop-scope.stderr index ac32f217fd769..112bfc003048d 100644 --- a/src/test/ui/static/static-drop-scope.stderr +++ b/src/test/ui/static/static-drop-scope.stderr @@ -1,10 +1,10 @@ -error[E0493]: destructors cannot be evaluated at compile-time +error[E0493]: destructor of `WithDtor` cannot be evaluated at compile-time --> $DIR/static-drop-scope.rs:7:60 | LL | static PROMOTION_FAIL_S: Option<&'static WithDtor> = Some(&WithDtor); | ^^^^^^^^- value is dropped here | | - | statics cannot evaluate destructors + | the destructor for this type cannot be evaluated in statics error[E0716]: temporary value dropped while borrowed --> $DIR/static-drop-scope.rs:7:60 @@ -16,13 +16,13 @@ LL | static PROMOTION_FAIL_S: Option<&'static WithDtor> = Some(&WithDtor); | | creates a temporary which is freed while still in use | using this value as a static requires that borrow lasts for `'static` -error[E0493]: destructors cannot be evaluated at compile-time +error[E0493]: destructor of `WithDtor` cannot be evaluated at compile-time --> $DIR/static-drop-scope.rs:11:59 | LL | const PROMOTION_FAIL_C: Option<&'static WithDtor> = Some(&WithDtor); | ^^^^^^^^- value is dropped here | | - | constants cannot evaluate destructors + | the destructor for this type cannot be evaluated in constants error[E0716]: temporary value dropped while borrowed --> $DIR/static-drop-scope.rs:11:59 @@ -34,54 +34,54 @@ LL | const PROMOTION_FAIL_C: Option<&'static WithDtor> = Some(&WithDtor); | | creates a temporary which is freed while still in use | using this value as a constant requires that borrow lasts for `'static` -error[E0493]: destructors cannot be evaluated at compile-time +error[E0493]: destructor of `(WithDtor, i32)` cannot be evaluated at compile-time --> $DIR/static-drop-scope.rs:15:28 | LL | static EARLY_DROP_S: i32 = (WithDtor, 0).1; | ^^^^^^^^^^^^^ - value is dropped here | | - | statics cannot evaluate destructors + | the destructor for this type cannot be evaluated in statics -error[E0493]: destructors cannot be evaluated at compile-time +error[E0493]: destructor of `(WithDtor, i32)` cannot be evaluated at compile-time --> $DIR/static-drop-scope.rs:18:27 | LL | const EARLY_DROP_C: i32 = (WithDtor, 0).1; | ^^^^^^^^^^^^^ - value is dropped here | | - | constants cannot evaluate destructors + | the destructor for this type cannot be evaluated in constants -error[E0493]: destructors cannot be evaluated at compile-time +error[E0493]: destructor of `T` cannot be evaluated at compile-time --> $DIR/static-drop-scope.rs:21:24 | LL | const fn const_drop(_: T) {} | ^ - value is dropped here | | - | constant functions cannot evaluate destructors + | the destructor for this type cannot be evaluated in constant functions -error[E0493]: destructors cannot be evaluated at compile-time +error[E0493]: destructor of `(T, ())` cannot be evaluated at compile-time --> $DIR/static-drop-scope.rs:25:5 | LL | (x, ()).1 - | ^^^^^^^ constant functions cannot evaluate destructors + | ^^^^^^^ the destructor for this type cannot be evaluated in constant functions LL | LL | } | - value is dropped here -error[E0493]: destructors cannot be evaluated at compile-time +error[E0493]: destructor of `(Option, i32)` cannot be evaluated at compile-time --> $DIR/static-drop-scope.rs:29:34 | LL | const EARLY_DROP_C_OPTION: i32 = (Some(WithDtor), 0).1; | ^^^^^^^^^^^^^^^^^^^ - value is dropped here | | - | constants cannot evaluate destructors + | the destructor for this type cannot be evaluated in constants -error[E0493]: destructors cannot be evaluated at compile-time +error[E0493]: destructor of `(Option, i32)` cannot be evaluated at compile-time --> $DIR/static-drop-scope.rs:34:43 | LL | const EARLY_DROP_C_OPTION_CONSTANT: i32 = (HELPER, 0).1; | ^^^^^^^^^^^ - value is dropped here | | - | constants cannot evaluate destructors + | the destructor for this type cannot be evaluated in constants error: aborting due to 10 previous errors From d7bee58105e01b0e259bf6b0cb1b90c841ba00e0 Mon Sep 17 00:00:00 2001 From: Ellis Hoag Date: Sat, 24 Sep 2022 15:03:14 -0700 Subject: [PATCH 221/586] remove comment --- compiler/rustc_codegen_gcc/src/intrinsic/simd.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs b/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs index 22bd0a1de8230..ffc85b773a276 100644 --- a/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs +++ b/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs @@ -428,7 +428,6 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>, 32 => ("f32", elem_ty), 64 => ("f64", elem_ty), _ => { - // Can we pass elem_ty directly? return_error!(InvalidMonomorphizationInvalidFloatVector { span, name, elem_ty: f.name_str(), vec_ty: in_ty }); } } From 73c52bc4dc8714a058854d113acd5e4a7c9c0785 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Mon, 19 Sep 2022 22:53:21 +0200 Subject: [PATCH 222/586] Fix scoping for let-else. --- compiler/rustc_mir_build/src/build/block.rs | 43 +++++++++++++-------- 1 file changed, 27 insertions(+), 16 deletions(-) diff --git a/compiler/rustc_mir_build/src/build/block.rs b/compiler/rustc_mir_build/src/build/block.rs index 4bab583c96018..fc1b301402b73 100644 --- a/compiler/rustc_mir_build/src/build/block.rs +++ b/compiler/rustc_mir_build/src/build/block.rs @@ -221,27 +221,37 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let init = &this.thir[*initializer]; let initializer_span = init.span; - this.declare_bindings( - visibility_scope, - remainder_span, - pattern, - ArmHasGuard(false), - Some((None, initializer_span)), - ); - this.visit_primary_bindings( - pattern, - UserTypeProjections::none(), - &mut |this, _, _, _, node, span, _, _| { - this.storage_live_binding(block, node, span, OutsideGuard, true); - this.schedule_drop_for_binding(node, span, OutsideGuard); - }, - ); let failure = unpack!( block = this.in_opt_scope( opt_destruction_scope.map(|de| (de, source_info)), |this| { let scope = (*init_scope, source_info); this.in_scope(scope, *lint_level, |this| { + this.declare_bindings( + visibility_scope, + remainder_span, + pattern, + ArmHasGuard(false), + Some((None, initializer_span)), + ); + this.visit_primary_bindings( + pattern, + UserTypeProjections::none(), + &mut |this, _, _, _, node, span, _, _| { + this.storage_live_binding( + block, + node, + span, + OutsideGuard, + true, + ); + this.schedule_drop_for_binding( + node, + span, + OutsideGuard, + ); + }, + ); this.ast_let_else( block, init, @@ -306,7 +316,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { ArmHasGuard(false), Some((None, initializer_span)), ); - this.expr_into_pattern(block, &pattern, init) // irrefutable pattern + this.expr_into_pattern(block, &pattern, init) + // irrefutable pattern }) }, ) From 4411d5fcc7cc0c3c3ae9de6e38b9a259417000c6 Mon Sep 17 00:00:00 2001 From: Gimgim <93856041+gimbles@users.noreply.github.com> Date: Sun, 25 Sep 2022 15:48:08 +0530 Subject: [PATCH 223/586] Update option.rs --- library/core/src/option.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/library/core/src/option.rs b/library/core/src/option.rs index 96b16b13256ce..ed7703befcfa3 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -842,6 +842,7 @@ impl Option { /// ``` /// let good_year_from_input = "1909"; /// let bad_year_from_input = "190blarg"; + /// // Result::ok() converts a Result to an Option /// let good_year = good_year_from_input.parse().ok().unwrap_or_default(); /// let bad_year = bad_year_from_input.parse().ok().unwrap_or_default(); /// From a20672c91910461ff1a9e89118631029297ddd37 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 25 Sep 2022 14:09:41 +0200 Subject: [PATCH 224/586] Clarify Iterator::rposition code example --- library/core/src/iter/traits/iterator.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index 45be7bdd8dba5..e26920b25ccf6 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -2906,14 +2906,14 @@ pub trait Iterator { /// Stopping at the first `true`: /// /// ``` - /// let a = [1, 2, 3]; + /// let a = [-1, 2, 3, 4]; /// /// let mut iter = a.iter(); /// - /// assert_eq!(iter.rposition(|&x| x == 2), Some(1)); + /// assert_eq!(iter.rposition(|&x| x >= 2), Some(3)); /// /// // we can still use `iter`, as there are more elements. - /// assert_eq!(iter.next(), Some(&1)); + /// assert_eq!(iter.next(), Some(&-1)); /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] From 439597bc1b3cbf6c8ceec7c81ae0143baee2c329 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Sun, 25 Sep 2022 10:23:33 -0400 Subject: [PATCH 225/586] Support overriding initial rustc and cargo paths This restores functionality broken by #98483. Unfortunately, it doesn't add a test to verify this works, but in this case we notice pretty quickly as perf uses this functionality and so reports breakage immediately after merging. --- src/bootstrap/config.rs | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index a6333976f2ac2..74530dec97b70 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -901,9 +901,7 @@ impl Config { config.config = toml_path; let build = toml.build.unwrap_or_default(); - let has_custom_rustc = build.rustc.is_some(); - set(&mut config.initial_rustc, build.rustc.map(PathBuf::from)); set(&mut config.out, flags.build_dir.or_else(|| build.build_dir.map(PathBuf::from))); // NOTE: Bootstrap spawns various commands with different working directories. // To avoid writing to random places on the file system, `config.out` needs to be an absolute path. @@ -912,10 +910,14 @@ impl Config { config.out = crate::util::absolute(&config.out); } - if !has_custom_rustc && !config.initial_rustc.starts_with(&config.out) { - config.initial_rustc = config.out.join(config.build.triple).join("stage0/bin/rustc"); - config.initial_cargo = config.out.join(config.build.triple).join("stage0/bin/cargo"); - } + config.initial_rustc = build + .rustc + .map(PathBuf::from) + .unwrap_or_else(|| config.out.join(config.build.triple).join("stage0/bin/rustc")); + config.initial_cargo = build + .cargo + .map(PathBuf::from) + .unwrap_or_else(|| config.out.join(config.build.triple).join("stage0/bin/cargo")); // NOTE: it's important this comes *after* we set `initial_rustc` just above. if config.dry_run { From 41ac87dd38e47fef2de46045ea9c1cb2eba93a8a Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Sun, 25 Sep 2022 09:42:01 -0500 Subject: [PATCH 226/586] Don't set RUSTC in the bootstrap build script We no longer use this for anything since https://github.com/rust-lang/rust/pull/98483/files#diff-7eddc76f1be9eca2599a9ae58c65ffe247fbdff9b02ef687439894cab9afe749L781. Remove it, so that we spuriously rebuild bootstrap fewer times on Windows (where PATH changes often). --- src/bootstrap/build.rs | 36 ------------------------------------ 1 file changed, 36 deletions(-) diff --git a/src/bootstrap/build.rs b/src/bootstrap/build.rs index ab34d5c1e5504..cd1f418028c62 100644 --- a/src/bootstrap/build.rs +++ b/src/bootstrap/build.rs @@ -1,43 +1,7 @@ -use env::consts::{EXE_EXTENSION, EXE_SUFFIX}; use std::env; -use std::ffi::OsString; -use std::path::PathBuf; - -/// Given an executable called `name`, return the filename for the -/// executable for a particular target. -pub fn exe(name: &PathBuf) -> PathBuf { - if EXE_EXTENSION != "" && name.extension() != Some(EXE_EXTENSION.as_ref()) { - let mut name: OsString = name.clone().into(); - name.push(EXE_SUFFIX); - name.into() - } else { - name.clone() - } -} fn main() { let host = env::var("HOST").unwrap(); println!("cargo:rerun-if-changed=build.rs"); - println!("cargo:rerun-if-env-changed=RUSTC"); println!("cargo:rustc-env=BUILD_TRIPLE={}", host); - - // This may not be a canonicalized path. - let mut rustc = PathBuf::from(env::var_os("RUSTC").unwrap()); - - if rustc.is_relative() { - println!("cargo:rerun-if-env-changed=PATH"); - for dir in env::split_paths(&env::var_os("PATH").unwrap_or_default()) { - let absolute = dir.join(&exe(&rustc)); - if absolute.exists() { - rustc = absolute; - break; - } - } - } - assert!(rustc.is_absolute()); - - // FIXME: if the path is not utf-8, this is going to break. Unfortunately - // Cargo doesn't have a way for us to specify non-utf-8 paths easily, so - // we'll need to invent some encoding scheme if this becomes a problem. - println!("cargo:rustc-env=RUSTC={}", rustc.to_str().unwrap()); } From 7a8369096c27312b1beda84c8f5c2ab207d8a3c7 Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Tue, 13 Sep 2022 18:32:22 -0500 Subject: [PATCH 227/586] Use function pointers instead of macro-unrolled loops in rustc_query_impl By making these standalone functions, we a) allow making them extensible in the future with a new `QueryStruct` b) greatly decrease the amount of code in each individual function, avoiding exponential blowup in llvm --- compiler/rustc_query_impl/src/lib.rs | 2 + compiler/rustc_query_impl/src/plumbing.rs | 124 ++++++++++++------ .../rustc_query_impl/src/profiling_support.rs | 25 +--- 3 files changed, 95 insertions(+), 56 deletions(-) diff --git a/compiler/rustc_query_impl/src/lib.rs b/compiler/rustc_query_impl/src/lib.rs index c87d26b3950a1..8e018d3e4a4bc 100644 --- a/compiler/rustc_query_impl/src/lib.rs +++ b/compiler/rustc_query_impl/src/lib.rs @@ -1,6 +1,8 @@ //! Support for serializing the dep-graph and reloading it. #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] +// this shouldn't be necessary, but the check for `&mut _` is too naive and denies returning a function pointer that takes a mut ref +#![feature(const_mut_refs)] #![feature(min_specialization)] #![feature(never_type)] #![feature(once_cell)] diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index d819f4774d54d..a4d9d07bc8a2b 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -3,7 +3,8 @@ //! manage the caches, and so forth. use crate::keys::Key; -use crate::on_disk_cache::CacheDecoder; +use crate::on_disk_cache::{CacheDecoder, CacheEncoder, EncodedDepNodeIndex}; +use crate::profiling_support::QueryKeyStringCache; use crate::{on_disk_cache, Queries}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::sync::{AtomicU64, Lock}; @@ -173,34 +174,14 @@ impl<'tcx> QueryCtxt<'tcx> { pub(super) fn encode_query_results( self, - encoder: &mut on_disk_cache::CacheEncoder<'_, 'tcx>, - query_result_index: &mut on_disk_cache::EncodedDepNodeIndex, + encoder: &mut CacheEncoder<'_, 'tcx>, + query_result_index: &mut EncodedDepNodeIndex, ) { - macro_rules! expand_if_cached { - ([] $encode:expr) => {}; - ([(cache) $($rest:tt)*] $encode:expr) => { - $encode - }; - ([$other:tt $($modifiers:tt)*] $encode:expr) => { - expand_if_cached!([$($modifiers)*] $encode) - }; - } - - macro_rules! encode_queries { - ( - $($(#[$attr:meta])* - [$($modifiers:tt)*] fn $query:ident($($K:tt)*) -> $V:ty,)*) => { - $( - expand_if_cached!([$($modifiers)*] on_disk_cache::encode_query_results::<_, super::queries::$query<'_>>( - self, - encoder, - query_result_index - )); - )* + for query in &self.queries.query_structs { + if let Some(encode) = query.encode_query_results { + encode(self, encoder, query_result_index); } } - - rustc_query_append!(encode_queries!); } pub fn try_print_query_stack( @@ -213,6 +194,14 @@ impl<'tcx> QueryCtxt<'tcx> { } } +#[derive(Clone, Copy)] +pub(crate) struct QueryStruct<'tcx> { + pub try_collect_active_jobs: fn(QueryCtxt<'tcx>, &mut QueryMap) -> Option<()>, + pub alloc_self_profile_query_strings: fn(TyCtxt<'tcx>, &mut QueryKeyStringCache), + pub encode_query_results: + Option, &mut CacheEncoder<'_, 'tcx>, &mut EncodedDepNodeIndex)>, +} + macro_rules! handle_cycle_error { ([]) => {{ rustc_query_system::HandleCycleError::Error @@ -420,6 +409,18 @@ where } } +macro_rules! expand_if_cached { + ([], $tokens:expr) => {{ + None + }}; + ([(cache) $($rest:tt)*], $tokens:expr) => {{ + Some($tokens) + }}; + ([$other:tt $($modifiers:tt)*], $tokens:expr) => { + expand_if_cached!([$($modifiers)*], $tokens) + }; +} + // NOTE: `$V` isn't used here, but we still need to match on it so it can be passed to other macros // invoked by `rustc_query_append`. macro_rules! define_queries { @@ -553,6 +554,59 @@ macro_rules! define_queries { })* } + mod query_structs { + use rustc_middle::ty::TyCtxt; + use $crate::plumbing::{QueryStruct, QueryCtxt}; + use $crate::profiling_support::QueryKeyStringCache; + use rustc_query_system::query::{QueryDescription, QueryMap}; + + pub(super) const fn dummy_query_struct<'tcx>() -> QueryStruct<'tcx> { + fn noop_try_collect_active_jobs(_: QueryCtxt<'_>, _: &mut QueryMap) -> Option<()> { + None + } + fn noop_alloc_self_profile_query_strings(_: TyCtxt<'_>, _: &mut QueryKeyStringCache) {} + + QueryStruct { + try_collect_active_jobs: noop_try_collect_active_jobs, + alloc_self_profile_query_strings: noop_alloc_self_profile_query_strings, + encode_query_results: None, + } + } + + pub(super) use dummy_query_struct as Null; + pub(super) use dummy_query_struct as Red; + pub(super) use dummy_query_struct as TraitSelect; + pub(super) use dummy_query_struct as CompileCodegenUnit; + pub(super) use dummy_query_struct as CompileMonoItem; + + $( + pub(super) const fn $name<'tcx>() -> QueryStruct<'tcx> { QueryStruct { + try_collect_active_jobs: |tcx, qmap| { + let make_query = |tcx, key| { + let kind = rustc_middle::dep_graph::DepKind::$name; + let name = stringify!($name); + $crate::plumbing::create_query_frame(tcx, super::queries::$name::describe, key, kind, name) + }; + tcx.queries.$name.try_collect_active_jobs( + tcx, + make_query, + qmap, + ) + }, + alloc_self_profile_query_strings: |tcx, string_cache| { + $crate::profiling_support::alloc_self_profile_query_strings_for_query_cache( + tcx, + stringify!($name), + &tcx.query_caches.$name, + string_cache, + ) + }, + encode_query_results: expand_if_cached!([$($modifiers)*], |tcx, encoder, query_result_index| + $crate::on_disk_cache::encode_query_results::<_, super::queries::$name<'_>>(tcx, encoder, query_result_index) + ), + }})* + } + pub fn query_callbacks<'tcx>(arena: &'tcx Arena<'tcx>) -> &'tcx [DepKindStruct<'tcx>] { arena.alloc_from_iter(make_dep_kind_array!(query_callbacks)) } @@ -567,9 +621,11 @@ impl<'tcx> Queries<'tcx> { extern_providers: ExternProviders, on_disk_cache: Option>, ) -> Self { + use crate::query_structs; Queries { local_providers: Box::new(local_providers), extern_providers: Box::new(extern_providers), + query_structs: make_dep_kind_array!(query_structs).to_vec(), on_disk_cache, jobs: AtomicU64::new(1), ..Queries::default() @@ -584,6 +640,7 @@ macro_rules! define_queries_struct { pub struct Queries<'tcx> { local_providers: Box, extern_providers: Box, + query_structs: Vec<$crate::plumbing::QueryStruct<'tcx>>, pub on_disk_cache: Option>, @@ -600,18 +657,9 @@ macro_rules! define_queries_struct { let tcx = QueryCtxt { tcx, queries: self }; let mut jobs = QueryMap::default(); - $( - let make_query = |tcx, key| { - let kind = dep_graph::DepKind::$name; - let name = stringify!($name); - $crate::plumbing::create_query_frame(tcx, queries::$name::describe, key, kind, name) - }; - self.$name.try_collect_active_jobs( - tcx, - make_query, - &mut jobs, - )?; - )* + for query in &self.query_structs { + (query.try_collect_active_jobs)(tcx, &mut jobs); + } Some(jobs) } diff --git a/compiler/rustc_query_impl/src/profiling_support.rs b/compiler/rustc_query_impl/src/profiling_support.rs index 98ec3bc097732..2cc311d48c8f6 100644 --- a/compiler/rustc_query_impl/src/profiling_support.rs +++ b/compiler/rustc_query_impl/src/profiling_support.rs @@ -1,3 +1,4 @@ +use crate::QueryCtxt; use measureme::{StringComponent, StringId}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::profiling::SelfProfiler; @@ -8,7 +9,7 @@ use rustc_query_system::query::QueryCache; use std::fmt::Debug; use std::io::Write; -struct QueryKeyStringCache { +pub(crate) struct QueryKeyStringCache { def_id_cache: FxHashMap, } @@ -226,7 +227,7 @@ where /// Allocate the self-profiling query strings for a single query cache. This /// method is called from `alloc_self_profile_query_strings` which knows all /// the queries via macro magic. -fn alloc_self_profile_query_strings_for_query_cache<'tcx, C>( +pub(crate) fn alloc_self_profile_query_strings_for_query_cache<'tcx, C>( tcx: TyCtxt<'tcx>, query_name: &'static str, query_cache: &C, @@ -298,27 +299,15 @@ fn alloc_self_profile_query_strings_for_query_cache<'tcx, C>( /// If we are recording only summary data, the ids will point to /// just the query names. If we are recording query keys too, we /// allocate the corresponding strings here. -pub fn alloc_self_profile_query_strings(tcx: TyCtxt<'_>) { +pub fn alloc_self_profile_query_strings<'tcx>(tcx: TyCtxt<'tcx>) { if !tcx.prof.enabled() { return; } let mut string_cache = QueryKeyStringCache::new(); + let queries = QueryCtxt::from_tcx(tcx); - macro_rules! alloc_once { - ( - $($(#[$attr:meta])* - [$($modifiers:tt)*] fn $name:ident($($K:tt)*) -> $V:ty,)*) => { - $( - alloc_self_profile_query_strings_for_query_cache( - tcx, - stringify!($name), - &tcx.query_caches.$name, - &mut string_cache, - ); - )+ - } + for query in &queries.queries.query_structs { + (query.alloc_self_profile_query_strings)(tcx, &mut string_cache); } - - rustc_query_append! { alloc_once! } } From ddf79827418eea02baf6652eac5bbcf60c061dbb Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Sun, 25 Sep 2022 18:35:43 +0200 Subject: [PATCH 228/586] Remove benches from `rustc_middle` These benches benchmark rust langauge features and not the compiler, so they seem to be in the wrong place here. They also all take <1ns, making them pretty useless. Looking at their git history, they just seem to have been carried around for many, many years. This commit ends their journey. --- compiler/rustc_middle/benches/lib.rs | 54 ---------------------------- 1 file changed, 54 deletions(-) delete mode 100644 compiler/rustc_middle/benches/lib.rs diff --git a/compiler/rustc_middle/benches/lib.rs b/compiler/rustc_middle/benches/lib.rs deleted file mode 100644 index 237751bcbd787..0000000000000 --- a/compiler/rustc_middle/benches/lib.rs +++ /dev/null @@ -1,54 +0,0 @@ -#![feature(test)] - -extern crate test; - -use test::Bencher; - -// Static/dynamic method dispatch - -struct Struct { - field: isize, -} - -trait Trait { - fn method(&self) -> isize; -} - -impl Trait for Struct { - fn method(&self) -> isize { - self.field - } -} - -#[bench] -fn trait_vtable_method_call(b: &mut Bencher) { - let s = Struct { field: 10 }; - let t = &s as &dyn Trait; - b.iter(|| t.method()); -} - -#[bench] -fn trait_static_method_call(b: &mut Bencher) { - let s = Struct { field: 10 }; - b.iter(|| s.method()); -} - -// Overhead of various match forms - -#[bench] -fn option_some(b: &mut Bencher) { - let x = Some(10); - b.iter(|| match x { - Some(y) => y, - None => 11, - }); -} - -#[bench] -fn vec_pattern(b: &mut Bencher) { - let x = [1, 2, 3, 4, 5, 6]; - b.iter(|| match x { - [1, 2, 3, ..] => 10, - _ => 11, - }); -} From fdda7e0a33a1aec94966248de4a210d45ead67a6 Mon Sep 17 00:00:00 2001 From: yukang Date: Mon, 26 Sep 2022 00:40:57 +0800 Subject: [PATCH 229/586] more code refactor on smart_resolve_report_errors --- .../rustc_resolve/src/late/diagnostics.rs | 382 ++++++++++-------- 1 file changed, 207 insertions(+), 175 deletions(-) diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 7f3dc2085211f..c82e59ca44f12 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -131,13 +131,13 @@ pub(super) enum LifetimeElisionCandidate { } /// Only used for diagnostics. -struct BaseError<'a> { +struct BaseError { msg: String, fallback_label: String, span: Span, - span_label: Option<(Span, &'a str)>, + span_label: Option<(Span, &'static str)>, could_be_expr: bool, - suggestion: Option<(Span, &'a str, String)>, + suggestion: Option<(Span, &'static str, String)>, } impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { @@ -154,7 +154,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { span: Span, source: PathSource<'_>, res: Option, - ) -> BaseError<'static> { + ) -> BaseError { // Make the base error. let mut expected = source.descr_expected(); let path_str = Segment::names_to_string(path); @@ -290,7 +290,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { self.suggest_swapping_misplaced_self_ty_and_trait(&mut err, source, res, base_error.span); - if let Some((span, label)) = base_error.span_label.clone() { + if let Some((span, label)) = base_error.span_label { err.span_label(span, label); } @@ -303,17 +303,29 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { self.suggest_self_or_self_ref(&mut err, path, span); self.detect_assoct_type_constraint_meant_as_path(&mut err, &base_error); - if self.suggest_self_ty_or_self_value(&mut err, source, path, span) { + if self.suggest_self_ty(&mut err, source, path, span) + || self.suggest_self_value(&mut err, source, path, span) + { return (err, Vec::new()); } let (found, candidates) = - self.try_lookup_name_with_relex_fashion(&mut err, source, path, span, res, &base_error); + self.try_lookup_name_relaxed(&mut err, source, path, span, res, &base_error); if found { return (err, candidates); } - self.suggest_type_ascription(&mut err, source, path, res, span, &base_error); + if !self.type_ascription_suggestion(&mut err, base_error.span) { + let mut fallback = + self.suggest_trait_and_bounds(&mut err, source, res, span, &base_error); + if self.suggest_typo(&mut err, source, path, span, &base_error) { + fallback = true; + } + if fallback { + // Fallback label. + err.span_label(base_error.span, &base_error.fallback_label); + } + } self.err_code_special_cases(&mut err, source, path, span); (err, candidates) @@ -322,7 +334,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { fn detect_assoct_type_constraint_meant_as_path( &self, err: &mut Diagnostic, - base_error: &BaseError<'static>, + base_error: &BaseError, ) { let Some(ty) = self.diagnostic_metadata.current_type_path else { return; }; let TyKind::Path(_, path) = &ty.kind else { return; }; @@ -355,7 +367,8 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { fn suggest_self_or_self_ref(&mut self, err: &mut Diagnostic, path: &[Segment], span: Span) { let is_assoc_fn = self.self_type_is_available(); - let item_str = path.last().unwrap().ident; + let Some(path_last_segment) = path.last() else { return }; + let item_str = path_last_segment.ident; // Emit help message for fake-self from other languages (e.g., `this` in Javascript). if ["this", "my"].contains(&item_str.as_str()) && is_assoc_fn { err.span_suggestion_short( @@ -392,14 +405,14 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { } } - fn try_lookup_name_with_relex_fashion( + fn try_lookup_name_relaxed( &mut self, err: &mut DiagnosticBuilder<'_, ErrorGuaranteed>, source: PathSource<'_>, path: &[Segment], span: Span, res: Option, - base_error: &BaseError<'static>, + base_error: &BaseError, ) -> (bool, Vec) { // Try to lookup name in more relaxed fashion for better error reporting. let ident = path.last().unwrap().ident; @@ -563,109 +576,114 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { return (false, candidates); } - fn suggest_type_ascription( + fn suggest_trait_and_bounds( &mut self, err: &mut DiagnosticBuilder<'_, ErrorGuaranteed>, source: PathSource<'_>, - path: &[Segment], res: Option, span: Span, - base_error: &BaseError<'static>, - ) { + base_error: &BaseError, + ) -> bool { let is_macro = base_error.span.from_expansion() && base_error.span.desugaring_kind().is_none(); - if !self.type_ascription_suggestion(err, base_error.span) { - let mut fallback = false; - if let ( - PathSource::Trait(AliasPossibility::Maybe), - Some(Res::Def(DefKind::Struct | DefKind::Enum | DefKind::Union, _)), - false, - ) = (source, res, is_macro) - { - if let Some(bounds @ [_, .., _]) = self.diagnostic_metadata.current_trait_object { - fallback = true; - let spans: Vec = bounds - .iter() - .map(|bound| bound.span()) - .filter(|&sp| sp != base_error.span) - .collect(); + let mut fallback = false; - let start_span = bounds[0].span(); - // `end_span` is the end of the poly trait ref (Foo + 'baz + Bar><) - let end_span = bounds.last().unwrap().span(); - // `last_bound_span` is the last bound of the poly trait ref (Foo + >'baz< + Bar) - let last_bound_span = spans.last().cloned().unwrap(); - let mut multi_span: MultiSpan = spans.clone().into(); - for sp in spans { - let msg = if sp == last_bound_span { - format!( - "...because of {these} bound{s}", - these = pluralize!("this", bounds.len() - 1), - s = pluralize!(bounds.len() - 1), - ) - } else { - String::new() - }; - multi_span.push_span_label(sp, msg); - } - multi_span - .push_span_label(base_error.span, "expected this type to be a trait..."); - err.span_help( - multi_span, - "`+` is used to constrain a \"trait object\" type with lifetimes or \ - auto-traits; structs and enums can't be bound in that way", - ); - if bounds.iter().all(|bound| match bound { - ast::GenericBound::Outlives(_) => true, - ast::GenericBound::Trait(tr, _) => tr.span == base_error.span, - }) { - let mut sugg = vec![]; - if base_error.span != start_span { - sugg.push((start_span.until(base_error.span), String::new())); - } - if base_error.span != end_span { - sugg.push((base_error.span.shrink_to_hi().to(end_span), String::new())); - } + if let ( + PathSource::Trait(AliasPossibility::Maybe), + Some(Res::Def(DefKind::Struct | DefKind::Enum | DefKind::Union, _)), + false, + ) = (source, res, is_macro) + { + if let Some(bounds @ [_, .., _]) = self.diagnostic_metadata.current_trait_object { + fallback = true; + let spans: Vec = bounds + .iter() + .map(|bound| bound.span()) + .filter(|&sp| sp != base_error.span) + .collect(); - err.multipart_suggestion( - "if you meant to use a type and not a trait here, remove the bounds", - sugg, - Applicability::MaybeIncorrect, - ); + let start_span = bounds[0].span(); + // `end_span` is the end of the poly trait ref (Foo + 'baz + Bar><) + let end_span = bounds.last().unwrap().span(); + // `last_bound_span` is the last bound of the poly trait ref (Foo + >'baz< + Bar) + let last_bound_span = spans.last().cloned().unwrap(); + let mut multi_span: MultiSpan = spans.clone().into(); + for sp in spans { + let msg = if sp == last_bound_span { + format!( + "...because of {these} bound{s}", + these = pluralize!("this", bounds.len() - 1), + s = pluralize!(bounds.len() - 1), + ) + } else { + String::new() + }; + multi_span.push_span_label(sp, msg); + } + multi_span.push_span_label(base_error.span, "expected this type to be a trait..."); + err.span_help( + multi_span, + "`+` is used to constrain a \"trait object\" type with lifetimes or \ + auto-traits; structs and enums can't be bound in that way", + ); + if bounds.iter().all(|bound| match bound { + ast::GenericBound::Outlives(_) => true, + ast::GenericBound::Trait(tr, _) => tr.span == base_error.span, + }) { + let mut sugg = vec![]; + if base_error.span != start_span { + sugg.push((start_span.until(base_error.span), String::new())); + } + if base_error.span != end_span { + sugg.push((base_error.span.shrink_to_hi().to(end_span), String::new())); } + + err.multipart_suggestion( + "if you meant to use a type and not a trait here, remove the bounds", + sugg, + Applicability::MaybeIncorrect, + ); } } + } - let is_expected = &|res| source.is_expected(res); - let ident_span = path.last().map_or(span, |ident| ident.ident.span); - fallback |= self.restrict_assoc_type_in_where_clause(span, err); + fallback |= self.restrict_assoc_type_in_where_clause(span, err); + fallback + } - let typo_sugg = self.lookup_typo_candidate(path, source.namespace(), is_expected); - if !self.r.add_typo_suggestion(err, typo_sugg, ident_span) { - fallback = true; - match self.diagnostic_metadata.current_let_binding { - Some((pat_sp, Some(ty_sp), None)) - if ty_sp.contains(base_error.span) && base_error.could_be_expr => - { - err.span_suggestion_short( - pat_sp.between(ty_sp), - "use `=` if you meant to assign", - " = ", - Applicability::MaybeIncorrect, - ); - } - _ => {} + fn suggest_typo( + &mut self, + err: &mut DiagnosticBuilder<'_, ErrorGuaranteed>, + source: PathSource<'_>, + path: &[Segment], + span: Span, + base_error: &BaseError, + ) -> bool { + let is_expected = &|res| source.is_expected(res); + let ident_span = path.last().map_or(span, |ident| ident.ident.span); + let typo_sugg = self.lookup_typo_candidate(path, source.namespace(), is_expected); + let mut fallback = false; + if !self.r.add_typo_suggestion(err, typo_sugg, ident_span) { + fallback = true; + match self.diagnostic_metadata.current_let_binding { + Some((pat_sp, Some(ty_sp), None)) + if ty_sp.contains(base_error.span) && base_error.could_be_expr => + { + err.span_suggestion_short( + pat_sp.between(ty_sp), + "use `=` if you meant to assign", + " = ", + Applicability::MaybeIncorrect, + ); } - - // If the trait has a single item (which wasn't matched by Levenshtein), suggest it - let suggestion = self.get_single_associated_item(&path, &source, is_expected); - self.r.add_typo_suggestion(err, suggestion, ident_span); - } - if fallback { - // Fallback label. - err.span_label(base_error.span, &base_error.fallback_label); + _ => {} } + + // If the trait has a single item (which wasn't matched by Levenshtein), suggest it + let suggestion = self.get_single_associated_item(&path, &source, is_expected); + self.r.add_typo_suggestion(err, suggestion, ident_span); } + fallback } fn err_code_special_cases( @@ -713,36 +731,48 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { } /// Emit special messages for unresolved `Self` and `self`. - fn suggest_self_ty_or_self_value( + fn suggest_self_ty( &mut self, err: &mut Diagnostic, source: PathSource<'_>, path: &[Segment], span: Span, ) -> bool { - if is_self_type(path, source.namespace()) { - err.code(rustc_errors::error_code!(E0411)); + if !is_self_type(path, source.namespace()) { + return false; + } + err.code(rustc_errors::error_code!(E0411)); + err.span_label( + span, + "`Self` is only available in impls, traits, and type definitions".to_string(), + ); + if let Some(item_kind) = self.diagnostic_metadata.current_item { err.span_label( - span, - "`Self` is only available in impls, traits, and type definitions".to_string(), + item_kind.ident.span, + format!( + "`Self` not allowed in {} {}", + item_kind.kind.article(), + item_kind.kind.descr() + ), ); - if let Some(item_kind) = self.diagnostic_metadata.current_item { - err.span_label( - item_kind.ident.span, - format!( - "`Self` not allowed in {} {}", - item_kind.kind.article(), - item_kind.kind.descr() - ), - ); - } - return true; } + true + } - if is_self_value(path, source.namespace()) { - debug!("smart_resolve_path_fragment: E0424, source={:?}", source); - err.code(rustc_errors::error_code!(E0424)); - err.span_label( + fn suggest_self_value( + &mut self, + err: &mut Diagnostic, + source: PathSource<'_>, + path: &[Segment], + span: Span, + ) -> bool { + if !is_self_value(path, source.namespace()) { + return false; + } + + debug!("smart_resolve_path_fragment: E0424, source={:?}", source); + err.code(rustc_errors::error_code!(E0424)); + err.span_label( span, match source { PathSource::Pat => { @@ -750,66 +780,64 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { } _ => "`self` value is a keyword only available in methods with a `self` parameter", }, - ); - let is_assoc_fn = self.self_type_is_available(); - if let Some((fn_kind, span)) = &self.diagnostic_metadata.current_function { - // The current function has a `self' parameter, but we were unable to resolve - // a reference to `self`. This can only happen if the `self` identifier we - // are resolving came from a different hygiene context. - if fn_kind.decl().inputs.get(0).map_or(false, |p| p.is_self()) { - err.span_label(*span, "this function has a `self` parameter, but a macro invocation can only access identifiers it receives from parameters"); + ); + let is_assoc_fn = self.self_type_is_available(); + if let Some((fn_kind, span)) = &self.diagnostic_metadata.current_function { + // The current function has a `self' parameter, but we were unable to resolve + // a reference to `self`. This can only happen if the `self` identifier we + // are resolving came from a different hygiene context. + if fn_kind.decl().inputs.get(0).map_or(false, |p| p.is_self()) { + err.span_label(*span, "this function has a `self` parameter, but a macro invocation can only access identifiers it receives from parameters"); + } else { + let doesnt = if is_assoc_fn { + let (span, sugg) = fn_kind + .decl() + .inputs + .get(0) + .map(|p| (p.span.shrink_to_lo(), "&self, ")) + .unwrap_or_else(|| { + // Try to look for the "(" after the function name, if possible. + // This avoids placing the suggestion into the visibility specifier. + let span = fn_kind + .ident() + .map_or(*span, |ident| span.with_lo(ident.span.hi())); + ( + self.r + .session + .source_map() + .span_through_char(span, '(') + .shrink_to_hi(), + "&self", + ) + }); + err.span_suggestion_verbose( + span, + "add a `self` receiver parameter to make the associated `fn` a method", + sugg, + Applicability::MaybeIncorrect, + ); + "doesn't" } else { - let doesnt = if is_assoc_fn { - let (span, sugg) = fn_kind - .decl() - .inputs - .get(0) - .map(|p| (p.span.shrink_to_lo(), "&self, ")) - .unwrap_or_else(|| { - // Try to look for the "(" after the function name, if possible. - // This avoids placing the suggestion into the visibility specifier. - let span = fn_kind - .ident() - .map_or(*span, |ident| span.with_lo(ident.span.hi())); - ( - self.r - .session - .source_map() - .span_through_char(span, '(') - .shrink_to_hi(), - "&self", - ) - }); - err.span_suggestion_verbose( - span, - "add a `self` receiver parameter to make the associated `fn` a method", - sugg, - Applicability::MaybeIncorrect, - ); - "doesn't" - } else { - "can't" - }; - if let Some(ident) = fn_kind.ident() { - err.span_label( - ident.span, - &format!("this function {} have a `self` parameter", doesnt), - ); - } + "can't" + }; + if let Some(ident) = fn_kind.ident() { + err.span_label( + ident.span, + &format!("this function {} have a `self` parameter", doesnt), + ); } - } else if let Some(item_kind) = self.diagnostic_metadata.current_item { - err.span_label( - item_kind.ident.span, - format!( - "`self` not allowed in {} {}", - item_kind.kind.article(), - item_kind.kind.descr() - ), - ); } - return true; + } else if let Some(item_kind) = self.diagnostic_metadata.current_item { + err.span_label( + item_kind.ident.span, + format!( + "`self` not allowed in {} {}", + item_kind.kind.article(), + item_kind.kind.descr() + ), + ); } - false + true } fn suggest_swapping_misplaced_self_ty_and_trait( @@ -861,7 +889,11 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { span: Span, ) { if let PathSource::Expr(_) = source && - let Some(Expr { span: expr_span, kind: ExprKind::Assign(lhs, _, _), .. } ) = self.diagnostic_metadata.in_if_condition { + let Some(Expr { + span: expr_span, + kind: ExprKind::Assign(lhs, _, _), + .. + }) = self.diagnostic_metadata.in_if_condition { // Icky heuristic so we don't suggest: // `if (i + 2) = 2` => `if let (i + 2) = 2` (approximately pattern) // `if 2 = i` => `if let 2 = i` (lhs needs to contain error span) From db0877f653c61f79457f02ea0bb643017cbb2490 Mon Sep 17 00:00:00 2001 From: yukang Date: Mon, 26 Sep 2022 00:53:55 +0800 Subject: [PATCH 230/586] trivial fix on fallback --- compiler/rustc_resolve/src/late/diagnostics.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index c82e59ca44f12..bd3336b715311 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -318,9 +318,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { if !self.type_ascription_suggestion(&mut err, base_error.span) { let mut fallback = self.suggest_trait_and_bounds(&mut err, source, res, span, &base_error); - if self.suggest_typo(&mut err, source, path, span, &base_error) { - fallback = true; - } + fallback |= self.suggest_typo(&mut err, source, path, span, &base_error); if fallback { // Fallback label. err.span_label(base_error.span, &base_error.fallback_label); From 93a0fb190e9a781a36f9ab2faf02f2e3dc303234 Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Sun, 11 Sep 2022 21:10:53 -0500 Subject: [PATCH 231/586] Move `DepKindStruct` from rustc_middle to rustc_query_system --- .../rustc_middle/src/dep_graph/dep_node.rs | 61 ------------------- compiler/rustc_middle/src/dep_graph/mod.rs | 4 +- .../src/dep_graph/dep_node.rs | 61 +++++++++++++++++++ .../rustc_query_system/src/dep_graph/mod.rs | 2 +- 4 files changed, 65 insertions(+), 63 deletions(-) diff --git a/compiler/rustc_middle/src/dep_graph/dep_node.rs b/compiler/rustc_middle/src/dep_graph/dep_node.rs index ac106764c0217..32dacc25dcb79 100644 --- a/compiler/rustc_middle/src/dep_graph/dep_node.rs +++ b/compiler/rustc_middle/src/dep_graph/dep_node.rs @@ -69,67 +69,6 @@ use std::hash::Hash; pub use rustc_query_system::dep_graph::{DepContext, DepNodeParams}; -/// This struct stores metadata about each DepKind. -/// -/// Information is retrieved by indexing the `DEP_KINDS` array using the integer value -/// of the `DepKind`. Overall, this allows to implement `DepContext` using this manual -/// jump table instead of large matches. -pub struct DepKindStruct<'tcx> { - /// Anonymous queries cannot be replayed from one compiler invocation to the next. - /// When their result is needed, it is recomputed. They are useful for fine-grained - /// dependency tracking, and caching within one compiler invocation. - pub is_anon: bool, - - /// Eval-always queries do not track their dependencies, and are always recomputed, even if - /// their inputs have not changed since the last compiler invocation. The result is still - /// cached within one compiler invocation. - pub is_eval_always: bool, - - /// Whether the query key can be recovered from the hashed fingerprint. - /// See [DepNodeParams] trait for the behaviour of each key type. - pub fingerprint_style: FingerprintStyle, - - /// The red/green evaluation system will try to mark a specific DepNode in the - /// dependency graph as green by recursively trying to mark the dependencies of - /// that `DepNode` as green. While doing so, it will sometimes encounter a `DepNode` - /// where we don't know if it is red or green and we therefore actually have - /// to recompute its value in order to find out. Since the only piece of - /// information that we have at that point is the `DepNode` we are trying to - /// re-evaluate, we need some way to re-run a query from just that. This is what - /// `force_from_dep_node()` implements. - /// - /// In the general case, a `DepNode` consists of a `DepKind` and an opaque - /// GUID/fingerprint that will uniquely identify the node. This GUID/fingerprint - /// is usually constructed by computing a stable hash of the query-key that the - /// `DepNode` corresponds to. Consequently, it is not in general possible to go - /// back from hash to query-key (since hash functions are not reversible). For - /// this reason `force_from_dep_node()` is expected to fail from time to time - /// because we just cannot find out, from the `DepNode` alone, what the - /// corresponding query-key is and therefore cannot re-run the query. - /// - /// The system deals with this case letting `try_mark_green` fail which forces - /// the root query to be re-evaluated. - /// - /// Now, if `force_from_dep_node()` would always fail, it would be pretty useless. - /// Fortunately, we can use some contextual information that will allow us to - /// reconstruct query-keys for certain kinds of `DepNode`s. In particular, we - /// enforce by construction that the GUID/fingerprint of certain `DepNode`s is a - /// valid `DefPathHash`. Since we also always build a huge table that maps every - /// `DefPathHash` in the current codebase to the corresponding `DefId`, we have - /// everything we need to re-run the query. - /// - /// Take the `mir_promoted` query as an example. Like many other queries, it - /// just has a single parameter: the `DefId` of the item it will compute the - /// validated MIR for. Now, when we call `force_from_dep_node()` on a `DepNode` - /// with kind `MirValidated`, we know that the GUID/fingerprint of the `DepNode` - /// is actually a `DefPathHash`, and can therefore just look up the corresponding - /// `DefId` in `tcx.def_path_hash_to_def_id`. - pub force_from_dep_node: Option, dep_node: DepNode) -> bool>, - - /// Invoke a query to put the on-disk cached value in memory. - pub try_load_from_on_disk_cache: Option, DepNode)>, -} - impl DepKind { #[inline(always)] pub fn fingerprint_style(self, tcx: TyCtxt<'_>) -> FingerprintStyle { diff --git a/compiler/rustc_middle/src/dep_graph/mod.rs b/compiler/rustc_middle/src/dep_graph/mod.rs index c8b3b52b0fb2b..0e9955e2972a7 100644 --- a/compiler/rustc_middle/src/dep_graph/mod.rs +++ b/compiler/rustc_middle/src/dep_graph/mod.rs @@ -11,15 +11,17 @@ pub use rustc_query_system::dep_graph::{ SerializedDepNodeIndex, WorkProduct, WorkProductId, }; -pub use dep_node::{label_strs, DepKind, DepKindStruct, DepNode, DepNodeExt}; +pub use dep_node::{label_strs, DepKind, DepNode, DepNodeExt}; pub(crate) use dep_node::{make_compile_codegen_unit, make_compile_mono_item}; pub type DepGraph = rustc_query_system::dep_graph::DepGraph; + pub type TaskDeps = rustc_query_system::dep_graph::TaskDeps; pub type TaskDepsRef<'a> = rustc_query_system::dep_graph::TaskDepsRef<'a, DepKind>; pub type DepGraphQuery = rustc_query_system::dep_graph::DepGraphQuery; pub type SerializedDepGraph = rustc_query_system::dep_graph::SerializedDepGraph; pub type EdgeFilter = rustc_query_system::dep_graph::debug::EdgeFilter; +pub type DepKindStruct<'tcx> = rustc_query_system::dep_graph::DepKindStruct>; impl rustc_query_system::dep_graph::DepKind for DepKind { const NULL: Self = DepKind::Null; diff --git a/compiler/rustc_query_system/src/dep_graph/dep_node.rs b/compiler/rustc_query_system/src/dep_graph/dep_node.rs index 162c274d8a296..2a3657780eca5 100644 --- a/compiler/rustc_query_system/src/dep_graph/dep_node.rs +++ b/compiler/rustc_query_system/src/dep_graph/dep_node.rs @@ -149,6 +149,67 @@ where } } +/// This struct stores metadata about each DepKind. +/// +/// Information is retrieved by indexing the `DEP_KINDS` array using the integer value +/// of the `DepKind`. Overall, this allows to implement `DepContext` using this manual +/// jump table instead of large matches. +pub struct DepKindStruct { + /// Anonymous queries cannot be replayed from one compiler invocation to the next. + /// When their result is needed, it is recomputed. They are useful for fine-grained + /// dependency tracking, and caching within one compiler invocation. + pub is_anon: bool, + + /// Eval-always queries do not track their dependencies, and are always recomputed, even if + /// their inputs have not changed since the last compiler invocation. The result is still + /// cached within one compiler invocation. + pub is_eval_always: bool, + + /// Whether the query key can be recovered from the hashed fingerprint. + /// See [DepNodeParams] trait for the behaviour of each key type. + pub fingerprint_style: FingerprintStyle, + + /// The red/green evaluation system will try to mark a specific DepNode in the + /// dependency graph as green by recursively trying to mark the dependencies of + /// that `DepNode` as green. While doing so, it will sometimes encounter a `DepNode` + /// where we don't know if it is red or green and we therefore actually have + /// to recompute its value in order to find out. Since the only piece of + /// information that we have at that point is the `DepNode` we are trying to + /// re-evaluate, we need some way to re-run a query from just that. This is what + /// `force_from_dep_node()` implements. + /// + /// In the general case, a `DepNode` consists of a `DepKind` and an opaque + /// GUID/fingerprint that will uniquely identify the node. This GUID/fingerprint + /// is usually constructed by computing a stable hash of the query-key that the + /// `DepNode` corresponds to. Consequently, it is not in general possible to go + /// back from hash to query-key (since hash functions are not reversible). For + /// this reason `force_from_dep_node()` is expected to fail from time to time + /// because we just cannot find out, from the `DepNode` alone, what the + /// corresponding query-key is and therefore cannot re-run the query. + /// + /// The system deals with this case letting `try_mark_green` fail which forces + /// the root query to be re-evaluated. + /// + /// Now, if `force_from_dep_node()` would always fail, it would be pretty useless. + /// Fortunately, we can use some contextual information that will allow us to + /// reconstruct query-keys for certain kinds of `DepNode`s. In particular, we + /// enforce by construction that the GUID/fingerprint of certain `DepNode`s is a + /// valid `DefPathHash`. Since we also always build a huge table that maps every + /// `DefPathHash` in the current codebase to the corresponding `DefId`, we have + /// everything we need to re-run the query. + /// + /// Take the `mir_promoted` query as an example. Like many other queries, it + /// just has a single parameter: the `DefId` of the item it will compute the + /// validated MIR for. Now, when we call `force_from_dep_node()` on a `DepNode` + /// with kind `MirValidated`, we know that the GUID/fingerprint of the `DepNode` + /// is actually a `DefPathHash`, and can therefore just look up the corresponding + /// `DefId` in `tcx.def_path_hash_to_def_id`. + pub force_from_dep_node: Option) -> bool>, + + /// Invoke a query to put the on-disk cached value in memory. + pub try_load_from_on_disk_cache: Option)>, +} + /// A "work product" corresponds to a `.o` (or other) file that we /// save in between runs. These IDs do not have a `DefId` but rather /// some independent path or string that persists between runs without diff --git a/compiler/rustc_query_system/src/dep_graph/mod.rs b/compiler/rustc_query_system/src/dep_graph/mod.rs index 342d95ca490ea..2b62a9ee42a6f 100644 --- a/compiler/rustc_query_system/src/dep_graph/mod.rs +++ b/compiler/rustc_query_system/src/dep_graph/mod.rs @@ -4,7 +4,7 @@ mod graph; mod query; mod serialized; -pub use dep_node::{DepNode, DepNodeParams, WorkProductId}; +pub use dep_node::{DepKindStruct, DepNode, DepNodeParams, WorkProductId}; pub use graph::{ hash_result, DepGraph, DepNodeColor, DepNodeIndex, TaskDeps, TaskDepsRef, WorkProduct, }; From f3f91bb51477084cdff194d8908053844fc6d9ea Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Sun, 11 Sep 2022 23:18:08 -0500 Subject: [PATCH 232/586] Move functions on `DepKindStruct` from rustc_middle to rustc_query_system --- .../rustc_middle/src/dep_graph/dep_node.rs | 18 +----- compiler/rustc_middle/src/dep_graph/mod.rs | 52 +++-------------- compiler/rustc_middle/src/ty/context.rs | 8 +-- .../rustc_query_system/src/dep_graph/mod.rs | 57 +++++++++++++++++-- 4 files changed, 64 insertions(+), 71 deletions(-) diff --git a/compiler/rustc_middle/src/dep_graph/dep_node.rs b/compiler/rustc_middle/src/dep_graph/dep_node.rs index 32dacc25dcb79..9b5b688d98a93 100644 --- a/compiler/rustc_middle/src/dep_graph/dep_node.rs +++ b/compiler/rustc_middle/src/dep_graph/dep_node.rs @@ -69,18 +69,6 @@ use std::hash::Hash; pub use rustc_query_system::dep_graph::{DepContext, DepNodeParams}; -impl DepKind { - #[inline(always)] - pub fn fingerprint_style(self, tcx: TyCtxt<'_>) -> FingerprintStyle { - // Only fetch the DepKindStruct once. - let data = tcx.query_kind(self); - if data.is_anon { - return FingerprintStyle::Opaque; - } - data.fingerprint_style - } -} - macro_rules! define_dep_nodes { ( $($(#[$attr:meta])* @@ -186,7 +174,7 @@ impl DepNodeExt for DepNode { /// method will assert that the given DepKind actually requires a /// single DefId/DefPathHash parameter. fn from_def_path_hash(tcx: TyCtxt<'_>, def_path_hash: DefPathHash, kind: DepKind) -> DepNode { - debug_assert!(kind.fingerprint_style(tcx) == FingerprintStyle::DefPathHash); + debug_assert!(tcx.fingerprint_style(kind) == FingerprintStyle::DefPathHash); DepNode { kind, hash: def_path_hash.0.into() } } @@ -201,7 +189,7 @@ impl DepNodeExt for DepNode { /// refers to something from the previous compilation session that /// has been removed. fn extract_def_id<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Option { - if self.kind.fingerprint_style(tcx) == FingerprintStyle::DefPathHash { + if tcx.fingerprint_style(self.kind) == FingerprintStyle::DefPathHash { Some(tcx.def_path_hash_to_def_id(DefPathHash(self.hash.into()), &mut || { panic!("Failed to extract DefId: {:?} {}", self.kind, self.hash) })) @@ -218,7 +206,7 @@ impl DepNodeExt for DepNode { ) -> Result { let kind = dep_kind_from_label_string(label)?; - match kind.fingerprint_style(tcx) { + match tcx.fingerprint_style(kind) { FingerprintStyle::Opaque => Err(()), FingerprintStyle::Unit => Ok(DepNode::new_no_params(tcx, kind)), FingerprintStyle::DefPathHash => { diff --git a/compiler/rustc_middle/src/dep_graph/mod.rs b/compiler/rustc_middle/src/dep_graph/mod.rs index 0e9955e2972a7..6226fdd923aac 100644 --- a/compiler/rustc_middle/src/dep_graph/mod.rs +++ b/compiler/rustc_middle/src/dep_graph/mod.rs @@ -27,6 +27,10 @@ impl rustc_query_system::dep_graph::DepKind for DepKind { const NULL: Self = DepKind::Null; const RED: Self = DepKind::Red; + fn is_codegen_unit_query(self) -> bool { + self == DepKind::codegen_unit + } + fn debug_node(node: &DepNode, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{:?}(", node.kind)?; @@ -93,50 +97,8 @@ impl<'tcx> DepContext for TyCtxt<'tcx> { self.sess } - #[inline(always)] - fn fingerprint_style(&self, kind: DepKind) -> rustc_query_system::dep_graph::FingerprintStyle { - kind.fingerprint_style(*self) - } - - #[inline(always)] - fn is_eval_always(&self, kind: DepKind) -> bool { - self.query_kind(kind).is_eval_always - } - - fn try_force_from_dep_node(&self, dep_node: DepNode) -> bool { - debug!("try_force_from_dep_node({:?}) --- trying to force", dep_node); - - // We must avoid ever having to call `force_from_dep_node()` for a - // `DepNode::codegen_unit`: - // Since we cannot reconstruct the query key of a `DepNode::codegen_unit`, we - // would always end up having to evaluate the first caller of the - // `codegen_unit` query that *is* reconstructible. This might very well be - // the `compile_codegen_unit` query, thus re-codegenning the whole CGU just - // to re-trigger calling the `codegen_unit` query with the right key. At - // that point we would already have re-done all the work we are trying to - // avoid doing in the first place. - // The solution is simple: Just explicitly call the `codegen_unit` query for - // each CGU, right after partitioning. This way `try_mark_green` will always - // hit the cache instead of having to go through `force_from_dep_node`. - // This assertion makes sure, we actually keep applying the solution above. - debug_assert!( - dep_node.kind != DepKind::codegen_unit, - "calling force_from_dep_node() on DepKind::codegen_unit" - ); - - let cb = self.query_kind(dep_node.kind); - if let Some(f) = cb.force_from_dep_node { - f(*self, dep_node); - true - } else { - false - } - } - - fn try_load_from_on_disk_cache(&self, dep_node: DepNode) { - let cb = self.query_kind(dep_node.kind); - if let Some(f) = cb.try_load_from_on_disk_cache { - f(*self, dep_node) - } + #[inline] + fn dep_kind_info(&self, dep_kind: DepKind) -> &DepKindStruct<'tcx> { + &self.query_kinds[dep_kind as usize] } } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 69bb9bb6fe04e..e430c327efe7c 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -1,7 +1,7 @@ //! Type context book-keeping. use crate::arena::Arena; -use crate::dep_graph::{DepGraph, DepKind, DepKindStruct}; +use crate::dep_graph::{DepGraph, DepKindStruct}; use crate::hir::place::Place as HirPlace; use crate::infer::canonical::{Canonical, CanonicalVarInfo, CanonicalVarInfos}; use crate::lint::{struct_lint_level, LintLevelSource}; @@ -1085,7 +1085,7 @@ pub struct GlobalCtxt<'tcx> { pub queries: &'tcx dyn query::QueryEngine<'tcx>, pub query_caches: query::QueryCaches<'tcx>, - query_kinds: &'tcx [DepKindStruct<'tcx>], + pub(crate) query_kinds: &'tcx [DepKindStruct<'tcx>], // Internal caches for metadata decoding. No need to track deps on this. pub ty_rcache: Lock>>, @@ -1292,10 +1292,6 @@ impl<'tcx> TyCtxt<'tcx> { } } - pub(crate) fn query_kind(self, k: DepKind) -> &'tcx DepKindStruct<'tcx> { - &self.query_kinds[k as usize] - } - /// Constructs a `TyKind::Error` type and registers a `delay_span_bug` to ensure it gets used. #[track_caller] pub fn ty_error(self) -> Ty<'tcx> { diff --git a/compiler/rustc_query_system/src/dep_graph/mod.rs b/compiler/rustc_query_system/src/dep_graph/mod.rs index 2b62a9ee42a6f..a5c274791261d 100644 --- a/compiler/rustc_query_system/src/dep_graph/mod.rs +++ b/compiler/rustc_query_system/src/dep_graph/mod.rs @@ -34,16 +34,61 @@ pub trait DepContext: Copy { /// Access the compiler session. fn sess(&self) -> &Session; - /// Return whether this kind always require evaluation. - fn is_eval_always(&self, kind: Self::DepKind) -> bool; + fn dep_kind_info(&self, dep_node: Self::DepKind) -> &DepKindStruct; + + #[inline(always)] + fn fingerprint_style(&self, kind: Self::DepKind) -> FingerprintStyle { + let data = self.dep_kind_info(kind); + if data.is_anon { + return FingerprintStyle::Opaque; + } + data.fingerprint_style + } - fn fingerprint_style(&self, kind: Self::DepKind) -> FingerprintStyle; + #[inline(always)] + /// Return whether this kind always require evaluation. + fn is_eval_always(&self, kind: Self::DepKind) -> bool { + self.dep_kind_info(kind).is_eval_always + } /// Try to force a dep node to execute and see if it's green. - fn try_force_from_dep_node(&self, dep_node: DepNode) -> bool; + fn try_force_from_dep_node(self, dep_node: DepNode) -> bool { + debug!("try_force_from_dep_node({:?}) --- trying to force", dep_node); + + // We must avoid ever having to call `force_from_dep_node()` for a + // `DepNode::codegen_unit`: + // Since we cannot reconstruct the query key of a `DepNode::codegen_unit`, we + // would always end up having to evaluate the first caller of the + // `codegen_unit` query that *is* reconstructible. This might very well be + // the `compile_codegen_unit` query, thus re-codegenning the whole CGU just + // to re-trigger calling the `codegen_unit` query with the right key. At + // that point we would already have re-done all the work we are trying to + // avoid doing in the first place. + // The solution is simple: Just explicitly call the `codegen_unit` query for + // each CGU, right after partitioning. This way `try_mark_green` will always + // hit the cache instead of having to go through `force_from_dep_node`. + // This assertion makes sure, we actually keep applying the solution above. + debug_assert!( + !dep_node.kind.is_codegen_unit_query(), + "calling force_from_dep_node() on DepKind::codegen_unit" + ); + + let cb = self.dep_kind_info(dep_node.kind); + if let Some(f) = cb.force_from_dep_node { + f(self, dep_node); + true + } else { + false + } + } /// Load data from the on-disk cache. - fn try_load_from_on_disk_cache(&self, dep_node: DepNode); + fn try_load_from_on_disk_cache(self, dep_node: DepNode) { + let cb = self.dep_kind_info(dep_node.kind); + if let Some(f) = cb.try_load_from_on_disk_cache { + f(self, dep_node) + } + } } pub trait HasDepContext: Copy { @@ -91,6 +136,8 @@ pub trait DepKind: Copy + fmt::Debug + Eq + Hash + Send + Encodable /// DepKind to use to create the initial forever-red node. const RED: Self; + fn is_codegen_unit_query(self) -> bool; + /// Implementation of `std::fmt::Debug` for `DepNode`. fn debug_node(node: &DepNode, f: &mut fmt::Formatter<'_>) -> fmt::Result; From ccc8d000f2281efc17f9329214116aedada088a5 Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Sun, 11 Sep 2022 23:31:50 -0500 Subject: [PATCH 233/586] Move some more code from rustc_middle to rustc_query_system --- compiler/rustc_middle/src/dep_graph/dep_node.rs | 15 +-------------- .../rustc_query_system/src/dep_graph/dep_node.rs | 12 ++++++++++++ 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_middle/src/dep_graph/dep_node.rs b/compiler/rustc_middle/src/dep_graph/dep_node.rs index 9b5b688d98a93..40b9d73db94cf 100644 --- a/compiler/rustc_middle/src/dep_graph/dep_node.rs +++ b/compiler/rustc_middle/src/dep_graph/dep_node.rs @@ -86,7 +86,7 @@ macro_rules! define_dep_nodes { $( $( #[$attr] )* $variant),* } - fn dep_kind_from_label_string(label: &str) -> Result { + pub(super) fn dep_kind_from_label_string(label: &str) -> Result { match label { $(stringify!($variant) => Ok(DepKind::$variant),)* _ => Err(()), @@ -141,11 +141,6 @@ static_assert_size!(DepNode, 18); static_assert_size!(DepNode, 24); pub trait DepNodeExt: Sized { - /// Construct a DepNode from the given DepKind and DefPathHash. This - /// method will assert that the given DepKind actually requires a - /// single DefId/DefPathHash parameter. - fn from_def_path_hash(tcx: TyCtxt<'_>, def_path_hash: DefPathHash, kind: DepKind) -> Self; - /// Extracts the DefId corresponding to this DepNode. This will work /// if two conditions are met: /// @@ -170,14 +165,6 @@ pub trait DepNodeExt: Sized { } impl DepNodeExt for DepNode { - /// Construct a DepNode from the given DepKind and DefPathHash. This - /// method will assert that the given DepKind actually requires a - /// single DefId/DefPathHash parameter. - fn from_def_path_hash(tcx: TyCtxt<'_>, def_path_hash: DefPathHash, kind: DepKind) -> DepNode { - debug_assert!(tcx.fingerprint_style(kind) == FingerprintStyle::DefPathHash); - DepNode { kind, hash: def_path_hash.0.into() } - } - /// Extracts the DefId corresponding to this DepNode. This will work /// if two conditions are met: /// diff --git a/compiler/rustc_query_system/src/dep_graph/dep_node.rs b/compiler/rustc_query_system/src/dep_graph/dep_node.rs index 2a3657780eca5..5c6ce0556eb8a 100644 --- a/compiler/rustc_query_system/src/dep_graph/dep_node.rs +++ b/compiler/rustc_query_system/src/dep_graph/dep_node.rs @@ -47,6 +47,7 @@ use crate::ich::StableHashingContext; use rustc_data_structures::fingerprint::{Fingerprint, PackedFingerprint}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; +use rustc_hir::definitions::DefPathHash; use std::fmt; use std::hash::Hash; @@ -88,6 +89,17 @@ impl DepNode { dep_node } + + /// Construct a DepNode from the given DepKind and DefPathHash. This + /// method will assert that the given DepKind actually requires a + /// single DefId/DefPathHash parameter. + pub fn from_def_path_hash(tcx: Ctxt, def_path_hash: DefPathHash, kind: K) -> Self + where + Ctxt: super::DepContext, + { + debug_assert!(tcx.fingerprint_style(kind) == FingerprintStyle::DefPathHash); + DepNode { kind, hash: def_path_hash.0.into() } + } } impl fmt::Debug for DepNode { From 00cde6d4b94bba23ad06b352bc589805574f62b2 Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Sun, 18 Sep 2022 16:35:48 -0500 Subject: [PATCH 234/586] Move the `codegen_unit` debug assert from `rustc_query_system` to `query_impl` This allows removing a function from the `DepKind` trait. --- compiler/rustc_middle/src/dep_graph/mod.rs | 4 ---- compiler/rustc_query_impl/src/plumbing.rs | 18 +++++++++++++++++ .../rustc_query_system/src/dep_graph/mod.rs | 20 ------------------- 3 files changed, 18 insertions(+), 24 deletions(-) diff --git a/compiler/rustc_middle/src/dep_graph/mod.rs b/compiler/rustc_middle/src/dep_graph/mod.rs index 6226fdd923aac..2e62bebc8525b 100644 --- a/compiler/rustc_middle/src/dep_graph/mod.rs +++ b/compiler/rustc_middle/src/dep_graph/mod.rs @@ -27,10 +27,6 @@ impl rustc_query_system::dep_graph::DepKind for DepKind { const NULL: Self = DepKind::Null; const RED: Self = DepKind::Red; - fn is_codegen_unit_query(self) -> bool { - self == DepKind::codegen_unit - } - fn debug_node(node: &DepNode, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{:?}(", node.kind)?; diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index d819f4774d54d..ac95c8edf3f12 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -380,6 +380,24 @@ where Q::Key: DepNodeParams>, Q::Value: Value>, { + // We must avoid ever having to call `force_from_dep_node()` for a + // `DepNode::codegen_unit`: + // Since we cannot reconstruct the query key of a `DepNode::codegen_unit`, we + // would always end up having to evaluate the first caller of the + // `codegen_unit` query that *is* reconstructible. This might very well be + // the `compile_codegen_unit` query, thus re-codegenning the whole CGU just + // to re-trigger calling the `codegen_unit` query with the right key. At + // that point we would already have re-done all the work we are trying to + // avoid doing in the first place. + // The solution is simple: Just explicitly call the `codegen_unit` query for + // each CGU, right after partitioning. This way `try_mark_green` will always + // hit the cache instead of having to go through `force_from_dep_node`. + // This assertion makes sure, we actually keep applying the solution above. + debug_assert!( + dep_node.kind != DepKind::codegen_unit, + "calling force_from_dep_node() on DepKind::codegen_unit" + ); + if let Some(key) = Q::Key::recover(tcx, &dep_node) { #[cfg(debug_assertions)] let _guard = tracing::span!(tracing::Level::TRACE, stringify!($name), ?key).entered(); diff --git a/compiler/rustc_query_system/src/dep_graph/mod.rs b/compiler/rustc_query_system/src/dep_graph/mod.rs index a5c274791261d..5003a14b91083 100644 --- a/compiler/rustc_query_system/src/dep_graph/mod.rs +++ b/compiler/rustc_query_system/src/dep_graph/mod.rs @@ -55,24 +55,6 @@ pub trait DepContext: Copy { fn try_force_from_dep_node(self, dep_node: DepNode) -> bool { debug!("try_force_from_dep_node({:?}) --- trying to force", dep_node); - // We must avoid ever having to call `force_from_dep_node()` for a - // `DepNode::codegen_unit`: - // Since we cannot reconstruct the query key of a `DepNode::codegen_unit`, we - // would always end up having to evaluate the first caller of the - // `codegen_unit` query that *is* reconstructible. This might very well be - // the `compile_codegen_unit` query, thus re-codegenning the whole CGU just - // to re-trigger calling the `codegen_unit` query with the right key. At - // that point we would already have re-done all the work we are trying to - // avoid doing in the first place. - // The solution is simple: Just explicitly call the `codegen_unit` query for - // each CGU, right after partitioning. This way `try_mark_green` will always - // hit the cache instead of having to go through `force_from_dep_node`. - // This assertion makes sure, we actually keep applying the solution above. - debug_assert!( - !dep_node.kind.is_codegen_unit_query(), - "calling force_from_dep_node() on DepKind::codegen_unit" - ); - let cb = self.dep_kind_info(dep_node.kind); if let Some(f) = cb.force_from_dep_node { f(self, dep_node); @@ -136,8 +118,6 @@ pub trait DepKind: Copy + fmt::Debug + Eq + Hash + Send + Encodable /// DepKind to use to create the initial forever-red node. const RED: Self; - fn is_codegen_unit_query(self) -> bool; - /// Implementation of `std::fmt::Debug` for `DepNode`. fn debug_node(node: &DepNode, f: &mut fmt::Formatter<'_>) -> fmt::Result; From a7c25b29575c17434406b69773f8c2961af343b3 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Sun, 25 Sep 2022 13:09:22 -0700 Subject: [PATCH 235/586] rustdoc: clean up `.out-of-band`/`.in-band` CSS * Remove the `float: right` fallback from the main header, which hasn't been needed since IE11 support was dropped. * Remove `in-band` from low-level headers, which hasn't been needed since `.rightside` switched to `float: right` in 593d6d1cb15c55c88319470dabb40126c7b7f1e2 * Remove unreachable `.in-band > code, .in-band > .code-header` CSS, since the `in-band` class was attached to the `code-header` itself, not nested directly below it. * Use `rem` instead of `em` for code header margins. * This results in a slight change in spacing around impls and item-info, but since it makes it more consistent with the way methods are presented, it's probably fine. --- src/librustdoc/html/render/mod.rs | 2 +- src/librustdoc/html/static/css/rustdoc.css | 19 +++++++------------ src/librustdoc/html/static/js/main.js | 1 - src/test/rustdoc-gui/headers-color.goml | 6 +++--- src/test/rustdoc-gui/implementors.goml | 8 ++++---- src/test/rustdoc-gui/src-font-size.goml | 2 +- 6 files changed, 16 insertions(+), 22 deletions(-) diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 1c4e666cd94af..75ac11a3a886e 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -1790,7 +1790,7 @@ pub(crate) fn render_impl_summary( write!(w, "
", id, aliases); render_rightside(w, cx, &i.impl_item, containing_item, RenderMode::Normal); write!(w, "", id); - write!(w, "

"); + write!(w, "

"); if let Some(use_absolute) = use_absolute { write!(w, "{}", inner_impl.print(use_absolute, cx)); diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index c4da1e4600955..28dc4bf30108e 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -176,8 +176,8 @@ h4.code-header { border-bottom-style: none; margin: 0; padding: 0; - margin-top: 0.6em; - margin-bottom: 0.4em; + margin-top: 0.6rem; + margin-bottom: 0.4rem; } .impl, .impl-items .method, @@ -658,18 +658,17 @@ h2.location a { overflow-x: auto; } -.content .out-of-band { +.out-of-band { flex-grow: 0; font-size: 1.125rem; font-weight: normal; - float: right; } .method > .code-header, .trait-impl > .code-header { display: block; } -.content .in-band { +.in-band { flex-grow: 1; margin: 0px; padding: 0px; @@ -682,10 +681,6 @@ h2.location a { background-color: var(--main-background-color); } -.in-band > code, .in-band > .code-header { - display: inline-block; -} - .docblock code, .docblock-short code, pre, .rustdoc.source .example-wrap { background-color: var(--code-block-background-color); @@ -1731,13 +1726,13 @@ in storage.js plus the media query with (min-width: 701px) flex-direction: column; } - .content .out-of-band { + .out-of-band { text-align: left; margin-left: initial; padding: initial; } - .content .out-of-band .since::before { + .out-of-band .since::before { content: "Since "; } @@ -1969,7 +1964,7 @@ in storage.js plus the media query with (min-width: 701px) } @media print { - nav.sidebar, nav.sub, .content .out-of-band, a.srclink, #copy-path, + nav.sidebar, nav.sub, .out-of-band, a.srclink, #copy-path, details.rustdoc-toggle[open] > summary::before, details.rustdoc-toggle > summary::before, details.rustdoc-toggle.top-doc > summary { display: none; diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js index 5fbe540c32045..c9674f11a5ecf 100644 --- a/src/librustdoc/html/static/js/main.js +++ b/src/librustdoc/html/static/js/main.js @@ -555,7 +555,6 @@ function loadCss(cssFileName) { const code = document.createElement("h3"); code.innerHTML = struct[TEXT_IDX]; addClass(code, "code-header"); - addClass(code, "in-band"); onEachLazy(code.getElementsByTagName("a"), elem => { const href = elem.getAttribute("href"); diff --git a/src/test/rustdoc-gui/headers-color.goml b/src/test/rustdoc-gui/headers-color.goml index a47a9c8a14c1f..4f01f1a162457 100644 --- a/src/test/rustdoc-gui/headers-color.goml +++ b/src/test/rustdoc-gui/headers-color.goml @@ -19,7 +19,7 @@ assert-css: ( ) assert-css: ( ".impl .code-header", - {"color": "rgb(230, 225, 207)", "background-color": "rgb(15, 20, 25)"}, + {"color": "rgb(230, 225, 207)", "background-color": "rgba(0, 0, 0, 0)"}, ALL, ) @@ -58,7 +58,7 @@ assert-css: ( ) assert-css: ( ".impl .code-header", - {"color": "rgb(221, 221, 221)", "background-color": "rgb(53, 53, 53)"}, + {"color": "rgb(221, 221, 221)", "background-color": "rgba(0, 0, 0, 0)"}, ALL, ) @@ -95,7 +95,7 @@ assert-css: ( ) assert-css: ( ".impl .code-header", - {"color": "rgb(0, 0, 0)", "background-color": "rgb(255, 255, 255)"}, + {"color": "rgb(0, 0, 0)", "background-color": "rgba(0, 0, 0, 0)"}, ALL, ) diff --git a/src/test/rustdoc-gui/implementors.goml b/src/test/rustdoc-gui/implementors.goml index 666a6e1253d9d..dc3b2e122680c 100644 --- a/src/test/rustdoc-gui/implementors.goml +++ b/src/test/rustdoc-gui/implementors.goml @@ -8,23 +8,23 @@ assert-count: ("#implementors-list .impl", 2) assert: ("#implementors-list .impl:nth-child(1) > a.anchor") assert-attribute: ("#implementors-list .impl:nth-child(1)", {"id": "impl-Whatever-for-Struct"}) assert-attribute: ("#implementors-list .impl:nth-child(1) > a.anchor", {"href": "#impl-Whatever-for-Struct"}) -assert: "#implementors-list .impl:nth-child(1) > .code-header.in-band" +assert: "#implementors-list .impl:nth-child(1) > .code-header" assert: ("#implementors-list .impl:nth-child(2) > a.anchor") assert-attribute: ("#implementors-list .impl:nth-child(2)", {"id": "impl-Whatever-1"}) assert-attribute: ("#implementors-list .impl:nth-child(2) > a.anchor", {"href": "#impl-Whatever-1"}) -assert: "#implementors-list .impl:nth-child(2) > .code-header.in-band" +assert: "#implementors-list .impl:nth-child(2) > .code-header" goto: file://|DOC_PATH|/test_docs/struct.HasEmptyTraits.html compare-elements-position-near-false: ( "#impl-EmptyTrait1-for-HasEmptyTraits", "#impl-EmptyTrait2-for-HasEmptyTraits", - {"y": 30}, + {"y": 34.1875}, ) compare-elements-position-near: ( "#impl-EmptyTrait3-for-HasEmptyTraits h3", "#impl-EmptyTrait3-for-HasEmptyTraits .item-info", - {"y": 30}, + {"y": 34.1875}, ) // Now check that re-exports work correctly. diff --git a/src/test/rustdoc-gui/src-font-size.goml b/src/test/rustdoc-gui/src-font-size.goml index 0c01e25455486..9797f196c5545 100644 --- a/src/test/rustdoc-gui/src-font-size.goml +++ b/src/test/rustdoc-gui/src-font-size.goml @@ -5,7 +5,7 @@ goto: file://|DOC_PATH|/test_docs/struct.Foo.html show-text: true // Check the impl headers. assert-css: (".impl.has-srclink .srclink", {"font-size": "16px"}, ALL) -assert-css: (".impl.has-srclink .code-header.in-band", {"font-size": "18px"}, ALL) +assert-css: (".impl.has-srclink .code-header", {"font-size": "18px"}, ALL) // Check the impl items. assert-css: (".impl-items .has-srclink .srclink", {"font-size": "16px"}, ALL) assert-css: (".impl-items .has-srclink .code-header", {"font-size": "16px"}, ALL) From 4ba40314e1a28e6230c6f404ee3b23de3efb7709 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Sun, 25 Sep 2022 13:52:26 -0700 Subject: [PATCH 236/586] rustdoc: update test cases now that code-header is used without in-band --- src/test/rustdoc/anonymous-lifetime.rs | 2 +- src/test/rustdoc/assoc-consts.rs | 4 ++-- src/test/rustdoc/blanket-reexport-item.rs | 2 +- src/test/rustdoc/const-generics/add-impl.rs | 2 +- .../const-generics/const-generics-docs.rs | 12 +++++------ src/test/rustdoc/const-generics/const-impl.rs | 10 +++++----- .../const-equate-pred.rs | 2 +- .../rustdoc/duplicate_impls/issue-33054.rs | 6 +++--- src/test/rustdoc/empty-impl-block.rs | 2 +- src/test/rustdoc/extern-impl.rs | 6 +++--- src/test/rustdoc/fn-bound.rs | 2 +- src/test/rustdoc/generic-impl.rs | 2 +- .../rustdoc/higher-ranked-trait-bounds.rs | 2 +- src/test/rustdoc/impl-disambiguation.rs | 10 +++++----- src/test/rustdoc/impl-parts.rs | 4 ++-- .../rustdoc/inline_cross/issue-31948-1.rs | 20 +++++++++---------- .../rustdoc/inline_cross/issue-31948-2.rs | 12 +++++------ src/test/rustdoc/inline_cross/issue-31948.rs | 20 +++++++++---------- src/test/rustdoc/inline_cross/issue-32881.rs | 4 ++-- src/test/rustdoc/inline_cross/issue-33113.rs | 4 ++-- src/test/rustdoc/inline_cross/trait-vis.rs | 2 +- src/test/rustdoc/inline_local/trait-vis.rs | 4 ++-- src/test/rustdoc/issue-29503.rs | 2 +- src/test/rustdoc/issue-33592.rs | 4 ++-- src/test/rustdoc/issue-46727.rs | 2 +- src/test/rustdoc/issue-50159.rs | 4 ++-- src/test/rustdoc/issue-51236.rs | 2 +- src/test/rustdoc/issue-54705.rs | 4 ++-- src/test/rustdoc/issue-55321.rs | 8 ++++---- src/test/rustdoc/issue-56822.rs | 2 +- src/test/rustdoc/issue-60726.rs | 4 ++-- src/test/rustdoc/issue-75588.rs | 4 ++-- .../issue-80233-normalize-auto-trait.rs | 2 +- .../issue-82465-asref-for-and-of-local.rs | 4 ++-- src/test/rustdoc/issue-98697.rs | 4 ++-- src/test/rustdoc/negative-impl.rs | 4 ++-- src/test/rustdoc/primitive-reference.rs | 2 +- .../primitive/primitive-generic-impl.rs | 2 +- src/test/rustdoc/recursive-deref.rs | 18 ++++++++--------- src/test/rustdoc/rfc-2632-const-trait-impl.rs | 8 ++++---- .../rustdoc/sidebar-links-to-foreign-impl.rs | 4 ++-- src/test/rustdoc/sized_trait.rs | 2 +- src/test/rustdoc/src-links-auto-impls.rs | 6 +++--- src/test/rustdoc/synthetic_auto/basic.rs | 4 ++-- src/test/rustdoc/synthetic_auto/complex.rs | 2 +- .../rustdoc/synthetic_auto/crate-local.rs | 6 +++--- src/test/rustdoc/synthetic_auto/lifetimes.rs | 4 ++-- src/test/rustdoc/synthetic_auto/manual.rs | 4 ++-- src/test/rustdoc/synthetic_auto/negative.rs | 4 ++-- src/test/rustdoc/synthetic_auto/nested.rs | 4 ++-- .../rustdoc/synthetic_auto/no-redundancy.rs | 2 +- src/test/rustdoc/synthetic_auto/overflow.rs | 2 +- src/test/rustdoc/synthetic_auto/project.rs | 4 ++-- .../synthetic_auto/self-referential.rs | 2 +- .../rustdoc/synthetic_auto/static-region.rs | 2 +- src/test/rustdoc/traits-in-bodies.rs | 6 +++--- src/test/rustdoc/typedef.rs | 4 ++-- src/test/rustdoc/where.rs | 10 +++++----- 58 files changed, 143 insertions(+), 143 deletions(-) diff --git a/src/test/rustdoc/anonymous-lifetime.rs b/src/test/rustdoc/anonymous-lifetime.rs index f5a7d225847c4..390ed5a1f938b 100644 --- a/src/test/rustdoc/anonymous-lifetime.rs +++ b/src/test/rustdoc/anonymous-lifetime.rs @@ -12,7 +12,7 @@ pub trait Stream { } // @has 'foo/trait.Stream.html' -// @has - '//*[@class="code-header in-band"]' 'impl Stream for &mut S' +// @has - '//*[@class="code-header"]' 'impl Stream for &mut S' impl Stream for &mut S { type Item = S::Item; diff --git a/src/test/rustdoc/assoc-consts.rs b/src/test/rustdoc/assoc-consts.rs index 97b7739b4c975..a3e10ee5555a0 100644 --- a/src/test/rustdoc/assoc-consts.rs +++ b/src/test/rustdoc/assoc-consts.rs @@ -13,7 +13,7 @@ pub trait Foo { pub struct Bar; impl Foo for Bar { - // @has assoc_consts/struct.Bar.html '//h3[@class="code-header in-band"]' 'impl Foo for Bar' + // @has assoc_consts/struct.Bar.html '//h3[@class="code-header"]' 'impl Foo for Bar' // @has - '//*[@id="associatedconstant.FOO"]' 'const FOO: usize' const FOO: usize = 12; // @has - '//*[@id="associatedconstant.FOO_NO_DEFAULT"]' 'const FOO_NO_DEFAULT: bool' @@ -81,7 +81,7 @@ pub trait Qux { const QUX_DEFAULT2: u32 = 3; } -// @has assoc_consts/struct.Bar.html '//h3[@class="code-header in-band"]' 'impl Qux for Bar' +// @has assoc_consts/struct.Bar.html '//h3[@class="code-header"]' 'impl Qux for Bar' impl Qux for Bar { // @has - '//*[@id="associatedconstant.QUX0"]' 'const QUX0: u8' // @has - '//*[@class="docblock"]' "Docs for QUX0 in trait." diff --git a/src/test/rustdoc/blanket-reexport-item.rs b/src/test/rustdoc/blanket-reexport-item.rs index 676d656dabf47..437f0001fcfc4 100644 --- a/src/test/rustdoc/blanket-reexport-item.rs +++ b/src/test/rustdoc/blanket-reexport-item.rs @@ -1,6 +1,6 @@ #![crate_name = "foo"] -// @has foo/struct.S.html '//*[@id="impl-Into%3CU%3E-for-S"]//h3[@class="code-header in-band"]' 'impl Into for T' +// @has foo/struct.S.html '//*[@id="impl-Into%3CU%3E-for-S"]//h3[@class="code-header"]' 'impl Into for T' pub struct S2 {} mod m { pub struct S {} diff --git a/src/test/rustdoc/const-generics/add-impl.rs b/src/test/rustdoc/const-generics/add-impl.rs index 591139523456e..6cbae9abebb73 100644 --- a/src/test/rustdoc/const-generics/add-impl.rs +++ b/src/test/rustdoc/const-generics/add-impl.rs @@ -7,7 +7,7 @@ pub struct Simd { inner: T, } -// @has foo/struct.Simd.html '//div[@id="trait-implementations-list"]//h3[@class="code-header in-band"]' 'impl Add> for Simd' +// @has foo/struct.Simd.html '//div[@id="trait-implementations-list"]//h3[@class="code-header"]' 'impl Add> for Simd' impl Add for Simd { type Output = Self; diff --git a/src/test/rustdoc/const-generics/const-generics-docs.rs b/src/test/rustdoc/const-generics/const-generics-docs.rs index 87d2f29e26055..5bf76e3c46908 100644 --- a/src/test/rustdoc/const-generics/const-generics-docs.rs +++ b/src/test/rustdoc/const-generics/const-generics-docs.rs @@ -19,10 +19,10 @@ pub use extern_crate::WTrait; // @has foo/trait.Trait.html '//pre[@class="rust trait"]' \ // 'pub trait Trait' -// @has - '//*[@id="impl-Trait%3C1%3E-for-u8"]//h3[@class="code-header in-band"]' 'impl Trait<1> for u8' -// @has - '//*[@id="impl-Trait%3C2%3E-for-u8"]//h3[@class="code-header in-band"]' 'impl Trait<2> for u8' -// @has - '//*[@id="impl-Trait%3C{1%20+%202}%3E-for-u8"]//h3[@class="code-header in-band"]' 'impl Trait<{1 + 2}> for u8' -// @has - '//*[@id="impl-Trait%3CN%3E-for-%5Bu8%3B%20N%5D"]//h3[@class="code-header in-band"]' \ +// @has - '//*[@id="impl-Trait%3C1%3E-for-u8"]//h3[@class="code-header"]' 'impl Trait<1> for u8' +// @has - '//*[@id="impl-Trait%3C2%3E-for-u8"]//h3[@class="code-header"]' 'impl Trait<2> for u8' +// @has - '//*[@id="impl-Trait%3C{1%20+%202}%3E-for-u8"]//h3[@class="code-header"]' 'impl Trait<{1 + 2}> for u8' +// @has - '//*[@id="impl-Trait%3CN%3E-for-%5Bu8%3B%20N%5D"]//h3[@class="code-header"]' \ // 'impl Trait for [u8; N]' pub trait Trait {} impl Trait<1> for u8 {} @@ -36,7 +36,7 @@ pub struct Foo where u8: Trait; // @has foo/struct.Bar.html '//pre[@class="rust struct"]' 'pub struct Bar(_)' pub struct Bar([T; N]); -// @has foo/struct.Foo.html '//*[@id="impl-Foo%3CM%3E"]/h3[@class="code-header in-band"]' 'impl Foowhere u8: Trait' +// @has foo/struct.Foo.html '//*[@id="impl-Foo%3CM%3E"]/h3[@class="code-header"]' 'impl Foowhere u8: Trait' impl Foo where u8: Trait { // @has - '//*[@id="associatedconstant.FOO_ASSOC"]' 'pub const FOO_ASSOC: usize' pub const FOO_ASSOC: usize = M + 13; @@ -47,7 +47,7 @@ impl Foo where u8: Trait { } } -// @has foo/struct.Bar.html '//*[@id="impl-Bar%3Cu8%2C%20M%3E"]/h3[@class="code-header in-band"]' 'impl Bar' +// @has foo/struct.Bar.html '//*[@id="impl-Bar%3Cu8%2C%20M%3E"]/h3[@class="code-header"]' 'impl Bar' impl Bar { // @has - '//*[@id="method.hey"]' \ // 'pub fn hey(&self) -> Foowhere u8: Trait' diff --git a/src/test/rustdoc/const-generics/const-impl.rs b/src/test/rustdoc/const-generics/const-impl.rs index f1181d54ac87f..75ee84279be3c 100644 --- a/src/test/rustdoc/const-generics/const-impl.rs +++ b/src/test/rustdoc/const-generics/const-impl.rs @@ -9,20 +9,20 @@ pub enum Order { } // @has foo/struct.VSet.html '//pre[@class="rust struct"]' 'pub struct VSet' -// @has foo/struct.VSet.html '//*[@id="impl-Send-for-VSet%3CT%2C%20ORDER%3E"]/h3[@class="code-header in-band"]' 'impl Send for VSet' -// @has foo/struct.VSet.html '//*[@id="impl-Sync-for-VSet%3CT%2C%20ORDER%3E"]/h3[@class="code-header in-band"]' 'impl Sync for VSet' +// @has foo/struct.VSet.html '//*[@id="impl-Send-for-VSet%3CT%2C%20ORDER%3E"]/h3[@class="code-header"]' 'impl Send for VSet' +// @has foo/struct.VSet.html '//*[@id="impl-Sync-for-VSet%3CT%2C%20ORDER%3E"]/h3[@class="code-header"]' 'impl Sync for VSet' pub struct VSet { inner: Vec, } -// @has foo/struct.VSet.html '//*[@id="impl-VSet%3CT%2C%20{%20Order%3A%3ASorted%20}%3E"]/h3[@class="code-header in-band"]' 'impl VSet' +// @has foo/struct.VSet.html '//*[@id="impl-VSet%3CT%2C%20{%20Order%3A%3ASorted%20}%3E"]/h3[@class="code-header"]' 'impl VSet' impl VSet { pub fn new() -> Self { Self { inner: Vec::new() } } } -// @has foo/struct.VSet.html '//*[@id="impl-VSet%3CT%2C%20{%20Order%3A%3AUnsorted%20}%3E"]/h3[@class="code-header in-band"]' 'impl VSet' +// @has foo/struct.VSet.html '//*[@id="impl-VSet%3CT%2C%20{%20Order%3A%3AUnsorted%20}%3E"]/h3[@class="code-header"]' 'impl VSet' impl VSet { pub fn new() -> Self { Self { inner: Vec::new() } @@ -31,7 +31,7 @@ impl VSet { pub struct Escape; -// @has foo/struct.Escape.html '//*[@id="impl-Escape%3Cr#%22%3Cscript%3Ealert(%22Escape%22)%3B%3C/script%3E%22#%3E"]/h3[@class="code-header in-band"]' 'impl Escapealert("Escape");"#>' +// @has foo/struct.Escape.html '//*[@id="impl-Escape%3Cr#%22%3Cscript%3Ealert(%22Escape%22)%3B%3C/script%3E%22#%3E"]/h3[@class="code-header"]' 'impl Escapealert("Escape");"#>' impl Escapealert("Escape");"#> { pub fn f() {} } diff --git a/src/test/rustdoc/const-generics/lazy_normalization_consts/const-equate-pred.rs b/src/test/rustdoc/const-generics/lazy_normalization_consts/const-equate-pred.rs index 4eac8e31e4529..310e89a35c4a9 100644 --- a/src/test/rustdoc/const-generics/lazy_normalization_consts/const-equate-pred.rs +++ b/src/test/rustdoc/const-generics/lazy_normalization_consts/const-equate-pred.rs @@ -12,7 +12,7 @@ pub struct Hasher { unsafe impl Send for Hasher {} // @has foo/struct.Foo.html -// @has - '//h3[@class="code-header in-band"]' 'impl Send for Foo' +// @has - '//h3[@class="code-header"]' 'impl Send for Foo' pub struct Foo { hasher: Hasher<[u8; 3]>, } diff --git a/src/test/rustdoc/duplicate_impls/issue-33054.rs b/src/test/rustdoc/duplicate_impls/issue-33054.rs index 84c9e4ac0cd84..c1f95ac91c394 100644 --- a/src/test/rustdoc/duplicate_impls/issue-33054.rs +++ b/src/test/rustdoc/duplicate_impls/issue-33054.rs @@ -1,12 +1,12 @@ // 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' +// @has - '//h3[@class="code-header"]' 'impl Foo' +// @has - '//h3[@class="code-header"]' 'impl Bar for Foo' // @count - '//*[@id="trait-implementations-list"]//*[@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' +// @has - '//h3[@class="code-header"]' 'impl Bar for Foo' // @count - '//*[@class="struct"]' 1 pub mod impls; diff --git a/src/test/rustdoc/empty-impl-block.rs b/src/test/rustdoc/empty-impl-block.rs index 6a2a254f63a7f..95d4db06b3171 100644 --- a/src/test/rustdoc/empty-impl-block.rs +++ b/src/test/rustdoc/empty-impl-block.rs @@ -16,5 +16,5 @@ pub struct Another; pub trait Bar {} // @has 'foo/struct.Another.html' -// @has - '//h3[@class="code-header in-band"]' 'impl Bar for Another' +// @has - '//h3[@class="code-header"]' 'impl Bar for Another' impl Bar for Another {} diff --git a/src/test/rustdoc/extern-impl.rs b/src/test/rustdoc/extern-impl.rs index f357d65df94be..fd1bc21400837 100644 --- a/src/test/rustdoc/extern-impl.rs +++ b/src/test/rustdoc/extern-impl.rs @@ -19,9 +19,9 @@ impl Foo { // @has foo/trait.Bar.html pub trait Bar {} -// @has - '//h3[@class="code-header in-band"]' 'impl Bar for fn()' +// @has - '//h3[@class="code-header"]' 'impl Bar for fn()' impl Bar for fn() {} -// @has - '//h3[@class="code-header in-band"]' 'impl Bar for extern "C" fn()' +// @has - '//h3[@class="code-header"]' 'impl Bar for extern "C" fn()' impl Bar for extern fn() {} -// @has - '//h3[@class="code-header in-band"]' 'impl Bar for extern "system" fn()' +// @has - '//h3[@class="code-header"]' 'impl Bar for extern "system" fn()' impl Bar for extern "system" fn() {} diff --git a/src/test/rustdoc/fn-bound.rs b/src/test/rustdoc/fn-bound.rs index 4c4ffddc8a648..9e060ff2026f6 100644 --- a/src/test/rustdoc/fn-bound.rs +++ b/src/test/rustdoc/fn-bound.rs @@ -11,7 +11,7 @@ pub struct ConditionalIterator { } -// @has 'fn_bound/struct.ConditionalIterator.html' '//h3[@class="code-header in-band"]' 'impl Iterator for ConditionalIterator' +// @has 'fn_bound/struct.ConditionalIterator.html' '//h3[@class="code-header"]' 'impl Iterator for ConditionalIterator' impl Iterator for ConditionalIterator { type Item = (); diff --git a/src/test/rustdoc/generic-impl.rs b/src/test/rustdoc/generic-impl.rs index c6beed70abeb1..6f68b1574992b 100644 --- a/src/test/rustdoc/generic-impl.rs +++ b/src/test/rustdoc/generic-impl.rs @@ -5,7 +5,7 @@ use std::fmt; // @!has foo/struct.Bar.html '//*[@id="impl-ToString-for-Bar"]' '' pub struct Bar; -// @has foo/struct.Foo.html '//*[@id="impl-ToString-for-Foo"]//h3[@class="code-header in-band"]' 'impl ToString for T' +// @has foo/struct.Foo.html '//*[@id="impl-ToString-for-Foo"]//h3[@class="code-header"]' 'impl ToString for T' pub struct Foo; // @has foo/struct.Foo.html '//*[@class="sidebar-elems"]//section//a[@href="#impl-ToString-for-Foo"]' 'ToString' diff --git a/src/test/rustdoc/higher-ranked-trait-bounds.rs b/src/test/rustdoc/higher-ranked-trait-bounds.rs index 59b5b6e5797cc..3493ae6d2bbb5 100644 --- a/src/test/rustdoc/higher-ranked-trait-bounds.rs +++ b/src/test/rustdoc/higher-ranked-trait-bounds.rs @@ -49,7 +49,7 @@ impl<'a> Foo<'a> { // @has foo/trait.B.html pub trait B<'x> {} -// @has - '//h3[@class="code-header in-band"]' "impl<'a> B<'a> for dyn for<'b> Trait<'b>" +// @has - '//h3[@class="code-header"]' "impl<'a> B<'a> for dyn for<'b> Trait<'b>" impl<'a> B<'a> for dyn for<'b> Trait<'b> {} // @has foo/struct.Bar.html diff --git a/src/test/rustdoc/impl-disambiguation.rs b/src/test/rustdoc/impl-disambiguation.rs index d1d39ccff328f..bb978dc0f3ec8 100644 --- a/src/test/rustdoc/impl-disambiguation.rs +++ b/src/test/rustdoc/impl-disambiguation.rs @@ -4,13 +4,13 @@ pub trait Foo {} pub struct Bar { field: T } -// @has foo/trait.Foo.html '//*[@class="item-list"]//h3[@class="code-header in-band"]' \ +// @has foo/trait.Foo.html '//*[@class="item-list"]//h3[@class="code-header"]' \ // "impl Foo for Bar" impl Foo for Bar {} -// @has foo/trait.Foo.html '//*[@class="item-list"]//h3[@class="code-header in-band"]' \ +// @has foo/trait.Foo.html '//*[@class="item-list"]//h3[@class="code-header"]' \ // "impl Foo for Bar" impl Foo for Bar {} -// @has foo/trait.Foo.html '//*[@class="item-list"]//h3[@class="code-header in-band"]' \ +// @has foo/trait.Foo.html '//*[@class="item-list"]//h3[@class="code-header"]' \ // "impl<'a> Foo for &'a Bar" impl<'a> Foo for &'a Bar {} @@ -22,9 +22,9 @@ pub mod mod2 { pub enum Baz {} } -// @has foo/trait.Foo.html '//*[@class="item-list"]//h3[@class="code-header in-band"]' \ +// @has foo/trait.Foo.html '//*[@class="item-list"]//h3[@class="code-header"]' \ // "impl Foo for foo::mod1::Baz" impl Foo for mod1::Baz {} -// @has foo/trait.Foo.html '//*[@class="item-list"]//h3[@class="code-header in-band"]' \ +// @has foo/trait.Foo.html '//*[@class="item-list"]//h3[@class="code-header"]' \ // "impl<'a> Foo for &'a foo::mod2::Baz" impl<'a> Foo for &'a mod2::Baz {} diff --git a/src/test/rustdoc/impl-parts.rs b/src/test/rustdoc/impl-parts.rs index b1481e1f27978..0a8c2c8d2a9e6 100644 --- a/src/test/rustdoc/impl-parts.rs +++ b/src/test/rustdoc/impl-parts.rs @@ -5,8 +5,8 @@ pub auto trait AnAutoTrait {} pub struct Foo { field: T } -// @has impl_parts/struct.Foo.html '//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ +// @has impl_parts/struct.Foo.html '//*[@class="impl has-srclink"]//h3[@class="code-header"]' \ // "impl !AnAutoTrait for Foowhere T: Sync," -// @has impl_parts/trait.AnAutoTrait.html '//*[@class="item-list"]//h3[@class="code-header in-band"]' \ +// @has impl_parts/trait.AnAutoTrait.html '//*[@class="item-list"]//h3[@class="code-header"]' \ // "impl !AnAutoTrait for Foowhere T: Sync," impl !AnAutoTrait for Foo where T: Sync {} diff --git a/src/test/rustdoc/inline_cross/issue-31948-1.rs b/src/test/rustdoc/inline_cross/issue-31948-1.rs index be8585dd16e17..6e89167b3a451 100644 --- a/src/test/rustdoc/inline_cross/issue-31948-1.rs +++ b/src/test/rustdoc/inline_cross/issue-31948-1.rs @@ -5,22 +5,22 @@ extern crate rustdoc_nonreachable_impls; // @has issue_31948_1/struct.Wobble.html -// @has - '//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' 'Bark for' -// @has - '//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' 'Woof for' -// @!has - '//*[@class="impl"]//h3[@class="code-header in-band"]' 'Bar for' -// @!has - '//*[@class="impl"]//h3[@class="code-header in-band"]' 'Qux for' +// @has - '//*[@class="impl has-srclink"]//h3[@class="code-header"]' 'Bark for' +// @has - '//*[@class="impl has-srclink"]//h3[@class="code-header"]' 'Woof for' +// @!has - '//*[@class="impl"]//h3[@class="code-header"]' 'Bar for' +// @!has - '//*[@class="impl"]//h3[@class="code-header"]' 'Qux for' pub use rustdoc_nonreachable_impls::hidden::Wobble; // @has issue_31948_1/trait.Bark.html -// @has - '//h3[@class="code-header in-band"]' 'for Foo' -// @has - '//h3[@class="code-header in-band"]' 'for Wobble' -// @!has - '//h3[@class="code-header in-band"]' 'for Wibble' +// @has - '//h3[@class="code-header"]' 'for Foo' +// @has - '//h3[@class="code-header"]' 'for Wobble' +// @!has - '//h3[@class="code-header"]' 'for Wibble' pub use rustdoc_nonreachable_impls::Bark; // @has issue_31948_1/trait.Woof.html -// @has - '//h3[@class="code-header in-band"]' 'for Foo' -// @has - '//h3[@class="code-header in-band"]' 'for Wobble' -// @!has - '//h3[@class="code-header in-band"]' 'for Wibble' +// @has - '//h3[@class="code-header"]' 'for Foo' +// @has - '//h3[@class="code-header"]' 'for Wobble' +// @!has - '//h3[@class="code-header"]' 'for Wibble' pub use rustdoc_nonreachable_impls::Woof; // @!has issue_31948_1/trait.Bar.html diff --git a/src/test/rustdoc/inline_cross/issue-31948-2.rs b/src/test/rustdoc/inline_cross/issue-31948-2.rs index 7aa994f19d6f1..141e07656a09c 100644 --- a/src/test/rustdoc/inline_cross/issue-31948-2.rs +++ b/src/test/rustdoc/inline_cross/issue-31948-2.rs @@ -5,15 +5,15 @@ extern crate rustdoc_nonreachable_impls; // @has issue_31948_2/struct.Wobble.html -// @has - '//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' 'Qux for' -// @has - '//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' 'Bark for' -// @has - '//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' 'Woof for' -// @!has - '//*[@class="impl"]//h3[@class="code-header in-band"]' 'Bar for' +// @has - '//*[@class="impl has-srclink"]//h3[@class="code-header"]' 'Qux for' +// @has - '//*[@class="impl has-srclink"]//h3[@class="code-header"]' 'Bark for' +// @has - '//*[@class="impl has-srclink"]//h3[@class="code-header"]' 'Woof for' +// @!has - '//*[@class="impl"]//h3[@class="code-header"]' 'Bar for' pub use rustdoc_nonreachable_impls::hidden::Wobble; // @has issue_31948_2/trait.Qux.html -// @has - '//h3[@class="code-header in-band"]' 'for Foo' -// @has - '//h3[@class="code-header in-band"]' 'for Wobble' +// @has - '//h3[@class="code-header"]' 'for Foo' +// @has - '//h3[@class="code-header"]' 'for Wobble' pub use rustdoc_nonreachable_impls::hidden::Qux; // @!has issue_31948_2/trait.Bar.html diff --git a/src/test/rustdoc/inline_cross/issue-31948.rs b/src/test/rustdoc/inline_cross/issue-31948.rs index 7bf4110d32ac1..96fc6ca47e7f6 100644 --- a/src/test/rustdoc/inline_cross/issue-31948.rs +++ b/src/test/rustdoc/inline_cross/issue-31948.rs @@ -5,22 +5,22 @@ extern crate rustdoc_nonreachable_impls; // @has issue_31948/struct.Foo.html -// @has - '//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' 'Bark for' -// @has - '//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' 'Woof for' -// @!has - '//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' 'Bar for' -// @!has - '//*[@class="impl"]//h3[@class="code-header in-band"]' 'Qux for' +// @has - '//*[@class="impl has-srclink"]//h3[@class="code-header"]' 'Bark for' +// @has - '//*[@class="impl has-srclink"]//h3[@class="code-header"]' 'Woof for' +// @!has - '//*[@class="impl has-srclink"]//h3[@class="code-header"]' 'Bar for' +// @!has - '//*[@class="impl"]//h3[@class="code-header"]' 'Qux for' pub use rustdoc_nonreachable_impls::Foo; // @has issue_31948/trait.Bark.html -// @has - '//h3[@class="code-header in-band"]' 'for Foo' -// @!has - '//h3[@class="code-header in-band"]' 'for Wibble' -// @!has - '//h3[@class="code-header in-band"]' 'for Wobble' +// @has - '//h3[@class="code-header"]' 'for Foo' +// @!has - '//h3[@class="code-header"]' 'for Wibble' +// @!has - '//h3[@class="code-header"]' 'for Wobble' pub use rustdoc_nonreachable_impls::Bark; // @has issue_31948/trait.Woof.html -// @has - '//h3[@class="code-header in-band"]' 'for Foo' -// @!has - '//h3[@class="code-header in-band"]' 'for Wibble' -// @!has - '//h3[@class="code-header in-band"]' 'for Wobble' +// @has - '//h3[@class="code-header"]' 'for Foo' +// @!has - '//h3[@class="code-header"]' 'for Wibble' +// @!has - '//h3[@class="code-header"]' 'for Wobble' pub use rustdoc_nonreachable_impls::Woof; // @!has issue_31948/trait.Bar.html diff --git a/src/test/rustdoc/inline_cross/issue-32881.rs b/src/test/rustdoc/inline_cross/issue-32881.rs index 8052339a83b6d..183fd15abbe17 100644 --- a/src/test/rustdoc/inline_cross/issue-32881.rs +++ b/src/test/rustdoc/inline_cross/issue-32881.rs @@ -5,7 +5,7 @@ extern crate rustdoc_trait_object_impl; // @has issue_32881/trait.Bar.html -// @has - '//h3[@class="code-header in-band"]' "impl<'a> dyn Bar" -// @has - '//h3[@class="code-header in-band"]' "impl<'a> Debug for dyn Bar" +// @has - '//h3[@class="code-header"]' "impl<'a> dyn Bar" +// @has - '//h3[@class="code-header"]' "impl<'a> Debug for dyn Bar" pub use rustdoc_trait_object_impl::Bar; diff --git a/src/test/rustdoc/inline_cross/issue-33113.rs b/src/test/rustdoc/inline_cross/issue-33113.rs index c60859bbcea98..d954707facfe6 100644 --- a/src/test/rustdoc/inline_cross/issue-33113.rs +++ b/src/test/rustdoc/inline_cross/issue-33113.rs @@ -5,6 +5,6 @@ extern crate bar; // @has issue_33113/trait.Bar.html -// @has - '//h3[@class="code-header in-band"]' "for &'a char" -// @has - '//h3[@class="code-header in-band"]' "for Foo" +// @has - '//h3[@class="code-header"]' "for &'a char" +// @has - '//h3[@class="code-header"]' "for Foo" pub use bar::Bar; diff --git a/src/test/rustdoc/inline_cross/trait-vis.rs b/src/test/rustdoc/inline_cross/trait-vis.rs index 363c52a336e42..b646babacc5cc 100644 --- a/src/test/rustdoc/inline_cross/trait-vis.rs +++ b/src/test/rustdoc/inline_cross/trait-vis.rs @@ -3,5 +3,5 @@ extern crate inner; // @has trait_vis/struct.SomeStruct.html -// @has - '//h3[@class="code-header in-band"]' 'impl Clone for SomeStruct' +// @has - '//h3[@class="code-header"]' 'impl Clone for SomeStruct' pub use inner::SomeStruct; diff --git a/src/test/rustdoc/inline_local/trait-vis.rs b/src/test/rustdoc/inline_local/trait-vis.rs index e7b08088f4032..19b69da15138b 100644 --- a/src/test/rustdoc/inline_local/trait-vis.rs +++ b/src/test/rustdoc/inline_local/trait-vis.rs @@ -13,6 +13,6 @@ mod asdf { } // @has trait_vis/struct.SomeStruct.html -// @has - '//h3[@class="code-header in-band"]' 'impl ThisTrait for SomeStruct' -// @!has - '//h3[@class="code-header in-band"]' 'impl PrivateTrait for SomeStruct' +// @has - '//h3[@class="code-header"]' 'impl ThisTrait for SomeStruct' +// @!has - '//h3[@class="code-header"]' 'impl PrivateTrait for SomeStruct' pub use asdf::SomeStruct; diff --git a/src/test/rustdoc/issue-29503.rs b/src/test/rustdoc/issue-29503.rs index 134821e1ef3ea..01ae4438500da 100644 --- a/src/test/rustdoc/issue-29503.rs +++ b/src/test/rustdoc/issue-29503.rs @@ -5,7 +5,7 @@ pub trait MyTrait { fn my_string(&self) -> String; } -// @has - "//div[@id='implementors-list']//*[@id='impl-MyTrait-for-T']//h3[@class='code-header in-band']" "impl MyTrait for Twhere T: Debug" +// @has - "//div[@id='implementors-list']//*[@id='impl-MyTrait-for-T']//h3[@class='code-header']" "impl MyTrait for Twhere T: Debug" impl MyTrait for T where T: fmt::Debug, diff --git a/src/test/rustdoc/issue-33592.rs b/src/test/rustdoc/issue-33592.rs index 815439db9bfd2..7a128f0b897ed 100644 --- a/src/test/rustdoc/issue-33592.rs +++ b/src/test/rustdoc/issue-33592.rs @@ -6,8 +6,8 @@ pub struct Bar; pub struct Baz; -// @has foo/trait.Foo.html '//h3[@class="code-header in-band"]' 'impl Foo for Bar' +// @has foo/trait.Foo.html '//h3[@class="code-header"]' 'impl Foo for Bar' impl Foo for Bar {} -// @has foo/trait.Foo.html '//h3[@class="code-header in-band"]' 'impl Foo for Baz' +// @has foo/trait.Foo.html '//h3[@class="code-header"]' 'impl Foo for Baz' impl Foo for Baz {} diff --git a/src/test/rustdoc/issue-46727.rs b/src/test/rustdoc/issue-46727.rs index 00e9127a34d20..8cfc4827a7f4c 100644 --- a/src/test/rustdoc/issue-46727.rs +++ b/src/test/rustdoc/issue-46727.rs @@ -3,5 +3,5 @@ extern crate issue_46727; // @has issue_46727/trait.Foo.html -// @has - '//h3[@class="code-header in-band"]' 'impl Foo for Bar<[T; 3]>' +// @has - '//h3[@class="code-header"]' 'impl Foo for Bar<[T; 3]>' pub use issue_46727::{Foo, Bar}; diff --git a/src/test/rustdoc/issue-50159.rs b/src/test/rustdoc/issue-50159.rs index 43fb705f58994..04bc4f304d68a 100644 --- a/src/test/rustdoc/issue-50159.rs +++ b/src/test/rustdoc/issue-50159.rs @@ -11,8 +11,8 @@ impl Signal2 for B where B: Signal { } // @has issue_50159/struct.Switch.html -// @has - '//h3[@class="code-header in-band"]' 'impl Send for Switchwhere ::Item: Send' -// @has - '//h3[@class="code-header in-band"]' 'impl Sync for Switchwhere ::Item: Sync' +// @has - '//h3[@class="code-header"]' 'impl Send for Switchwhere ::Item: Send' +// @has - '//h3[@class="code-header"]' 'impl Sync for Switchwhere ::Item: Sync' // @count - '//*[@id="implementations-list"]//*[@class="impl"]' 0 // @count - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]' 5 pub struct Switch { diff --git a/src/test/rustdoc/issue-51236.rs b/src/test/rustdoc/issue-51236.rs index aa5890a84514f..1c7aa9c7eefe5 100644 --- a/src/test/rustdoc/issue-51236.rs +++ b/src/test/rustdoc/issue-51236.rs @@ -7,7 +7,7 @@ pub mod traits { } // @has issue_51236/struct.Owned.html -// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ +// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header"]' \ // "impl Send for Ownedwhere >::Reader: Send" pub struct Owned where T: for<'a> ::traits::Owned<'a> { marker: PhantomData<>::Reader>, diff --git a/src/test/rustdoc/issue-54705.rs b/src/test/rustdoc/issue-54705.rs index ce0f85d25da56..7b7290ab4b77c 100644 --- a/src/test/rustdoc/issue-54705.rs +++ b/src/test/rustdoc/issue-54705.rs @@ -1,10 +1,10 @@ pub trait ScopeHandle<'scope> {} // @has issue_54705/struct.ScopeFutureContents.html -// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ +// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header"]' \ // "impl<'scope, S> Send for ScopeFutureContents<'scope, S>where S: Sync" // -// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ +// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header"]' \ // "impl<'scope, S> Sync for ScopeFutureContents<'scope, S>where S: Sync" pub struct ScopeFutureContents<'scope, S> where S: ScopeHandle<'scope>, diff --git a/src/test/rustdoc/issue-55321.rs b/src/test/rustdoc/issue-55321.rs index ee2420d86d236..22a18ef90e13a 100644 --- a/src/test/rustdoc/issue-55321.rs +++ b/src/test/rustdoc/issue-55321.rs @@ -1,9 +1,9 @@ #![feature(negative_impls)] // @has issue_55321/struct.A.html -// @has - '//*[@id="trait-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ +// @has - '//*[@id="trait-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header"]' \ // "impl !Send for A" -// @has - '//*[@id="trait-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ +// @has - '//*[@id="trait-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header"]' \ // "impl !Sync for A" pub struct A(); @@ -11,8 +11,8 @@ impl !Send for A {} impl !Sync for A {} // @has issue_55321/struct.B.html -// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ +// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header"]' \ // "impl !Send for B" -// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ +// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header"]' \ // "impl !Sync for B" pub struct B(A, Box); diff --git a/src/test/rustdoc/issue-56822.rs b/src/test/rustdoc/issue-56822.rs index aef6ddd8d23bc..b4eef344b5f3b 100644 --- a/src/test/rustdoc/issue-56822.rs +++ b/src/test/rustdoc/issue-56822.rs @@ -17,7 +17,7 @@ impl<'a, T> MyTrait for Inner<'a, T> { } // @has issue_56822/struct.Parser.html -// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ +// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header"]' \ // "impl<'a> Send for Parser<'a>" pub struct Parser<'a> { field: > as MyTrait>::Output diff --git a/src/test/rustdoc/issue-60726.rs b/src/test/rustdoc/issue-60726.rs index 167f0f039c15e..fbb0f82ae3957 100644 --- a/src/test/rustdoc/issue-60726.rs +++ b/src/test/rustdoc/issue-60726.rs @@ -26,9 +26,9 @@ where {} // @has issue_60726/struct.IntoIter.html -// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ +// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header"]' \ // "impl !Send for IntoIter" -// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ +// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header"]' \ // "impl !Sync for IntoIter" pub struct IntoIter{ hello:DynTrait>, diff --git a/src/test/rustdoc/issue-75588.rs b/src/test/rustdoc/issue-75588.rs index ac97b94fb351b..3b11059a755d0 100644 --- a/src/test/rustdoc/issue-75588.rs +++ b/src/test/rustdoc/issue-75588.rs @@ -10,8 +10,8 @@ extern crate realcore; extern crate real_gimli; // issue #74672 -// @!has foo/trait.Deref.html '//*[@id="impl-Deref-for-EndianSlice"]//h3[@class="code-header in-band"]' 'impl Deref for EndianSlice' +// @!has foo/trait.Deref.html '//*[@id="impl-Deref-for-EndianSlice"]//h3[@class="code-header"]' 'impl Deref for EndianSlice' pub use realcore::Deref; -// @has foo/trait.Join.html '//*[@id="impl-Join-for-Foo"]//h3[@class="code-header in-band"]' 'impl Join for Foo' +// @has foo/trait.Join.html '//*[@id="impl-Join-for-Foo"]//h3[@class="code-header"]' 'impl Join for Foo' pub use realcore::Join; diff --git a/src/test/rustdoc/issue-80233-normalize-auto-trait.rs b/src/test/rustdoc/issue-80233-normalize-auto-trait.rs index 515e617b4f4ce..62fbc2444dbc2 100644 --- a/src/test/rustdoc/issue-80233-normalize-auto-trait.rs +++ b/src/test/rustdoc/issue-80233-normalize-auto-trait.rs @@ -31,7 +31,7 @@ impl Trait3 for Vec { pub struct Struct1 {} // @has issue_80233_normalize_auto_trait/struct.Question.html -// @has - '//h3[@class="code-header in-band"]' 'impl Send for Question' +// @has - '//h3[@class="code-header"]' 'impl Send for Question' pub struct Question { pub ins: < as Trait3>::Type3 as Trait2>::Type2, } diff --git a/src/test/rustdoc/issue-82465-asref-for-and-of-local.rs b/src/test/rustdoc/issue-82465-asref-for-and-of-local.rs index 8999e6a889bda..adf4d111a6cb9 100644 --- a/src/test/rustdoc/issue-82465-asref-for-and-of-local.rs +++ b/src/test/rustdoc/issue-82465-asref-for-and-of-local.rs @@ -1,14 +1,14 @@ use std::convert::AsRef; pub struct Local; -// @has issue_82465_asref_for_and_of_local/struct.Local.html '//h3[@class="code-header in-band"]' 'impl AsRef for Local' +// @has issue_82465_asref_for_and_of_local/struct.Local.html '//h3[@class="code-header"]' 'impl AsRef for Local' impl AsRef for Local { fn as_ref(&self) -> &str { todo!() } } -// @has - '//h3[@class="code-header in-band"]' 'impl AsRef for str' +// @has - '//h3[@class="code-header"]' 'impl AsRef for str' impl AsRef for str { fn as_ref(&self) -> &Local { todo!() diff --git a/src/test/rustdoc/issue-98697.rs b/src/test/rustdoc/issue-98697.rs index a8841f137fecf..d50268509b2c1 100644 --- a/src/test/rustdoc/issue-98697.rs +++ b/src/test/rustdoc/issue-98697.rs @@ -12,6 +12,6 @@ extern crate issue_98697_reexport_with_anonymous_lifetime; // @!has issue_98697/fn.repro.html '//pre[@class="rust fn"]/code' 'for<' pub use issue_98697_reexport_with_anonymous_lifetime::repro; -// @has issue_98697/struct.Extra.html '//div[@id="trait-implementations-list"]//h3[@class="code-header in-band"]' 'impl MyTrait<&Extra> for Extra' -// @!has issue_98697/struct.Extra.html '//div[@id="trait-implementations-list"]//h3[@class="code-header in-band"]' 'impl<' +// @has issue_98697/struct.Extra.html '//div[@id="trait-implementations-list"]//h3[@class="code-header"]' 'impl MyTrait<&Extra> for Extra' +// @!has issue_98697/struct.Extra.html '//div[@id="trait-implementations-list"]//h3[@class="code-header"]' 'impl<' pub use issue_98697_reexport_with_anonymous_lifetime::Extra; diff --git a/src/test/rustdoc/negative-impl.rs b/src/test/rustdoc/negative-impl.rs index 61a2398686230..af19c784d6d05 100644 --- a/src/test/rustdoc/negative-impl.rs +++ b/src/test/rustdoc/negative-impl.rs @@ -5,10 +5,10 @@ pub struct Alpha; // @matches negative_impl/struct.Bravo.html '//pre' "pub struct Bravo" pub struct Bravo(B); -// @matches negative_impl/struct.Alpha.html '//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ +// @matches negative_impl/struct.Alpha.html '//*[@class="impl has-srclink"]//h3[@class="code-header"]' \ // "impl !Send for Alpha" impl !Send for Alpha {} -// @matches negative_impl/struct.Bravo.html '//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' "\ +// @matches negative_impl/struct.Bravo.html '//*[@class="impl has-srclink"]//h3[@class="code-header"]' "\ // impl !Send for Bravo" impl !Send for Bravo {} diff --git a/src/test/rustdoc/primitive-reference.rs b/src/test/rustdoc/primitive-reference.rs index 5c11934060922..431c9aa79c7f9 100644 --- a/src/test/rustdoc/primitive-reference.rs +++ b/src/test/rustdoc/primitive-reference.rs @@ -14,7 +14,7 @@ // There should be only one implementation listed. // @count - '//*[@class="impl has-srclink"]' 1 -// @has - '//*[@id="impl-Foo%3C%26A%3E-for-%26B"]/*[@class="code-header in-band"]' \ +// @has - '//*[@id="impl-Foo%3C%26A%3E-for-%26B"]/*[@class="code-header"]' \ // 'impl Foo<&A> for &B' #[doc(primitive = "reference")] /// this is a test! diff --git a/src/test/rustdoc/primitive/primitive-generic-impl.rs b/src/test/rustdoc/primitive/primitive-generic-impl.rs index eebb2cf5a355d..7b336b3981047 100644 --- a/src/test/rustdoc/primitive/primitive-generic-impl.rs +++ b/src/test/rustdoc/primitive/primitive-generic-impl.rs @@ -1,7 +1,7 @@ #![feature(rustdoc_internals)] #![crate_name = "foo"] -// @has foo/primitive.i32.html '//*[@id="impl-ToString-for-i32"]//h3[@class="code-header in-band"]' 'impl ToString for T' +// @has foo/primitive.i32.html '//*[@id="impl-ToString-for-i32"]//h3[@class="code-header"]' 'impl ToString for T' #[doc(primitive = "i32")] /// Some useless docs, wouhou! diff --git a/src/test/rustdoc/recursive-deref.rs b/src/test/rustdoc/recursive-deref.rs index 2ab9d44be6dac..aa38485c44558 100644 --- a/src/test/rustdoc/recursive-deref.rs +++ b/src/test/rustdoc/recursive-deref.rs @@ -9,7 +9,7 @@ impl C { pub fn c(&self) {} } -// @has recursive_deref/struct.A.html '//h3[@class="code-header in-band"]' 'impl Deref for A' +// @has recursive_deref/struct.A.html '//h3[@class="code-header"]' 'impl Deref for A' // @has '-' '//*[@class="impl-items"]//*[@id="method.c"]' 'pub fn c(&self)' impl Deref for A { type Target = B; @@ -19,7 +19,7 @@ impl Deref for A { } } -// @has recursive_deref/struct.B.html '//h3[@class="code-header in-band"]' 'impl Deref for B' +// @has recursive_deref/struct.B.html '//h3[@class="code-header"]' 'impl Deref for B' // @has '-' '//*[@class="impl-items"]//*[@id="method.c"]' 'pub fn c(&self)' impl Deref for B { type Target = C; @@ -29,7 +29,7 @@ impl Deref for B { } } -// @has recursive_deref/struct.C.html '//h3[@class="code-header in-band"]' 'impl Deref for C' +// @has recursive_deref/struct.C.html '//h3[@class="code-header"]' 'impl Deref for C' impl Deref for C { type Target = B; @@ -49,7 +49,7 @@ impl G { pub fn g() {} } -// @has recursive_deref/struct.D.html '//h3[@class="code-header in-band"]' 'impl Deref for D' +// @has recursive_deref/struct.D.html '//h3[@class="code-header"]' 'impl Deref for D' // We also check that `G::g` method isn't rendered because there is no `self` argument. // @!has '-' '//*[@id="deref-methods-G"]' '' impl Deref for D { @@ -60,7 +60,7 @@ impl Deref for D { } } -// @has recursive_deref/struct.E.html '//h3[@class="code-header in-band"]' 'impl Deref for E' +// @has recursive_deref/struct.E.html '//h3[@class="code-header"]' 'impl Deref for E' // We also check that `G::g` method isn't rendered because there is no `self` argument. // @!has '-' '//*[@id="deref-methods-G"]' '' impl Deref for E { @@ -71,7 +71,7 @@ impl Deref for E { } } -// @has recursive_deref/struct.F.html '//h3[@class="code-header in-band"]' 'impl Deref for F' +// @has recursive_deref/struct.F.html '//h3[@class="code-header"]' 'impl Deref for F' // We also check that `G::g` method isn't rendered because there is no `self` argument. // @!has '-' '//*[@id="deref-methods-G"]' '' impl Deref for F { @@ -82,7 +82,7 @@ impl Deref for F { } } -// @has recursive_deref/struct.G.html '//h3[@class="code-header in-band"]' 'impl Deref for G' +// @has recursive_deref/struct.G.html '//h3[@class="code-header"]' 'impl Deref for G' impl Deref for G { type Target = E; @@ -100,7 +100,7 @@ impl I { pub fn i() {} } -// @has recursive_deref/struct.H.html '//h3[@class="code-header in-band"]' 'impl Deref for H' +// @has recursive_deref/struct.H.html '//h3[@class="code-header"]' 'impl Deref for H' // @!has '-' '//*[@id="deref-methods-I"]' '' impl Deref for H { type Target = I; @@ -110,7 +110,7 @@ impl Deref for H { } } -// @has recursive_deref/struct.I.html '//h3[@class="code-header in-band"]' 'impl Deref for I' +// @has recursive_deref/struct.I.html '//h3[@class="code-header"]' 'impl Deref for I' impl Deref for I { type Target = H; diff --git a/src/test/rustdoc/rfc-2632-const-trait-impl.rs b/src/test/rustdoc/rfc-2632-const-trait-impl.rs index f3e211e301742..8bd402291aabf 100644 --- a/src/test/rustdoc/rfc-2632-const-trait-impl.rs +++ b/src/test/rustdoc/rfc-2632-const-trait-impl.rs @@ -30,10 +30,10 @@ pub trait Tr { } // @has - '//section[@id="impl-Tr%3CT%3E-for-T"]' '' -// @!has - '//section[@id="impl-Tr%3CT%3E-for-T"]/h3[@class="code-header in-band"]' '~const' -// @has - '//section[@id="impl-Tr%3CT%3E-for-T"]/h3[@class="code-header in-band"]/a[@class="trait"]' 'Clone' -// @!has - '//section[@id="impl-Tr%3CT%3E-for-T"]/h3[@class="code-header in-band"]/span[@class="where"]' '~const' -// @has - '//section[@id="impl-Tr%3CT%3E-for-T"]/h3[@class="code-header in-band"]/span[@class="where fmt-newline"]' ': Clone' +// @!has - '//section[@id="impl-Tr%3CT%3E-for-T"]/h3[@class="code-header"]' '~const' +// @has - '//section[@id="impl-Tr%3CT%3E-for-T"]/h3[@class="code-header"]/a[@class="trait"]' 'Clone' +// @!has - '//section[@id="impl-Tr%3CT%3E-for-T"]/h3[@class="code-header"]/span[@class="where"]' '~const' +// @has - '//section[@id="impl-Tr%3CT%3E-for-T"]/h3[@class="code-header"]/span[@class="where fmt-newline"]' ': Clone' impl const Tr for T where Option: ~const Clone + ~const Destruct, diff --git a/src/test/rustdoc/sidebar-links-to-foreign-impl.rs b/src/test/rustdoc/sidebar-links-to-foreign-impl.rs index 1551503965999..6712af527a377 100644 --- a/src/test/rustdoc/sidebar-links-to-foreign-impl.rs +++ b/src/test/rustdoc/sidebar-links-to-foreign-impl.rs @@ -6,9 +6,9 @@ // @has - '//*[@class="sidebar-title"]/a[@href="#foreign-impls"]' 'Implementations on Foreign Types' // @has - '//h2[@id="foreign-impls"]' 'Implementations on Foreign Types' // @has - '//*[@class="sidebar-elems"]//section//a[@href="#impl-Foo-for-u32"]' 'u32' -// @has - '//*[@id="impl-Foo-for-u32"]//h3[@class="code-header in-band"]' 'impl Foo for u32' +// @has - '//*[@id="impl-Foo-for-u32"]//h3[@class="code-header"]' 'impl Foo for u32' // @has - '//*[@class="sidebar-elems"]//section//a[@href="#impl-Foo-for-%26%27a%20str"]' "&'a str" -// @has - '//*[@id="impl-Foo-for-%26%27a%20str"]//h3[@class="code-header in-band"]' "impl<'a> Foo for &'a str" +// @has - '//*[@id="impl-Foo-for-%26%27a%20str"]//h3[@class="code-header"]' "impl<'a> Foo for &'a str" pub trait Foo {} impl Foo for u32 {} diff --git a/src/test/rustdoc/sized_trait.rs b/src/test/rustdoc/sized_trait.rs index 36718ebe1a630..feef4de8d57fe 100644 --- a/src/test/rustdoc/sized_trait.rs +++ b/src/test/rustdoc/sized_trait.rs @@ -11,7 +11,7 @@ pub struct Bar { pub struct Foo(T); // @has foo/struct.Unsized.html -// @has - '//*[@id="impl-Sized-for-Unsized"]//h3[@class="code-header in-band"]' 'impl !Sized for Unsized' +// @has - '//*[@id="impl-Sized-for-Unsized"]//h3[@class="code-header"]' 'impl !Sized for Unsized' pub struct Unsized { data: [u8], } diff --git a/src/test/rustdoc/src-links-auto-impls.rs b/src/test/rustdoc/src-links-auto-impls.rs index 313a4b1189334..953563833c9c7 100644 --- a/src/test/rustdoc/src-links-auto-impls.rs +++ b/src/test/rustdoc/src-links-auto-impls.rs @@ -1,11 +1,11 @@ #![crate_name = "foo"] // @has foo/struct.Unsized.html -// @has - '//*[@id="impl-Sized-for-Unsized"]/h3[@class="code-header in-band"]' 'impl !Sized for Unsized' +// @has - '//*[@id="impl-Sized-for-Unsized"]/h3[@class="code-header"]' 'impl !Sized for Unsized' // @!has - '//*[@id="impl-Sized-for-Unsized"]//a[@class="srclink"]' 'source' -// @has - '//*[@id="impl-Sync-for-Unsized"]/h3[@class="code-header in-band"]' 'impl Sync for Unsized' +// @has - '//*[@id="impl-Sync-for-Unsized"]/h3[@class="code-header"]' 'impl Sync for Unsized' // @!has - '//*[@id="impl-Sync-for-Unsized"]//a[@class="srclink"]' 'source' -// @has - '//*[@id="impl-Any-for-Unsized"]/h3[@class="code-header in-band"]' 'impl Any for T' +// @has - '//*[@id="impl-Any-for-Unsized"]/h3[@class="code-header"]' 'impl Any for T' // @has - '//*[@id="impl-Any-for-Unsized"]//a[@class="srclink rightside"]' 'source' pub struct Unsized { data: [u8], diff --git a/src/test/rustdoc/synthetic_auto/basic.rs b/src/test/rustdoc/synthetic_auto/basic.rs index 19138fd1aceb2..7c6a388653c49 100644 --- a/src/test/rustdoc/synthetic_auto/basic.rs +++ b/src/test/rustdoc/synthetic_auto/basic.rs @@ -1,6 +1,6 @@ // @has basic/struct.Foo.html -// @has - '//h3[@class="code-header in-band"]' 'impl Send for Foowhere T: Send' -// @has - '//h3[@class="code-header in-band"]' 'impl Sync for Foowhere T: Sync' +// @has - '//h3[@class="code-header"]' 'impl Send for Foowhere T: Send' +// @has - '//h3[@class="code-header"]' 'impl Sync for Foowhere T: Sync' // @count - '//*[@id="implementations-list"]//*[@class="impl has-srclink"]' 0 // @count - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]' 5 pub struct Foo { diff --git a/src/test/rustdoc/synthetic_auto/complex.rs b/src/test/rustdoc/synthetic_auto/complex.rs index 39f78983da2b0..43393c21fddb4 100644 --- a/src/test/rustdoc/synthetic_auto/complex.rs +++ b/src/test/rustdoc/synthetic_auto/complex.rs @@ -20,7 +20,7 @@ mod foo { } // @has complex/struct.NotOuter.html -// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ +// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header"]' \ // "impl<'a, T, K: ?Sized> Send for Outer<'a, T, K>where K: for<'b> Fn((&'b bool, &'a u8)) \ // -> &'b i8, T: MyTrait<'a>, >::MyItem: Copy, 'a: 'static" diff --git a/src/test/rustdoc/synthetic_auto/crate-local.rs b/src/test/rustdoc/synthetic_auto/crate-local.rs index 58b787dfafc7c..ed01f63f998b9 100644 --- a/src/test/rustdoc/synthetic_auto/crate-local.rs +++ b/src/test/rustdoc/synthetic_auto/crate-local.rs @@ -3,7 +3,7 @@ pub auto trait Banana {} // @has crate_local/struct.Peach.html -// @has - '//h3[@class="code-header in-band"]' 'impl Banana for Peach' -// @has - '//h3[@class="code-header in-band"]' 'impl Send for Peach' -// @has - '//h3[@class="code-header in-band"]' 'impl Sync for Peach' +// @has - '//h3[@class="code-header"]' 'impl Banana for Peach' +// @has - '//h3[@class="code-header"]' 'impl Send for Peach' +// @has - '//h3[@class="code-header"]' 'impl Sync for Peach' pub struct Peach; diff --git a/src/test/rustdoc/synthetic_auto/lifetimes.rs b/src/test/rustdoc/synthetic_auto/lifetimes.rs index 0c94850e78608..33170a844359b 100644 --- a/src/test/rustdoc/synthetic_auto/lifetimes.rs +++ b/src/test/rustdoc/synthetic_auto/lifetimes.rs @@ -9,10 +9,10 @@ where {} // @has lifetimes/struct.Foo.html -// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ +// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header"]' \ // "impl<'c, K> Send for Foo<'c, K>where K: for<'b> Fn(&'b bool) -> &'c u8, 'c: 'static" // -// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ +// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header"]' \ // "impl<'c, K> Sync for Foo<'c, K>where K: Sync" pub struct Foo<'c, K: 'c> { inner_field: Inner<'c, K>, diff --git a/src/test/rustdoc/synthetic_auto/manual.rs b/src/test/rustdoc/synthetic_auto/manual.rs index 35047e3e8c071..77c04ad2ad942 100644 --- a/src/test/rustdoc/synthetic_auto/manual.rs +++ b/src/test/rustdoc/synthetic_auto/manual.rs @@ -1,8 +1,8 @@ // @has manual/struct.Foo.html -// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ +// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header"]' \ // 'impl Sync for Foowhere T: Sync' // -// @has - '//*[@id="trait-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ +// @has - '//*[@id="trait-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header"]' \ // 'impl Send for Foo' // // @count - '//*[@id="trait-implementations-list"]//*[@class="impl has-srclink"]' 1 diff --git a/src/test/rustdoc/synthetic_auto/negative.rs b/src/test/rustdoc/synthetic_auto/negative.rs index 66e749ac38d96..2c2c848a5e0fb 100644 --- a/src/test/rustdoc/synthetic_auto/negative.rs +++ b/src/test/rustdoc/synthetic_auto/negative.rs @@ -3,10 +3,10 @@ pub struct Inner { } // @has negative/struct.Outer.html -// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ +// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header"]' \ // "impl !Send for Outer" // -// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ +// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header"]' \ // "impl !Sync for Outer" pub struct Outer { inner_field: Inner, diff --git a/src/test/rustdoc/synthetic_auto/nested.rs b/src/test/rustdoc/synthetic_auto/nested.rs index 09587bcc30f13..423bf115ab165 100644 --- a/src/test/rustdoc/synthetic_auto/nested.rs +++ b/src/test/rustdoc/synthetic_auto/nested.rs @@ -9,10 +9,10 @@ where } // @has nested/struct.Foo.html -// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ +// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header"]' \ // 'impl Send for Foowhere T: Copy' // -// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ +// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header"]' \ // 'impl Sync for Foowhere T: Sync' pub struct Foo { inner_field: Inner, diff --git a/src/test/rustdoc/synthetic_auto/no-redundancy.rs b/src/test/rustdoc/synthetic_auto/no-redundancy.rs index 41375decc8a4a..59f33623322a9 100644 --- a/src/test/rustdoc/synthetic_auto/no-redundancy.rs +++ b/src/test/rustdoc/synthetic_auto/no-redundancy.rs @@ -9,7 +9,7 @@ where } // @has no_redundancy/struct.Outer.html -// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ +// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header"]' \ // "impl Send for Outerwhere T: Send + Copy" pub struct Outer { inner_field: Inner, diff --git a/src/test/rustdoc/synthetic_auto/overflow.rs b/src/test/rustdoc/synthetic_auto/overflow.rs index c132ab6fb1b3e..35a487c764dc3 100644 --- a/src/test/rustdoc/synthetic_auto/overflow.rs +++ b/src/test/rustdoc/synthetic_auto/overflow.rs @@ -21,7 +21,7 @@ enum TyData { struct VariableKind(I::InternedType); // @has overflow/struct.BoundVarsCollector.html -// @has - '//h3[@class="code-header in-band"]' "impl<'tcx> Send for BoundVarsCollector<'tcx>" +// @has - '//h3[@class="code-header"]' "impl<'tcx> Send for BoundVarsCollector<'tcx>" pub struct BoundVarsCollector<'tcx> { val: VariableKind> } diff --git a/src/test/rustdoc/synthetic_auto/project.rs b/src/test/rustdoc/synthetic_auto/project.rs index e80b1b1dc9bcf..558ff2add400c 100644 --- a/src/test/rustdoc/synthetic_auto/project.rs +++ b/src/test/rustdoc/synthetic_auto/project.rs @@ -23,10 +23,10 @@ where } // @has project/struct.Foo.html -// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ +// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header"]' \ // "impl<'c, K> Send for Foo<'c, K>where K: MyTrait, 'c: 'static" // -// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ +// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header"]' \ // "impl<'c, K> Sync for Foo<'c, K>where K: MyTrait, ::MyItem: OtherTrait, \ // 'c: 'static," pub struct Foo<'c, K: 'c> { diff --git a/src/test/rustdoc/synthetic_auto/self-referential.rs b/src/test/rustdoc/synthetic_auto/self-referential.rs index d15a8de7d2fe1..c6ae96de77672 100644 --- a/src/test/rustdoc/synthetic_auto/self-referential.rs +++ b/src/test/rustdoc/synthetic_auto/self-referential.rs @@ -23,7 +23,7 @@ impl Pattern for Wrapper { // @has self_referential/struct.WriteAndThen.html -// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ +// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header"]' \ // "impl Send for WriteAndThenwhere ::Value: Send" pub struct WriteAndThen(pub P1::Value,pub > as Pattern>::Value) where P1: Pattern; diff --git a/src/test/rustdoc/synthetic_auto/static-region.rs b/src/test/rustdoc/synthetic_auto/static-region.rs index 08e9567313e22..1a76cb919c298 100644 --- a/src/test/rustdoc/synthetic_auto/static-region.rs +++ b/src/test/rustdoc/synthetic_auto/static-region.rs @@ -3,7 +3,7 @@ pub trait OwnedTrait<'a> { } // @has static_region/struct.Owned.html -// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ +// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header"]' \ // "impl Send for Ownedwhere >::Reader: Send" pub struct Owned where T: OwnedTrait<'static> { marker: >::Reader, diff --git a/src/test/rustdoc/traits-in-bodies.rs b/src/test/rustdoc/traits-in-bodies.rs index 6d450a625d0bf..a65dd7a546cdc 100644 --- a/src/test/rustdoc/traits-in-bodies.rs +++ b/src/test/rustdoc/traits-in-bodies.rs @@ -4,7 +4,7 @@ pub struct Bounded(T); // @has traits_in_bodies/struct.SomeStruct.html -// @has - '//h3[@class="code-header in-band"]' 'impl Clone for SomeStruct' +// @has - '//h3[@class="code-header"]' 'impl Clone for SomeStruct' pub struct SomeStruct; fn asdf() -> Bounded { @@ -18,7 +18,7 @@ fn asdf() -> Bounded { } // @has traits_in_bodies/struct.Point.html -// @has - '//h3[@class="code-header in-band"]' 'impl Copy for Point' +// @has - '//h3[@class="code-header"]' 'impl Copy for Point' #[derive(Clone)] pub struct Point { x: i32, @@ -31,7 +31,7 @@ const _FOO: () = { }; // @has traits_in_bodies/struct.Inception.html -// @has - '//h3[@class="code-header in-band"]' 'impl Clone for Inception' +// @has - '//h3[@class="code-header"]' 'impl Clone for Inception' pub struct Inception; static _BAR: usize = { diff --git a/src/test/rustdoc/typedef.rs b/src/test/rustdoc/typedef.rs index b68ec4557ad55..d5dfa9484891a 100644 --- a/src/test/rustdoc/typedef.rs +++ b/src/test/rustdoc/typedef.rs @@ -9,8 +9,8 @@ impl MyStruct { } // @has typedef/type.MyAlias.html -// @has - '//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' 'impl MyAlias' -// @has - '//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' 'impl MyTrait for MyAlias' +// @has - '//*[@class="impl has-srclink"]//h3[@class="code-header"]' 'impl MyAlias' +// @has - '//*[@class="impl has-srclink"]//h3[@class="code-header"]' 'impl MyTrait for MyAlias' // @hasraw - 'Alias docstring' // @has - '//*[@class="sidebar"]//*[@class="location"]' 'MyAlias' // @has - '//*[@class="sidebar"]//a[@href="#implementations"]' 'Methods' diff --git a/src/test/rustdoc/where.rs b/src/test/rustdoc/where.rs index 68a146bfa55b8..8b5bce28f5a2a 100644 --- a/src/test/rustdoc/where.rs +++ b/src/test/rustdoc/where.rs @@ -13,7 +13,7 @@ pub fn charlie() where C: MyTrait {} pub struct Delta(D); -// @has foo/struct.Delta.html '//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ +// @has foo/struct.Delta.html '//*[@class="impl has-srclink"]//h3[@class="code-header"]' \ // "impl Deltawhere D: MyTrait" impl Delta where D: MyTrait { pub fn delta() {} @@ -43,17 +43,17 @@ pub trait TraitWhere { { todo!() } } -// @has foo/struct.Echo.html '//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ +// @has foo/struct.Echo.html '//*[@class="impl has-srclink"]//h3[@class="code-header"]' \ // "impl MyTrait for Echowhere E: MyTrait" -// @has foo/trait.MyTrait.html '//*[@id="implementors-list"]//h3[@class="code-header in-band"]' \ +// @has foo/trait.MyTrait.html '//*[@id="implementors-list"]//h3[@class="code-header"]' \ // "impl MyTrait for Echowhere E: MyTrait" impl MyTrait for Echowhere E: MyTrait {} pub enum Foxtrot { Foxtrot1(F) } -// @has foo/enum.Foxtrot.html '//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ +// @has foo/enum.Foxtrot.html '//*[@class="impl has-srclink"]//h3[@class="code-header"]' \ // "impl MyTrait for Foxtrotwhere F: MyTrait" -// @has foo/trait.MyTrait.html '//*[@id="implementors-list"]//h3[@class="code-header in-band"]' \ +// @has foo/trait.MyTrait.html '//*[@id="implementors-list"]//h3[@class="code-header"]' \ // "impl MyTrait for Foxtrotwhere F: MyTrait" impl MyTrait for Foxtrotwhere F: MyTrait {} From a50081e102c72642c87e27ab23ed07f4c9c8efc9 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Sun, 25 Sep 2022 14:58:49 -0700 Subject: [PATCH 237/586] Round offset to whole integer --- src/test/rustdoc-gui/implementors.goml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/rustdoc-gui/implementors.goml b/src/test/rustdoc-gui/implementors.goml index dc3b2e122680c..2fcbee27147e4 100644 --- a/src/test/rustdoc-gui/implementors.goml +++ b/src/test/rustdoc-gui/implementors.goml @@ -19,12 +19,12 @@ goto: file://|DOC_PATH|/test_docs/struct.HasEmptyTraits.html compare-elements-position-near-false: ( "#impl-EmptyTrait1-for-HasEmptyTraits", "#impl-EmptyTrait2-for-HasEmptyTraits", - {"y": 34.1875}, + {"y": 34}, ) compare-elements-position-near: ( "#impl-EmptyTrait3-for-HasEmptyTraits h3", "#impl-EmptyTrait3-for-HasEmptyTraits .item-info", - {"y": 34.1875}, + {"y": 34}, ) // Now check that re-exports work correctly. From 66e9b1149c7fbc1fb8108de72b9da1ec0f35afec Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 21 Sep 2022 14:01:39 +1000 Subject: [PATCH 238/586] Rearrange `TokenTreesReader::parse_token_tree`. `parse_token_tree` is basically a match with four arms: `Eof`, `OpenDelim`, `CloseDelim`, and "other". It has two call sites, and at each call site one of the arms is unreachable. It's also not inlined. This commit removes `parse_token_tree` by splitting it into four functions and inlining them. This avoids some repeated conditional tests and also some non-inlined function calls on the hot path. --- compiler/rustc_errors/src/lib.rs | 3 +- compiler/rustc_parse/src/lexer/tokentrees.rs | 346 +++++++++---------- 2 files changed, 170 insertions(+), 179 deletions(-) diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index b44cf352233e3..babab1fa112fc 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -63,7 +63,8 @@ pub mod translation; pub use diagnostic_builder::IntoDiagnostic; pub use snippet::Style; -pub type PResult<'a, T> = Result>; +pub type PErr<'a> = DiagnosticBuilder<'a, ErrorGuaranteed>; +pub type PResult<'a, T> = Result>; // `PResult` is used a lot. Make sure it doesn't unintentionally get bigger. // (See also the comment on `DiagnosticBuilder`'s `diagnostic` field.) diff --git a/compiler/rustc_parse/src/lexer/tokentrees.rs b/compiler/rustc_parse/src/lexer/tokentrees.rs index aa70912dcde4c..3372544a579a3 100644 --- a/compiler/rustc_parse/src/lexer/tokentrees.rs +++ b/compiler/rustc_parse/src/lexer/tokentrees.rs @@ -4,7 +4,7 @@ use rustc_ast::token::{self, Delimiter, Token}; use rustc_ast::tokenstream::{DelimSpan, Spacing, TokenStream, TokenTree}; use rustc_ast_pretty::pprust::token_to_string; use rustc_data_structures::fx::FxHashMap; -use rustc_errors::PResult; +use rustc_errors::{PErr, PResult}; use rustc_span::Span; impl<'a> StringReader<'a> { @@ -48,220 +48,210 @@ impl<'a> TokenTreesReader<'a> { let mut buf = TokenStreamBuilder::default(); self.bump(); - while self.token != token::Eof { - buf.push(self.parse_token_tree()?); + loop { + match self.token.kind { + token::OpenDelim(delim) => buf.push(self.parse_token_tree_open_delim(delim)), + token::CloseDelim(delim) => return Err(self.close_delim_err(delim)), + token::Eof => return Ok(buf.into_token_stream()), + _ => buf.push(self.parse_token_tree_other()), + } } - - Ok(buf.into_token_stream()) } // Parse a stream of tokens into a list of `TokenTree`s, up to a `CloseDelim`. fn parse_token_trees_until_close_delim(&mut self) -> TokenStream { let mut buf = TokenStreamBuilder::default(); loop { - if let token::CloseDelim(..) = self.token.kind { - return buf.into_token_stream(); - } - - match self.parse_token_tree() { - Ok(tree) => buf.push(tree), - Err(mut e) => { - e.emit(); + match self.token.kind { + token::OpenDelim(delim) => buf.push(self.parse_token_tree_open_delim(delim)), + token::CloseDelim(..) => return buf.into_token_stream(), + token::Eof => { + let mut err = self.eof_err(); + err.emit(); return buf.into_token_stream(); } + _ => buf.push(self.parse_token_tree_other()), } } } - fn parse_token_tree(&mut self) -> PResult<'a, TokenTree> { - let sm = self.string_reader.sess.source_map(); - - match self.token.kind { - token::Eof => { - let msg = "this file contains an unclosed delimiter"; - let mut err = - self.string_reader.sess.span_diagnostic.struct_span_err(self.token.span, msg); - for &(_, sp) in &self.open_braces { - err.span_label(sp, "unclosed delimiter"); - self.unmatched_braces.push(UnmatchedBrace { - expected_delim: Delimiter::Brace, - found_delim: None, - found_span: self.token.span, - unclosed_span: Some(sp), - candidate_span: None, - }); - } + fn eof_err(&mut self) -> PErr<'a> { + let msg = "this file contains an unclosed delimiter"; + let mut err = self.string_reader.sess.span_diagnostic.struct_span_err(self.token.span, msg); + for &(_, sp) in &self.open_braces { + err.span_label(sp, "unclosed delimiter"); + self.unmatched_braces.push(UnmatchedBrace { + expected_delim: Delimiter::Brace, + found_delim: None, + found_span: self.token.span, + unclosed_span: Some(sp), + candidate_span: None, + }); + } - if let Some((delim, _)) = self.open_braces.last() { - if let Some((_, open_sp, close_sp)) = - self.matching_delim_spans.iter().find(|(d, open_sp, close_sp)| { - if let Some(close_padding) = sm.span_to_margin(*close_sp) { - if let Some(open_padding) = sm.span_to_margin(*open_sp) { - return delim == d && close_padding != open_padding; - } - } - false - }) - // these are in reverse order as they get inserted on close, but - { - // we want the last open/first close - err.span_label(*open_sp, "this delimiter might not be properly closed..."); - err.span_label( - *close_sp, - "...as it matches this but it has different indentation", - ); + if let Some((delim, _)) = self.open_braces.last() { + if let Some((_, open_sp, close_sp)) = + self.matching_delim_spans.iter().find(|(d, open_sp, close_sp)| { + let sm = self.string_reader.sess.source_map(); + if let Some(close_padding) = sm.span_to_margin(*close_sp) { + if let Some(open_padding) = sm.span_to_margin(*open_sp) { + return delim == d && close_padding != open_padding; + } } - } - Err(err) + false + }) + // these are in reverse order as they get inserted on close, but + { + // we want the last open/first close + err.span_label(*open_sp, "this delimiter might not be properly closed..."); + err.span_label(*close_sp, "...as it matches this but it has different indentation"); } - token::OpenDelim(delim) => { - // The span for beginning of the delimited section - let pre_span = self.token.span; - - // Parse the open delimiter. - self.open_braces.push((delim, self.token.span)); - self.bump(); + } + err + } - // Parse the token trees within the delimiters. - // We stop at any delimiter so we can try to recover if the user - // uses an incorrect delimiter. - let tts = self.parse_token_trees_until_close_delim(); + fn parse_token_tree_open_delim(&mut self, delim: Delimiter) -> TokenTree { + // The span for beginning of the delimited section + let pre_span = self.token.span; - // Expand to cover the entire delimited token tree - let delim_span = DelimSpan::from_pair(pre_span, self.token.span); + // Parse the open delimiter. + self.open_braces.push((delim, self.token.span)); + self.bump(); - match self.token.kind { - // Correct delimiter. - token::CloseDelim(d) if d == delim => { - let (open_brace, open_brace_span) = self.open_braces.pop().unwrap(); - let close_brace_span = self.token.span; + // Parse the token trees within the delimiters. + // We stop at any delimiter so we can try to recover if the user + // uses an incorrect delimiter. + let tts = self.parse_token_trees_until_close_delim(); - if tts.is_empty() { - let empty_block_span = open_brace_span.to(close_brace_span); - if !sm.is_multiline(empty_block_span) { - // Only track if the block is in the form of `{}`, otherwise it is - // likely that it was written on purpose. - self.last_delim_empty_block_spans.insert(delim, empty_block_span); - } - } + // Expand to cover the entire delimited token tree + let delim_span = DelimSpan::from_pair(pre_span, self.token.span); - //only add braces - if let (Delimiter::Brace, Delimiter::Brace) = (open_brace, delim) { - self.matching_block_spans.push((open_brace_span, close_brace_span)); - } + match self.token.kind { + // Correct delimiter. + token::CloseDelim(d) if d == delim => { + let (open_brace, open_brace_span) = self.open_braces.pop().unwrap(); + let close_brace_span = self.token.span; - if self.open_braces.is_empty() { - // Clear up these spans to avoid suggesting them as we've found - // properly matched delimiters so far for an entire block. - self.matching_delim_spans.clear(); - } else { - self.matching_delim_spans.push(( - open_brace, - open_brace_span, - close_brace_span, - )); - } - // Parse the closing delimiter. - self.bump(); + if tts.is_empty() { + let empty_block_span = open_brace_span.to(close_brace_span); + let sm = self.string_reader.sess.source_map(); + if !sm.is_multiline(empty_block_span) { + // Only track if the block is in the form of `{}`, otherwise it is + // likely that it was written on purpose. + self.last_delim_empty_block_spans.insert(delim, empty_block_span); } - // Incorrect delimiter. - token::CloseDelim(other) => { - let mut unclosed_delimiter = None; - let mut candidate = None; + } + + //only add braces + if let (Delimiter::Brace, Delimiter::Brace) = (open_brace, delim) { + self.matching_block_spans.push((open_brace_span, close_brace_span)); + } + + if self.open_braces.is_empty() { + // Clear up these spans to avoid suggesting them as we've found + // properly matched delimiters so far for an entire block. + self.matching_delim_spans.clear(); + } else { + self.matching_delim_spans.push((open_brace, open_brace_span, close_brace_span)); + } + // Parse the closing delimiter. + self.bump(); + } + // Incorrect delimiter. + token::CloseDelim(other) => { + let mut unclosed_delimiter = None; + let mut candidate = None; - if self.last_unclosed_found_span != Some(self.token.span) { - // do not complain about the same unclosed delimiter multiple times - self.last_unclosed_found_span = Some(self.token.span); - // This is a conservative error: only report the last unclosed - // delimiter. The previous unclosed delimiters could actually be - // closed! The parser just hasn't gotten to them yet. - if let Some(&(_, sp)) = self.open_braces.last() { - unclosed_delimiter = Some(sp); - }; - if let Some(current_padding) = sm.span_to_margin(self.token.span) { - for (brace, brace_span) in &self.open_braces { - if let Some(padding) = sm.span_to_margin(*brace_span) { - // high likelihood of these two corresponding - if current_padding == padding && brace == &other { - candidate = Some(*brace_span); - } - } + if self.last_unclosed_found_span != Some(self.token.span) { + // do not complain about the same unclosed delimiter multiple times + self.last_unclosed_found_span = Some(self.token.span); + // This is a conservative error: only report the last unclosed + // delimiter. The previous unclosed delimiters could actually be + // closed! The parser just hasn't gotten to them yet. + if let Some(&(_, sp)) = self.open_braces.last() { + unclosed_delimiter = Some(sp); + }; + let sm = self.string_reader.sess.source_map(); + if let Some(current_padding) = sm.span_to_margin(self.token.span) { + for (brace, brace_span) in &self.open_braces { + if let Some(padding) = sm.span_to_margin(*brace_span) { + // high likelihood of these two corresponding + if current_padding == padding && brace == &other { + candidate = Some(*brace_span); } } - let (tok, _) = self.open_braces.pop().unwrap(); - self.unmatched_braces.push(UnmatchedBrace { - expected_delim: tok, - found_delim: Some(other), - found_span: self.token.span, - unclosed_span: unclosed_delimiter, - candidate_span: candidate, - }); - } else { - self.open_braces.pop(); - } - - // If the incorrect delimiter matches an earlier opening - // delimiter, then don't consume it (it can be used to - // close the earlier one). Otherwise, consume it. - // E.g., we try to recover from: - // fn foo() { - // bar(baz( - // } // Incorrect delimiter but matches the earlier `{` - if !self.open_braces.iter().any(|&(b, _)| b == other) { - self.bump(); } } - token::Eof => { - // Silently recover, the EOF token will be seen again - // and an error emitted then. Thus we don't pop from - // self.open_braces here. - } - _ => {} + let (tok, _) = self.open_braces.pop().unwrap(); + self.unmatched_braces.push(UnmatchedBrace { + expected_delim: tok, + found_delim: Some(other), + found_span: self.token.span, + unclosed_span: unclosed_delimiter, + candidate_span: candidate, + }); + } else { + self.open_braces.pop(); } - Ok(TokenTree::Delimited(delim_span, delim, tts)) + // If the incorrect delimiter matches an earlier opening + // delimiter, then don't consume it (it can be used to + // close the earlier one). Otherwise, consume it. + // E.g., we try to recover from: + // fn foo() { + // bar(baz( + // } // Incorrect delimiter but matches the earlier `{` + if !self.open_braces.iter().any(|&(b, _)| b == other) { + self.bump(); + } } - token::CloseDelim(delim) => { - // An unexpected closing delimiter (i.e., there is no - // matching opening delimiter). - let token_str = token_to_string(&self.token); - let msg = format!("unexpected closing delimiter: `{}`", token_str); - let mut err = - self.string_reader.sess.span_diagnostic.struct_span_err(self.token.span, &msg); + token::Eof => { + // Silently recover, the EOF token will be seen again + // and an error emitted then. Thus we don't pop from + // self.open_braces here. + } + _ => {} + } - // Braces are added at the end, so the last element is the biggest block - if let Some(parent) = self.matching_block_spans.last() { - if let Some(span) = self.last_delim_empty_block_spans.remove(&delim) { - // Check if the (empty block) is in the last properly closed block - if (parent.0.to(parent.1)).contains(span) { - err.span_label( - span, - "block is empty, you might have not meant to close it", - ); - } else { - err.span_label(parent.0, "this opening brace..."); + TokenTree::Delimited(delim_span, delim, tts) + } - err.span_label(parent.1, "...matches this closing brace"); - } - } else { - err.span_label(parent.0, "this opening brace..."); + fn close_delim_err(&mut self, delim: Delimiter) -> PErr<'a> { + // An unexpected closing delimiter (i.e., there is no + // matching opening delimiter). + let token_str = token_to_string(&self.token); + let msg = format!("unexpected closing delimiter: `{}`", token_str); + let mut err = + self.string_reader.sess.span_diagnostic.struct_span_err(self.token.span, &msg); - err.span_label(parent.1, "...matches this closing brace"); - } + // Braces are added at the end, so the last element is the biggest block + if let Some(parent) = self.matching_block_spans.last() { + if let Some(span) = self.last_delim_empty_block_spans.remove(&delim) { + // Check if the (empty block) is in the last properly closed block + if (parent.0.to(parent.1)).contains(span) { + err.span_label(span, "block is empty, you might have not meant to close it"); + } else { + err.span_label(parent.0, "this opening brace..."); + err.span_label(parent.1, "...matches this closing brace"); } - - err.span_label(self.token.span, "unexpected closing delimiter"); - Err(err) - } - _ => { - let tok = self.token.take(); - let mut spacing = self.bump(); - if !self.token.is_op() { - spacing = Spacing::Alone; - } - Ok(TokenTree::Token(tok, spacing)) + } else { + err.span_label(parent.0, "this opening brace..."); + err.span_label(parent.1, "...matches this closing brace"); } } + + err.span_label(self.token.span, "unexpected closing delimiter"); + err + } + + #[inline] + fn parse_token_tree_other(&mut self) -> TokenTree { + let tok = self.token.take(); + let mut spacing = self.bump(); + if !self.token.is_op() { + spacing = Spacing::Alone; + } + TokenTree::Token(tok, spacing) } fn bump(&mut self) -> Spacing { From 14281e614759f6e761a01acaf9dccbd0da4ff1ef Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 21 Sep 2022 15:13:20 +1000 Subject: [PATCH 239/586] Remove unnecessary `spacing` assignment. It has no useful effect. --- compiler/rustc_parse/src/lexer/mod.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs index 63819a2f98df5..394a5b8648088 100644 --- a/compiler/rustc_parse/src/lexer/mod.rs +++ b/compiler/rustc_parse/src/lexer/mod.rs @@ -70,7 +70,6 @@ impl<'a> StringReader<'a> { && let Some(shebang_len) = rustc_lexer::strip_shebang(self.src) { self.pos = self.pos + BytePos::from_usize(shebang_len); - spacing = Spacing::Alone; } // Skip trivial (whitespace & comments) tokens From 4d0d688a3cfd3d58cbd5d8065a7af774a7bb82b6 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 25 Sep 2022 22:20:01 +0000 Subject: [PATCH 240/586] Recover some items that expect braces and don't take semicolons --- .../locales/en-US/parser.ftl | 3 ++ .../rustc_parse/src/parser/diagnostics.rs | 8 +++++ compiler/rustc_parse/src/parser/item.rs | 29 ++++++++++++++----- src/test/ui/parser/empty-impl-semicolon.rs | 5 +++- .../ui/parser/empty-impl-semicolon.stderr | 8 +++-- src/test/ui/parser/item-needs-block.rs | 10 +++++++ src/test/ui/parser/item-needs-block.stderr | 26 +++++++++++++++++ 7 files changed, 78 insertions(+), 11 deletions(-) create mode 100644 src/test/ui/parser/item-needs-block.rs create mode 100644 src/test/ui/parser/item-needs-block.stderr diff --git a/compiler/rustc_error_messages/locales/en-US/parser.ftl b/compiler/rustc_error_messages/locales/en-US/parser.ftl index 9459cfebde936..07dd03e6e504e 100644 --- a/compiler/rustc_error_messages/locales/en-US/parser.ftl +++ b/compiler/rustc_error_messages/locales/en-US/parser.ftl @@ -158,3 +158,6 @@ parser_remove_let = expected pattern, found `let` parser_use_eq_instead = unexpected `==` .suggestion = try using `=` instead + +parser_use_empty_block_not_semi = expected { "`{}`" }, found `;` + .suggestion = try using { "`{}`" } instead diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index dcea11eadcbf1..8750873c3a4a3 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -745,6 +745,14 @@ pub(crate) struct UseEqInstead { pub span: Span, } +#[derive(Diagnostic)] +#[diag(parser::use_empty_block_not_semi)] +pub(crate) struct UseEmptyBlockNotSemi { + #[primary_span] + #[suggestion_hidden(applicability = "machine-applicable", code = "{{}}")] + pub span: Span, +} + // SnapshotParser is used to create a snapshot of the parser // without causing duplicate errors being emitted when the `Parser` // is dropped. diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index e55b5ce71cded..802dfc048f825 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -1,4 +1,4 @@ -use super::diagnostics::{dummy_arg, ConsumeClosingDelim, Error}; +use super::diagnostics::{dummy_arg, ConsumeClosingDelim, Error, UseEmptyBlockNotSemi}; use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign}; use super::{AttrWrapper, FollowedByType, ForceCollect, Parser, PathStyle, TrailingToken}; @@ -664,6 +664,14 @@ impl<'a> Parser<'a> { mut parse_item: impl FnMut(&mut Parser<'a>) -> PResult<'a, Option>>, ) -> PResult<'a, Vec> { let open_brace_span = self.token.span; + + // Recover `impl Ty;` instead of `impl Ty {}` + if self.token == TokenKind::Semi { + self.sess.emit_err(UseEmptyBlockNotSemi { span: self.token.span }); + self.bump(); + return Ok(vec![]); + } + self.expect(&token::OpenDelim(Delimiter::Brace))?; attrs.extend(self.parse_inner_attributes()?); @@ -1305,12 +1313,19 @@ impl<'a> Parser<'a> { let mut generics = self.parse_generics()?; generics.where_clause = self.parse_where_clause()?; - let (variants, _) = self - .parse_delim_comma_seq(Delimiter::Brace, |p| p.parse_enum_variant()) - .map_err(|e| { - self.recover_stmt(); - e - })?; + // Possibly recover `enum Foo;` instead of `enum Foo {}` + let (variants, _) = if self.token == TokenKind::Semi { + self.sess.emit_err(UseEmptyBlockNotSemi { span: self.token.span }); + self.bump(); + (vec![], false) + } else { + self.parse_delim_comma_seq(Delimiter::Brace, |p| p.parse_enum_variant()).map_err( + |e| { + self.recover_stmt(); + e + }, + )? + }; let enum_definition = EnumDef { variants: variants.into_iter().flatten().collect() }; Ok((id, ItemKind::Enum(enum_definition, generics))) diff --git a/src/test/ui/parser/empty-impl-semicolon.rs b/src/test/ui/parser/empty-impl-semicolon.rs index 207ebef642bfa..2485f5b855202 100644 --- a/src/test/ui/parser/empty-impl-semicolon.rs +++ b/src/test/ui/parser/empty-impl-semicolon.rs @@ -1 +1,4 @@ -impl Foo; //~ ERROR expected one of `!`, `(`, `+`, `::`, `<`, `for`, `where`, or `{`, found `;` +struct Foo; +impl Foo; //~ ERROR expected `{}`, found `;` + +fn main() {} diff --git a/src/test/ui/parser/empty-impl-semicolon.stderr b/src/test/ui/parser/empty-impl-semicolon.stderr index 398eb5c898cdd..6ed309eba9392 100644 --- a/src/test/ui/parser/empty-impl-semicolon.stderr +++ b/src/test/ui/parser/empty-impl-semicolon.stderr @@ -1,8 +1,10 @@ -error: expected one of `!`, `(`, `+`, `::`, `<`, `for`, `where`, or `{`, found `;` - --> $DIR/empty-impl-semicolon.rs:1:9 +error: expected `{}`, found `;` + --> $DIR/empty-impl-semicolon.rs:2:9 | LL | impl Foo; - | ^ expected one of 8 possible tokens + | ^ + | + = help: try using `{}` instead error: aborting due to previous error diff --git a/src/test/ui/parser/item-needs-block.rs b/src/test/ui/parser/item-needs-block.rs new file mode 100644 index 0000000000000..4edac588eee97 --- /dev/null +++ b/src/test/ui/parser/item-needs-block.rs @@ -0,0 +1,10 @@ +trait Trait; +//~^ ERROR expected `{}`, found `;` + +impl Trait for (); +//~^ ERROR expected `{}`, found `;` + +enum Enum; +//~^ ERROR expected `{}`, found `;` + +fn main() {} diff --git a/src/test/ui/parser/item-needs-block.stderr b/src/test/ui/parser/item-needs-block.stderr new file mode 100644 index 0000000000000..3cabd0c73a3c9 --- /dev/null +++ b/src/test/ui/parser/item-needs-block.stderr @@ -0,0 +1,26 @@ +error: expected `{}`, found `;` + --> $DIR/item-needs-block.rs:1:12 + | +LL | trait Trait; + | ^ + | + = help: try using `{}` instead + +error: expected `{}`, found `;` + --> $DIR/item-needs-block.rs:4:18 + | +LL | impl Trait for (); + | ^ + | + = help: try using `{}` instead + +error: expected `{}`, found `;` + --> $DIR/item-needs-block.rs:7:10 + | +LL | enum Enum; + | ^ + | + = help: try using `{}` instead + +error: aborting due to 3 previous errors + From 730ead80479d98de5cc1b555c558b5b0176fded8 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 24 Sep 2022 18:53:53 +0000 Subject: [PATCH 241/586] Only generate closure def id for async fns with body --- compiler/rustc_resolve/src/def_collector.rs | 10 +++++++--- src/test/ui/async-await/in-trait/issue-102219.rs | 10 ++++++++++ 2 files changed, 17 insertions(+), 3 deletions(-) create mode 100644 src/test/ui/async-await/in-trait/issue-102219.rs diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs index 3f88f44ff21a3..7e83f2a722107 100644 --- a/compiler/rustc_resolve/src/def_collector.rs +++ b/compiler/rustc_resolve/src/def_collector.rs @@ -1,6 +1,5 @@ use crate::{ImplTraitContext, Resolver}; use rustc_ast::visit::{self, FnKind}; -use rustc_ast::walk_list; use rustc_ast::*; use rustc_expand::expand::AstFragment; use rustc_hir::def_id::LocalDefId; @@ -148,8 +147,13 @@ impl<'a, 'b> visit::Visitor<'a> for DefCollector<'a, 'b> { self.with_parent(return_impl_trait_id, |this| { this.visit_fn_ret_ty(&sig.decl.output) }); - let closure_def = self.create_def(closure_id, DefPathData::ClosureExpr, span); - self.with_parent(closure_def, |this| walk_list!(this, visit_block, body)); + // If this async fn has no body (i.e. it's an async fn signature in a trait) + // then the closure_def will never be used, and we should avoid generating a + // def-id for it. + if let Some(body) = body { + let closure_def = self.create_def(closure_id, DefPathData::ClosureExpr, span); + self.with_parent(closure_def, |this| this.visit_block(body)); + } return; } } diff --git a/src/test/ui/async-await/in-trait/issue-102219.rs b/src/test/ui/async-await/in-trait/issue-102219.rs new file mode 100644 index 0000000000000..9a35f6515cb1a --- /dev/null +++ b/src/test/ui/async-await/in-trait/issue-102219.rs @@ -0,0 +1,10 @@ +// compile-flags:--crate-type=lib +// edition:2021 +// check-pass + +#![feature(async_fn_in_trait)] +#![allow(incomplete_features)] + +trait T { + async fn foo(); +} From e99f6fee441dfa71d58b37a10366bf8c5c9d52ac Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 24 Sep 2022 19:22:01 +0000 Subject: [PATCH 242/586] Only lower async fn body if it actually has a body --- compiler/rustc_ast_lowering/src/item.rs | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 1251702c1ff6b..d9b18d68e537f 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -1055,9 +1055,9 @@ impl<'hir> LoweringContext<'_, 'hir> { asyncness: Async, body: Option<&Block>, ) -> hir::BodyId { - let closure_id = match asyncness { - Async::Yes { closure_id, .. } => closure_id, - Async::No => return self.lower_fn_body_block(span, decl, body), + let (closure_id, body) = match (asyncness, body) { + (Async::Yes { closure_id, .. }, Some(body)) => (closure_id, body), + _ => return self.lower_fn_body_block(span, decl, body), }; self.lower_body(|this| { @@ -1199,16 +1199,15 @@ impl<'hir> LoweringContext<'_, 'hir> { parameters.push(new_parameter); } - let body_span = body.map_or(span, |b| b.span); let async_expr = this.make_async_expr( CaptureBy::Value, closure_id, None, - body_span, + body.span, hir::AsyncGeneratorKind::Fn, |this| { // Create a block from the user's function body: - let user_body = this.lower_block_expr_opt(body_span, body); + let user_body = this.lower_block_expr(body); // Transform into `drop-temps { }`, an expression: let desugared_span = @@ -1240,7 +1239,7 @@ impl<'hir> LoweringContext<'_, 'hir> { ( this.arena.alloc_from_iter(parameters), - this.expr(body_span, async_expr, AttrVec::new()), + this.expr(body.span, async_expr, AttrVec::new()), ) }) } From 672e3f4d77f8b9f86a999992b459a95909aa74c2 Mon Sep 17 00:00:00 2001 From: yukang Date: Fri, 23 Sep 2022 15:28:48 +0800 Subject: [PATCH 243/586] fix #102087, Suggest Default::default() when binding isn't initialized --- .../src/diagnostics/conflict_errors.rs | 70 +++++++++ src/test/ui/asm/aarch64/type-check-2-2.stderr | 10 ++ src/test/ui/asm/x86_64/type-check-5.stderr | 10 ++ .../ui/borrowck/borrowck-block-unint.stderr | 5 + .../borrowck/borrowck-break-uninit-2.stderr | 4 + .../ui/borrowck/borrowck-break-uninit.stderr | 4 + .../borrowck-init-in-called-fn-expr.stderr | 5 + .../borrowck/borrowck-init-in-fn-expr.stderr | 5 + .../ui/borrowck/borrowck-init-in-fru.stderr | 5 + .../ui/borrowck/borrowck-init-op-equal.stderr | 5 + .../borrowck/borrowck-init-plus-equal.stderr | 5 + src/test/ui/borrowck/borrowck-return.stderr | 5 + .../ui/borrowck/borrowck-storage-dead.stderr | 5 + .../borrowck-uninit-after-item.stderr | 5 + .../borrowck-uninit-field-access.stderr | 5 + .../borrowck-uninit-in-assignop.stderr | 50 +++++++ .../borrowck/borrowck-uninit-ref-chain.stderr | 15 ++ src/test/ui/borrowck/borrowck-uninit.stderr | 5 + .../borrowck-use-in-index-lvalue.stderr | 10 ++ ...wck-use-uninitialized-in-cast-trait.stderr | 5 + .../borrowck-use-uninitialized-in-cast.stderr | 5 + .../ui/borrowck/borrowck-while-cond.stderr | 5 + .../ui/borrowck/issue-24267-flow-exit.stderr | 8 + .../issue-62107-match-arm-scopes.stderr | 5 + src/test/ui/borrowck/suggest-assign-rvalue.rs | 57 ++++++++ .../ui/borrowck/suggest-assign-rvalue.stderr | 138 ++++++++++++++++++ .../match/pattern-matching-should-fail.stderr | 5 + ...const-generic-default-wont-borrowck.stderr | 5 + src/test/ui/consts/issue-78655.stderr | 5 + src/test/ui/drop/repeat-drop-2.stderr | 5 + src/test/ui/loops/loop-proper-liveness.stderr | 4 + ...op-elaboration-after-borrowck-error.stderr | 5 + .../moves/issue-72649-uninit-in-loop.stderr | 10 ++ .../ui/moves/move-into-dead-array-1.stderr | 5 + src/test/ui/moves/move-of-addr-of-mut.stderr | 4 + src/test/ui/nll/match-cfg-fake-edges.stderr | 5 + src/test/ui/nll/match-on-borrowed.stderr | 5 + .../privately-uninhabited-mir-call.stderr | 5 + 38 files changed, 514 insertions(+) create mode 100644 src/test/ui/borrowck/suggest-assign-rvalue.rs create mode 100644 src/test/ui/borrowck/suggest-assign-rvalue.stderr diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 69ad7f6627500..3182656b6aa92 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -369,6 +369,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let mut visitor = ConditionVisitor { spans: &spans, name: &name, errors: vec![] }; visitor.visit_body(&body); + let mut show_assign_sugg = false; let isnt_initialized = if let InitializationRequiringAction::PartialAssignment | InitializationRequiringAction::Assignment = desired_action { @@ -396,6 +397,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { .count() == 0 { + show_assign_sugg = true; "isn't initialized" } else { "is possibly-uninitialized" @@ -446,10 +448,78 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } } } + err.span_label(decl_span, "binding declared here but left uninitialized"); + if show_assign_sugg { + struct LetVisitor { + decl_span: Span, + sugg_span: Option, + } + + impl<'v> Visitor<'v> for LetVisitor { + fn visit_stmt(&mut self, ex: &'v hir::Stmt<'v>) { + if self.sugg_span.is_some() { + return; + } + if let hir::StmtKind::Local(hir::Local { + span, ty, init: None, .. + }) = &ex.kind && span.contains(self.decl_span) { + self.sugg_span = ty.map_or(Some(self.decl_span), |ty| Some(ty.span)); + } + hir::intravisit::walk_stmt(self, ex); + } + } + + let mut visitor = LetVisitor { decl_span, sugg_span: None }; + visitor.visit_body(&body); + if let Some(span) = visitor.sugg_span { + self.suggest_assign_value(&mut err, moved_place, span); + } + } err } + fn suggest_assign_value( + &self, + err: &mut Diagnostic, + moved_place: PlaceRef<'tcx>, + sugg_span: Span, + ) { + let ty = moved_place.ty(self.body, self.infcx.tcx).ty; + debug!("ty: {:?}, kind: {:?}", ty, ty.kind()); + + let tcx = self.infcx.tcx; + let implements_default = |ty, param_env| { + let Some(default_trait) = tcx.get_diagnostic_item(sym::Default) else { + return false; + }; + tcx.infer_ctxt().enter(|infcx| { + infcx + .type_implements_trait(default_trait, ty, ty::List::empty(), param_env) + .may_apply() + }) + }; + + let assign_value = match ty.kind() { + ty::Bool => "false", + ty::Float(_) => "0.0", + ty::Int(_) | ty::Uint(_) => "0", + ty::Never | ty::Error(_) => "", + ty::Adt(def, _) if Some(def.did()) == tcx.get_diagnostic_item(sym::Vec) => "vec![]", + ty::Adt(_, _) if implements_default(ty, self.param_env) => "Default::default()", + _ => "todo!()", + }; + + if !assign_value.is_empty() { + err.span_suggestion_verbose( + sugg_span.shrink_to_hi(), + format!("consider assigning a value"), + format!(" = {}", assign_value), + Applicability::MaybeIncorrect, + ); + } + } + fn suggest_borrow_fn_like( &self, err: &mut Diagnostic, diff --git a/src/test/ui/asm/aarch64/type-check-2-2.stderr b/src/test/ui/asm/aarch64/type-check-2-2.stderr index b2a695529f948..eef16a165a875 100644 --- a/src/test/ui/asm/aarch64/type-check-2-2.stderr +++ b/src/test/ui/asm/aarch64/type-check-2-2.stderr @@ -5,6 +5,11 @@ LL | let x: u64; | - binding declared here but left uninitialized LL | asm!("{}", in(reg) x); | ^ `x` used here but it isn't initialized + | +help: consider assigning a value + | +LL | let x: u64 = 0; + | +++ error[E0381]: used binding `y` isn't initialized --> $DIR/type-check-2-2.rs:22:9 @@ -13,6 +18,11 @@ LL | let mut y: u64; | ----- binding declared here but left uninitialized LL | asm!("{}", inout(reg) y); | ^^^^^^^^^^^^^^^^^^^^^^^^ `y` used here but it isn't initialized + | +help: consider assigning a value + | +LL | let mut y: u64 = 0; + | +++ error[E0596]: cannot borrow `v` as mutable, as it is not declared as mutable --> $DIR/type-check-2-2.rs:30:29 diff --git a/src/test/ui/asm/x86_64/type-check-5.stderr b/src/test/ui/asm/x86_64/type-check-5.stderr index e9c93fea561a8..bd90461e52c17 100644 --- a/src/test/ui/asm/x86_64/type-check-5.stderr +++ b/src/test/ui/asm/x86_64/type-check-5.stderr @@ -5,6 +5,11 @@ LL | let x: u64; | - binding declared here but left uninitialized LL | asm!("{}", in(reg) x); | ^ `x` used here but it isn't initialized + | +help: consider assigning a value + | +LL | let x: u64 = 0; + | +++ error[E0381]: used binding `y` isn't initialized --> $DIR/type-check-5.rs:18:9 @@ -13,6 +18,11 @@ LL | let mut y: u64; | ----- binding declared here but left uninitialized LL | asm!("{}", inout(reg) y); | ^^^^^^^^^^^^^^^^^^^^^^^^ `y` used here but it isn't initialized + | +help: consider assigning a value + | +LL | let mut y: u64 = 0; + | +++ error[E0596]: cannot borrow `v` as mutable, as it is not declared as mutable --> $DIR/type-check-5.rs:26:29 diff --git a/src/test/ui/borrowck/borrowck-block-unint.stderr b/src/test/ui/borrowck/borrowck-block-unint.stderr index e720db1c6961b..f47921a975269 100644 --- a/src/test/ui/borrowck/borrowck-block-unint.stderr +++ b/src/test/ui/borrowck/borrowck-block-unint.stderr @@ -7,6 +7,11 @@ LL | force(|| { | ^^ `x` used here but it isn't initialized LL | println!("{}", x); | - borrow occurs due to use in closure + | +help: consider assigning a value + | +LL | let x: isize = 0; + | +++ error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-break-uninit-2.stderr b/src/test/ui/borrowck/borrowck-break-uninit-2.stderr index 91038b3adca9d..ea93a8f409ce4 100644 --- a/src/test/ui/borrowck/borrowck-break-uninit-2.stderr +++ b/src/test/ui/borrowck/borrowck-break-uninit-2.stderr @@ -8,6 +8,10 @@ LL | println!("{}", x); | ^ `x` used here but it isn't initialized | = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider assigning a value + | +LL | let x: isize = 0; + | +++ error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-break-uninit.stderr b/src/test/ui/borrowck/borrowck-break-uninit.stderr index 8d0c9582fda92..a7a8fc2ff8378 100644 --- a/src/test/ui/borrowck/borrowck-break-uninit.stderr +++ b/src/test/ui/borrowck/borrowck-break-uninit.stderr @@ -8,6 +8,10 @@ LL | println!("{}", x); | ^ `x` used here but it isn't initialized | = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider assigning a value + | +LL | let x: isize = 0; + | +++ error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-init-in-called-fn-expr.stderr b/src/test/ui/borrowck/borrowck-init-in-called-fn-expr.stderr index e8a2fbc91ea64..1a22b5f0975c0 100644 --- a/src/test/ui/borrowck/borrowck-init-in-called-fn-expr.stderr +++ b/src/test/ui/borrowck/borrowck-init-in-called-fn-expr.stderr @@ -5,6 +5,11 @@ LL | let i: isize; | - binding declared here but left uninitialized LL | i | ^ `i` used here but it isn't initialized + | +help: consider assigning a value + | +LL | let i: isize = 0; + | +++ error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-init-in-fn-expr.stderr b/src/test/ui/borrowck/borrowck-init-in-fn-expr.stderr index 1e950d6a20def..f1b9b9aa7090a 100644 --- a/src/test/ui/borrowck/borrowck-init-in-fn-expr.stderr +++ b/src/test/ui/borrowck/borrowck-init-in-fn-expr.stderr @@ -5,6 +5,11 @@ LL | let i: isize; | - binding declared here but left uninitialized LL | i | ^ `i` used here but it isn't initialized + | +help: consider assigning a value + | +LL | let i: isize = 0; + | +++ error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-init-in-fru.stderr b/src/test/ui/borrowck/borrowck-init-in-fru.stderr index 83a3e3e0e3ae0..39b28811a0c27 100644 --- a/src/test/ui/borrowck/borrowck-init-in-fru.stderr +++ b/src/test/ui/borrowck/borrowck-init-in-fru.stderr @@ -5,6 +5,11 @@ LL | let mut origin: Point; | ---------- binding declared here but left uninitialized LL | origin = Point { x: 10, ..origin }; | ^^^^^^^^^^^^^^^^^^^^^^^^^ `origin.y` used here but it isn't initialized + | +help: consider assigning a value + | +LL | let mut origin: Point = todo!(); + | +++++++++ error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-init-op-equal.stderr b/src/test/ui/borrowck/borrowck-init-op-equal.stderr index 74704b2abfee8..ef0fa6df4fb7e 100644 --- a/src/test/ui/borrowck/borrowck-init-op-equal.stderr +++ b/src/test/ui/borrowck/borrowck-init-op-equal.stderr @@ -5,6 +5,11 @@ LL | let v: isize; | - binding declared here but left uninitialized LL | v += 1; | ^^^^^^ `v` used here but it isn't initialized + | +help: consider assigning a value + | +LL | let v: isize = 0; + | +++ error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-init-plus-equal.stderr b/src/test/ui/borrowck/borrowck-init-plus-equal.stderr index 7542576d636be..cec0533183647 100644 --- a/src/test/ui/borrowck/borrowck-init-plus-equal.stderr +++ b/src/test/ui/borrowck/borrowck-init-plus-equal.stderr @@ -5,6 +5,11 @@ LL | let mut v: isize; | ----- binding declared here but left uninitialized LL | v = v + 1; | ^ `v` used here but it isn't initialized + | +help: consider assigning a value + | +LL | let mut v: isize = 0; + | +++ error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-return.stderr b/src/test/ui/borrowck/borrowck-return.stderr index 1c916e223175c..9799357c9ca19 100644 --- a/src/test/ui/borrowck/borrowck-return.stderr +++ b/src/test/ui/borrowck/borrowck-return.stderr @@ -5,6 +5,11 @@ LL | let x: isize; | - binding declared here but left uninitialized LL | return x; | ^ `x` used here but it isn't initialized + | +help: consider assigning a value + | +LL | let x: isize = 0; + | +++ error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-storage-dead.stderr b/src/test/ui/borrowck/borrowck-storage-dead.stderr index 2cea4392d6adb..3a413153acd19 100644 --- a/src/test/ui/borrowck/borrowck-storage-dead.stderr +++ b/src/test/ui/borrowck/borrowck-storage-dead.stderr @@ -5,6 +5,11 @@ LL | let x: i32; | - binding declared here but left uninitialized LL | let _ = x + 1; | ^ `x` used here but it isn't initialized + | +help: consider assigning a value + | +LL | let x: i32 = 0; + | +++ error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-uninit-after-item.stderr b/src/test/ui/borrowck/borrowck-uninit-after-item.stderr index 588b1b0c9729c..071598b42eecd 100644 --- a/src/test/ui/borrowck/borrowck-uninit-after-item.stderr +++ b/src/test/ui/borrowck/borrowck-uninit-after-item.stderr @@ -6,6 +6,11 @@ LL | let bar; LL | fn baz(_x: isize) { } LL | baz(bar); | ^^^ `bar` used here but it isn't initialized + | +help: consider assigning a value + | +LL | let bar = 0; + | +++ error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-uninit-field-access.stderr b/src/test/ui/borrowck/borrowck-uninit-field-access.stderr index 6a38a79891970..f0f4ad704b7ca 100644 --- a/src/test/ui/borrowck/borrowck-uninit-field-access.stderr +++ b/src/test/ui/borrowck/borrowck-uninit-field-access.stderr @@ -5,6 +5,11 @@ LL | let mut a: Point; | ----- binding declared here but left uninitialized LL | let _ = a.x + 1; | ^^^ `a.x` used here but it isn't initialized + | +help: consider assigning a value + | +LL | let mut a: Point = Default::default(); + | ++++++++++++++++++++ error[E0382]: use of moved value: `line1.origin` --> $DIR/borrowck-uninit-field-access.rs:25:13 diff --git a/src/test/ui/borrowck/borrowck-uninit-in-assignop.stderr b/src/test/ui/borrowck/borrowck-uninit-in-assignop.stderr index 744cb14e662b3..fdbb451bde4e8 100644 --- a/src/test/ui/borrowck/borrowck-uninit-in-assignop.stderr +++ b/src/test/ui/borrowck/borrowck-uninit-in-assignop.stderr @@ -5,6 +5,11 @@ LL | let x: isize; | - binding declared here but left uninitialized LL | x += 1; | ^^^^^^ `x` used here but it isn't initialized + | +help: consider assigning a value + | +LL | let x: isize = 0; + | +++ error[E0381]: used binding `x` isn't initialized --> $DIR/borrowck-uninit-in-assignop.rs:9:5 @@ -13,6 +18,11 @@ LL | let x: isize; | - binding declared here but left uninitialized LL | x -= 1; | ^^^^^^ `x` used here but it isn't initialized + | +help: consider assigning a value + | +LL | let x: isize = 0; + | +++ error[E0381]: used binding `x` isn't initialized --> $DIR/borrowck-uninit-in-assignop.rs:12:5 @@ -21,6 +31,11 @@ LL | let x: isize; | - binding declared here but left uninitialized LL | x *= 1; | ^^^^^^ `x` used here but it isn't initialized + | +help: consider assigning a value + | +LL | let x: isize = 0; + | +++ error[E0381]: used binding `x` isn't initialized --> $DIR/borrowck-uninit-in-assignop.rs:15:5 @@ -29,6 +44,11 @@ LL | let x: isize; | - binding declared here but left uninitialized LL | x /= 1; | ^^^^^^ `x` used here but it isn't initialized + | +help: consider assigning a value + | +LL | let x: isize = 0; + | +++ error[E0381]: used binding `x` isn't initialized --> $DIR/borrowck-uninit-in-assignop.rs:18:5 @@ -37,6 +57,11 @@ LL | let x: isize; | - binding declared here but left uninitialized LL | x %= 1; | ^^^^^^ `x` used here but it isn't initialized + | +help: consider assigning a value + | +LL | let x: isize = 0; + | +++ error[E0381]: used binding `x` isn't initialized --> $DIR/borrowck-uninit-in-assignop.rs:21:5 @@ -45,6 +70,11 @@ LL | let x: isize; | - binding declared here but left uninitialized LL | x ^= 1; | ^^^^^^ `x` used here but it isn't initialized + | +help: consider assigning a value + | +LL | let x: isize = 0; + | +++ error[E0381]: used binding `x` isn't initialized --> $DIR/borrowck-uninit-in-assignop.rs:24:5 @@ -53,6 +83,11 @@ LL | let x: isize; | - binding declared here but left uninitialized LL | x &= 1; | ^^^^^^ `x` used here but it isn't initialized + | +help: consider assigning a value + | +LL | let x: isize = 0; + | +++ error[E0381]: used binding `x` isn't initialized --> $DIR/borrowck-uninit-in-assignop.rs:27:5 @@ -61,6 +96,11 @@ LL | let x: isize; | - binding declared here but left uninitialized LL | x |= 1; | ^^^^^^ `x` used here but it isn't initialized + | +help: consider assigning a value + | +LL | let x: isize = 0; + | +++ error[E0381]: used binding `x` isn't initialized --> $DIR/borrowck-uninit-in-assignop.rs:30:5 @@ -69,6 +109,11 @@ LL | let x: isize; | - binding declared here but left uninitialized LL | x <<= 1; | ^^^^^^^ `x` used here but it isn't initialized + | +help: consider assigning a value + | +LL | let x: isize = 0; + | +++ error[E0381]: used binding `x` isn't initialized --> $DIR/borrowck-uninit-in-assignop.rs:33:5 @@ -77,6 +122,11 @@ LL | let x: isize; | - binding declared here but left uninitialized LL | x >>= 1; | ^^^^^^^ `x` used here but it isn't initialized + | +help: consider assigning a value + | +LL | let x: isize = 0; + | +++ error: aborting due to 10 previous errors diff --git a/src/test/ui/borrowck/borrowck-uninit-ref-chain.stderr b/src/test/ui/borrowck/borrowck-uninit-ref-chain.stderr index c486cb6dd0cd3..73fded7545cc6 100644 --- a/src/test/ui/borrowck/borrowck-uninit-ref-chain.stderr +++ b/src/test/ui/borrowck/borrowck-uninit-ref-chain.stderr @@ -5,6 +5,11 @@ LL | let x: &&Box; | - binding declared here but left uninitialized LL | let _y = &**x; | ^^^^ `**x` used here but it isn't initialized + | +help: consider assigning a value + | +LL | let x: &&Box = todo!(); + | +++++++++ error[E0381]: used binding `x` isn't initialized --> $DIR/borrowck-uninit-ref-chain.rs:11:14 @@ -13,6 +18,11 @@ LL | let x: &&S; | - binding declared here but left uninitialized LL | let _y = &**x; | ^^^^ `**x` used here but it isn't initialized + | +help: consider assigning a value + | +LL | let x: &&S = todo!(); + | +++++++++ error[E0381]: used binding `x` isn't initialized --> $DIR/borrowck-uninit-ref-chain.rs:14:14 @@ -21,6 +31,11 @@ LL | let x: &&i32; | - binding declared here but left uninitialized LL | let _y = &**x; | ^^^^ `**x` used here but it isn't initialized + | +help: consider assigning a value + | +LL | let x: &&i32 = todo!(); + | +++++++++ error[E0381]: partially assigned binding `a` isn't fully initialized --> $DIR/borrowck-uninit-ref-chain.rs:18:5 diff --git a/src/test/ui/borrowck/borrowck-uninit.stderr b/src/test/ui/borrowck/borrowck-uninit.stderr index d5566691a8200..eeafc4ce191c6 100644 --- a/src/test/ui/borrowck/borrowck-uninit.stderr +++ b/src/test/ui/borrowck/borrowck-uninit.stderr @@ -5,6 +5,11 @@ LL | let x: isize; | - binding declared here but left uninitialized LL | foo(x); | ^ `x` used here but it isn't initialized + | +help: consider assigning a value + | +LL | let x: isize = 0; + | +++ error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-use-in-index-lvalue.stderr b/src/test/ui/borrowck/borrowck-use-in-index-lvalue.stderr index 459cf1398b750..18e808f10d0c6 100644 --- a/src/test/ui/borrowck/borrowck-use-in-index-lvalue.stderr +++ b/src/test/ui/borrowck/borrowck-use-in-index-lvalue.stderr @@ -5,6 +5,11 @@ LL | let w: &mut [isize]; | - binding declared here but left uninitialized LL | w[5] = 0; | ^^^^ `*w` used here but it isn't initialized + | +help: consider assigning a value + | +LL | let w: &mut [isize] = todo!(); + | +++++++++ error[E0381]: used binding `w` isn't initialized --> $DIR/borrowck-use-in-index-lvalue.rs:6:5 @@ -13,6 +18,11 @@ LL | let mut w: &mut [isize]; | ----- binding declared here but left uninitialized LL | w[5] = 0; | ^^^^ `*w` used here but it isn't initialized + | +help: consider assigning a value + | +LL | let mut w: &mut [isize] = todo!(); + | +++++++++ error: aborting due to 2 previous errors diff --git a/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast-trait.stderr b/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast-trait.stderr index 942ed4fc6cabf..55f3ff553c13c 100644 --- a/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast-trait.stderr +++ b/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast-trait.stderr @@ -5,6 +5,11 @@ LL | let x: &i32; | - binding declared here but left uninitialized LL | let y = x as *const dyn Foo; | ^ `*x` used here but it isn't initialized + | +help: consider assigning a value + | +LL | let x: &i32 = todo!(); + | +++++++++ error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast.stderr b/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast.stderr index f3289e239818a..ea3d0d3ef51cb 100644 --- a/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast.stderr +++ b/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast.stderr @@ -5,6 +5,11 @@ LL | let x: &i32; | - binding declared here but left uninitialized LL | let y = x as *const i32; | ^ `*x` used here but it isn't initialized + | +help: consider assigning a value + | +LL | let x: &i32 = todo!(); + | +++++++++ error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-while-cond.stderr b/src/test/ui/borrowck/borrowck-while-cond.stderr index e41c1c55e6024..5d01949895639 100644 --- a/src/test/ui/borrowck/borrowck-while-cond.stderr +++ b/src/test/ui/borrowck/borrowck-while-cond.stderr @@ -5,6 +5,11 @@ LL | let x: bool; | - binding declared here but left uninitialized LL | while x { } | ^ `x` used here but it isn't initialized + | +help: consider assigning a value + | +LL | let x: bool = false; + | +++++++ error: aborting due to previous error diff --git a/src/test/ui/borrowck/issue-24267-flow-exit.stderr b/src/test/ui/borrowck/issue-24267-flow-exit.stderr index b85e8f216e5df..58d1c8c0f73ad 100644 --- a/src/test/ui/borrowck/issue-24267-flow-exit.stderr +++ b/src/test/ui/borrowck/issue-24267-flow-exit.stderr @@ -8,6 +8,10 @@ LL | println!("{}", x); | ^ `x` used here but it isn't initialized | = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider assigning a value + | +LL | let x: i32 = 0; + | +++ error[E0381]: used binding `x` isn't initialized --> $DIR/issue-24267-flow-exit.rs:18:20 @@ -19,6 +23,10 @@ LL | println!("{}", x); | ^ `x` used here but it isn't initialized | = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider assigning a value + | +LL | let x: i32 = 0; + | +++ error: aborting due to 2 previous errors diff --git a/src/test/ui/borrowck/issue-62107-match-arm-scopes.stderr b/src/test/ui/borrowck/issue-62107-match-arm-scopes.stderr index f5d2eecfa91a3..9683da919aaf3 100644 --- a/src/test/ui/borrowck/issue-62107-match-arm-scopes.stderr +++ b/src/test/ui/borrowck/issue-62107-match-arm-scopes.stderr @@ -5,6 +5,11 @@ LL | let e: i32; | - binding declared here but left uninitialized LL | match e { | ^ `e` used here but it isn't initialized + | +help: consider assigning a value + | +LL | let e: i32 = 0; + | +++ error: aborting due to previous error diff --git a/src/test/ui/borrowck/suggest-assign-rvalue.rs b/src/test/ui/borrowck/suggest-assign-rvalue.rs new file mode 100644 index 0000000000000..aaca9d47f0aee --- /dev/null +++ b/src/test/ui/borrowck/suggest-assign-rvalue.rs @@ -0,0 +1,57 @@ +#![allow(dead_code)] +#![feature(never_type)] + +#[derive(Debug, Default)] +struct Demo {} + +#[derive(Debug)] +struct DemoNoDef {} + +fn apple(_: u32) {} + +fn banana() { + let chaenomeles; + apple(chaenomeles); + //~^ ERROR used binding `chaenomeles` isn't initialized [E0381] +} + +fn main() { + let my_bool: bool = bool::default(); + println!("my_bool: {}", my_bool); + + let my_float: f32; + println!("my_float: {}", my_float); + //~^ ERROR used binding `my_float` isn't initialized + let demo: Demo; + println!("demo: {:?}", demo); + //~^ ERROR used binding `demo` isn't initialized + + let demo_no: DemoNoDef; + println!("demo_no: {:?}", demo_no); + //~^ ERROR used binding `demo_no` isn't initialized + + let arr: [i32; 5]; + println!("arr: {:?}", arr); + //~^ ERROR used binding `arr` isn't initialized + let foo: Vec<&str>; + println!("foo: {:?}", foo); + //~^ ERROR used binding `foo` isn't initialized + + let my_string: String; + println!("my_string: {}", my_string); + //~^ ERROR used binding `my_string` isn't initialized + + let my_int: &i32; + println!("my_int: {}", *my_int); + //~^ ERROR used binding `my_int` isn't initialized + + let hello: &str; + println!("hello: {}", hello); + //~^ ERROR used binding `hello` isn't initialized + + let never: !; + println!("never: {}", never); + //~^ ERROR used binding `never` isn't initialized [E0381] + + banana(); +} diff --git a/src/test/ui/borrowck/suggest-assign-rvalue.stderr b/src/test/ui/borrowck/suggest-assign-rvalue.stderr new file mode 100644 index 0000000000000..92acba640d756 --- /dev/null +++ b/src/test/ui/borrowck/suggest-assign-rvalue.stderr @@ -0,0 +1,138 @@ +error[E0381]: used binding `chaenomeles` isn't initialized + --> $DIR/suggest-assign-rvalue.rs:14:11 + | +LL | let chaenomeles; + | ----------- binding declared here but left uninitialized +LL | apple(chaenomeles); + | ^^^^^^^^^^^ `chaenomeles` used here but it isn't initialized + | +help: consider assigning a value + | +LL | let chaenomeles = 0; + | +++ + +error[E0381]: used binding `my_float` isn't initialized + --> $DIR/suggest-assign-rvalue.rs:23:30 + | +LL | let my_float: f32; + | -------- binding declared here but left uninitialized +LL | println!("my_float: {}", my_float); + | ^^^^^^^^ `my_float` used here but it isn't initialized + | + = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider assigning a value + | +LL | let my_float: f32 = 0.0; + | +++++ + +error[E0381]: used binding `demo` isn't initialized + --> $DIR/suggest-assign-rvalue.rs:26:28 + | +LL | let demo: Demo; + | ---- binding declared here but left uninitialized +LL | println!("demo: {:?}", demo); + | ^^^^ `demo` used here but it isn't initialized + | + = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider assigning a value + | +LL | let demo: Demo = Default::default(); + | ++++++++++++++++++++ + +error[E0381]: used binding `demo_no` isn't initialized + --> $DIR/suggest-assign-rvalue.rs:30:31 + | +LL | let demo_no: DemoNoDef; + | ------- binding declared here but left uninitialized +LL | println!("demo_no: {:?}", demo_no); + | ^^^^^^^ `demo_no` used here but it isn't initialized + | + = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider assigning a value + | +LL | let demo_no: DemoNoDef = todo!(); + | +++++++++ + +error[E0381]: used binding `arr` isn't initialized + --> $DIR/suggest-assign-rvalue.rs:34:27 + | +LL | let arr: [i32; 5]; + | --- binding declared here but left uninitialized +LL | println!("arr: {:?}", arr); + | ^^^ `arr` used here but it isn't initialized + | + = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider assigning a value + | +LL | let arr: [i32; 5] = todo!(); + | +++++++++ + +error[E0381]: used binding `foo` isn't initialized + --> $DIR/suggest-assign-rvalue.rs:37:27 + | +LL | let foo: Vec<&str>; + | --- binding declared here but left uninitialized +LL | println!("foo: {:?}", foo); + | ^^^ `foo` used here but it isn't initialized + | + = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider assigning a value + | +LL | let foo: Vec<&str> = vec![]; + | ++++++++ + +error[E0381]: used binding `my_string` isn't initialized + --> $DIR/suggest-assign-rvalue.rs:41:31 + | +LL | let my_string: String; + | --------- binding declared here but left uninitialized +LL | println!("my_string: {}", my_string); + | ^^^^^^^^^ `my_string` used here but it isn't initialized + | + = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider assigning a value + | +LL | let my_string: String = Default::default(); + | ++++++++++++++++++++ + +error[E0381]: used binding `my_int` isn't initialized + --> $DIR/suggest-assign-rvalue.rs:45:28 + | +LL | let my_int: &i32; + | ------ binding declared here but left uninitialized +LL | println!("my_int: {}", *my_int); + | ^^^^^^^ `*my_int` used here but it isn't initialized + | + = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider assigning a value + | +LL | let my_int: &i32 = todo!(); + | +++++++++ + +error[E0381]: used binding `hello` isn't initialized + --> $DIR/suggest-assign-rvalue.rs:49:27 + | +LL | let hello: &str; + | ----- binding declared here but left uninitialized +LL | println!("hello: {}", hello); + | ^^^^^ `hello` used here but it isn't initialized + | + = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider assigning a value + | +LL | let hello: &str = todo!(); + | +++++++++ + +error[E0381]: used binding `never` isn't initialized + --> $DIR/suggest-assign-rvalue.rs:53:27 + | +LL | let never: !; + | ----- binding declared here but left uninitialized +LL | println!("never: {}", never); + | ^^^^^ `never` used here but it isn't initialized + | + = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 10 previous errors + +For more information about this error, try `rustc --explain E0381`. diff --git a/src/test/ui/closures/2229_closure_analysis/match/pattern-matching-should-fail.stderr b/src/test/ui/closures/2229_closure_analysis/match/pattern-matching-should-fail.stderr index fea5441ec673d..ad061d93cb242 100644 --- a/src/test/ui/closures/2229_closure_analysis/match/pattern-matching-should-fail.stderr +++ b/src/test/ui/closures/2229_closure_analysis/match/pattern-matching-should-fail.stderr @@ -76,6 +76,11 @@ LL | let x: u8; | - binding declared here but left uninitialized LL | let c1 = || match x { }; | ^ `x` used here but it isn't initialized + | +help: consider assigning a value + | +LL | let x: u8 = 0; + | +++ error: aborting due to 8 previous errors diff --git a/src/test/ui/const-generics/const-generic-default-wont-borrowck.stderr b/src/test/ui/const-generics/const-generic-default-wont-borrowck.stderr index c62f1d1d23061..0ed370b83c552 100644 --- a/src/test/ui/const-generics/const-generic-default-wont-borrowck.stderr +++ b/src/test/ui/const-generics/const-generic-default-wont-borrowck.stderr @@ -5,6 +5,11 @@ LL | let s: &'static str; s.len() | - ^^^^^^^ `*s` used here but it isn't initialized | | | binding declared here but left uninitialized + | +help: consider assigning a value + | +LL | let s: &'static str = todo!(); s.len() + | +++++++++ error: aborting due to previous error diff --git a/src/test/ui/consts/issue-78655.stderr b/src/test/ui/consts/issue-78655.stderr index f5b1123e7f343..6b83fa0e5a01f 100644 --- a/src/test/ui/consts/issue-78655.stderr +++ b/src/test/ui/consts/issue-78655.stderr @@ -5,6 +5,11 @@ LL | let x; | - binding declared here but left uninitialized LL | &x | ^^ `x` used here but it isn't initialized + | +help: consider assigning a value + | +LL | let x = 0; + | +++ error: could not evaluate constant pattern --> $DIR/issue-78655.rs:7:9 diff --git a/src/test/ui/drop/repeat-drop-2.stderr b/src/test/ui/drop/repeat-drop-2.stderr index 48fa2bfa975c0..e8d98477d3268 100644 --- a/src/test/ui/drop/repeat-drop-2.stderr +++ b/src/test/ui/drop/repeat-drop-2.stderr @@ -24,6 +24,11 @@ LL | let x: u8; | - binding declared here but left uninitialized LL | let _ = [x; 0]; | ^ `x` used here but it isn't initialized + | +help: consider assigning a value + | +LL | let x: u8 = 0; + | +++ error: aborting due to 3 previous errors diff --git a/src/test/ui/loops/loop-proper-liveness.stderr b/src/test/ui/loops/loop-proper-liveness.stderr index 14e86aee059b2..f9d94b6810cb0 100644 --- a/src/test/ui/loops/loop-proper-liveness.stderr +++ b/src/test/ui/loops/loop-proper-liveness.stderr @@ -8,6 +8,10 @@ LL | println!("{:?}", x); | ^ `x` used here but it isn't initialized | = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider assigning a value + | +LL | let x: i32 = 0; + | +++ error: aborting due to previous error diff --git a/src/test/ui/mir/drop-elaboration-after-borrowck-error.stderr b/src/test/ui/mir/drop-elaboration-after-borrowck-error.stderr index d8154f8d2cbc4..49f24ed39b427 100644 --- a/src/test/ui/mir/drop-elaboration-after-borrowck-error.stderr +++ b/src/test/ui/mir/drop-elaboration-after-borrowck-error.stderr @@ -24,6 +24,11 @@ LL | let a: [String; 1]; LL | LL | a[0] = String::new(); | ^^^^ `a` used here but it isn't initialized + | +help: consider assigning a value + | +LL | let a: [String; 1] = todo!(); + | +++++++++ error[E0493]: destructors cannot be evaluated at compile-time --> $DIR/drop-elaboration-after-borrowck-error.rs:18:9 diff --git a/src/test/ui/moves/issue-72649-uninit-in-loop.stderr b/src/test/ui/moves/issue-72649-uninit-in-loop.stderr index c7373b5be9d8d..974994223a3fd 100644 --- a/src/test/ui/moves/issue-72649-uninit-in-loop.stderr +++ b/src/test/ui/moves/issue-72649-uninit-in-loop.stderr @@ -47,6 +47,11 @@ LL | let value: NonCopy; | ----- binding declared here but left uninitialized LL | let _used = value; | ^^^^^ `value` used here but it isn't initialized + | +help: consider assigning a value + | +LL | let value: NonCopy = todo!(); + | +++++++++ error[E0381]: used binding `value` isn't initialized --> $DIR/issue-72649-uninit-in-loop.rs:69:21 @@ -56,6 +61,11 @@ LL | let mut value: NonCopy; LL | loop { LL | let _used = value; | ^^^^^ `value` used here but it isn't initialized + | +help: consider assigning a value + | +LL | let mut value: NonCopy = todo!(); + | +++++++++ error: aborting due to 6 previous errors diff --git a/src/test/ui/moves/move-into-dead-array-1.stderr b/src/test/ui/moves/move-into-dead-array-1.stderr index 344a6bbf0c92c..6db0f0bcbffee 100644 --- a/src/test/ui/moves/move-into-dead-array-1.stderr +++ b/src/test/ui/moves/move-into-dead-array-1.stderr @@ -5,6 +5,11 @@ LL | let mut a: [D; 4]; | ----- binding declared here but left uninitialized LL | a[i] = d(); | ^^^^ `a` used here but it isn't initialized + | +help: consider assigning a value + | +LL | let mut a: [D; 4] = todo!(); + | +++++++++ error: aborting due to previous error diff --git a/src/test/ui/moves/move-of-addr-of-mut.stderr b/src/test/ui/moves/move-of-addr-of-mut.stderr index e75f2b1c0894c..ddebaa0129a43 100644 --- a/src/test/ui/moves/move-of-addr-of-mut.stderr +++ b/src/test/ui/moves/move-of-addr-of-mut.stderr @@ -7,6 +7,10 @@ LL | std::ptr::addr_of_mut!(x); | ^^^^^^^^^^^^^^^^^^^^^^^^^ `x` used here but it isn't initialized | = note: this error originates in the macro `std::ptr::addr_of_mut` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider assigning a value + | +LL | let mut x: S = todo!(); + | +++++++++ error: aborting due to previous error diff --git a/src/test/ui/nll/match-cfg-fake-edges.stderr b/src/test/ui/nll/match-cfg-fake-edges.stderr index 250aa482e5c67..2d48a914218fd 100644 --- a/src/test/ui/nll/match-cfg-fake-edges.stderr +++ b/src/test/ui/nll/match-cfg-fake-edges.stderr @@ -9,6 +9,11 @@ LL | _ if { x = 2; true } => 1, LL | _ if { LL | x; | ^ `x` used here but it isn't initialized + | +help: consider assigning a value + | +LL | let x = 0; + | +++ error[E0382]: use of moved value: `x` --> $DIR/match-cfg-fake-edges.rs:35:13 diff --git a/src/test/ui/nll/match-on-borrowed.stderr b/src/test/ui/nll/match-on-borrowed.stderr index 664f36f695cf3..32666529f3f95 100644 --- a/src/test/ui/nll/match-on-borrowed.stderr +++ b/src/test/ui/nll/match-on-borrowed.stderr @@ -40,6 +40,11 @@ LL | let n: Never; | - binding declared here but left uninitialized LL | match n {} | ^ `n` used here but it isn't initialized + | +help: consider assigning a value + | +LL | let n: Never = todo!(); + | +++++++++ error: aborting due to 4 previous errors diff --git a/src/test/ui/uninhabited/privately-uninhabited-mir-call.stderr b/src/test/ui/uninhabited/privately-uninhabited-mir-call.stderr index 95c209f47c92a..0dfd22a30acc7 100644 --- a/src/test/ui/uninhabited/privately-uninhabited-mir-call.stderr +++ b/src/test/ui/uninhabited/privately-uninhabited-mir-call.stderr @@ -6,6 +6,11 @@ LL | let y: &mut u32; ... LL | *y = 2; | ^^^^^^ `y` used here but it isn't initialized + | +help: consider assigning a value + | +LL | let y: &mut u32 = todo!(); + | +++++++++ error: aborting due to previous error From 9640d1c02354dc3167f775e56629aaf8974e78f7 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 21 Sep 2022 15:18:36 +1000 Subject: [PATCH 244/586] Move `#!` checking. Currently does the "is this a `#!` at the start of the file?" check for every single token(!) This commit moves it so it only happens once. --- compiler/rustc_parse/src/lexer/mod.rs | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs index 394a5b8648088..0e8a739fb628f 100644 --- a/compiler/rustc_parse/src/lexer/mod.rs +++ b/compiler/rustc_parse/src/lexer/mod.rs @@ -38,10 +38,16 @@ pub struct UnmatchedBrace { pub(crate) fn parse_token_trees<'a>( sess: &'a ParseSess, - src: &'a str, - start_pos: BytePos, + mut src: &'a str, + mut start_pos: BytePos, override_span: Option, ) -> (PResult<'a, TokenStream>, Vec) { + // Skip `#!`, if present. + if let Some(shebang_len) = rustc_lexer::strip_shebang(src) { + src = &src[shebang_len..]; + start_pos = start_pos + BytePos::from_usize(shebang_len); + } + StringReader { sess, start_pos, pos: start_pos, src, override_span }.into_token_trees() } @@ -65,13 +71,6 @@ impl<'a> StringReader<'a> { fn next_token(&mut self) -> (Spacing, Token) { let mut spacing = Spacing::Joint; - // Skip `#!` at the start of the file - if self.pos == self.start_pos - && let Some(shebang_len) = rustc_lexer::strip_shebang(self.src) - { - self.pos = self.pos + BytePos::from_usize(shebang_len); - } - // Skip trivial (whitespace & comments) tokens loop { let start_src_index = self.src_index(self.pos); From d7928a92e588e11a6c7145cde9ccfd75c4c7cc01 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 21 Sep 2022 16:38:28 +1000 Subject: [PATCH 245/586] Clarify spacing computation. The spacing computation is done in two parts. In the first part `next_token` and `bump` use `Spacing::Alone` to mean "preceded by whitespace" and `Spacing::Joint` to mean the opposite. In the second part `parse_token_tree_other` then adjusts the `spacing` value to mean the usual thing (i.e. "is the following token joinable punctuation?"). This shift in meaning is very confusing and it took me some time to understand what was going on. This commit changes the first part to use a bool, and adds some comments, which makes things much clearer. --- compiler/rustc_parse/src/lexer/mod.rs | 15 ++++++++------- compiler/rustc_parse/src/lexer/tokentrees.rs | 18 ++++++++++++------ 2 files changed, 20 insertions(+), 13 deletions(-) diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs index 0e8a739fb628f..7d5f736a6f4c5 100644 --- a/compiler/rustc_parse/src/lexer/mod.rs +++ b/compiler/rustc_parse/src/lexer/mod.rs @@ -1,7 +1,7 @@ use crate::lexer::unicode_chars::UNICODE_ARRAY; use rustc_ast::ast::{self, AttrStyle}; use rustc_ast::token::{self, CommentKind, Delimiter, Token, TokenKind}; -use rustc_ast::tokenstream::{Spacing, TokenStream}; +use rustc_ast::tokenstream::TokenStream; use rustc_ast::util::unicode::contains_text_flow_control_chars; use rustc_errors::{error_code, Applicability, DiagnosticBuilder, ErrorGuaranteed, PResult}; use rustc_lexer::unescape::{self, Mode}; @@ -67,9 +67,10 @@ impl<'a> StringReader<'a> { self.override_span.unwrap_or_else(|| Span::with_root_ctxt(lo, hi)) } - /// Returns the next token, and info about preceding whitespace, if any. - fn next_token(&mut self) -> (Spacing, Token) { - let mut spacing = Spacing::Joint; + /// Returns the next token, paired with a bool indicating if the token was + /// preceded by whitespace. + fn next_token(&mut self) -> (Token, bool) { + let mut preceded_by_whitespace = false; // Skip trivial (whitespace & comments) tokens loop { @@ -78,7 +79,7 @@ impl<'a> StringReader<'a> { if text.is_empty() { let span = self.mk_sp(self.pos, self.pos); - return (spacing, Token::new(token::Eof, span)); + return (Token::new(token::Eof, span), preceded_by_whitespace); } let token = rustc_lexer::first_token(text); @@ -91,9 +92,9 @@ impl<'a> StringReader<'a> { match self.cook_lexer_token(token.kind, start) { Some(kind) => { let span = self.mk_sp(start, self.pos); - return (spacing, Token::new(kind, span)); + return (Token::new(kind, span), preceded_by_whitespace); } - None => spacing = Spacing::Alone, + None => preceded_by_whitespace = true, } } } diff --git a/compiler/rustc_parse/src/lexer/tokentrees.rs b/compiler/rustc_parse/src/lexer/tokentrees.rs index 3372544a579a3..fe95742972f58 100644 --- a/compiler/rustc_parse/src/lexer/tokentrees.rs +++ b/compiler/rustc_parse/src/lexer/tokentrees.rs @@ -246,16 +246,22 @@ impl<'a> TokenTreesReader<'a> { #[inline] fn parse_token_tree_other(&mut self) -> TokenTree { + // `spacing` for the returned token is determined by the next token: + // its kind and its `preceded_by_whitespace` status. let tok = self.token.take(); - let mut spacing = self.bump(); - if !self.token.is_op() { - spacing = Spacing::Alone; - } + let is_next_tok_preceded_by_whitespace = self.bump(); + let spacing = if is_next_tok_preceded_by_whitespace || !self.token.is_op() { + Spacing::Alone + } else { + Spacing::Joint + }; TokenTree::Token(tok, spacing) } - fn bump(&mut self) -> Spacing { - let (spacing, token) = self.string_reader.next_token(); + // Set `self.token` to the next token. Returns a bool indicating if that + // token was preceded by whitespace. + fn bump(&mut self) -> bool { + let (token, spacing) = self.string_reader.next_token(); self.token = token; spacing } From 5b2075e03d90b53dddda4459ad299c1ffa9cf960 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 21 Sep 2022 17:03:09 +1000 Subject: [PATCH 246/586] Remove `TokenTreesReader::bump`. It's an unnecessary layer that obfuscates when I am looking for optimizations. --- compiler/rustc_parse/src/lexer/tokentrees.rs | 26 +++++++------------- 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/compiler/rustc_parse/src/lexer/tokentrees.rs b/compiler/rustc_parse/src/lexer/tokentrees.rs index fe95742972f58..ae82d09ba4100 100644 --- a/compiler/rustc_parse/src/lexer/tokentrees.rs +++ b/compiler/rustc_parse/src/lexer/tokentrees.rs @@ -45,9 +45,8 @@ struct TokenTreesReader<'a> { impl<'a> TokenTreesReader<'a> { // Parse a stream of tokens into a list of `TokenTree`s, up to an `Eof`. fn parse_all_token_trees(&mut self) -> PResult<'a, TokenStream> { + self.token = self.string_reader.next_token().0; let mut buf = TokenStreamBuilder::default(); - - self.bump(); loop { match self.token.kind { token::OpenDelim(delim) => buf.push(self.parse_token_tree_open_delim(delim)), @@ -116,7 +115,7 @@ impl<'a> TokenTreesReader<'a> { // Parse the open delimiter. self.open_braces.push((delim, self.token.span)); - self.bump(); + self.token = self.string_reader.next_token().0; // Parse the token trees within the delimiters. // We stop at any delimiter so we can try to recover if the user @@ -155,7 +154,7 @@ impl<'a> TokenTreesReader<'a> { self.matching_delim_spans.push((open_brace, open_brace_span, close_brace_span)); } // Parse the closing delimiter. - self.bump(); + self.token = self.string_reader.next_token().0; } // Incorrect delimiter. token::CloseDelim(other) => { @@ -202,7 +201,7 @@ impl<'a> TokenTreesReader<'a> { // bar(baz( // } // Incorrect delimiter but matches the earlier `{` if !self.open_braces.iter().any(|&(b, _)| b == other) { - self.bump(); + self.token = self.string_reader.next_token().0; } } token::Eof => { @@ -248,22 +247,15 @@ impl<'a> TokenTreesReader<'a> { fn parse_token_tree_other(&mut self) -> TokenTree { // `spacing` for the returned token is determined by the next token: // its kind and its `preceded_by_whitespace` status. - let tok = self.token.take(); - let is_next_tok_preceded_by_whitespace = self.bump(); - let spacing = if is_next_tok_preceded_by_whitespace || !self.token.is_op() { + let this_tok = self.token.take(); + let (next_tok, is_next_tok_preceded_by_whitespace) = self.string_reader.next_token(); + let this_spacing = if is_next_tok_preceded_by_whitespace || !next_tok.is_op() { Spacing::Alone } else { Spacing::Joint }; - TokenTree::Token(tok, spacing) - } - - // Set `self.token` to the next token. Returns a bool indicating if that - // token was preceded by whitespace. - fn bump(&mut self) -> bool { - let (token, spacing) = self.string_reader.next_token(); - self.token = token; - spacing + self.token = next_tok; + TokenTree::Token(this_tok, this_spacing) } } From 33ba2776c903dab45e4c9a8c9313ce5d59e69af1 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 26 Sep 2022 12:57:37 +1000 Subject: [PATCH 247/586] Remove `ast::Token::take`. Instead of replacing `TokenTreesReader::token` in two steps, we can just do it in one, which is both simpler and faster. --- compiler/rustc_ast/src/token.rs | 7 +------ compiler/rustc_parse/src/lexer/tokentrees.rs | 3 +-- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs index 97dfb7837674f..fa6162c51847a 100644 --- a/compiler/rustc_ast/src/token.rs +++ b/compiler/rustc_ast/src/token.rs @@ -13,7 +13,7 @@ use rustc_span::symbol::{kw, sym}; use rustc_span::symbol::{Ident, Symbol}; use rustc_span::{self, edition::Edition, Span, DUMMY_SP}; use std::borrow::Cow; -use std::{fmt, mem}; +use std::fmt; #[derive(Clone, Copy, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)] pub enum CommentKind { @@ -335,11 +335,6 @@ impl Token { Token::new(Ident(ident.name, ident.is_raw_guess()), ident.span) } - /// Return this token by value and leave a dummy token in its place. - pub fn take(&mut self) -> Self { - mem::replace(self, Token::dummy()) - } - /// For interpolated tokens, returns a span of the fragment to which the interpolated /// token refers. For all other tokens this is just a regular span. /// It is particularly important to use this for identifiers and lifetimes diff --git a/compiler/rustc_parse/src/lexer/tokentrees.rs b/compiler/rustc_parse/src/lexer/tokentrees.rs index ae82d09ba4100..c23090e714239 100644 --- a/compiler/rustc_parse/src/lexer/tokentrees.rs +++ b/compiler/rustc_parse/src/lexer/tokentrees.rs @@ -247,14 +247,13 @@ impl<'a> TokenTreesReader<'a> { fn parse_token_tree_other(&mut self) -> TokenTree { // `spacing` for the returned token is determined by the next token: // its kind and its `preceded_by_whitespace` status. - let this_tok = self.token.take(); let (next_tok, is_next_tok_preceded_by_whitespace) = self.string_reader.next_token(); let this_spacing = if is_next_tok_preceded_by_whitespace || !next_tok.is_op() { Spacing::Alone } else { Spacing::Joint }; - self.token = next_tok; + let this_tok = std::mem::replace(&mut self.token, next_tok); TokenTree::Token(this_tok, this_spacing) } } From 33516ac09af7038efce6332afdedc758a3943609 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 26 Sep 2022 08:50:52 +1000 Subject: [PATCH 248/586] [ui] Rearrange `StringReader`/`TokenTreesReader` creation. `TokenTreesReader` wraps a `StringReader`, but the `into_token_trees` function obscures this. This commit moves to a more straightforward control flow. --- compiler/rustc_parse/src/lexer/mod.rs | 3 +- compiler/rustc_parse/src/lexer/tokentrees.rs | 37 ++++++++++---------- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs index 7d5f736a6f4c5..bdc8e96b88951 100644 --- a/compiler/rustc_parse/src/lexer/mod.rs +++ b/compiler/rustc_parse/src/lexer/mod.rs @@ -48,7 +48,8 @@ pub(crate) fn parse_token_trees<'a>( start_pos = start_pos + BytePos::from_usize(shebang_len); } - StringReader { sess, start_pos, pos: start_pos, src, override_span }.into_token_trees() + let string_reader = StringReader { sess, start_pos, pos: start_pos, src, override_span }; + tokentrees::TokenTreesReader::parse_token_trees(string_reader) } struct StringReader<'a> { diff --git a/compiler/rustc_parse/src/lexer/tokentrees.rs b/compiler/rustc_parse/src/lexer/tokentrees.rs index c23090e714239..749a640f92eab 100644 --- a/compiler/rustc_parse/src/lexer/tokentrees.rs +++ b/compiler/rustc_parse/src/lexer/tokentrees.rs @@ -1,5 +1,4 @@ use super::{StringReader, UnmatchedBrace}; - use rustc_ast::token::{self, Delimiter, Token}; use rustc_ast::tokenstream::{DelimSpan, Spacing, TokenStream, TokenTree}; use rustc_ast_pretty::pprust::token_to_string; @@ -7,24 +6,7 @@ use rustc_data_structures::fx::FxHashMap; use rustc_errors::{PErr, PResult}; use rustc_span::Span; -impl<'a> StringReader<'a> { - pub(super) fn into_token_trees(self) -> (PResult<'a, TokenStream>, Vec) { - let mut tt_reader = TokenTreesReader { - string_reader: self, - token: Token::dummy(), - open_braces: Vec::new(), - unmatched_braces: Vec::new(), - matching_delim_spans: Vec::new(), - last_unclosed_found_span: None, - last_delim_empty_block_spans: FxHashMap::default(), - matching_block_spans: Vec::new(), - }; - let res = tt_reader.parse_all_token_trees(); - (res, tt_reader.unmatched_braces) - } -} - -struct TokenTreesReader<'a> { +pub(super) struct TokenTreesReader<'a> { string_reader: StringReader<'a>, token: Token, /// Stack of open delimiters and their spans. Used for error message. @@ -43,6 +25,23 @@ struct TokenTreesReader<'a> { } impl<'a> TokenTreesReader<'a> { + pub(super) fn parse_token_trees( + string_reader: StringReader<'a>, + ) -> (PResult<'a, TokenStream>, Vec) { + let mut tt_reader = TokenTreesReader { + string_reader, + token: Token::dummy(), + open_braces: Vec::new(), + unmatched_braces: Vec::new(), + matching_delim_spans: Vec::new(), + last_unclosed_found_span: None, + last_delim_empty_block_spans: FxHashMap::default(), + matching_block_spans: Vec::new(), + }; + let res = tt_reader.parse_all_token_trees(); + (res, tt_reader.unmatched_braces) + } + // Parse a stream of tokens into a list of `TokenTree`s, up to an `Eof`. fn parse_all_token_trees(&mut self) -> PResult<'a, TokenStream> { self.token = self.string_reader.next_token().0; From aa6bfaf04b258e3e23d3f7063de4f2d37845ddec Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 26 Sep 2022 09:18:23 +1000 Subject: [PATCH 249/586] Make `rustc_lexer::cursor::Cursor` public. `Cursor` is currently hidden, and the main tokenization path uses `rustc_lexer::first_token` which involves constructing a new `Cursor` for every single token, which is weird. Also, `first_token` also can't handle empty input, so callers have to check for that first. This commit makes `Cursor` public, so `StringReader` can contain a `Cursor`, which results in a simpler structure. The commit also changes `StringReader::advance_token` so it returns an `Option`, simplifying the the empty input case. --- compiler/rustc_lexer/src/cursor.rs | 4 ++-- compiler/rustc_lexer/src/lib.rs | 26 +++++++------------------- compiler/rustc_parse/src/lexer/mod.rs | 23 +++++++++++++---------- src/librustdoc/html/highlight.rs | 9 ++++----- 4 files changed, 26 insertions(+), 36 deletions(-) diff --git a/compiler/rustc_lexer/src/cursor.rs b/compiler/rustc_lexer/src/cursor.rs index 21557a9c85401..df9b6afdf5625 100644 --- a/compiler/rustc_lexer/src/cursor.rs +++ b/compiler/rustc_lexer/src/cursor.rs @@ -4,7 +4,7 @@ use std::str::Chars; /// /// Next characters can be peeked via `first` method, /// and position can be shifted forward via `bump` method. -pub(crate) struct Cursor<'a> { +pub struct Cursor<'a> { initial_len: usize, /// Iterator over chars. Slightly faster than a &str. chars: Chars<'a>, @@ -15,7 +15,7 @@ pub(crate) struct Cursor<'a> { pub(crate) const EOF_CHAR: char = '\0'; impl<'a> Cursor<'a> { - pub(crate) fn new(input: &'a str) -> Cursor<'a> { + pub fn new(input: &'a str) -> Cursor<'a> { Cursor { initial_len: input.len(), chars: input.chars(), diff --git a/compiler/rustc_lexer/src/lib.rs b/compiler/rustc_lexer/src/lib.rs index a79c982649afc..9182b649bf3d9 100644 --- a/compiler/rustc_lexer/src/lib.rs +++ b/compiler/rustc_lexer/src/lib.rs @@ -23,7 +23,7 @@ // We want to be able to build this crate with a stable compiler, so no // `#![feature]` attributes should be added. -mod cursor; +pub mod cursor; pub mod unescape; #[cfg(test)] @@ -219,13 +219,6 @@ pub fn strip_shebang(input: &str) -> Option { None } -/// Parses the first token from the provided input string. -#[inline] -pub fn first_token(input: &str) -> Token { - debug_assert!(!input.is_empty()); - Cursor::new(input).advance_token() -} - /// Validates a raw string literal. Used for getting more information about a /// problem with a `RawStr`/`RawByteStr` with a `None` field. #[inline] @@ -242,14 +235,7 @@ pub fn validate_raw_str(input: &str, prefix_len: u32) -> Result<(), RawStrError> /// Creates an iterator that produces tokens from the input string. pub fn tokenize(input: &str) -> impl Iterator + '_ { let mut cursor = Cursor::new(input); - std::iter::from_fn(move || { - if cursor.is_eof() { - None - } else { - cursor.reset_len_consumed(); - Some(cursor.advance_token()) - } - }) + std::iter::from_fn(move || cursor.advance_token()) } /// True if `c` is considered a whitespace according to Rust language definition. @@ -311,8 +297,8 @@ pub fn is_ident(string: &str) -> bool { impl Cursor<'_> { /// Parses a token from the input string. - fn advance_token(&mut self) -> Token { - let first_char = self.bump().unwrap(); + pub fn advance_token(&mut self) -> Option { + let first_char = self.bump()?; let token_kind = match first_char { // Slash, comment or block comment. '/' => match self.first() { @@ -433,7 +419,9 @@ impl Cursor<'_> { } _ => Unknown, }; - Token::new(token_kind, self.len_consumed()) + let res = Some(Token::new(token_kind, self.len_consumed())); + self.reset_len_consumed(); + res } fn line_comment(&mut self) -> TokenKind { diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs index bdc8e96b88951..c182e86332a3c 100644 --- a/compiler/rustc_parse/src/lexer/mod.rs +++ b/compiler/rustc_parse/src/lexer/mod.rs @@ -4,6 +4,7 @@ use rustc_ast::token::{self, CommentKind, Delimiter, Token, TokenKind}; use rustc_ast::tokenstream::TokenStream; use rustc_ast::util::unicode::contains_text_flow_control_chars; use rustc_errors::{error_code, Applicability, DiagnosticBuilder, ErrorGuaranteed, PResult}; +use rustc_lexer::cursor::Cursor; use rustc_lexer::unescape::{self, Mode}; use rustc_lexer::{Base, DocStyle, RawStrError}; use rustc_session::lint::builtin::{ @@ -48,7 +49,9 @@ pub(crate) fn parse_token_trees<'a>( start_pos = start_pos + BytePos::from_usize(shebang_len); } - let string_reader = StringReader { sess, start_pos, pos: start_pos, src, override_span }; + let cursor = Cursor::new(src); + let string_reader = + StringReader { sess, start_pos, pos: start_pos, src, cursor, override_span }; tokentrees::TokenTreesReader::parse_token_trees(string_reader) } @@ -60,6 +63,8 @@ struct StringReader<'a> { pos: BytePos, /// Source text to tokenize. src: &'a str, + /// Cursor for getting lexer tokens. + cursor: Cursor<'a>, override_span: Option, } @@ -75,15 +80,13 @@ impl<'a> StringReader<'a> { // Skip trivial (whitespace & comments) tokens loop { - let start_src_index = self.src_index(self.pos); - let text: &str = &self.src[start_src_index..]; - - if text.is_empty() { - let span = self.mk_sp(self.pos, self.pos); - return (Token::new(token::Eof, span), preceded_by_whitespace); - } - - let token = rustc_lexer::first_token(text); + let token = match self.cursor.advance_token() { + Some(token) => token, + None => { + let span = self.mk_sp(self.pos, self.pos); + return (Token::new(token::Eof, span), preceded_by_whitespace); + } + }; let start = self.pos; self.pos = self.pos + BytePos(token.len); diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs index 8922bf377858e..0870d6f382458 100644 --- a/src/librustdoc/html/highlight.rs +++ b/src/librustdoc/html/highlight.rs @@ -13,6 +13,7 @@ use std::collections::VecDeque; use std::fmt::{Display, Write}; use rustc_data_structures::fx::FxHashMap; +use rustc_lexer::cursor::Cursor; use rustc_lexer::{LiteralKind, TokenKind}; use rustc_span::edition::Edition; use rustc_span::symbol::Symbol; @@ -408,15 +409,13 @@ enum Highlight<'a> { struct TokenIter<'a> { src: &'a str, + cursor: Cursor<'a>, } impl<'a> Iterator for TokenIter<'a> { type Item = (TokenKind, &'a str); fn next(&mut self) -> Option<(TokenKind, &'a str)> { - if self.src.is_empty() { - return None; - } - let token = rustc_lexer::first_token(self.src); + let token = self.cursor.advance_token()?; let (text, rest) = self.src.split_at(token.len as usize); self.src = rest; Some((token.kind, text)) @@ -525,7 +524,7 @@ impl<'a> Classifier<'a> { /// Takes as argument the source code to HTML-ify, the rust edition to use and the source code /// file span which will be used later on by the `span_correspondance_map`. fn new(src: &str, file_span: Span, decoration_info: Option) -> Classifier<'_> { - let tokens = PeekIter::new(TokenIter { src }); + let tokens = PeekIter::new(TokenIter { src, cursor: Cursor::new(src) }); let decorations = decoration_info.map(Decorations::new); Classifier { tokens, From ceb25d125f98b82fe264e5b9d1b992f0766939a8 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 26 Sep 2022 11:12:06 +1000 Subject: [PATCH 250/586] Use less DRY in `cook_lexer_token`. This is a case where a small amount of repetition results in code that is faster and easier to read. --- compiler/rustc_parse/src/lexer/mod.rs | 38 +++++++++++++-------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs index c182e86332a3c..0f9d585230e20 100644 --- a/compiler/rustc_parse/src/lexer/mod.rs +++ b/compiler/rustc_parse/src/lexer/mod.rs @@ -201,28 +201,28 @@ impl<'a> StringReader<'a> { self.cook_doc_comment(content_start, content, CommentKind::Block, doc_style) } rustc_lexer::TokenKind::Whitespace => return None, - rustc_lexer::TokenKind::Ident - | rustc_lexer::TokenKind::RawIdent - | rustc_lexer::TokenKind::UnknownPrefix => { - let is_raw_ident = token == rustc_lexer::TokenKind::RawIdent; - let is_unknown_prefix = token == rustc_lexer::TokenKind::UnknownPrefix; - let mut ident_start = start; - if is_raw_ident { - ident_start = ident_start + BytePos(2); - } - if is_unknown_prefix { - self.report_unknown_prefix(start); - } - let sym = nfc_normalize(self.str_from(ident_start)); + rustc_lexer::TokenKind::Ident => { + let sym = nfc_normalize(self.str_from(start)); let span = self.mk_sp(start, self.pos); self.sess.symbol_gallery.insert(sym, span); - if is_raw_ident { - if !sym.can_be_raw() { - self.err_span(span, &format!("`{}` cannot be a raw identifier", sym)); - } - self.sess.raw_identifier_spans.borrow_mut().push(span); + token::Ident(sym, false) + } + rustc_lexer::TokenKind::RawIdent => { + let sym = nfc_normalize(self.str_from(start + BytePos(2))); + let span = self.mk_sp(start, self.pos); + self.sess.symbol_gallery.insert(sym, span); + if !sym.can_be_raw() { + self.err_span(span, &format!("`{}` cannot be a raw identifier", sym)); } - token::Ident(sym, is_raw_ident) + self.sess.raw_identifier_spans.borrow_mut().push(span); + token::Ident(sym, true) + } + rustc_lexer::TokenKind::UnknownPrefix => { + self.report_unknown_prefix(start); + let sym = nfc_normalize(self.str_from(start)); + let span = self.mk_sp(start, self.pos); + self.sess.symbol_gallery.insert(sym, span); + token::Ident(sym, false) } rustc_lexer::TokenKind::InvalidIdent // Do not recover an identifier with emoji if the codepoint is a confusable From cc0022a3634dd4a931ac9f68e63017c959bc8be7 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 26 Sep 2022 13:05:54 +1000 Subject: [PATCH 251/586] Rename some things. `Cursor` keeps track of the position within the current token. But it uses confusing names that don't make it clear that the "length consumed" is just within the current token. This commit renames things to make this clearer. --- compiler/rustc_lexer/src/cursor.rs | 12 ++++++------ compiler/rustc_lexer/src/lib.rs | 24 ++++++++++++------------ 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/compiler/rustc_lexer/src/cursor.rs b/compiler/rustc_lexer/src/cursor.rs index df9b6afdf5625..eceef59802eb9 100644 --- a/compiler/rustc_lexer/src/cursor.rs +++ b/compiler/rustc_lexer/src/cursor.rs @@ -5,7 +5,7 @@ use std::str::Chars; /// Next characters can be peeked via `first` method, /// and position can be shifted forward via `bump` method. pub struct Cursor<'a> { - initial_len: usize, + len_remaining: usize, /// Iterator over chars. Slightly faster than a &str. chars: Chars<'a>, #[cfg(debug_assertions)] @@ -17,7 +17,7 @@ pub(crate) const EOF_CHAR: char = '\0'; impl<'a> Cursor<'a> { pub fn new(input: &'a str) -> Cursor<'a> { Cursor { - initial_len: input.len(), + len_remaining: input.len(), chars: input.chars(), #[cfg(debug_assertions)] prev: EOF_CHAR, @@ -61,13 +61,13 @@ impl<'a> Cursor<'a> { } /// Returns amount of already consumed symbols. - pub(crate) fn len_consumed(&self) -> u32 { - (self.initial_len - self.chars.as_str().len()) as u32 + pub(crate) fn pos_within_token(&self) -> u32 { + (self.len_remaining - self.chars.as_str().len()) as u32 } /// Resets the number of bytes consumed to 0. - pub(crate) fn reset_len_consumed(&mut self) { - self.initial_len = self.chars.as_str().len(); + pub(crate) fn reset_pos_within_token(&mut self) { + self.len_remaining = self.chars.as_str().len(); } /// Moves to the next character. diff --git a/compiler/rustc_lexer/src/lib.rs b/compiler/rustc_lexer/src/lib.rs index 9182b649bf3d9..69e772c69243b 100644 --- a/compiler/rustc_lexer/src/lib.rs +++ b/compiler/rustc_lexer/src/lib.rs @@ -315,7 +315,7 @@ impl Cursor<'_> { ('#', c1) if is_id_start(c1) => self.raw_ident(), ('#', _) | ('"', _) => { let res = self.raw_double_quoted_string(1); - let suffix_start = self.len_consumed(); + let suffix_start = self.pos_within_token(); if res.is_ok() { self.eat_literal_suffix(); } @@ -330,7 +330,7 @@ impl Cursor<'_> { ('\'', _) => { self.bump(); let terminated = self.single_quoted_string(); - let suffix_start = self.len_consumed(); + let suffix_start = self.pos_within_token(); if terminated { self.eat_literal_suffix(); } @@ -340,7 +340,7 @@ impl Cursor<'_> { ('"', _) => { self.bump(); let terminated = self.double_quoted_string(); - let suffix_start = self.len_consumed(); + let suffix_start = self.pos_within_token(); if terminated { self.eat_literal_suffix(); } @@ -350,7 +350,7 @@ impl Cursor<'_> { ('r', '"') | ('r', '#') => { self.bump(); let res = self.raw_double_quoted_string(2); - let suffix_start = self.len_consumed(); + let suffix_start = self.pos_within_token(); if res.is_ok() { self.eat_literal_suffix(); } @@ -367,7 +367,7 @@ impl Cursor<'_> { // Numeric literal. c @ '0'..='9' => { let literal_kind = self.number(c); - let suffix_start = self.len_consumed(); + let suffix_start = self.pos_within_token(); self.eat_literal_suffix(); TokenKind::Literal { kind: literal_kind, suffix_start } } @@ -406,7 +406,7 @@ impl Cursor<'_> { // String literal. '"' => { let terminated = self.double_quoted_string(); - let suffix_start = self.len_consumed(); + let suffix_start = self.pos_within_token(); if terminated { self.eat_literal_suffix(); } @@ -419,8 +419,8 @@ impl Cursor<'_> { } _ => Unknown, }; - let res = Some(Token::new(token_kind, self.len_consumed())); - self.reset_len_consumed(); + let res = Some(Token::new(token_kind, self.pos_within_token())); + self.reset_pos_within_token(); res } @@ -606,7 +606,7 @@ impl Cursor<'_> { if !can_be_a_lifetime { let terminated = self.single_quoted_string(); - let suffix_start = self.len_consumed(); + let suffix_start = self.pos_within_token(); if terminated { self.eat_literal_suffix(); } @@ -631,7 +631,7 @@ impl Cursor<'_> { if self.first() == '\'' { self.bump(); let kind = Char { terminated: true }; - Literal { kind, suffix_start: self.len_consumed() } + Literal { kind, suffix_start: self.pos_within_token() } } else { Lifetime { starts_with_number } } @@ -712,7 +712,7 @@ impl Cursor<'_> { fn raw_string_unvalidated(&mut self, prefix_len: u32) -> Result { debug_assert!(self.prev() == 'r'); - let start_pos = self.len_consumed(); + let start_pos = self.pos_within_token(); let mut possible_terminator_offset = None; let mut max_hashes = 0; @@ -766,7 +766,7 @@ impl Cursor<'_> { // Keep track of possible terminators to give a hint about // where there might be a missing terminator possible_terminator_offset = - Some(self.len_consumed() - start_pos - n_end_hashes + prefix_len); + Some(self.pos_within_token() - start_pos - n_end_hashes + prefix_len); max_hashes = n_end_hashes; } } From da84f0f4c31914c14dd03628395e9c53f28b88b9 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 26 Sep 2022 13:06:15 +1000 Subject: [PATCH 252/586] Add `rustc_lexer::TokenKind::Eof`. For alignment with `rust_ast::TokenKind::Eof`. Plus it's a bit faster, due to less `Option` manipulation in `StringReader::next_token`. --- compiler/rustc_lexer/src/lib.rs | 17 +++++++++++++---- compiler/rustc_parse/src/lexer/mod.rs | 10 ++-------- src/librustdoc/html/highlight.rs | 6 +++++- 3 files changed, 20 insertions(+), 13 deletions(-) diff --git a/compiler/rustc_lexer/src/lib.rs b/compiler/rustc_lexer/src/lib.rs index 69e772c69243b..18ebed7c70e15 100644 --- a/compiler/rustc_lexer/src/lib.rs +++ b/compiler/rustc_lexer/src/lib.rs @@ -139,6 +139,9 @@ pub enum TokenKind { /// Unknown token, not expected by the lexer, e.g. "№" Unknown, + + /// End of input. + Eof, } #[derive(Clone, Copy, Debug, PartialEq, Eq)] @@ -235,7 +238,10 @@ pub fn validate_raw_str(input: &str, prefix_len: u32) -> Result<(), RawStrError> /// Creates an iterator that produces tokens from the input string. pub fn tokenize(input: &str) -> impl Iterator + '_ { let mut cursor = Cursor::new(input); - std::iter::from_fn(move || cursor.advance_token()) + std::iter::from_fn(move || { + let token = cursor.advance_token(); + if token.kind != TokenKind::Eof { Some(token) } else { None } + }) } /// True if `c` is considered a whitespace according to Rust language definition. @@ -297,8 +303,11 @@ pub fn is_ident(string: &str) -> bool { impl Cursor<'_> { /// Parses a token from the input string. - pub fn advance_token(&mut self) -> Option { - let first_char = self.bump()?; + pub fn advance_token(&mut self) -> Token { + let first_char = match self.bump() { + Some(c) => c, + None => return Token::new(TokenKind::Eof, 0), + }; let token_kind = match first_char { // Slash, comment or block comment. '/' => match self.first() { @@ -419,7 +428,7 @@ impl Cursor<'_> { } _ => Unknown, }; - let res = Some(Token::new(token_kind, self.pos_within_token())); + let res = Token::new(token_kind, self.pos_within_token()); self.reset_pos_within_token(); res } diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs index 0f9d585230e20..67fefd19d8b25 100644 --- a/compiler/rustc_parse/src/lexer/mod.rs +++ b/compiler/rustc_parse/src/lexer/mod.rs @@ -80,14 +80,7 @@ impl<'a> StringReader<'a> { // Skip trivial (whitespace & comments) tokens loop { - let token = match self.cursor.advance_token() { - Some(token) => token, - None => { - let span = self.mk_sp(self.pos, self.pos); - return (Token::new(token::Eof, span), preceded_by_whitespace); - } - }; - + let token = self.cursor.advance_token(); let start = self.pos; self.pos = self.pos + BytePos(token.len); @@ -327,6 +320,7 @@ impl<'a> StringReader<'a> { err.emit(); token? } + rustc_lexer::TokenKind::Eof => token::Eof, }) } diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs index 0870d6f382458..ea65a6334c9e4 100644 --- a/src/librustdoc/html/highlight.rs +++ b/src/librustdoc/html/highlight.rs @@ -415,7 +415,10 @@ struct TokenIter<'a> { impl<'a> Iterator for TokenIter<'a> { type Item = (TokenKind, &'a str); fn next(&mut self) -> Option<(TokenKind, &'a str)> { - let token = self.cursor.advance_token()?; + let token = self.cursor.advance_token(); + if token.kind == TokenKind::Eof { + return None; + } let (text, rest) = self.src.split_at(token.len as usize); self.src = rest; Some((token.kind, text)) @@ -849,6 +852,7 @@ impl<'a> Classifier<'a> { Class::Ident(self.new_span(before, text)) } TokenKind::Lifetime { .. } => Class::Lifetime, + TokenKind::Eof => panic!("Eof in advance"), }; // Anything that didn't return above is the simple case where we the // class just spans a single token, so we can use the `string` method. From fb4dba0a17b6eb241b4fd3732b976ab38fe2cdc0 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 26 Sep 2022 12:12:58 +1000 Subject: [PATCH 253/586] Inline and remove `cook_lexer_token`. This is a small performance win, alas. --- compiler/rustc_parse/src/lexer/mod.rs | 345 +++++++++++++------------- 1 file changed, 174 insertions(+), 171 deletions(-) diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs index 67fefd19d8b25..151e80e2b3e9d 100644 --- a/compiler/rustc_parse/src/lexer/mod.rs +++ b/compiler/rustc_parse/src/lexer/mod.rs @@ -86,13 +86,182 @@ impl<'a> StringReader<'a> { debug!("next_token: {:?}({:?})", token.kind, self.str_from(start)); - match self.cook_lexer_token(token.kind, start) { - Some(kind) => { + // Now "cook" the token, converting the simple `rustc_lexer::TokenKind` enum into a + // rich `rustc_ast::TokenKind`. This turns strings into interned symbols and runs + // additional validation. + let kind = match token.kind { + rustc_lexer::TokenKind::LineComment { doc_style } => { + // Skip non-doc comments + let Some(doc_style) = doc_style else { + self.lint_unicode_text_flow(start); + preceded_by_whitespace = true; + continue; + }; + + // Opening delimiter of the length 3 is not included into the symbol. + let content_start = start + BytePos(3); + let content = self.str_from(content_start); + self.cook_doc_comment(content_start, content, CommentKind::Line, doc_style) + } + rustc_lexer::TokenKind::BlockComment { doc_style, terminated } => { + if !terminated { + self.report_unterminated_block_comment(start, doc_style); + } + + // Skip non-doc comments + let Some(doc_style) = doc_style else { + self.lint_unicode_text_flow(start); + preceded_by_whitespace = true; + continue; + }; + + // Opening delimiter of the length 3 and closing delimiter of the length 2 + // are not included into the symbol. + let content_start = start + BytePos(3); + let content_end = self.pos - BytePos(if terminated { 2 } else { 0 }); + let content = self.str_from_to(content_start, content_end); + self.cook_doc_comment(content_start, content, CommentKind::Block, doc_style) + } + rustc_lexer::TokenKind::Whitespace => { + preceded_by_whitespace = true; + continue; + } + rustc_lexer::TokenKind::Ident => { + let sym = nfc_normalize(self.str_from(start)); let span = self.mk_sp(start, self.pos); - return (Token::new(kind, span), preceded_by_whitespace); + self.sess.symbol_gallery.insert(sym, span); + token::Ident(sym, false) } - None => preceded_by_whitespace = true, - } + rustc_lexer::TokenKind::RawIdent => { + let sym = nfc_normalize(self.str_from(start + BytePos(2))); + let span = self.mk_sp(start, self.pos); + self.sess.symbol_gallery.insert(sym, span); + if !sym.can_be_raw() { + self.err_span(span, &format!("`{}` cannot be a raw identifier", sym)); + } + self.sess.raw_identifier_spans.borrow_mut().push(span); + token::Ident(sym, true) + } + rustc_lexer::TokenKind::UnknownPrefix => { + self.report_unknown_prefix(start); + let sym = nfc_normalize(self.str_from(start)); + let span = self.mk_sp(start, self.pos); + self.sess.symbol_gallery.insert(sym, span); + token::Ident(sym, false) + } + rustc_lexer::TokenKind::InvalidIdent + // Do not recover an identifier with emoji if the codepoint is a confusable + // with a recoverable substitution token, like `➖`. + if !UNICODE_ARRAY + .iter() + .any(|&(c, _, _)| { + let sym = self.str_from(start); + sym.chars().count() == 1 && c == sym.chars().next().unwrap() + }) => + { + let sym = nfc_normalize(self.str_from(start)); + let span = self.mk_sp(start, self.pos); + self.sess.bad_unicode_identifiers.borrow_mut().entry(sym).or_default() + .push(span); + token::Ident(sym, false) + } + rustc_lexer::TokenKind::Literal { kind, suffix_start } => { + let suffix_start = start + BytePos(suffix_start); + let (kind, symbol) = self.cook_lexer_literal(start, suffix_start, kind); + let suffix = if suffix_start < self.pos { + let string = self.str_from(suffix_start); + if string == "_" { + self.sess + .span_diagnostic + .struct_span_warn( + self.mk_sp(suffix_start, self.pos), + "underscore literal suffix is not allowed", + ) + .warn( + "this was previously accepted by the compiler but is \ + being phased out; it will become a hard error in \ + a future release!", + ) + .note( + "see issue #42326 \ + \ + for more information", + ) + .emit(); + None + } else { + Some(Symbol::intern(string)) + } + } else { + None + }; + token::Literal(token::Lit { kind, symbol, suffix }) + } + rustc_lexer::TokenKind::Lifetime { starts_with_number } => { + // Include the leading `'` in the real identifier, for macro + // expansion purposes. See #12512 for the gory details of why + // this is necessary. + let lifetime_name = self.str_from(start); + if starts_with_number { + self.err_span_(start, self.pos, "lifetimes cannot start with a number"); + } + let ident = Symbol::intern(lifetime_name); + token::Lifetime(ident) + } + rustc_lexer::TokenKind::Semi => token::Semi, + rustc_lexer::TokenKind::Comma => token::Comma, + rustc_lexer::TokenKind::Dot => token::Dot, + rustc_lexer::TokenKind::OpenParen => token::OpenDelim(Delimiter::Parenthesis), + rustc_lexer::TokenKind::CloseParen => token::CloseDelim(Delimiter::Parenthesis), + rustc_lexer::TokenKind::OpenBrace => token::OpenDelim(Delimiter::Brace), + rustc_lexer::TokenKind::CloseBrace => token::CloseDelim(Delimiter::Brace), + rustc_lexer::TokenKind::OpenBracket => token::OpenDelim(Delimiter::Bracket), + rustc_lexer::TokenKind::CloseBracket => token::CloseDelim(Delimiter::Bracket), + rustc_lexer::TokenKind::At => token::At, + rustc_lexer::TokenKind::Pound => token::Pound, + rustc_lexer::TokenKind::Tilde => token::Tilde, + rustc_lexer::TokenKind::Question => token::Question, + rustc_lexer::TokenKind::Colon => token::Colon, + rustc_lexer::TokenKind::Dollar => token::Dollar, + rustc_lexer::TokenKind::Eq => token::Eq, + rustc_lexer::TokenKind::Bang => token::Not, + rustc_lexer::TokenKind::Lt => token::Lt, + rustc_lexer::TokenKind::Gt => token::Gt, + rustc_lexer::TokenKind::Minus => token::BinOp(token::Minus), + rustc_lexer::TokenKind::And => token::BinOp(token::And), + rustc_lexer::TokenKind::Or => token::BinOp(token::Or), + rustc_lexer::TokenKind::Plus => token::BinOp(token::Plus), + rustc_lexer::TokenKind::Star => token::BinOp(token::Star), + rustc_lexer::TokenKind::Slash => token::BinOp(token::Slash), + rustc_lexer::TokenKind::Caret => token::BinOp(token::Caret), + rustc_lexer::TokenKind::Percent => token::BinOp(token::Percent), + + rustc_lexer::TokenKind::Unknown | rustc_lexer::TokenKind::InvalidIdent => { + let c = self.str_from(start).chars().next().unwrap(); + let mut err = + self.struct_err_span_char(start, self.pos, "unknown start of token", c); + // FIXME: the lexer could be used to turn the ASCII version of unicode + // homoglyphs, instead of keeping a table in `check_for_substitution`into the + // token. Ideally, this should be inside `rustc_lexer`. However, we should + // first remove compound tokens like `<<` from `rustc_lexer`, and then add + // fancier error recovery to it, as there will be less overall work to do this + // way. + let token = unicode_chars::check_for_substitution(self, start, c, &mut err); + if c == '\x00' { + err.help("source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used"); + } + err.emit(); + if let Some(token) = token { + token + } else { + preceded_by_whitespace = true; + continue; + } + } + rustc_lexer::TokenKind::Eof => token::Eof, + }; + let span = self.mk_sp(start, self.pos); + return (Token::new(kind, span), preceded_by_whitespace); } } @@ -158,172 +327,6 @@ impl<'a> StringReader<'a> { } } - /// Turns simple `rustc_lexer::TokenKind` enum into a rich - /// `rustc_ast::TokenKind`. This turns strings into interned - /// symbols and runs additional validation. - fn cook_lexer_token(&self, token: rustc_lexer::TokenKind, start: BytePos) -> Option { - Some(match token { - rustc_lexer::TokenKind::LineComment { doc_style } => { - // Skip non-doc comments - let Some(doc_style) = doc_style else { - self.lint_unicode_text_flow(start); - return None; - }; - - // Opening delimiter of the length 3 is not included into the symbol. - let content_start = start + BytePos(3); - let content = self.str_from(content_start); - self.cook_doc_comment(content_start, content, CommentKind::Line, doc_style) - } - rustc_lexer::TokenKind::BlockComment { doc_style, terminated } => { - if !terminated { - self.report_unterminated_block_comment(start, doc_style); - } - - // Skip non-doc comments - let Some(doc_style) = doc_style else { - self.lint_unicode_text_flow(start); - return None; - }; - - // Opening delimiter of the length 3 and closing delimiter of the length 2 - // are not included into the symbol. - let content_start = start + BytePos(3); - let content_end = self.pos - BytePos(if terminated { 2 } else { 0 }); - let content = self.str_from_to(content_start, content_end); - self.cook_doc_comment(content_start, content, CommentKind::Block, doc_style) - } - rustc_lexer::TokenKind::Whitespace => return None, - rustc_lexer::TokenKind::Ident => { - let sym = nfc_normalize(self.str_from(start)); - let span = self.mk_sp(start, self.pos); - self.sess.symbol_gallery.insert(sym, span); - token::Ident(sym, false) - } - rustc_lexer::TokenKind::RawIdent => { - let sym = nfc_normalize(self.str_from(start + BytePos(2))); - let span = self.mk_sp(start, self.pos); - self.sess.symbol_gallery.insert(sym, span); - if !sym.can_be_raw() { - self.err_span(span, &format!("`{}` cannot be a raw identifier", sym)); - } - self.sess.raw_identifier_spans.borrow_mut().push(span); - token::Ident(sym, true) - } - rustc_lexer::TokenKind::UnknownPrefix => { - self.report_unknown_prefix(start); - let sym = nfc_normalize(self.str_from(start)); - let span = self.mk_sp(start, self.pos); - self.sess.symbol_gallery.insert(sym, span); - token::Ident(sym, false) - } - rustc_lexer::TokenKind::InvalidIdent - // Do not recover an identifier with emoji if the codepoint is a confusable - // with a recoverable substitution token, like `➖`. - if !UNICODE_ARRAY - .iter() - .any(|&(c, _, _)| { - let sym = self.str_from(start); - sym.chars().count() == 1 && c == sym.chars().next().unwrap() - }) - => - { - let sym = nfc_normalize(self.str_from(start)); - let span = self.mk_sp(start, self.pos); - self.sess.bad_unicode_identifiers.borrow_mut().entry(sym).or_default().push(span); - token::Ident(sym, false) - } - rustc_lexer::TokenKind::Literal { kind, suffix_start } => { - let suffix_start = start + BytePos(suffix_start); - let (kind, symbol) = self.cook_lexer_literal(start, suffix_start, kind); - let suffix = if suffix_start < self.pos { - let string = self.str_from(suffix_start); - if string == "_" { - self.sess - .span_diagnostic - .struct_span_warn( - self.mk_sp(suffix_start, self.pos), - "underscore literal suffix is not allowed", - ) - .warn( - "this was previously accepted by the compiler but is \ - being phased out; it will become a hard error in \ - a future release!", - ) - .note( - "see issue #42326 \ - \ - for more information", - ) - .emit(); - None - } else { - Some(Symbol::intern(string)) - } - } else { - None - }; - token::Literal(token::Lit { kind, symbol, suffix }) - } - rustc_lexer::TokenKind::Lifetime { starts_with_number } => { - // Include the leading `'` in the real identifier, for macro - // expansion purposes. See #12512 for the gory details of why - // this is necessary. - let lifetime_name = self.str_from(start); - if starts_with_number { - self.err_span_(start, self.pos, "lifetimes cannot start with a number"); - } - let ident = Symbol::intern(lifetime_name); - token::Lifetime(ident) - } - rustc_lexer::TokenKind::Semi => token::Semi, - rustc_lexer::TokenKind::Comma => token::Comma, - rustc_lexer::TokenKind::Dot => token::Dot, - rustc_lexer::TokenKind::OpenParen => token::OpenDelim(Delimiter::Parenthesis), - rustc_lexer::TokenKind::CloseParen => token::CloseDelim(Delimiter::Parenthesis), - rustc_lexer::TokenKind::OpenBrace => token::OpenDelim(Delimiter::Brace), - rustc_lexer::TokenKind::CloseBrace => token::CloseDelim(Delimiter::Brace), - rustc_lexer::TokenKind::OpenBracket => token::OpenDelim(Delimiter::Bracket), - rustc_lexer::TokenKind::CloseBracket => token::CloseDelim(Delimiter::Bracket), - rustc_lexer::TokenKind::At => token::At, - rustc_lexer::TokenKind::Pound => token::Pound, - rustc_lexer::TokenKind::Tilde => token::Tilde, - rustc_lexer::TokenKind::Question => token::Question, - rustc_lexer::TokenKind::Colon => token::Colon, - rustc_lexer::TokenKind::Dollar => token::Dollar, - rustc_lexer::TokenKind::Eq => token::Eq, - rustc_lexer::TokenKind::Bang => token::Not, - rustc_lexer::TokenKind::Lt => token::Lt, - rustc_lexer::TokenKind::Gt => token::Gt, - rustc_lexer::TokenKind::Minus => token::BinOp(token::Minus), - rustc_lexer::TokenKind::And => token::BinOp(token::And), - rustc_lexer::TokenKind::Or => token::BinOp(token::Or), - rustc_lexer::TokenKind::Plus => token::BinOp(token::Plus), - rustc_lexer::TokenKind::Star => token::BinOp(token::Star), - rustc_lexer::TokenKind::Slash => token::BinOp(token::Slash), - rustc_lexer::TokenKind::Caret => token::BinOp(token::Caret), - rustc_lexer::TokenKind::Percent => token::BinOp(token::Percent), - - rustc_lexer::TokenKind::Unknown | rustc_lexer::TokenKind::InvalidIdent => { - let c = self.str_from(start).chars().next().unwrap(); - let mut err = - self.struct_err_span_char(start, self.pos, "unknown start of token", c); - // FIXME: the lexer could be used to turn the ASCII version of unicode homoglyphs, - // instead of keeping a table in `check_for_substitution`into the token. Ideally, - // this should be inside `rustc_lexer`. However, we should first remove compound - // tokens like `<<` from `rustc_lexer`, and then add fancier error recovery to it, - // as there will be less overall work to do this way. - let token = unicode_chars::check_for_substitution(self, start, c, &mut err); - if c == '\x00' { - err.help("source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used"); - } - err.emit(); - token? - } - rustc_lexer::TokenKind::Eof => token::Eof, - }) - } - fn cook_doc_comment( &self, content_start: BytePos, From e4b08ab241f19342400f7a1722de5e0d43cbe386 Mon Sep 17 00:00:00 2001 From: woppopo Date: Mon, 26 Sep 2022 05:00:31 +0000 Subject: [PATCH 254/586] Allow `~const` bounds on non-const functions --- .../rustc_ast_passes/src/ast_validation.rs | 7 ++-- .../tilde-const-and-const-params.rs | 34 +++++++++++++++++++ .../tilde-const-invalid-places.rs | 6 ---- .../tilde-const-invalid-places.stderr | 28 ++++----------- 4 files changed, 43 insertions(+), 32 deletions(-) create mode 100644 src/test/ui/rfc-2632-const-trait-impl/tilde-const-and-const-params.rs diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index b1d10e07ad0fb..ecf74c7602027 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -1415,7 +1415,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { if !self.is_tilde_const_allowed { self.err_handler() .struct_span_err(bound.span(), "`~const` is not allowed here") - .note("only allowed on bounds on traits' associated types and functions, const fns, const impls and its associated functions") + .note("only allowed on bounds on functions, traits' associated types and functions, const impls and its associated functions") .emit(); } } @@ -1523,9 +1523,8 @@ impl<'a> Visitor<'a> for AstValidator<'a> { }); } - let tilde_const_allowed = - matches!(fk.header(), Some(FnHeader { constness: Const::Yes(_), .. })) - || matches!(fk.ctxt(), Some(FnCtxt::Assoc(_))); + let tilde_const_allowed = matches!(fk.header(), Some(FnHeader { .. })) + || matches!(fk.ctxt(), Some(FnCtxt::Assoc(_))); self.with_tilde_const(tilde_const_allowed, |this| visit::walk_fn(this, fk)); } diff --git a/src/test/ui/rfc-2632-const-trait-impl/tilde-const-and-const-params.rs b/src/test/ui/rfc-2632-const-trait-impl/tilde-const-and-const-params.rs new file mode 100644 index 0000000000000..b29b633cff644 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/tilde-const-and-const-params.rs @@ -0,0 +1,34 @@ +// check-pass +#![feature(const_trait_impl)] +#![feature(generic_arg_infer)] +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +struct Foo; + +impl Foo { + fn add(self) -> Foo<{ A::add(N) }> { + Foo + } +} + +#[const_trait] +trait Add42 { + fn add(a: usize) -> usize; +} + +impl const Add42 for () { + fn add(a: usize) -> usize { + a + 42 + } +} + +fn bar(_: Foo) -> Foo<{ A::add(N) }> { + Foo +} + +fn main() { + let foo = Foo::<0>; + let foo = bar::<(), _>(foo); + let _foo = bar::<(), _>(foo); +} diff --git a/src/test/ui/rfc-2632-const-trait-impl/tilde-const-invalid-places.rs b/src/test/ui/rfc-2632-const-trait-impl/tilde-const-invalid-places.rs index b4302f3e75fd4..350be4d8250d6 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/tilde-const-invalid-places.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/tilde-const-invalid-places.rs @@ -17,12 +17,6 @@ fn rpit_assoc_bound() -> impl IntoIterator { Some(S) } fn apit_assoc_bound(_: impl IntoIterator) {} //~^ ERROR `~const` is not allowed -fn generic() {} -//~^ ERROR `~const` is not allowed - -fn where_clause

() where P: ~const T {} -//~^ ERROR `~const` is not allowed - struct TildeQuestion(std::marker::PhantomData); //~^ ERROR `~const` and `?` are mutually exclusive diff --git a/src/test/ui/rfc-2632-const-trait-impl/tilde-const-invalid-places.stderr b/src/test/ui/rfc-2632-const-trait-impl/tilde-const-invalid-places.stderr index 033ec21ba8408..8d781d063d1c0 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/tilde-const-invalid-places.stderr +++ b/src/test/ui/rfc-2632-const-trait-impl/tilde-const-invalid-places.stderr @@ -4,7 +4,7 @@ error: `~const` is not allowed here LL | fn rpit() -> impl ~const T { S } | ^^^^^^^^ | - = note: only allowed on bounds on traits' associated types and functions, const fns, const impls and its associated functions + = note: only allowed on bounds on functions, traits' associated types and functions, const impls and its associated functions error: `~const` is not allowed here --> $DIR/tilde-const-invalid-places.rs:11:17 @@ -12,7 +12,7 @@ error: `~const` is not allowed here LL | fn apit(_: impl ~const T) {} | ^^^^^^^^ | - = note: only allowed on bounds on traits' associated types and functions, const fns, const impls and its associated functions + = note: only allowed on bounds on functions, traits' associated types and functions, const impls and its associated functions error: `~const` is not allowed here --> $DIR/tilde-const-invalid-places.rs:14:50 @@ -20,7 +20,7 @@ error: `~const` is not allowed here LL | fn rpit_assoc_bound() -> impl IntoIterator { Some(S) } | ^^^^^^^^ | - = note: only allowed on bounds on traits' associated types and functions, const fns, const impls and its associated functions + = note: only allowed on bounds on functions, traits' associated types and functions, const impls and its associated functions error: `~const` is not allowed here --> $DIR/tilde-const-invalid-places.rs:17:48 @@ -28,29 +28,13 @@ error: `~const` is not allowed here LL | fn apit_assoc_bound(_: impl IntoIterator) {} | ^^^^^^^^ | - = note: only allowed on bounds on traits' associated types and functions, const fns, const impls and its associated functions - -error: `~const` is not allowed here - --> $DIR/tilde-const-invalid-places.rs:20:15 - | -LL | fn generic() {} - | ^^^^^^^^ - | - = note: only allowed on bounds on traits' associated types and functions, const fns, const impls and its associated functions - -error: `~const` is not allowed here - --> $DIR/tilde-const-invalid-places.rs:23:31 - | -LL | fn where_clause

() where P: ~const T {} - | ^^^^^^^^ - | - = note: only allowed on bounds on traits' associated types and functions, const fns, const impls and its associated functions + = note: only allowed on bounds on functions, traits' associated types and functions, const impls and its associated functions error: `~const` and `?` are mutually exclusive - --> $DIR/tilde-const-invalid-places.rs:26:25 + --> $DIR/tilde-const-invalid-places.rs:20:25 | LL | struct TildeQuestion(std::marker::PhantomData); | ^^^^^^^^^^^^^ -error: aborting due to 7 previous errors +error: aborting due to 5 previous errors From ab05c48dbc815c9084d3ae9e7241e6fb87a060dd Mon Sep 17 00:00:00 2001 From: reez12g Date: Sun, 18 Sep 2022 17:32:12 +0900 Subject: [PATCH 255/586] Make fmt downloaded on every invocation of bootstrap --- src/bootstrap/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index cd421c249d8da..00fe899a2d4b4 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -668,6 +668,7 @@ impl Build { job::setup(self); } + let _ = &builder::Builder::new(&self).initial_rustfmt(); self.maybe_update_submodules(); if let Subcommand::Format { check, paths } = &self.config.cmd { From c19daa472b69fdcbbb15402e8d1e8e05bae39f38 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 25 Sep 2022 22:56:01 +0200 Subject: [PATCH 256/586] make invalid_value lint a bit smarter around enums --- compiler/rustc_lint/src/builtin.rs | 160 +++++++++----- .../validate_uninhabited_zsts.32bit.stderr | 8 +- .../validate_uninhabited_zsts.64bit.stderr | 8 +- ...initialized-zeroed.rs => invalid_value.rs} | 30 ++- ...zed-zeroed.stderr => invalid_value.stderr} | 207 ++++++++++++------ src/test/ui/statics/uninhabited-static.stderr | 12 +- 6 files changed, 298 insertions(+), 127 deletions(-) rename src/test/ui/lint/{uninitialized-zeroed.rs => invalid_value.rs} (88%) rename src/test/ui/lint/{uninitialized-zeroed.stderr => invalid_value.stderr} (78%) diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 5fba1d3d3c7ac..529e709c5db30 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -46,8 +46,7 @@ use rustc_middle::lint::in_external_macro; use rustc_middle::ty::layout::{LayoutError, LayoutOf}; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::subst::GenericArgKind; -use rustc_middle::ty::Instance; -use rustc_middle::ty::{self, Ty, TyCtxt}; +use rustc_middle::ty::{self, Instance, Ty, TyCtxt, VariantDef}; use rustc_session::lint::{BuiltinLintDiagnostics, FutureIncompatibilityReason}; use rustc_span::edition::Edition; use rustc_span::source_map::Spanned; @@ -2425,12 +2424,56 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue { None } - /// Test if this enum has several actually "existing" variants. - /// Zero-sized uninhabited variants do not always have a tag assigned and thus do not "exist". - fn is_multi_variant<'tcx>(adt: ty::AdtDef<'tcx>) -> bool { - // As an approximation, we only count dataless variants. Those are definitely inhabited. - let existing_variants = adt.variants().iter().filter(|v| v.fields.is_empty()).count(); - existing_variants > 1 + /// Determines whether the given type is inhabited. `None` means that we don't know. + fn ty_inhabited(ty: Ty<'_>) -> Option { + use rustc_type_ir::sty::TyKind::*; + match ty.kind() { + Never => Some(false), + Int(_) | Uint(_) | Float(_) | Bool | Char | RawPtr(_) => Some(true), + // Fallback for more complicated types. (Note that `&!` might be considered + // uninhabited so references are "complicated", too.) + _ => None, + } + } + /// Determines whether a product type formed from a list of types is inhabited. + fn tys_inhabited<'tcx>(tys: impl Iterator>) -> Option { + let mut definitely_inhabited = true; // with no fields, we are definitely inhabited. + for ty in tys { + match ty_inhabited(ty) { + // If any type is uninhabited, the product is uninhabited. + Some(false) => return Some(false), + // Otherwise go searching for a `None`. + None => { + // We don't know. + definitely_inhabited = false; + } + Some(true) => {} + } + } + if definitely_inhabited { Some(true) } else { None } + } + + fn variant_find_init_error<'tcx>( + cx: &LateContext<'tcx>, + variant: &VariantDef, + substs: ty::SubstsRef<'tcx>, + descr: &str, + init: InitKind, + ) -> Option { + variant.fields.iter().find_map(|field| { + ty_find_init_error(cx, field.ty(cx.tcx, substs), init).map(|(mut msg, span)| { + if span.is_none() { + // Point to this field, should be helpful for figuring + // out where the source of the error is. + let span = cx.tcx.def_span(field.did); + write!(&mut msg, " (in this {descr})").unwrap(); + (msg, Some(span)) + } else { + // Just forward. + (msg, span) + } + }) + }) } /// Return `Some` only if we are sure this type does *not* @@ -2468,7 +2511,7 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue { RawPtr(_) if init == InitKind::Uninit => { Some(("raw pointers must not be uninitialized".to_string(), None)) } - // Recurse and checks for some compound types. + // Recurse and checks for some compound types. (but not unions) Adt(adt_def, substs) if !adt_def.is_union() => { // First check if this ADT has a layout attribute (like `NonNull` and friends). use std::ops::Bound; @@ -2476,6 +2519,7 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue { // We exploit here that `layout_scalar_valid_range` will never // return `Bound::Excluded`. (And we have tests checking that we // handle the attribute correctly.) + // We don't add a span since users cannot declare such types anyway. (Bound::Included(lo), _) if lo > 0 => { return Some((format!("`{}` must be non-null", ty), None)); } @@ -2492,50 +2536,64 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue { } _ => {} } - // Now, recurse. - match adt_def.variants().len() { - 0 => Some(("enums with no variants have no valid value".to_string(), None)), - 1 => { - // Struct, or enum with exactly one variant. - // Proceed recursively, check all fields. - let variant = &adt_def.variant(VariantIdx::from_u32(0)); - variant.fields.iter().find_map(|field| { - ty_find_init_error(cx, field.ty(cx.tcx, substs), init).map( - |(mut msg, span)| { - if span.is_none() { - // Point to this field, should be helpful for figuring - // out where the source of the error is. - let span = cx.tcx.def_span(field.did); - write!( - &mut msg, - " (in this {} field)", - adt_def.descr() - ) - .unwrap(); - (msg, Some(span)) - } else { - // Just forward. - (msg, span) - } - }, - ) - }) - } - // Multi-variant enum. - _ => { - if init == InitKind::Uninit && is_multi_variant(*adt_def) { - let span = cx.tcx.def_span(adt_def.did()); - Some(( - "enums have to be initialized to a variant".to_string(), - Some(span), - )) - } else { - // In principle, for zero-initialization we could figure out which variant corresponds - // to tag 0, and check that... but for now we just accept all zero-initializations. - None - } + // Handle structs. + if adt_def.is_struct() { + return variant_find_init_error( + cx, + adt_def.non_enum_variant(), + substs, + "struct field", + init, + ); + } + // And now, enums. + let span = cx.tcx.def_span(adt_def.did()); + let mut potential_variants = adt_def.variants().iter().filter_map(|variant| { + let inhabited = tys_inhabited( + variant.fields.iter().map(|field| field.ty(cx.tcx, substs)), + ); + let definitely_inhabited = match inhabited { + // Entirely skip uninhbaited variants. + Some(false) => return None, + // Forward the others, but remember which ones are definitely inhabited. + Some(true) => true, + None => false, + }; + Some((variant, definitely_inhabited)) + }); + let Some(first_variant) = potential_variants.next() else { + return Some(("enums with no inhabited variants have no valid value".to_string(), Some(span))); + }; + // So we have at least one potentially inhabited variant. Might we have two? + let Some(second_variant) = potential_variants.next() else { + // There is only one potentially inhabited variant. So we can recursively check that variant! + return variant_find_init_error( + cx, + &first_variant.0, + substs, + "field of the only potentially inhabited enum variant", + init, + ); + }; + // So we have at least two potentially inhabited variants. + // If we can prove that we have at least two *definitely* inhabited variants, + // then we have a tag and hence leaving this uninit is definitely disallowed. + // (Leaving it zeroed could be okay, depending on which variant is encoded as zero tag.) + if init == InitKind::Uninit { + let definitely_inhabited = (first_variant.1 as usize) + + (second_variant.1 as usize) + + potential_variants + .filter(|(_variant, definitely_inhabited)| *definitely_inhabited) + .count(); + if definitely_inhabited > 1 { + return Some(( + "enums with multiple inhabited variants have to be initialized to a variant".to_string(), + Some(span), + )); } } + // We couldn't find anything wrong here. + None } Tuple(..) => { // Proceed recursively, check all fields. diff --git a/src/test/ui/consts/const-eval/validate_uninhabited_zsts.32bit.stderr b/src/test/ui/consts/const-eval/validate_uninhabited_zsts.32bit.stderr index bdaeb4a0fbee0..b568518b4499d 100644 --- a/src/test/ui/consts/const-eval/validate_uninhabited_zsts.32bit.stderr +++ b/src/test/ui/consts/const-eval/validate_uninhabited_zsts.32bit.stderr @@ -40,11 +40,11 @@ LL | const BAR: [empty::Empty; 3] = [unsafe { std::mem::transmute(()) }; 3]; | this code causes undefined behavior when executed | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done | -note: enums with no variants have no valid value (in this struct field) - --> $DIR/validate_uninhabited_zsts.rs:16:22 +note: enums with no inhabited variants have no valid value + --> $DIR/validate_uninhabited_zsts.rs:13:5 | -LL | pub struct Empty(Void); - | ^^^^ +LL | enum Void {} + | ^^^^^^^^^ error: aborting due to 2 previous errors; 2 warnings emitted diff --git a/src/test/ui/consts/const-eval/validate_uninhabited_zsts.64bit.stderr b/src/test/ui/consts/const-eval/validate_uninhabited_zsts.64bit.stderr index bdaeb4a0fbee0..b568518b4499d 100644 --- a/src/test/ui/consts/const-eval/validate_uninhabited_zsts.64bit.stderr +++ b/src/test/ui/consts/const-eval/validate_uninhabited_zsts.64bit.stderr @@ -40,11 +40,11 @@ LL | const BAR: [empty::Empty; 3] = [unsafe { std::mem::transmute(()) }; 3]; | this code causes undefined behavior when executed | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done | -note: enums with no variants have no valid value (in this struct field) - --> $DIR/validate_uninhabited_zsts.rs:16:22 +note: enums with no inhabited variants have no valid value + --> $DIR/validate_uninhabited_zsts.rs:13:5 | -LL | pub struct Empty(Void); - | ^^^^ +LL | enum Void {} + | ^^^^^^^^^ error: aborting due to 2 previous errors; 2 warnings emitted diff --git a/src/test/ui/lint/uninitialized-zeroed.rs b/src/test/ui/lint/invalid_value.rs similarity index 88% rename from src/test/ui/lint/uninitialized-zeroed.rs rename to src/test/ui/lint/invalid_value.rs index dae258407ebb0..c37a472ffe10f 100644 --- a/src/test/ui/lint/uninitialized-zeroed.rs +++ b/src/test/ui/lint/invalid_value.rs @@ -34,6 +34,16 @@ enum OneFruit { Banana, } +enum OneFruitNonZero { + Apple(!), + Banana(NonZeroU32), +} + +enum TwoUninhabited { + A(!), + B(!), +} + #[allow(unused)] fn generic() { unsafe { @@ -84,6 +94,12 @@ fn main() { let _val: [fn(); 2] = mem::zeroed(); //~ ERROR: does not permit zero-initialization let _val: [fn(); 2] = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized + let _val: TwoUninhabited = mem::zeroed(); //~ ERROR: does not permit zero-initialization + let _val: TwoUninhabited = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized + + let _val: OneFruitNonZero = mem::zeroed(); //~ ERROR: does not permit zero-initialization + let _val: OneFruitNonZero = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized + // Things that can be zero, but not uninit. let _val: bool = mem::zeroed(); let _val: bool = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized @@ -112,6 +128,16 @@ fn main() { let _val: *const [()] = mem::zeroed(); let _val: *const [()] = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized + // Things where 0 is okay due to rustc implementation details, + // but that are not guaranteed to keep working. + let _val: Result = mem::zeroed(); + let _val: Result = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized + + // Some things that happen to work due to rustc implementation details, + // but are not guaranteed to keep working. + let _val: OneFruit = mem::zeroed(); + let _val: OneFruit = mem::uninitialized(); + // Transmute-from-0 let _val: &'static i32 = mem::transmute(0usize); //~ ERROR: does not permit zero-initialization let _val: &'static [i32] = mem::transmute((0usize, 0usize)); //~ ERROR: does not permit zero-initialization @@ -129,9 +155,5 @@ fn main() { let _val: bool = MaybeUninit::zeroed().assume_init(); let _val: [bool; 0] = MaybeUninit::uninit().assume_init(); let _val: [!; 0] = MaybeUninit::zeroed().assume_init(); - - // Some things that happen to work due to rustc implementation details, - // but are not guaranteed to keep working. - let _val: OneFruit = mem::uninitialized(); } } diff --git a/src/test/ui/lint/uninitialized-zeroed.stderr b/src/test/ui/lint/invalid_value.stderr similarity index 78% rename from src/test/ui/lint/uninitialized-zeroed.stderr rename to src/test/ui/lint/invalid_value.stderr index b46042e7be43f..750b3c76c44c2 100644 --- a/src/test/ui/lint/uninitialized-zeroed.stderr +++ b/src/test/ui/lint/invalid_value.stderr @@ -1,5 +1,5 @@ error: the type `&T` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:40:32 + --> $DIR/invalid_value.rs:50:32 | LL | let _val: &'static T = mem::zeroed(); | ^^^^^^^^^^^^^ @@ -8,14 +8,14 @@ LL | let _val: &'static T = mem::zeroed(); | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done | note: the lint level is defined here - --> $DIR/uninitialized-zeroed.rs:6:9 + --> $DIR/invalid_value.rs:6:9 | LL | #![deny(invalid_value)] | ^^^^^^^^^^^^^ = note: references must be non-null error: the type `&T` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:41:32 + --> $DIR/invalid_value.rs:51:32 | LL | let _val: &'static T = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -26,7 +26,7 @@ LL | let _val: &'static T = mem::uninitialized(); = note: references must be non-null error: the type `Wrap<&T>` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:43:38 + --> $DIR/invalid_value.rs:53:38 | LL | let _val: Wrap<&'static T> = mem::zeroed(); | ^^^^^^^^^^^^^ @@ -35,13 +35,13 @@ LL | let _val: Wrap<&'static T> = mem::zeroed(); | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done | note: references must be non-null (in this struct field) - --> $DIR/uninitialized-zeroed.rs:17:18 + --> $DIR/invalid_value.rs:17:18 | LL | struct Wrap { wrapped: T } | ^^^^^^^^^^ error: the type `Wrap<&T>` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:44:38 + --> $DIR/invalid_value.rs:54:38 | LL | let _val: Wrap<&'static T> = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -50,13 +50,13 @@ LL | let _val: Wrap<&'static T> = mem::uninitialized(); | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done | note: references must be non-null (in this struct field) - --> $DIR/uninitialized-zeroed.rs:17:18 + --> $DIR/invalid_value.rs:17:18 | LL | struct Wrap { wrapped: T } | ^^^^^^^^^^ error: the type `!` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:51:23 + --> $DIR/invalid_value.rs:61:23 | LL | let _val: ! = mem::zeroed(); | ^^^^^^^^^^^^^ @@ -67,7 +67,7 @@ LL | let _val: ! = mem::zeroed(); = note: the `!` type has no valid value error: the type `!` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:52:23 + --> $DIR/invalid_value.rs:62:23 | LL | let _val: ! = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -78,7 +78,7 @@ LL | let _val: ! = mem::uninitialized(); = note: the `!` type has no valid value error: the type `(i32, !)` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:54:30 + --> $DIR/invalid_value.rs:64:30 | LL | let _val: (i32, !) = mem::zeroed(); | ^^^^^^^^^^^^^ @@ -89,7 +89,7 @@ LL | let _val: (i32, !) = mem::zeroed(); = note: the `!` type has no valid value error: the type `(i32, !)` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:55:30 + --> $DIR/invalid_value.rs:65:30 | LL | let _val: (i32, !) = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -100,7 +100,7 @@ LL | let _val: (i32, !) = mem::uninitialized(); = note: integers must not be uninitialized error: the type `Void` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:57:26 + --> $DIR/invalid_value.rs:67:26 | LL | let _val: Void = mem::zeroed(); | ^^^^^^^^^^^^^ @@ -108,10 +108,14 @@ LL | let _val: Void = mem::zeroed(); | this code causes undefined behavior when executed | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done | - = note: enums with no variants have no valid value +note: enums with no inhabited variants have no valid value + --> $DIR/invalid_value.rs:12:1 + | +LL | enum Void {} + | ^^^^^^^^^ error: the type `Void` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:58:26 + --> $DIR/invalid_value.rs:68:26 | LL | let _val: Void = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -119,10 +123,14 @@ LL | let _val: Void = mem::uninitialized(); | this code causes undefined behavior when executed | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done | - = note: enums with no variants have no valid value +note: enums with no inhabited variants have no valid value + --> $DIR/invalid_value.rs:12:1 + | +LL | enum Void {} + | ^^^^^^^^^ error: the type `&i32` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:60:34 + --> $DIR/invalid_value.rs:70:34 | LL | let _val: &'static i32 = mem::zeroed(); | ^^^^^^^^^^^^^ @@ -133,7 +141,7 @@ LL | let _val: &'static i32 = mem::zeroed(); = note: references must be non-null error: the type `&i32` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:61:34 + --> $DIR/invalid_value.rs:71:34 | LL | let _val: &'static i32 = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -144,7 +152,7 @@ LL | let _val: &'static i32 = mem::uninitialized(); = note: references must be non-null error: the type `Ref` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:63:25 + --> $DIR/invalid_value.rs:73:25 | LL | let _val: Ref = mem::zeroed(); | ^^^^^^^^^^^^^ @@ -153,13 +161,13 @@ LL | let _val: Ref = mem::zeroed(); | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done | note: references must be non-null (in this struct field) - --> $DIR/uninitialized-zeroed.rs:14:12 + --> $DIR/invalid_value.rs:14:12 | LL | struct Ref(&'static i32); | ^^^^^^^^^^^^ error: the type `Ref` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:64:25 + --> $DIR/invalid_value.rs:74:25 | LL | let _val: Ref = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -168,13 +176,13 @@ LL | let _val: Ref = mem::uninitialized(); | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done | note: references must be non-null (in this struct field) - --> $DIR/uninitialized-zeroed.rs:14:12 + --> $DIR/invalid_value.rs:14:12 | LL | struct Ref(&'static i32); | ^^^^^^^^^^^^ error: the type `fn()` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:66:26 + --> $DIR/invalid_value.rs:76:26 | LL | let _val: fn() = mem::zeroed(); | ^^^^^^^^^^^^^ @@ -185,7 +193,7 @@ LL | let _val: fn() = mem::zeroed(); = note: function pointers must be non-null error: the type `fn()` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:67:26 + --> $DIR/invalid_value.rs:77:26 | LL | let _val: fn() = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -196,7 +204,7 @@ LL | let _val: fn() = mem::uninitialized(); = note: function pointers must be non-null error: the type `Wrap` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:69:32 + --> $DIR/invalid_value.rs:79:32 | LL | let _val: Wrap = mem::zeroed(); | ^^^^^^^^^^^^^ @@ -205,13 +213,13 @@ LL | let _val: Wrap = mem::zeroed(); | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done | note: function pointers must be non-null (in this struct field) - --> $DIR/uninitialized-zeroed.rs:17:18 + --> $DIR/invalid_value.rs:17:18 | LL | struct Wrap { wrapped: T } | ^^^^^^^^^^ error: the type `Wrap` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:70:32 + --> $DIR/invalid_value.rs:80:32 | LL | let _val: Wrap = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -220,13 +228,13 @@ LL | let _val: Wrap = mem::uninitialized(); | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done | note: function pointers must be non-null (in this struct field) - --> $DIR/uninitialized-zeroed.rs:17:18 + --> $DIR/invalid_value.rs:17:18 | LL | struct Wrap { wrapped: T } | ^^^^^^^^^^ error: the type `WrapEnum` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:72:36 + --> $DIR/invalid_value.rs:82:36 | LL | let _val: WrapEnum = mem::zeroed(); | ^^^^^^^^^^^^^ @@ -234,14 +242,14 @@ LL | let _val: WrapEnum = mem::zeroed(); | this code causes undefined behavior when executed | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done | -note: function pointers must be non-null (in this enum field) - --> $DIR/uninitialized-zeroed.rs:18:28 +note: function pointers must be non-null (in this field of the only potentially inhabited enum variant) + --> $DIR/invalid_value.rs:18:28 | LL | enum WrapEnum { Wrapped(T) } | ^ error: the type `WrapEnum` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:73:36 + --> $DIR/invalid_value.rs:83:36 | LL | let _val: WrapEnum = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -249,14 +257,14 @@ LL | let _val: WrapEnum = mem::uninitialized(); | this code causes undefined behavior when executed | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done | -note: function pointers must be non-null (in this enum field) - --> $DIR/uninitialized-zeroed.rs:18:28 +note: function pointers must be non-null (in this field of the only potentially inhabited enum variant) + --> $DIR/invalid_value.rs:18:28 | LL | enum WrapEnum { Wrapped(T) } | ^ error: the type `Wrap<(RefPair, i32)>` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:75:42 + --> $DIR/invalid_value.rs:85:42 | LL | let _val: Wrap<(RefPair, i32)> = mem::zeroed(); | ^^^^^^^^^^^^^ @@ -265,13 +273,13 @@ LL | let _val: Wrap<(RefPair, i32)> = mem::zeroed(); | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done | note: references must be non-null (in this struct field) - --> $DIR/uninitialized-zeroed.rs:15:16 + --> $DIR/invalid_value.rs:15:16 | LL | struct RefPair((&'static i32, i32)); | ^^^^^^^^^^^^^^^^^^^ error: the type `Wrap<(RefPair, i32)>` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:76:42 + --> $DIR/invalid_value.rs:86:42 | LL | let _val: Wrap<(RefPair, i32)> = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -280,13 +288,13 @@ LL | let _val: Wrap<(RefPair, i32)> = mem::uninitialized(); | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done | note: references must be non-null (in this struct field) - --> $DIR/uninitialized-zeroed.rs:15:16 + --> $DIR/invalid_value.rs:15:16 | LL | struct RefPair((&'static i32, i32)); | ^^^^^^^^^^^^^^^^^^^ error: the type `NonNull` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:78:34 + --> $DIR/invalid_value.rs:88:34 | LL | let _val: NonNull = mem::zeroed(); | ^^^^^^^^^^^^^ @@ -297,7 +305,7 @@ LL | let _val: NonNull = mem::zeroed(); = note: `std::ptr::NonNull` must be non-null error: the type `NonNull` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:79:34 + --> $DIR/invalid_value.rs:89:34 | LL | let _val: NonNull = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -308,7 +316,7 @@ LL | let _val: NonNull = mem::uninitialized(); = note: `std::ptr::NonNull` must be non-null error: the type `*const dyn Send` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:81:37 + --> $DIR/invalid_value.rs:91:37 | LL | let _val: *const dyn Send = mem::zeroed(); | ^^^^^^^^^^^^^ @@ -319,7 +327,7 @@ LL | let _val: *const dyn Send = mem::zeroed(); = note: the vtable of a wide raw pointer must be non-null error: the type `*const dyn Send` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:82:37 + --> $DIR/invalid_value.rs:92:37 | LL | let _val: *const dyn Send = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -330,7 +338,7 @@ LL | let _val: *const dyn Send = mem::uninitialized(); = note: the vtable of a wide raw pointer must be non-null error: the type `[fn(); 2]` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:84:31 + --> $DIR/invalid_value.rs:94:31 | LL | let _val: [fn(); 2] = mem::zeroed(); | ^^^^^^^^^^^^^ @@ -341,7 +349,7 @@ LL | let _val: [fn(); 2] = mem::zeroed(); = note: function pointers must be non-null error: the type `[fn(); 2]` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:85:31 + --> $DIR/invalid_value.rs:95:31 | LL | let _val: [fn(); 2] = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -351,8 +359,68 @@ LL | let _val: [fn(); 2] = mem::uninitialized(); | = note: function pointers must be non-null +error: the type `TwoUninhabited` does not permit zero-initialization + --> $DIR/invalid_value.rs:97:36 + | +LL | let _val: TwoUninhabited = mem::zeroed(); + | ^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | +note: enums with no inhabited variants have no valid value + --> $DIR/invalid_value.rs:42:1 + | +LL | enum TwoUninhabited { + | ^^^^^^^^^^^^^^^^^^^ + +error: the type `TwoUninhabited` does not permit being left uninitialized + --> $DIR/invalid_value.rs:98:36 + | +LL | let _val: TwoUninhabited = mem::uninitialized(); + | ^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | +note: enums with no inhabited variants have no valid value + --> $DIR/invalid_value.rs:42:1 + | +LL | enum TwoUninhabited { + | ^^^^^^^^^^^^^^^^^^^ + +error: the type `OneFruitNonZero` does not permit zero-initialization + --> $DIR/invalid_value.rs:100:37 + | +LL | let _val: OneFruitNonZero = mem::zeroed(); + | ^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | +note: `std::num::NonZeroU32` must be non-null (in this field of the only potentially inhabited enum variant) + --> $DIR/invalid_value.rs:39:12 + | +LL | Banana(NonZeroU32), + | ^^^^^^^^^^ + +error: the type `OneFruitNonZero` does not permit being left uninitialized + --> $DIR/invalid_value.rs:101:37 + | +LL | let _val: OneFruitNonZero = mem::uninitialized(); + | ^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | +note: `std::num::NonZeroU32` must be non-null (in this field of the only potentially inhabited enum variant) + --> $DIR/invalid_value.rs:39:12 + | +LL | Banana(NonZeroU32), + | ^^^^^^^^^^ + error: the type `bool` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:89:26 + --> $DIR/invalid_value.rs:105:26 | LL | let _val: bool = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -363,7 +431,7 @@ LL | let _val: bool = mem::uninitialized(); = note: booleans must be either `true` or `false` error: the type `Wrap` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:92:32 + --> $DIR/invalid_value.rs:108:32 | LL | let _val: Wrap = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -372,13 +440,13 @@ LL | let _val: Wrap = mem::uninitialized(); | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done | note: characters must be a valid Unicode codepoint (in this struct field) - --> $DIR/uninitialized-zeroed.rs:17:18 + --> $DIR/invalid_value.rs:17:18 | LL | struct Wrap { wrapped: T } | ^^^^^^^^^^ error: the type `NonBig` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:95:28 + --> $DIR/invalid_value.rs:111:28 | LL | let _val: NonBig = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -389,7 +457,7 @@ LL | let _val: NonBig = mem::uninitialized(); = note: `NonBig` must be initialized inside its custom valid range error: the type `Fruit` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:98:27 + --> $DIR/invalid_value.rs:114:27 | LL | let _val: Fruit = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -397,14 +465,14 @@ LL | let _val: Fruit = mem::uninitialized(); | this code causes undefined behavior when executed | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done | -note: enums have to be initialized to a variant - --> $DIR/uninitialized-zeroed.rs:26:1 +note: enums with multiple inhabited variants have to be initialized to a variant + --> $DIR/invalid_value.rs:26:1 | LL | enum Fruit { | ^^^^^^^^^^ error: the type `[bool; 2]` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:101:31 + --> $DIR/invalid_value.rs:117:31 | LL | let _val: [bool; 2] = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -415,7 +483,7 @@ LL | let _val: [bool; 2] = mem::uninitialized(); = note: booleans must be either `true` or `false` error: the type `i32` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:104:25 + --> $DIR/invalid_value.rs:120:25 | LL | let _val: i32 = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -426,7 +494,7 @@ LL | let _val: i32 = mem::uninitialized(); = note: integers must not be uninitialized error: the type `f32` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:107:25 + --> $DIR/invalid_value.rs:123:25 | LL | let _val: f32 = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -437,7 +505,7 @@ LL | let _val: f32 = mem::uninitialized(); = note: floats must not be uninitialized error: the type `*const ()` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:110:31 + --> $DIR/invalid_value.rs:126:31 | LL | let _val: *const () = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -448,7 +516,7 @@ LL | let _val: *const () = mem::uninitialized(); = note: raw pointers must not be uninitialized error: the type `*const [()]` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:113:33 + --> $DIR/invalid_value.rs:129:33 | LL | let _val: *const [()] = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -458,8 +526,23 @@ LL | let _val: *const [()] = mem::uninitialized(); | = note: raw pointers must not be uninitialized +error: the type `Result` does not permit being left uninitialized + --> $DIR/invalid_value.rs:134:38 + | +LL | let _val: Result = mem::uninitialized(); + | ^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | +note: enums with multiple inhabited variants have to be initialized to a variant + --> $SRC_DIR/core/src/result.rs:LL:COL + | +LL | pub enum Result { + | ^^^^^^^^^^^^^^^^^^^^^ + error: the type `&i32` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:116:34 + --> $DIR/invalid_value.rs:142:34 | LL | let _val: &'static i32 = mem::transmute(0usize); | ^^^^^^^^^^^^^^^^^^^^^^ @@ -470,7 +553,7 @@ LL | let _val: &'static i32 = mem::transmute(0usize); = note: references must be non-null error: the type `&[i32]` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:117:36 + --> $DIR/invalid_value.rs:143:36 | LL | let _val: &'static [i32] = mem::transmute((0usize, 0usize)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -481,7 +564,7 @@ LL | let _val: &'static [i32] = mem::transmute((0usize, 0usize)); = note: references must be non-null error: the type `NonZeroU32` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:118:32 + --> $DIR/invalid_value.rs:144:32 | LL | let _val: NonZeroU32 = mem::transmute(0); | ^^^^^^^^^^^^^^^^^ @@ -492,7 +575,7 @@ LL | let _val: NonZeroU32 = mem::transmute(0); = note: `std::num::NonZeroU32` must be non-null error: the type `NonNull` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:121:34 + --> $DIR/invalid_value.rs:147:34 | LL | let _val: NonNull = MaybeUninit::zeroed().assume_init(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -503,7 +586,7 @@ LL | let _val: NonNull = MaybeUninit::zeroed().assume_init(); = note: `std::ptr::NonNull` must be non-null error: the type `NonNull` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:122:34 + --> $DIR/invalid_value.rs:148:34 | LL | let _val: NonNull = MaybeUninit::uninit().assume_init(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -514,7 +597,7 @@ LL | let _val: NonNull = MaybeUninit::uninit().assume_init(); = note: `std::ptr::NonNull` must be non-null error: the type `bool` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:123:26 + --> $DIR/invalid_value.rs:149:26 | LL | let _val: bool = MaybeUninit::uninit().assume_init(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -524,5 +607,5 @@ LL | let _val: bool = MaybeUninit::uninit().assume_init(); | = note: booleans must be either `true` or `false` -error: aborting due to 43 previous errors +error: aborting due to 48 previous errors diff --git a/src/test/ui/statics/uninhabited-static.stderr b/src/test/ui/statics/uninhabited-static.stderr index 88ee4cbdc2efc..6d37de8ff3f68 100644 --- a/src/test/ui/statics/uninhabited-static.stderr +++ b/src/test/ui/statics/uninhabited-static.stderr @@ -59,7 +59,11 @@ LL | static VOID2: Void = unsafe { std::mem::transmute(()) }; | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done | = note: `#[warn(invalid_value)]` on by default - = note: enums with no variants have no valid value +note: enums with no inhabited variants have no valid value + --> $DIR/uninhabited-static.rs:4:1 + | +LL | enum Void {} + | ^^^^^^^^^ error[E0080]: could not evaluate static initializer --> $DIR/uninhabited-static.rs:16:32 @@ -76,7 +80,11 @@ LL | static NEVER2: Void = unsafe { std::mem::transmute(()) }; | this code causes undefined behavior when executed | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done | - = note: enums with no variants have no valid value +note: enums with no inhabited variants have no valid value + --> $DIR/uninhabited-static.rs:4:1 + | +LL | enum Void {} + | ^^^^^^^^^ error: aborting due to 6 previous errors; 2 warnings emitted From d0305b3d00f54aead795ca32314a6177849d900f Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Mon, 19 Sep 2022 14:54:16 +0200 Subject: [PATCH 257/586] replace stabilization placeholders --- compiler/rustc_feature/src/accepted.rs | 6 +++--- compiler/rustc_feature/src/active.rs | 12 ++++++------ compiler/rustc_feature/src/removed.rs | 2 +- library/core/src/ops/range.rs | 2 +- library/core/src/ptr/const_ptr.rs | 4 ++-- library/core/src/ptr/mut_ptr.rs | 4 ++-- library/std/src/backtrace.rs | 26 +++++++++++++------------- library/std/src/io/mod.rs | 2 +- 8 files changed, 29 insertions(+), 29 deletions(-) diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs index 5f7de94e72657..8efb7ccc1c71c 100644 --- a/compiler/rustc_feature/src/accepted.rs +++ b/compiler/rustc_feature/src/accepted.rs @@ -162,7 +162,7 @@ declare_features! ( /// Allows capturing variables in scope using format_args! (accepted, format_args_capture, "1.58.0", Some(67984), None), /// Allows associated types to be generic, e.g., `type Foo;` (RFC 1598). - (accepted, generic_associated_types, "CURRENT_RUSTC_VERSION", Some(44265), None), + (accepted, generic_associated_types, "1.65.0", Some(44265), None), /// Allows attributes on lifetime/type formal parameters in generics (RFC 1327). (accepted, generic_param_attrs, "1.27.0", Some(48848), None), /// Allows the `#[global_allocator]` attribute. @@ -189,9 +189,9 @@ declare_features! ( /// especially around globs and shadowing (RFC 1560). (accepted, item_like_imports, "1.15.0", Some(35120), None), /// Allows `'a: { break 'a; }`. - (accepted, label_break_value, "CURRENT_RUSTC_VERSION", Some(48594), None), + (accepted, label_break_value, "1.65.0", Some(48594), None), /// Allows `let...else` statements. - (accepted, let_else, "CURRENT_RUSTC_VERSION", Some(87335), None), + (accepted, let_else, "1.65.0", Some(87335), None), /// Allows `break {expr}` with a value inside `loop`s. (accepted, loop_break_value, "1.19.0", Some(37339), None), /// Allows use of `?` as the Kleene "at most one" operator in macros. diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index 4c891fbf16e94..71ad54291b286 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -341,7 +341,7 @@ declare_features! ( /// Allows to use the `#[cmse_nonsecure_entry]` attribute. (active, cmse_nonsecure_entry, "1.48.0", Some(75835), None), /// Allows use of the `#[collapse_debuginfo]` attribute. - (active, collapse_debuginfo, "CURRENT_RUSTC_VERSION", Some(100758), None), + (active, collapse_debuginfo, "1.65.0", Some(100758), None), /// Allows `async {}` expressions in const contexts. (active, const_async_blocks, "1.53.0", Some(85368), None), // Allows limiting the evaluation steps of const expressions @@ -387,7 +387,7 @@ declare_features! ( /// Allows `#[doc(masked)]`. (active, doc_masked, "1.21.0", Some(44027), None), /// Allows `dyn* Trait` objects. - (incomplete, dyn_star, "CURRENT_RUSTC_VERSION", Some(91611), None), + (incomplete, dyn_star, "1.65.0", Some(91611), None), /// Allows `X..Y` patterns. (active, exclusive_range_pattern, "1.11.0", Some(37854), None), /// Allows exhaustive pattern matching on types that contain uninhabited types. @@ -403,7 +403,7 @@ declare_features! ( /// Allows using `#[repr(align(...))]` on function items (active, fn_align, "1.53.0", Some(82232), None), /// Allows generators to be cloned. - (active, generator_clone, "CURRENT_RUSTC_VERSION", Some(95360), None), + (active, generator_clone, "1.65.0", Some(95360), None), /// Allows defining generators. (active, generators, "1.21.0", Some(43122), None), /// Infer generic args for both consts and types. @@ -484,7 +484,7 @@ declare_features! ( /// Allows macro attributes on expressions, statements and non-inline modules. (active, proc_macro_hygiene, "1.30.0", Some(54727), None), /// Allows the use of raw-dylibs (RFC 2627). - (active, raw_dylib, "CURRENT_RUSTC_VERSION", Some(58713), None), + (active, raw_dylib, "1.65.0", Some(58713), None), /// Allows `&raw const $place_expr` and `&raw mut $place_expr` expressions. (active, raw_ref_op, "1.41.0", Some(64490), None), /// Allows using the `#[register_tool]` attribute. @@ -494,7 +494,7 @@ declare_features! ( /// Allows `repr(simd)` and importing the various simd intrinsics. (active, repr_simd, "1.4.0", Some(27731), None), /// Allows return-position `impl Trait` in traits. - (incomplete, return_position_impl_trait_in_trait, "CURRENT_RUSTC_VERSION", Some(91611), None), + (incomplete, return_position_impl_trait_in_trait, "1.65.0", Some(91611), None), /// Allows `extern "rust-cold"`. (active, rust_cold_cc, "1.63.0", Some(97544), None), /// Allows the use of SIMD types in functions declared in `extern` blocks. @@ -528,7 +528,7 @@ declare_features! ( /// not changed from prior instances of the same struct (RFC #2528) (active, type_changing_struct_update, "1.58.0", Some(86555), None), /// Enables rustc to generate code that instructs libstd to NOT ignore SIGPIPE. - (active, unix_sigpipe, "CURRENT_RUSTC_VERSION", Some(97889), None), + (active, unix_sigpipe, "1.65.0", Some(97889), None), /// Allows unsized fn parameters. (active, unsized_fn_params, "1.49.0", Some(48055), None), /// Allows unsized rvalues at arguments and parameters. diff --git a/compiler/rustc_feature/src/removed.rs b/compiler/rustc_feature/src/removed.rs index 13f275bb6a0c9..79a12801de29d 100644 --- a/compiler/rustc_feature/src/removed.rs +++ b/compiler/rustc_feature/src/removed.rs @@ -164,7 +164,7 @@ declare_features! ( (removed, quote, "1.33.0", Some(29601), None, None), (removed, reflect, "1.0.0", Some(27749), None, None), /// Allows using the `#[register_attr]` attribute. - (removed, register_attr, "CURRENT_RUSTC_VERSION", Some(66080), None, + (removed, register_attr, "1.65.0", Some(66080), None, Some("removed in favor of `#![register_tool]`")), /// Allows using the macros: /// + `__diagnostic_used` diff --git a/library/core/src/ops/range.rs b/library/core/src/ops/range.rs index 7282028358184..d29ae35614c1c 100644 --- a/library/core/src/ops/range.rs +++ b/library/core/src/ops/range.rs @@ -677,7 +677,7 @@ pub enum Bound { impl Bound { /// Converts from `&Bound` to `Bound<&T>`. #[inline] - #[stable(feature = "bound_as_ref_shared", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "bound_as_ref_shared", since = "1.65.0")] pub fn as_ref(&self) -> Bound<&T> { match *self { Included(ref x) => Included(x), diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index fcdf69a7aaa40..43e883b8bf718 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -98,8 +98,8 @@ impl *const T { /// /// This is a bit safer than `as` because it wouldn't silently change the type if the code is /// refactored. - #[stable(feature = "ptr_const_cast", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "ptr_const_cast", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "ptr_const_cast", since = "1.65.0")] + #[rustc_const_stable(feature = "ptr_const_cast", since = "1.65.0")] pub const fn cast_mut(self) -> *mut T { self as _ } diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index 460f3df5feeab..e277b8181754e 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -103,8 +103,8 @@ impl *mut T { /// coercion. /// /// [`cast_mut`]: #method.cast_mut - #[stable(feature = "ptr_const_cast", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "ptr_const_cast", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "ptr_const_cast", since = "1.65.0")] + #[rustc_const_stable(feature = "ptr_const_cast", since = "1.65.0")] pub const fn cast_const(self) -> *const T { self as _ } diff --git a/library/std/src/backtrace.rs b/library/std/src/backtrace.rs index 354200d4c95e9..5cf6ec8178928 100644 --- a/library/std/src/backtrace.rs +++ b/library/std/src/backtrace.rs @@ -58,7 +58,7 @@ //! `RUST_LIB_BACKTRACE` or `RUST_BACKTRACE` at runtime might not actually change //! how backtraces are captured. -#![stable(feature = "backtrace", since = "CURRENT_RUSTC_VERSION")] +#![stable(feature = "backtrace", since = "1.65.0")] #[cfg(test)] mod tests; @@ -104,7 +104,7 @@ use crate::vec::Vec; /// previous point in time. In some instances the `Backtrace` type may /// internally be empty due to configuration. For more information see /// `Backtrace::capture`. -#[stable(feature = "backtrace", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "backtrace", since = "1.65.0")] #[must_use] pub struct Backtrace { inner: Inner, @@ -112,21 +112,21 @@ pub struct Backtrace { /// The current status of a backtrace, indicating whether it was captured or /// whether it is empty for some other reason. -#[stable(feature = "backtrace", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "backtrace", since = "1.65.0")] #[non_exhaustive] #[derive(Debug, PartialEq, Eq)] pub enum BacktraceStatus { /// Capturing a backtrace is not supported, likely because it's not /// implemented for the current platform. - #[stable(feature = "backtrace", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "backtrace", since = "1.65.0")] Unsupported, /// Capturing a backtrace has been disabled through either the /// `RUST_LIB_BACKTRACE` or `RUST_BACKTRACE` environment variables. - #[stable(feature = "backtrace", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "backtrace", since = "1.65.0")] Disabled, /// A backtrace has been captured and the `Backtrace` should print /// reasonable information when rendered. - #[stable(feature = "backtrace", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "backtrace", since = "1.65.0")] Captured, } @@ -173,7 +173,7 @@ enum BytesOrWide { Wide(Vec), } -#[stable(feature = "backtrace", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "backtrace", since = "1.65.0")] impl fmt::Debug for Backtrace { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { let capture = match &self.inner { @@ -289,7 +289,7 @@ impl Backtrace { /// /// To forcibly capture a backtrace regardless of environment variables, use /// the `Backtrace::force_capture` function. - #[stable(feature = "backtrace", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "backtrace", since = "1.65.0")] #[inline(never)] // want to make sure there's a frame here to remove pub fn capture() -> Backtrace { if !Backtrace::enabled() { @@ -308,7 +308,7 @@ impl Backtrace { /// Note that capturing a backtrace can be an expensive operation on some /// platforms, so this should be used with caution in performance-sensitive /// parts of code. - #[stable(feature = "backtrace", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "backtrace", since = "1.65.0")] #[inline(never)] // want to make sure there's a frame here to remove pub fn force_capture() -> Backtrace { Backtrace::create(Backtrace::force_capture as usize) @@ -316,8 +316,8 @@ impl Backtrace { /// Forcibly captures a disabled backtrace, regardless of environment /// variable configuration. - #[stable(feature = "backtrace", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "backtrace", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "backtrace", since = "1.65.0")] + #[rustc_const_stable(feature = "backtrace", since = "1.65.0")] pub const fn disabled() -> Backtrace { Backtrace { inner: Inner::Disabled } } @@ -361,7 +361,7 @@ impl Backtrace { /// Returns the status of this backtrace, indicating whether this backtrace /// request was unsupported, disabled, or a stack trace was actually /// captured. - #[stable(feature = "backtrace", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "backtrace", since = "1.65.0")] #[must_use] pub fn status(&self) -> BacktraceStatus { match self.inner { @@ -381,7 +381,7 @@ impl<'a> Backtrace { } } -#[stable(feature = "backtrace", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "backtrace", since = "1.65.0")] impl fmt::Display for Backtrace { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { let capture = match &self.inner { diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index 01a3873c75cec..eeace2c43c4a4 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -1045,7 +1045,7 @@ pub trait Read { /// Ok(()) /// } /// ``` -#[stable(feature = "io_read_to_string", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "io_read_to_string", since = "1.65.0")] pub fn read_to_string(mut reader: R) -> Result { let mut buf = String::new(); reader.read_to_string(&mut buf)?; From 317cab9bef9097eb2b1be8f24d3ee6c44742a8a8 Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Tue, 20 Sep 2022 12:44:15 +0200 Subject: [PATCH 258/586] bump stage0 --- src/stage0.json | 676 ++++++++++++++++++++++++------------------------ 1 file changed, 338 insertions(+), 338 deletions(-) diff --git a/src/stage0.json b/src/stage0.json index c4891a9858bfe..72308d50c8ebe 100644 --- a/src/stage0.json +++ b/src/stage0.json @@ -17,349 +17,349 @@ "tool is executed." ], "compiler": { - "date": "2022-08-19", + "date": "2022-09-20", "version": "beta" }, "rustfmt": { - "date": "2022-08-20", + "date": "2022-09-20", "version": "nightly" }, "checksums_sha256": { - "dist/2022-08-19/cargo-beta-aarch64-apple-darwin.tar.gz": "79196736248e8e0f76a5d365a45fda39d5bdd815f0f2a8e4341acba31b183a22", - "dist/2022-08-19/cargo-beta-aarch64-apple-darwin.tar.xz": "2cad3b28e9ee50c01d031b9c0086f40ccc16845ff2496e91fb1adebc8560b1ec", - "dist/2022-08-19/cargo-beta-aarch64-pc-windows-msvc.tar.gz": "c725c27d06a4201df716f50509651cf071708fc0860e2d482a8dcc7dc69011bc", - "dist/2022-08-19/cargo-beta-aarch64-pc-windows-msvc.tar.xz": "f5e1c07a8043d5e94c0450e896069262f825fa534c7688465fb0e50424b052ab", - "dist/2022-08-19/cargo-beta-aarch64-unknown-linux-gnu.tar.gz": "4f07b76c98206ade5b18a89af56004adae0abd51be1c295f6725b6b24bd2dfa1", - "dist/2022-08-19/cargo-beta-aarch64-unknown-linux-gnu.tar.xz": "9ef70808f78032f2d2f60c529dd43354752df510e7eb9d7db09abc34898a0243", - "dist/2022-08-19/cargo-beta-aarch64-unknown-linux-musl.tar.gz": "8c3fa219aad16a2c7a2858844bc3e9b39d2382907b5a145a21d88001d082b510", - "dist/2022-08-19/cargo-beta-aarch64-unknown-linux-musl.tar.xz": "60f18159e805894e5504d84999a33396cb27d32d2827ee6b903ed9efab5ae3e7", - "dist/2022-08-19/cargo-beta-arm-unknown-linux-gnueabi.tar.gz": "66ae9ea36d30e5e027e452b5e4e76e7deaa0d5f7c601b781c02559a99e5a888b", - "dist/2022-08-19/cargo-beta-arm-unknown-linux-gnueabi.tar.xz": "61c00674f1a33234f0622e7f2b770d641b8202d1e79ce231ad372c0c5e8a0cb2", - "dist/2022-08-19/cargo-beta-arm-unknown-linux-gnueabihf.tar.gz": "298e096659bf1a3903073f3c59bec22f763a2a8f8a9ee91f94589b8e9361bbc1", - "dist/2022-08-19/cargo-beta-arm-unknown-linux-gnueabihf.tar.xz": "dc57c0aea0ae45d781d9a000a36b9df66532b5434024cc6c4d99d8007a0bef8f", - "dist/2022-08-19/cargo-beta-armv7-unknown-linux-gnueabihf.tar.gz": "cd21f821f8e6ff9e0b0c3d3e841192fb81a6fecb6ebffd09fa880ac07c9fe677", - "dist/2022-08-19/cargo-beta-armv7-unknown-linux-gnueabihf.tar.xz": "8757bc726950c5e8507ad0d9ae518504a9467e8cfabe590b458714be3b6fc1bf", - "dist/2022-08-19/cargo-beta-i686-pc-windows-gnu.tar.gz": "4c3c891c19ab8990a892fc98ee5e1546b5a8626ebd769b1b6c26cfcc636f12b4", - "dist/2022-08-19/cargo-beta-i686-pc-windows-gnu.tar.xz": "2da6fa16707edccedc3fb37782ae2cbee1330cc89e646a16fbb288c07fe2502d", - "dist/2022-08-19/cargo-beta-i686-pc-windows-msvc.tar.gz": "76c4f8be3abfff215a9a565e378fe8e5853b164e2c1ea5f91c4791851457840b", - "dist/2022-08-19/cargo-beta-i686-pc-windows-msvc.tar.xz": "8f49f0ca8542ca72bfc05f4928a97ccc9e825a3b7f00dc7fadc58ba184169d07", - "dist/2022-08-19/cargo-beta-i686-unknown-linux-gnu.tar.gz": "51b48101522af0cae055e01d025ca657fd7284fb4e3cf81839774fdef97d6c21", - "dist/2022-08-19/cargo-beta-i686-unknown-linux-gnu.tar.xz": "63e34d3e51a99eac167f7567002026f63b830defcff364b3029d8819ccd4abb5", - "dist/2022-08-19/cargo-beta-mips-unknown-linux-gnu.tar.gz": "2888d73ea48e9ca5ffb6f2db7d1ce665413229d38454e625cad4d4d9e2111feb", - "dist/2022-08-19/cargo-beta-mips-unknown-linux-gnu.tar.xz": "cc361abd32f693e2b0d44d718c9d14cf4f4e9333eb965a888013abc1abf2e81d", - "dist/2022-08-19/cargo-beta-mips64-unknown-linux-gnuabi64.tar.gz": "7c180166f2ab5c91ed218d2f9fa2ad552e47818a268347bf5be48cad36f14858", - "dist/2022-08-19/cargo-beta-mips64-unknown-linux-gnuabi64.tar.xz": "1e5895d5ccd86c5fe13362d8763e9a75ec46909e7c4840dcc84286aa7bf4b367", - "dist/2022-08-19/cargo-beta-mips64el-unknown-linux-gnuabi64.tar.gz": "6890940f4e02979b6bb8496faf7e71d75c317be563b35c44fdaebdfe11b62cd1", - "dist/2022-08-19/cargo-beta-mips64el-unknown-linux-gnuabi64.tar.xz": "37bf3bed41ed98d1517d5e925ca22ca39c6d51ab1e65b2e7fd9e8f082364d258", - "dist/2022-08-19/cargo-beta-mipsel-unknown-linux-gnu.tar.gz": "aaaef89dd7ef0cf07a400cecdd70851be23d066b0522d2e89f94358ea196ebeb", - "dist/2022-08-19/cargo-beta-mipsel-unknown-linux-gnu.tar.xz": "17c883e6c59a892a4eceee482f27eef60a020f417e06e9c1282992fc085b6106", - "dist/2022-08-19/cargo-beta-powerpc-unknown-linux-gnu.tar.gz": "722efeb58b8d6802ecc52bfc686b4a1a24fd7b9494e93ed7cb8e4ac974e5c161", - "dist/2022-08-19/cargo-beta-powerpc-unknown-linux-gnu.tar.xz": "26b3572b77ff7faaf40c06204852683408fda2aa4256167611ac1d0c177789de", - "dist/2022-08-19/cargo-beta-powerpc64-unknown-linux-gnu.tar.gz": "93c504cbade48dc07b4e839d85fa6f477f28ab140c894e8f9acec6477f21e7db", - "dist/2022-08-19/cargo-beta-powerpc64-unknown-linux-gnu.tar.xz": "72354c21c154868a9b1c420047cf2a9eb5aaae20e93dde41f8283ad6e441a744", - "dist/2022-08-19/cargo-beta-powerpc64le-unknown-linux-gnu.tar.gz": "ba4c589975b4ca7ae10c98d07c02bae50b7c5d0bcaded77f1ccfefbf555d4116", - "dist/2022-08-19/cargo-beta-powerpc64le-unknown-linux-gnu.tar.xz": "fe9e8e7cbb9a1b00871e11b54ae3f64bc35dc4cc80ca49e59b4d8daf5fbdeea4", - "dist/2022-08-19/cargo-beta-riscv64gc-unknown-linux-gnu.tar.gz": "287e7a014a6d8e650124c71c87bbd9655785564f4ee1f179a9226ce371e8d78c", - "dist/2022-08-19/cargo-beta-riscv64gc-unknown-linux-gnu.tar.xz": "4e35f5a198bbcc06842569e2fda1985e77794425f2e85f1948d7a7664125099b", - "dist/2022-08-19/cargo-beta-s390x-unknown-linux-gnu.tar.gz": "05e091a433009843f0dcc295b5b53b46ba2f55a37f7057c777a9cd92c094cba3", - "dist/2022-08-19/cargo-beta-s390x-unknown-linux-gnu.tar.xz": "54202c092c265bff6be7f598ce1f6e96a84a5ba4c354d9bbd4986475cf0b809d", - "dist/2022-08-19/cargo-beta-x86_64-apple-darwin.tar.gz": "0ae9a6dde1693d33ff774f435bba3e18b67e2d8ce757df5e26ac3b757733cb29", - "dist/2022-08-19/cargo-beta-x86_64-apple-darwin.tar.xz": "d67c4c748443be773016d27a74e859428b404a7fb06e651b1fdbc205ea08c03b", - "dist/2022-08-19/cargo-beta-x86_64-pc-windows-gnu.tar.gz": "fd617b76eb4d9d951ca9757a31fe92c8cfeb76b093e09262728c7737aa9d2970", - "dist/2022-08-19/cargo-beta-x86_64-pc-windows-gnu.tar.xz": "14f263241b90e91fc40a75361e4b8de23165cf8b7c973bc7016a9bf337381ec0", - "dist/2022-08-19/cargo-beta-x86_64-pc-windows-msvc.tar.gz": "c5440958cc976526109ef17b4883e27394d6ce087d90653956371837de5a7f8f", - "dist/2022-08-19/cargo-beta-x86_64-pc-windows-msvc.tar.xz": "8e3c28a0e593651b530bed0fb5216ca8f04ebc54e98b8cb83cfae3ea13c1c8a1", - "dist/2022-08-19/cargo-beta-x86_64-unknown-freebsd.tar.gz": "c80991b59c39129fce5f775c5f1b530592d04060bfee7f7a7a443da698efc50f", - "dist/2022-08-19/cargo-beta-x86_64-unknown-freebsd.tar.xz": "81fe7a26762f503c04000f954986c25be1acbaa6687389b70a48e4230901fdfe", - "dist/2022-08-19/cargo-beta-x86_64-unknown-illumos.tar.gz": "8b08d6c4c41c3ab05ea3310d44943a3453254c96df92b5f25cc888c4fb7d31fe", - "dist/2022-08-19/cargo-beta-x86_64-unknown-illumos.tar.xz": "eb4705ba79bc9b7d2a3969748d966c7faf305ab196bd002856fe5a0499c11989", - "dist/2022-08-19/cargo-beta-x86_64-unknown-linux-gnu.tar.gz": "b0f14a0bfa064b4511dc34a71039af3c69b006b51906f9087bc7929014b9db76", - "dist/2022-08-19/cargo-beta-x86_64-unknown-linux-gnu.tar.xz": "3d8cdbc3679550a374e29b4a363b30048e2d65d3d4b9c9dbaeb0a907606afee3", - "dist/2022-08-19/cargo-beta-x86_64-unknown-linux-musl.tar.gz": "2f564886b29fece08e8ccf4fdaf6035b5819d03fc963ce46cd6225a79e2d4da0", - "dist/2022-08-19/cargo-beta-x86_64-unknown-linux-musl.tar.xz": "78f7ed8eb7e8d147113472f6402688e0127a41a1a26679c19c9e558bf39e8df7", - "dist/2022-08-19/cargo-beta-x86_64-unknown-netbsd.tar.gz": "3edff35d00c5af406b72db5e2ee33340c05d24a4bdf4658f172b7d74994825ff", - "dist/2022-08-19/cargo-beta-x86_64-unknown-netbsd.tar.xz": "96b290796ea1781fb5a69838f969591b70e5e193efeab85f4e7c45dfb2c698f2", - "dist/2022-08-19/rust-std-beta-aarch64-apple-darwin.tar.gz": "c7b09f59bdd2cf91a9aaf771257a474655ed5905f5455f9a3b47bb832d1f124c", - "dist/2022-08-19/rust-std-beta-aarch64-apple-darwin.tar.xz": "b82c8c4a454f59218b22eb04a346b78215c10269c001e28395080abefaa9e6f4", - "dist/2022-08-19/rust-std-beta-aarch64-apple-ios-sim.tar.gz": "cbccc251b16f41383845d5d1d6196f33d2769df7455f308c096e0af46b43d14c", - "dist/2022-08-19/rust-std-beta-aarch64-apple-ios-sim.tar.xz": "99be53158e3ee2b467d75d26d461e7aa4330301c6dba74c048331b16e09188c5", - "dist/2022-08-19/rust-std-beta-aarch64-apple-ios.tar.gz": "bf94ccc4bc6a4c171cd60d7a62c34d32e09b242a7029b69feef6159cf4c22fee", - "dist/2022-08-19/rust-std-beta-aarch64-apple-ios.tar.xz": "6a9a910573ea80de9618c7bf46e21e93341db652e4d82bee06e73544b92805f4", - "dist/2022-08-19/rust-std-beta-aarch64-fuchsia.tar.gz": "27693e376c29e561844e43ef21d006942e44263076ab4144643827b671ea3339", - "dist/2022-08-19/rust-std-beta-aarch64-fuchsia.tar.xz": "81d00752188815a7747f89ba76610d91d276459543e6c4362f1f86ecacc28f2d", - "dist/2022-08-19/rust-std-beta-aarch64-linux-android.tar.gz": "6f076bd4565d9af83003e1165e24fb912eca0adaf40a40f1d87956ff8dff535a", - "dist/2022-08-19/rust-std-beta-aarch64-linux-android.tar.xz": "a0f528910137d9b7e0e6dd371dad181f7d48d270e8ae289d8b7996440bef101b", - "dist/2022-08-19/rust-std-beta-aarch64-pc-windows-msvc.tar.gz": "6ac6afb78d0c3e55cffc6cc52bba51259fe83aac35075cebdb6940ad3d147b60", - "dist/2022-08-19/rust-std-beta-aarch64-pc-windows-msvc.tar.xz": "f1043c1fa0d0d75f8001d854967f2ec8be6def5845662505048742e6472ebb87", - "dist/2022-08-19/rust-std-beta-aarch64-unknown-linux-gnu.tar.gz": "d3390a8cb0617551cdce7bb9348fc39a304c877bf5c5ce02ec9cdf636a69571d", - "dist/2022-08-19/rust-std-beta-aarch64-unknown-linux-gnu.tar.xz": "81da17399275e43ec9b15983faa9828df2a8dbc72ea15d16671d0c31d4d0795c", - "dist/2022-08-19/rust-std-beta-aarch64-unknown-linux-musl.tar.gz": "3deca6def0ebb3476898e1ee7368592a034867d73948e51f24ad92445c6275b6", - "dist/2022-08-19/rust-std-beta-aarch64-unknown-linux-musl.tar.xz": "23bc4165841199f110293a627735624a2a37bc6d92019e9cb1533e006933f9d5", - "dist/2022-08-19/rust-std-beta-aarch64-unknown-none-softfloat.tar.gz": "3360ea38f8d8bc84f2419b4ca90bfca7a9709a6fbec2ba209fe335090a534c0e", - "dist/2022-08-19/rust-std-beta-aarch64-unknown-none-softfloat.tar.xz": "ce7643548eb6f797b7823795e27b748aaa09cd02baffaeee44bdc3c00ed796e3", - "dist/2022-08-19/rust-std-beta-aarch64-unknown-none.tar.gz": "5f6cd59b283ac76709e7c76c89f352e92b6818b1606b585332f36ba3c4b6a87b", - "dist/2022-08-19/rust-std-beta-aarch64-unknown-none.tar.xz": "60d00cacbd24576b0b247f2b12d6a63e9451912d874385b50165a312da080762", - "dist/2022-08-19/rust-std-beta-arm-linux-androideabi.tar.gz": "15494aade74e5e29bb0d881d243da37d3b929bd98baab7c6b0345e0a6a0ed803", - "dist/2022-08-19/rust-std-beta-arm-linux-androideabi.tar.xz": "d62cdfc5d0a41749ea90d6cabaa77f4f45630061a04dd3be9611cd5f0ea868d5", - "dist/2022-08-19/rust-std-beta-arm-unknown-linux-gnueabi.tar.gz": "40e532cd37262e7280a7c0bdd54808815adba533a911bd46a1d9b76d0446b958", - "dist/2022-08-19/rust-std-beta-arm-unknown-linux-gnueabi.tar.xz": "bb08d0ca767f257fb13f6a946e7c725dc877055f94d324128eab521d43cc552b", - "dist/2022-08-19/rust-std-beta-arm-unknown-linux-gnueabihf.tar.gz": "2f22a08cee234574c48e5022e0c5b1641c2ad01fad69537b03eb9f247e7877dd", - "dist/2022-08-19/rust-std-beta-arm-unknown-linux-gnueabihf.tar.xz": "8cb10237d87a4fcf2100b5aec0623ab04c2f1d976a0f30a1a89357cb41ce6d4e", - "dist/2022-08-19/rust-std-beta-arm-unknown-linux-musleabi.tar.gz": "811c691d678f08627758bba341e3ac06a2d465da78d819c49de494e0602073e6", - "dist/2022-08-19/rust-std-beta-arm-unknown-linux-musleabi.tar.xz": "50063b02901983e3ce37e98e57e664521cb5c99ab9a1015bb949a53dfda9b49c", - "dist/2022-08-19/rust-std-beta-arm-unknown-linux-musleabihf.tar.gz": "2ca7a740767463e432b22b846f81ab9983751279b65b4488d07202b77e378afc", - "dist/2022-08-19/rust-std-beta-arm-unknown-linux-musleabihf.tar.xz": "8b56365bd261fb6a4c2984b51dce14d8e2c996667ba4af866153042855043916", - "dist/2022-08-19/rust-std-beta-armebv7r-none-eabi.tar.gz": "83ece7e0db0e1ddd44b104d52def00ce06fea37dd8c90b1c0a840d0561a76d54", - "dist/2022-08-19/rust-std-beta-armebv7r-none-eabi.tar.xz": "e3a343fa5f35372ace7f23e6775c8c01b9803fca9e1b686d3db695c2f754db5b", - "dist/2022-08-19/rust-std-beta-armebv7r-none-eabihf.tar.gz": "874dec1039af060488f34be26ba54615a12ee4cb64f3a871932936e4e736fd76", - "dist/2022-08-19/rust-std-beta-armebv7r-none-eabihf.tar.xz": "cdc6b9a375a40847ee4938f3609f8c49f3368394b46fa9dccf1b5b16468852f7", - "dist/2022-08-19/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.gz": "28e72dd4c24716224b663d341d6f784f2b0deebbf52721709fb396240e327854", - "dist/2022-08-19/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.xz": "5c8cf5b47b567b8bc41c3ce831f34d076396179d050bf982e1949bef74a2b2fb", - "dist/2022-08-19/rust-std-beta-armv5te-unknown-linux-musleabi.tar.gz": "dcfd76d646b17521f5a7daf94a0617a731d914612368ff112345a03a2a5b5939", - "dist/2022-08-19/rust-std-beta-armv5te-unknown-linux-musleabi.tar.xz": "7d43dfef571dc4c2e883bdf92e05dd3465b9233c30f34bf282b57826339e9e96", - "dist/2022-08-19/rust-std-beta-armv7-linux-androideabi.tar.gz": "4bb1f0110629b7af1fbe09a6eb8387de9aa800a95053ef7177bba30a2d1b430c", - "dist/2022-08-19/rust-std-beta-armv7-linux-androideabi.tar.xz": "55f97c5a16e8d65dcfa13adf989039ffcafc5a4a09aec92083d00d7e2786def9", - "dist/2022-08-19/rust-std-beta-armv7-unknown-linux-gnueabi.tar.gz": "e7fb4da36908d6cc0c13a93ec3f4b01ea1b2c515213005479da45712614c0a69", - "dist/2022-08-19/rust-std-beta-armv7-unknown-linux-gnueabi.tar.xz": "c727568116de82658335c3be93d51a7e2850cc2824b9818a166594649dd5b3ce", - "dist/2022-08-19/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.gz": "1a186dab35dba7fcf4982e717a1ac6d1d846b87e50e6815ac0f9b2c40e44f4d2", - "dist/2022-08-19/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.xz": "7f5d3c66c57ba75d3c91328f3ceccddeeebdc08f015e762e26af770a968ab14d", - "dist/2022-08-19/rust-std-beta-armv7-unknown-linux-musleabi.tar.gz": "c0108882d6f80cb82a9fa016adfdca2478b4966c72c6d6d240c94c56fa668166", - "dist/2022-08-19/rust-std-beta-armv7-unknown-linux-musleabi.tar.xz": "4f30e1114c7c4ca187f9a2e4b2ffdd4fa66cd2346534c80ff5a7278a846f2c8c", - "dist/2022-08-19/rust-std-beta-armv7-unknown-linux-musleabihf.tar.gz": "a69c55803776f8ccfc1685181209463ebbbd82252ba2cd47387d6ce8f8f09afb", - "dist/2022-08-19/rust-std-beta-armv7-unknown-linux-musleabihf.tar.xz": "c12d6e9f9cec1aee0dcad3ac95a33dea0522a0e00c88e1d1e5ea4a0d98119128", - "dist/2022-08-19/rust-std-beta-armv7a-none-eabi.tar.gz": "91cb7d15d30bea14c3f7b9ad19ccc3cf58b69abf8ff7ec2ebaf1ed60cab4940d", - "dist/2022-08-19/rust-std-beta-armv7a-none-eabi.tar.xz": "887aad7c712055aca460a840bb1f5b69caf4fe11a458032df73038af94285abe", - "dist/2022-08-19/rust-std-beta-armv7r-none-eabi.tar.gz": "54a4f38e30039211e0199bc25733572d24dd5ad9eb6fec524146c1dc08b745d4", - "dist/2022-08-19/rust-std-beta-armv7r-none-eabi.tar.xz": "0b6b366e0380df3513f36eac4341d5562520eff0fc995280179c6424fcc4f5db", - "dist/2022-08-19/rust-std-beta-armv7r-none-eabihf.tar.gz": "76f33e20c3800f2a7cc53db4552a44b5269aa8678c7f3de970071ed0f3c66dfe", - "dist/2022-08-19/rust-std-beta-armv7r-none-eabihf.tar.xz": "e71d8e8a2144cd4ca220cb25218aaeca7d0ba776ef10d2adebd8745bc1fdf988", - "dist/2022-08-19/rust-std-beta-asmjs-unknown-emscripten.tar.gz": "50ba543bcfe3d1ca5d5606e7ea656968f70930ce074fb0110e65658e9cab9810", - "dist/2022-08-19/rust-std-beta-asmjs-unknown-emscripten.tar.xz": "b2498657da8c27464213afbbad1ff95db637236a9e0f88d2c9bf0c6940a0c583", - "dist/2022-08-19/rust-std-beta-i586-pc-windows-msvc.tar.gz": "8275136f11ddad506a9569d3e6d1ad4b48688a1e7e498e22566ff3453675ff4b", - "dist/2022-08-19/rust-std-beta-i586-pc-windows-msvc.tar.xz": "8c5fae3775152a3dd3d1bc47e1ab1861efa60b51f8087fb2a63da0eb45185a79", - "dist/2022-08-19/rust-std-beta-i586-unknown-linux-gnu.tar.gz": "628a29ee30489dc9bb6877a2aaccb4f5de05a5a58ef154be875643ce393776d4", - "dist/2022-08-19/rust-std-beta-i586-unknown-linux-gnu.tar.xz": "ff4f7ade08cb2337d20fbaa8a6e74f662b805cb2bf142a584e10b4aae66139a9", - "dist/2022-08-19/rust-std-beta-i586-unknown-linux-musl.tar.gz": "3f7859c372943096d3f6a258561584cee28adb9cfeff5b98036dd7cab74dab7d", - "dist/2022-08-19/rust-std-beta-i586-unknown-linux-musl.tar.xz": "40323fdb61ae453d42525ea13c41b5dedd322d859f9993315a798a87634ee386", - "dist/2022-08-19/rust-std-beta-i686-linux-android.tar.gz": "b103802c800524bc1dc6f3d996ad47d2c03fe03b236588f8a9de3fc763ba2eff", - "dist/2022-08-19/rust-std-beta-i686-linux-android.tar.xz": "ecb631362408d708e63093a0bec0b735b1cdc6bb7c0509ab5852e572f796812e", - "dist/2022-08-19/rust-std-beta-i686-pc-windows-gnu.tar.gz": "3b7af769cb25b75fc5a657e4f3dd489e6745df2d383c5e78cc033fb46345d72e", - "dist/2022-08-19/rust-std-beta-i686-pc-windows-gnu.tar.xz": "f1a65b9607cd153e421f27891b5ebcdc1e4a1571613ecead7402d8794eff3330", - "dist/2022-08-19/rust-std-beta-i686-pc-windows-msvc.tar.gz": "e5214f670f981c7b95e690c8487323dc2a564d34f5ad4f589d2862ee11225b83", - "dist/2022-08-19/rust-std-beta-i686-pc-windows-msvc.tar.xz": "efe17356f42fa47949151ebfdb75ee10d14cc5a279eb4361c79f36c5c322d9cb", - "dist/2022-08-19/rust-std-beta-i686-unknown-freebsd.tar.gz": "35a3dcfd6df77ac71cd01bec57814d9153d1358409cab11e206b98e86e14c701", - "dist/2022-08-19/rust-std-beta-i686-unknown-freebsd.tar.xz": "4dbeea93b2aa61076de0c84c2d5833474eec7adb66a96e90372b074e6c7790c7", - "dist/2022-08-19/rust-std-beta-i686-unknown-linux-gnu.tar.gz": "e07c47100a8719e54176bb2465ae62d1156a4264695739039b901c6ad16e5bd9", - "dist/2022-08-19/rust-std-beta-i686-unknown-linux-gnu.tar.xz": "2dab5f2fbc8c5900b0b4f35ffde00d0e6777c823b67a4632fddd19a3c3b5e20f", - "dist/2022-08-19/rust-std-beta-i686-unknown-linux-musl.tar.gz": "8b8131f8644c4cbf13003266dcfd5ff82f7b72aa8fdd14a27ff8281821ea6a5f", - "dist/2022-08-19/rust-std-beta-i686-unknown-linux-musl.tar.xz": "b47f1cd70533ab2a59a8ee8c218e7d94406a552df5d23061f9cea714301d973b", - "dist/2022-08-19/rust-std-beta-mips-unknown-linux-gnu.tar.gz": "415d22301e698a355fbc1a32181b02a72b7ff36fe1779460d6f380fde1608500", - "dist/2022-08-19/rust-std-beta-mips-unknown-linux-gnu.tar.xz": "2f3524f5908f0570b843304dc11eb8d1f7285eab7cda18581043321f65e2a1dd", - "dist/2022-08-19/rust-std-beta-mips-unknown-linux-musl.tar.gz": "6f25a53edc32d423752557cb65daf64f9e3a622ba5a6fdf3f07f95024b2348b6", - "dist/2022-08-19/rust-std-beta-mips-unknown-linux-musl.tar.xz": "a6223971aa5679e3db6df2afbdd31db05b58563347d01ae8682f37236ef2c402", - "dist/2022-08-19/rust-std-beta-mips64-unknown-linux-gnuabi64.tar.gz": "756c7cd706d57fb766c0e255c9a10146f4d8c2bef0118196706f268a5b1ac65e", - "dist/2022-08-19/rust-std-beta-mips64-unknown-linux-gnuabi64.tar.xz": "b54706a7faa146e4144e7c66d0f19289bebb155bc0adfaba3c4356866514e830", - "dist/2022-08-19/rust-std-beta-mips64-unknown-linux-muslabi64.tar.gz": "23fc1e3e7fd1b0f1ad210273090494246e45cf43d4c30076afd28925575a9447", - "dist/2022-08-19/rust-std-beta-mips64-unknown-linux-muslabi64.tar.xz": "ada4af591dbac60a137d00c4030e240eca53874604b2a306db1fe8af10bf0332", - "dist/2022-08-19/rust-std-beta-mips64el-unknown-linux-gnuabi64.tar.gz": "b9180c5bf936713c89f6f0f5f6a637810f72194a7742fdcbbf8fe6e4a6bfd358", - "dist/2022-08-19/rust-std-beta-mips64el-unknown-linux-gnuabi64.tar.xz": "1c2940139107d3aa8f6616e90f68fa42e62fd965f9e22cc264655ad5935971b6", - "dist/2022-08-19/rust-std-beta-mips64el-unknown-linux-muslabi64.tar.gz": "3dee776bf2aa9bdaaa38235d88a1ca98f0418adc10ceb3d0e3d8999339925bb2", - "dist/2022-08-19/rust-std-beta-mips64el-unknown-linux-muslabi64.tar.xz": "85f16418e4edc3b2d087104c51e4de61d7d9cf5631ee48065eaef9d796f662f7", - "dist/2022-08-19/rust-std-beta-mipsel-unknown-linux-gnu.tar.gz": "ba374a6acaa1eee5beb9c234d2aa6e46b8b1fc7be65e0ffe8d55d9ff85cc4ff1", - "dist/2022-08-19/rust-std-beta-mipsel-unknown-linux-gnu.tar.xz": "70621189ef43a8034d9f96765e35c43b17b16e077f143d3994e5e6cfc089e14e", - "dist/2022-08-19/rust-std-beta-mipsel-unknown-linux-musl.tar.gz": "143ab6fc7b3e57d551ada1d8335fdd77c4577d303d37663c4e7ce4b24557a752", - "dist/2022-08-19/rust-std-beta-mipsel-unknown-linux-musl.tar.xz": "a81db30558c46f43ef4c8cbf3480407af54bb6ad1813f0e912bab6ab0baef8b6", - "dist/2022-08-19/rust-std-beta-nvptx64-nvidia-cuda.tar.gz": "7def94fc92ad2ac6921d90efc821f37aa69bf59b6b6c8cddf958a7bc6e90ab51", - "dist/2022-08-19/rust-std-beta-nvptx64-nvidia-cuda.tar.xz": "c39b30a1dbb8c6a828b860f4b0685a3c0498a65dfde880df21e505c7b4ab545d", - "dist/2022-08-19/rust-std-beta-powerpc-unknown-linux-gnu.tar.gz": "184441ee82c9578b62f905e0e1fae2e27d63cc0729ddc4a58797905341a18c30", - "dist/2022-08-19/rust-std-beta-powerpc-unknown-linux-gnu.tar.xz": "b7677f219cb8158ce4a9dc64dafffb63f5bda0752d14390ba52c609bac629fd7", - "dist/2022-08-19/rust-std-beta-powerpc64-unknown-linux-gnu.tar.gz": "e295a74c453bf003d02d0aab07aa4b8c609878975cea9795ef467150b01f3b62", - "dist/2022-08-19/rust-std-beta-powerpc64-unknown-linux-gnu.tar.xz": "5c45723e1047a502718365252f66aa376e1ba7702fbf1453dee3a288367b3208", - "dist/2022-08-19/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.gz": "c348be9b8846b158b21cd73542dcfb891401421ad5fd4e0a8eacdb49e56cdb4c", - "dist/2022-08-19/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.xz": "f6036cb2c1fdb232016eb99f908a198c06bae44ac4d6d7536d3ebf42ba0b6db3", - "dist/2022-08-19/rust-std-beta-riscv32i-unknown-none-elf.tar.gz": "766ebdbc735cca0906a23683c5da5ada8a6e455dc12e49c7b34f71e66922f60a", - "dist/2022-08-19/rust-std-beta-riscv32i-unknown-none-elf.tar.xz": "83dc6727a20ac37273ad8b3ce043f005d5f2be7dab1d5d0c9658fe5897ee9ce2", - "dist/2022-08-19/rust-std-beta-riscv32imac-unknown-none-elf.tar.gz": "5f059405fde4d25ff250c7219a5b7d8c009a69672f4255867d23ebd50539515e", - "dist/2022-08-19/rust-std-beta-riscv32imac-unknown-none-elf.tar.xz": "2aad029aa8eaed74e95ac82d471bc750955323b2ef12066b5257e9779cdb9f79", - "dist/2022-08-19/rust-std-beta-riscv32imc-unknown-none-elf.tar.gz": "734e92db50a3793eefba0378dfe2daceb37b6c06f5a6ed1692b83553406060ef", - "dist/2022-08-19/rust-std-beta-riscv32imc-unknown-none-elf.tar.xz": "f2278a4aa83e2cba6ccf32744c3ae8b55fd44f77bdc31f08bff36105b945d2b8", - "dist/2022-08-19/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.gz": "4ce4d1659cd7ae70705c8f4808226814df18bfdedc079c44484fe1ce0dc06f00", - "dist/2022-08-19/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.xz": "77e5962551433593e6ee3a2b1ab6766706acdb9c364f5adc8c5b99e84338d3a0", - "dist/2022-08-19/rust-std-beta-riscv64gc-unknown-none-elf.tar.gz": "6a85f89c5211fc18f86cdea8874ce4ee4d5cf15299b3884dca207003715bb54d", - "dist/2022-08-19/rust-std-beta-riscv64gc-unknown-none-elf.tar.xz": "cfe8149d98fa1e6d1b406a5f4133ff6bcc9fe3cc5cdb006eebd354537efa55db", - "dist/2022-08-19/rust-std-beta-riscv64imac-unknown-none-elf.tar.gz": "45c5918df046c2ac5fdce3025eba539eac759d09fd1a134d51272647b829b3ba", - "dist/2022-08-19/rust-std-beta-riscv64imac-unknown-none-elf.tar.xz": "42d01adaa0a222270a303c10fe5b44e61817f317494595f09ab3101ab859e764", - "dist/2022-08-19/rust-std-beta-s390x-unknown-linux-gnu.tar.gz": "09ca832cd73a5f995a76ce9e6c330095417d8802d2b3afdcf3c42f646dc9346b", - "dist/2022-08-19/rust-std-beta-s390x-unknown-linux-gnu.tar.xz": "293fdda30521323f1cafe3cc0db92d80bca7fb25ec73a2b2e0c2cdcb48cc9564", - "dist/2022-08-19/rust-std-beta-sparc64-unknown-linux-gnu.tar.gz": "f74c4dd7526251aeab43172f5bf043bdd70b8819c899866086a98c45f7895583", - "dist/2022-08-19/rust-std-beta-sparc64-unknown-linux-gnu.tar.xz": "0de08e4670a7b5c3a4efd4b00ab6da6d2b3ceb37664d3adcc1050274b66f6a00", - "dist/2022-08-19/rust-std-beta-sparcv9-sun-solaris.tar.gz": "4b88e96c15cbcdc66f200fd216715c73ad26e0cdd5920105a15ba44cc02d9a50", - "dist/2022-08-19/rust-std-beta-sparcv9-sun-solaris.tar.xz": "819275f203ecff1bb37628dc0589b28a0667085f3e5115c3fcd26c4536b235aa", - "dist/2022-08-19/rust-std-beta-thumbv6m-none-eabi.tar.gz": "579d425d60bcb229cb61291caa8fcc99ea8a759b66c61b4f1c796d207ec08274", - "dist/2022-08-19/rust-std-beta-thumbv6m-none-eabi.tar.xz": "d2ebf00fda10f4f2e8476b5bcfce2be358f046f60a413b6e71aef4e76c6b55da", - "dist/2022-08-19/rust-std-beta-thumbv7em-none-eabi.tar.gz": "c898ca80eca184ed57125d8b463ca7bc60293bdedb6a3980a2c8da0d222f1869", - "dist/2022-08-19/rust-std-beta-thumbv7em-none-eabi.tar.xz": "01a73cb52d6fadb848eb672c567eedac339a6ebd432756c2a9e42c7273c4e9f4", - "dist/2022-08-19/rust-std-beta-thumbv7em-none-eabihf.tar.gz": "cdb64f9439964310c7a35edcb36596fb68b5925b7bd2c89a048dbbd5cbbdd434", - "dist/2022-08-19/rust-std-beta-thumbv7em-none-eabihf.tar.xz": "3f90031df2e3de1d423c327764cf7c83ff9b422414bceaeb8f4ca7786a17b6cd", - "dist/2022-08-19/rust-std-beta-thumbv7m-none-eabi.tar.gz": "626d6e503c6f72766d211faebb88cb8d8bba95775e8536eb181bd76e9a26434a", - "dist/2022-08-19/rust-std-beta-thumbv7m-none-eabi.tar.xz": "5bcd4b052b2699798c14bc2b50b40c9e538c24ed00bc7fc1f9c812816f47a965", - "dist/2022-08-19/rust-std-beta-thumbv7neon-linux-androideabi.tar.gz": "90196536e30d2ae5e59ab0bceac283a1934170484c98c4672a86f8a3198307e5", - "dist/2022-08-19/rust-std-beta-thumbv7neon-linux-androideabi.tar.xz": "8dbf82b8f8c9f5b054c5281bcb5429503d7e7f916aec7fbdd4e1422db6ccbee1", - "dist/2022-08-19/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.gz": "45010646984aa7d942288d74e60052a4da6a57312e56ec812ba34ee66ee32709", - "dist/2022-08-19/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.xz": "c2ced97a849a6600163ef798adcb8aa9f9b0800bc8554c02b635ce0c26b9dc16", - "dist/2022-08-19/rust-std-beta-thumbv8m.base-none-eabi.tar.gz": "3d4f2fc427971a1bfb7de12c876a03e553e8741887568fa8895996da84d96fd3", - "dist/2022-08-19/rust-std-beta-thumbv8m.base-none-eabi.tar.xz": "2f81f4c2168dae4a76f2705b88eead61dcdf805d6f3796c9f8fb4a0f8ace21c3", - "dist/2022-08-19/rust-std-beta-thumbv8m.main-none-eabi.tar.gz": "f045bb0963aeb3e4d4b08da616c4ef298f1916d7491ee624f334c21427e26e9e", - "dist/2022-08-19/rust-std-beta-thumbv8m.main-none-eabi.tar.xz": "b963e0af4532cba9611c9cfa62d816c45b9cac75e3d390772dcee1bbc0111408", - "dist/2022-08-19/rust-std-beta-thumbv8m.main-none-eabihf.tar.gz": "133a35f0ff672356dab8413aa7958fe70e1987eb95c7adfd2362e1f77fa1a17f", - "dist/2022-08-19/rust-std-beta-thumbv8m.main-none-eabihf.tar.xz": "70ef699fe52f695bedce35910eb85527d492c8f663ce926e111522d3c70c62d2", - "dist/2022-08-19/rust-std-beta-wasm32-unknown-emscripten.tar.gz": "386900d6fe52f807c20aa607cc76864406e096bc6282185bce4e1fe6c2e95350", - "dist/2022-08-19/rust-std-beta-wasm32-unknown-emscripten.tar.xz": "7c40bb5d55bd01c865de037695ed088671318b2a1a5d7c1aeeb9fccdfce666bd", - "dist/2022-08-19/rust-std-beta-wasm32-unknown-unknown.tar.gz": "41a606a2e9148e288baa8548312c993bd82f8b288d558472ba6cc84938a2f61a", - "dist/2022-08-19/rust-std-beta-wasm32-unknown-unknown.tar.xz": "bceb44ce91d28547ac123d17f10788268c27c9af8c8da463260dd7c574a30de7", - "dist/2022-08-19/rust-std-beta-wasm32-wasi.tar.gz": "1bd60b74b2e1555c669e273687b84db1da3818ef6c9b0dbe8168852c3e8810db", - "dist/2022-08-19/rust-std-beta-wasm32-wasi.tar.xz": "d98e83775d0340d27f2deb0cb17a05250bca53f00c2c1039ae34f412dc1249c7", - "dist/2022-08-19/rust-std-beta-x86_64-apple-darwin.tar.gz": "476760a9a396adbcf5312afc135f2eeb97c04da8654188726a63734ad8f88725", - "dist/2022-08-19/rust-std-beta-x86_64-apple-darwin.tar.xz": "caccc07d4fff2d394f5aefbea589ade137a3154eba0a2562f7a1a036928fc8c4", - "dist/2022-08-19/rust-std-beta-x86_64-apple-ios.tar.gz": "3fb5384aa267a2f4495483cf2857f7b33f7d1df0409539bc0735f78f5e8fa1a4", - "dist/2022-08-19/rust-std-beta-x86_64-apple-ios.tar.xz": "e2383658b0dfc4bbdcea69eb42a9c75686d578c0f15adce039f46aa0f25297f4", - "dist/2022-08-19/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.gz": "6cc9433de637d2156ede6bd9620ab7a6895894d8ec848563620df131e30e79c5", - "dist/2022-08-19/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.xz": "408d1d1ceccc78df145f804bdd848d4b595274ff2e5a32c76e979134aadba2f8", - "dist/2022-08-19/rust-std-beta-x86_64-fuchsia.tar.gz": "6ee5d79ba87acfa1f2093c1e9cfa26eb2851db48bec86d4f25654c40f9980900", - "dist/2022-08-19/rust-std-beta-x86_64-fuchsia.tar.xz": "eb3e2e365edc084594666862345d903165630034e4c6fe97e206be68920d1657", - "dist/2022-08-19/rust-std-beta-x86_64-linux-android.tar.gz": "1713831fd1675c317d7d6059a27181591b51d094b6c39978e1d52cc92fff4ba9", - "dist/2022-08-19/rust-std-beta-x86_64-linux-android.tar.xz": "864c4f5edf3602ae629fe77f6d08d8ed49d354ce88bc5ea034858b77aebb2c1d", - "dist/2022-08-19/rust-std-beta-x86_64-pc-solaris.tar.gz": "683bc54f134507fef80665397c3e2aff1b854d08cc8130b8cef2aa6e5b573561", - "dist/2022-08-19/rust-std-beta-x86_64-pc-solaris.tar.xz": "86f037d022446e277dc92c007ed531da9e0ec5013b7c757f0810f1abaa7376be", - "dist/2022-08-19/rust-std-beta-x86_64-pc-windows-gnu.tar.gz": "312db623e7d4711eb965d4826c19986019194fdd8528086aed6a08d3f6457b5c", - "dist/2022-08-19/rust-std-beta-x86_64-pc-windows-gnu.tar.xz": "1581eaf570f86f49189b4f8f51cf84e535a2bc3cb41fbd8043719d0dcf5185eb", - "dist/2022-08-19/rust-std-beta-x86_64-pc-windows-msvc.tar.gz": "0cd8dc6a60623bc64410cac94e89abbddcc7b3cba1b89f8fb2fa56ccea4493c1", - "dist/2022-08-19/rust-std-beta-x86_64-pc-windows-msvc.tar.xz": "1831ca7a6ed59064a201cae8f2fe919e74c05e825ff67c671d57393506e95edc", - "dist/2022-08-19/rust-std-beta-x86_64-sun-solaris.tar.gz": "9845a9ac85f716ab46d186696fc44993e701de7d89c2c5aad188d7b0fe1761a1", - "dist/2022-08-19/rust-std-beta-x86_64-sun-solaris.tar.xz": "16fa497ccd7fd94a6f7ab03ba975d00c63b60f1786fe2da1a7eedca3da62642c", - "dist/2022-08-19/rust-std-beta-x86_64-unknown-freebsd.tar.gz": "3c3e24897193e3feb947a387d09059d2ee495b642dd5a160cfd1ae61eb1ae155", - "dist/2022-08-19/rust-std-beta-x86_64-unknown-freebsd.tar.xz": "2ffd051693a8e831ede8e93285da11b0fef127473d95fcdcc40b4e6ef811ae5b", - "dist/2022-08-19/rust-std-beta-x86_64-unknown-illumos.tar.gz": "4d32d311dc0c3350c329d2aff147529db13e537f8405ae0bf317b8a85e9242a4", - "dist/2022-08-19/rust-std-beta-x86_64-unknown-illumos.tar.xz": "fb9d10ef315f2555a0374903d66695078d5f483167c4df2c680d48af4312d109", - "dist/2022-08-19/rust-std-beta-x86_64-unknown-linux-gnu.tar.gz": "67fa67de6bb7d34ca870a52346dc410084702705b1f9f9adf92d9b71afe11d1b", - "dist/2022-08-19/rust-std-beta-x86_64-unknown-linux-gnu.tar.xz": "b8df9d518bf30a87633745430f41172d10fd833ee94d6331a73de3649866b62d", - "dist/2022-08-19/rust-std-beta-x86_64-unknown-linux-gnux32.tar.gz": "42f03a9aeff106f40f3d2ada7a02b1e91135adfc98be1acda0f9ebd63b388097", - "dist/2022-08-19/rust-std-beta-x86_64-unknown-linux-gnux32.tar.xz": "da4f0915a71736b3d3c2479440f8a9728250eb50234b39aedbc17d9d1b390651", - "dist/2022-08-19/rust-std-beta-x86_64-unknown-linux-musl.tar.gz": "06d00f30c2332d68a924b50e42e813f2f8479d568b74c5edf51b7fbdf57b66d5", - "dist/2022-08-19/rust-std-beta-x86_64-unknown-linux-musl.tar.xz": "1e3b5a879ddd2e4fdc31c3853783cbe8a5a4183250b909198553a4d95f1a7cd5", - "dist/2022-08-19/rust-std-beta-x86_64-unknown-netbsd.tar.gz": "cc4e9cb8e856ee173eb028746487604f0436347223f163294aa1ad34c0d740a3", - "dist/2022-08-19/rust-std-beta-x86_64-unknown-netbsd.tar.xz": "02a2ef7754af534e1fe6be3a04ef4446dc6abb6e6c57326ca460a5ba6c96f9d2", - "dist/2022-08-19/rust-std-beta-x86_64-unknown-none.tar.gz": "62d55c2a36afbf210d0b9947ef2f05104e7da71bb7958509119b0336874f0f92", - "dist/2022-08-19/rust-std-beta-x86_64-unknown-none.tar.xz": "86270ba78b8d74d0f3ac6c2f9a38906d25ec888a8ab604b0c593e99ba5128eed", - "dist/2022-08-19/rust-std-beta-x86_64-unknown-redox.tar.gz": "194a933992ab2596af7966e1b10900b1a4627bfef99b0ff1fc87bdf0a4e2ca17", - "dist/2022-08-19/rust-std-beta-x86_64-unknown-redox.tar.xz": "1a2137c628946d1cb1a84e24abe3a44758425a7470ed4a48555f9c6dca8e7013", - "dist/2022-08-19/rustc-beta-aarch64-apple-darwin.tar.gz": "b4a4752c96d439c2977a148a40b63864041f903e5733419faacd96c5839bc8e5", - "dist/2022-08-19/rustc-beta-aarch64-apple-darwin.tar.xz": "f3f83489cd6890aed11a75f4b60d3edf2b32dfac023c93faa8cf1604a9e8fad3", - "dist/2022-08-19/rustc-beta-aarch64-pc-windows-msvc.tar.gz": "5d012c23083429116ffb171923343169380559f3ee90fbaee0989f77da878487", - "dist/2022-08-19/rustc-beta-aarch64-pc-windows-msvc.tar.xz": "15f3534ff3b881709eebaf55e55359d700686429bf55eb4b1c7292ad1a13ff54", - "dist/2022-08-19/rustc-beta-aarch64-unknown-linux-gnu.tar.gz": "d3aa46b9f2f052b080222a13e598ffa96227ec271c9db2efd2ddbeb0b1fef2ed", - "dist/2022-08-19/rustc-beta-aarch64-unknown-linux-gnu.tar.xz": "932d89e503d2b4fad90241c014c4b4f892ab8054d9555590819422abb51a999e", - "dist/2022-08-19/rustc-beta-aarch64-unknown-linux-musl.tar.gz": "5c006e8324bc8a5b9039da7b61d1147575d0383a18deca3b75d01ebe684c7850", - "dist/2022-08-19/rustc-beta-aarch64-unknown-linux-musl.tar.xz": "0d03091ccefff702877e2c38d131932125f0b2d25c8a94e260601c277a3e494f", - "dist/2022-08-19/rustc-beta-arm-unknown-linux-gnueabi.tar.gz": "373650c44db5568d8d2889b6002d3b5948acd0079773f257d9dc0e380de8c026", - "dist/2022-08-19/rustc-beta-arm-unknown-linux-gnueabi.tar.xz": "0cbd356980688e816baf4c88b7c8963e4c4b009cdf3e9bac057a3fedccf0c552", - "dist/2022-08-19/rustc-beta-arm-unknown-linux-gnueabihf.tar.gz": "de83386be1885fad366b0b3379f41a8c9e30ca6cfcc5752a0bd917ec635954ba", - "dist/2022-08-19/rustc-beta-arm-unknown-linux-gnueabihf.tar.xz": "a605234a11f44a65b80554bbfd10b6fe83c20a2a62102aaa46f0febc5ad846b9", - "dist/2022-08-19/rustc-beta-armv7-unknown-linux-gnueabihf.tar.gz": "22c323b69a4786bee149402c7c64d85795540e2143e0da1e48739b2dbb1a869a", - "dist/2022-08-19/rustc-beta-armv7-unknown-linux-gnueabihf.tar.xz": "f9daad394d53aa405f783d9013916610b014d930a355fdb88757b47469619cf3", - "dist/2022-08-19/rustc-beta-i686-pc-windows-gnu.tar.gz": "275d21aafcc272b18bdefdd6adf28116a493beb053eb214b6ab842ccd31e9cbb", - "dist/2022-08-19/rustc-beta-i686-pc-windows-gnu.tar.xz": "5a032ea14e3845de2f39305a4fb5b9a4415939f6bd0ff79a0e527c4ebd9af669", - "dist/2022-08-19/rustc-beta-i686-pc-windows-msvc.tar.gz": "d892ad811e831b6f1cedf8d352dc71f9f86a26089fe4fce4d22b4f77482094eb", - "dist/2022-08-19/rustc-beta-i686-pc-windows-msvc.tar.xz": "ca16e42ea493c869b53031ea80b52c66c5771fc25531fb13529931d0740ec92a", - "dist/2022-08-19/rustc-beta-i686-unknown-linux-gnu.tar.gz": "d3aa43cb3bef265d6d2fdb17c6962e906ff021c4ca0d638eba6a98f09324d942", - "dist/2022-08-19/rustc-beta-i686-unknown-linux-gnu.tar.xz": "9dbd9e4a20535c8e19d9cee1218f2b3e0d3289d118b840b27e12aab3e48c80d8", - "dist/2022-08-19/rustc-beta-mips-unknown-linux-gnu.tar.gz": "5c17afb542d3661dc31cd3d334de66706de956f45959404494f90cf73e6f6d21", - "dist/2022-08-19/rustc-beta-mips-unknown-linux-gnu.tar.xz": "68fc729c47c290c09a14fe450ab0b82eba568a4e687554e0f87d095fe64d056f", - "dist/2022-08-19/rustc-beta-mips64-unknown-linux-gnuabi64.tar.gz": "64e77868b050b0d237eae46f33a723daa2cac8c8736e3787664315e13d879629", - "dist/2022-08-19/rustc-beta-mips64-unknown-linux-gnuabi64.tar.xz": "c3c339f17752f334dacf18c75837578d8bcd1020a59a8a21ad0b3cca0e58e49b", - "dist/2022-08-19/rustc-beta-mips64el-unknown-linux-gnuabi64.tar.gz": "45e586abdfb8a46f126b2327e64e115f8acfa861d183a276ef3688c148e99d46", - "dist/2022-08-19/rustc-beta-mips64el-unknown-linux-gnuabi64.tar.xz": "7be6e24c013bc03ae28d494d78e767488c38f7487557d5debd5a42eceaa49e34", - "dist/2022-08-19/rustc-beta-mipsel-unknown-linux-gnu.tar.gz": "a3af91bc8d8179bd06d51615ee2ccbda0c838f99c2b30fb91c52c76304ce46e0", - "dist/2022-08-19/rustc-beta-mipsel-unknown-linux-gnu.tar.xz": "948b7598e5c7648b02c39757e50ad9550f78fda4943b578b4d19831c2496e86c", - "dist/2022-08-19/rustc-beta-powerpc-unknown-linux-gnu.tar.gz": "1f01de1fb0274b98424867fba7eef93e00485624a5fb6e21657d6591607d9f50", - "dist/2022-08-19/rustc-beta-powerpc-unknown-linux-gnu.tar.xz": "879bf1abc548a1dee7fc6c26c0b0881fab064be58a1540b67730b8d3643f8ddd", - "dist/2022-08-19/rustc-beta-powerpc64-unknown-linux-gnu.tar.gz": "3303c7dcbdd1a38a8e32e4b96071be4afd191bb6403d6fbf17fbc65087b1f15b", - "dist/2022-08-19/rustc-beta-powerpc64-unknown-linux-gnu.tar.xz": "cf8693715e3d58e016c2dbe0bf77a3933765ea5fe0a65091cc427b694a490d60", - "dist/2022-08-19/rustc-beta-powerpc64le-unknown-linux-gnu.tar.gz": "4ad0221a3df7e223d3bdf271f28f0a694aef8184cd377cae530fbca5c12d82d6", - "dist/2022-08-19/rustc-beta-powerpc64le-unknown-linux-gnu.tar.xz": "ad1390820e4fcc426a27d18f97fc8f952c9e949327d8d6b60e6853e4dc9e2c04", - "dist/2022-08-19/rustc-beta-riscv64gc-unknown-linux-gnu.tar.gz": "c9232ad8c52060c40ef35eae32e79585d550e2abc011d2b6562edb1b02244966", - "dist/2022-08-19/rustc-beta-riscv64gc-unknown-linux-gnu.tar.xz": "3e937985bbf7ef5af05e96e82114fec6ee17bc04f784c3e7472224dae1ebb148", - "dist/2022-08-19/rustc-beta-s390x-unknown-linux-gnu.tar.gz": "f4dfa226259ce0d9f8fb9295f82a18a130470f11479811717ddb0f5064a9eb81", - "dist/2022-08-19/rustc-beta-s390x-unknown-linux-gnu.tar.xz": "919dd5fbfc80c77f270e1eefee8dbe1c76ed7cc94cc11dff34f54ee05fd415de", - "dist/2022-08-19/rustc-beta-x86_64-apple-darwin.tar.gz": "482c51eef00cc238872b5002f12c351259a666e8b1380b08f5536fb87b046f4a", - "dist/2022-08-19/rustc-beta-x86_64-apple-darwin.tar.xz": "3b78a63fb9d27e7960ea35d8bef3734789bd48d80ed1605ddb9f547859977260", - "dist/2022-08-19/rustc-beta-x86_64-pc-windows-gnu.tar.gz": "4c7ec47ced7a7cbd9e6b038ac0f57d0e705801f42375011eac42a708808d75c5", - "dist/2022-08-19/rustc-beta-x86_64-pc-windows-gnu.tar.xz": "6935fbe4de2b5712fe15c865ef2eb4c41959267b03afe4f276f8fcc6eee992bd", - "dist/2022-08-19/rustc-beta-x86_64-pc-windows-msvc.tar.gz": "30b78a0ac0852bbb3aecea5d4f61f4e1737b5d4910e07a59c64e7cdfeb3da215", - "dist/2022-08-19/rustc-beta-x86_64-pc-windows-msvc.tar.xz": "73d15af622a7accb4a04bd596acc95cd0856545fe6a386df18905cd221107fee", - "dist/2022-08-19/rustc-beta-x86_64-unknown-freebsd.tar.gz": "dc00c8c6f6121ac1ba112120b82215ce811a4c518025cdc4d1202c53db88f65e", - "dist/2022-08-19/rustc-beta-x86_64-unknown-freebsd.tar.xz": "e827aa07bff90fb978b1055826d9e672e1e40056caab3d8a182afa3c371f0f4f", - "dist/2022-08-19/rustc-beta-x86_64-unknown-illumos.tar.gz": "05f6a99d63847d910e05a93d78944014c775c5b6e8b8bd742f2c74c39f7cd883", - "dist/2022-08-19/rustc-beta-x86_64-unknown-illumos.tar.xz": "86cde423efde88155ce35514399897fcb2248ddac9f77244827ba4e10189038a", - "dist/2022-08-19/rustc-beta-x86_64-unknown-linux-gnu.tar.gz": "e2dea522d946db96791f651fdbb098bcf7285bdb0182e14c573f87826f6d99b2", - "dist/2022-08-19/rustc-beta-x86_64-unknown-linux-gnu.tar.xz": "399847ea81239d666acdd890b4407bf2f62f3a527a60515fa38fdfd3ff61d0d0", - "dist/2022-08-19/rustc-beta-x86_64-unknown-linux-musl.tar.gz": "9e1511eb0704962ad3932578821bcfca877826cb18f14e4b7defbc08aaa9f0d8", - "dist/2022-08-19/rustc-beta-x86_64-unknown-linux-musl.tar.xz": "1e0eb9eb917a1db99764b374844ab3ed2cbc83495c50b28f3dcf9512edcb035f", - "dist/2022-08-19/rustc-beta-x86_64-unknown-netbsd.tar.gz": "28651213923b8009c6317b59a2a15f6f202108efa0b604a590b735b0cd031202", - "dist/2022-08-19/rustc-beta-x86_64-unknown-netbsd.tar.xz": "36591aefa17e1a4cb55625632bc97931db6f3c4252d457963353bbfa5e997a32", - "dist/2022-08-20/rustfmt-nightly-aarch64-apple-darwin.tar.gz": "3f90dbf1c64d8b4cddd1fcb589b85e4b76fae6c3fed88483210bf5bddecd2bf6", - "dist/2022-08-20/rustfmt-nightly-aarch64-apple-darwin.tar.xz": "1f850ef1e1a6ee89cbb862ec986cc3b5de2b4654db625a5da0906f3eff3e834c", - "dist/2022-08-20/rustfmt-nightly-aarch64-pc-windows-msvc.tar.gz": "3b1a7f2e5d380b58bd02fd1f28212869f9feeb2fbb971694425cb837f99f8f0f", - "dist/2022-08-20/rustfmt-nightly-aarch64-pc-windows-msvc.tar.xz": "f24153076383ad22da9cefd9073c1e6dc227c582ef7fb92c73cdfbd4cef6c295", - "dist/2022-08-20/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.gz": "e409988fc3bd50f2120d3f5828e8f5a5494fa0bc5296a97f1c26294fb2e1ade7", - "dist/2022-08-20/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.xz": "854e275ecd011e12606203f4b9737c373a678821b7f11df6bc08b774d670ada7", - "dist/2022-08-20/rustfmt-nightly-aarch64-unknown-linux-musl.tar.gz": "31bb41173b63d3aaae977b0ab48b0302d1ba2b7f6470fbd7b0206557e2dca2f3", - "dist/2022-08-20/rustfmt-nightly-aarch64-unknown-linux-musl.tar.xz": "7f4e356dca11bfc4bcfc9ffa588640cd9321cd73bc70c16d55901f04a119ca2d", - "dist/2022-08-20/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.gz": "1a8a63027aeaca5c9981567c862222b9c2d0de0456c4534213f5686862507890", - "dist/2022-08-20/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.xz": "2d217c695886cd59bf7bf40091813d427eb302323650d3641439f050308b2660", - "dist/2022-08-20/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.gz": "bc257cce6466ef7bfd30eb9790db3e72cc425ce78f763954861b28232dfe1d55", - "dist/2022-08-20/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.xz": "3326acc5adcf63dde12937d1ad9be4eb8c01ed3f24b07e1df28d194754506a77", - "dist/2022-08-20/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.gz": "14dc0a6e21cd6e7294995bf7c14238c97cccaf37910765602ca37292267060b0", - "dist/2022-08-20/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.xz": "93628b8ea58d6484423ff58666520701702f36eab86846a19b205a9c8d737313", - "dist/2022-08-20/rustfmt-nightly-i686-pc-windows-gnu.tar.gz": "199dfdf436b9ae97aa7a4a081d6a88b29e825e0e3e24409a008531dc3ea3ae5b", - "dist/2022-08-20/rustfmt-nightly-i686-pc-windows-gnu.tar.xz": "cbce925e5bc323d970d7df1c714b31b693208eae0a00eb43a616da3ba499cca2", - "dist/2022-08-20/rustfmt-nightly-i686-pc-windows-msvc.tar.gz": "0c899e9273fb04c73c3abbd9483e74cf0312aa61d0818acbd2737a515432cb1c", - "dist/2022-08-20/rustfmt-nightly-i686-pc-windows-msvc.tar.xz": "bc3d2e850d77f13b563ce3b286fd781f49abc6ac17f046aea7397655c3955194", - "dist/2022-08-20/rustfmt-nightly-i686-unknown-linux-gnu.tar.gz": "8940d2f6219a956521ef3c3c43001843cc5bd65706853e7b506848bf11c785d1", - "dist/2022-08-20/rustfmt-nightly-i686-unknown-linux-gnu.tar.xz": "bee2d0136087693ed3328b8264f4c652f843a18128bfbf3d679b6ce426b44d07", - "dist/2022-08-20/rustfmt-nightly-mips-unknown-linux-gnu.tar.gz": "37f383823d76b2f88fe7c7950b96aad73b94ffe5bf74f7af05d0bbe18c492f66", - "dist/2022-08-20/rustfmt-nightly-mips-unknown-linux-gnu.tar.xz": "832d60d4dad18f729638c5cea3b5a3a8577b1875977b8bf2110537a4b17a71e2", - "dist/2022-08-20/rustfmt-nightly-mips64-unknown-linux-gnuabi64.tar.gz": "e060d1a8925f9b7f670244718fc0d84519a590cc630e832b27a0bd8149c009af", - "dist/2022-08-20/rustfmt-nightly-mips64-unknown-linux-gnuabi64.tar.xz": "3743c798e26306d3f55afcf989221ade32e5174132e939bd4d3f0a2f1fd7523e", - "dist/2022-08-20/rustfmt-nightly-mips64el-unknown-linux-gnuabi64.tar.gz": "723509d619bb3f2c5423267afdbe082b426678d5d1df850b7e0d51cbcad99491", - "dist/2022-08-20/rustfmt-nightly-mips64el-unknown-linux-gnuabi64.tar.xz": "da258b293fa651db38348eee14239171010b230e390074a65f5975bfd9a990f2", - "dist/2022-08-20/rustfmt-nightly-mipsel-unknown-linux-gnu.tar.gz": "6ad271d28309c92a76bdef40052c624b8d9e62e389ab14c8df372a6d0cfb8883", - "dist/2022-08-20/rustfmt-nightly-mipsel-unknown-linux-gnu.tar.xz": "b3e71cedf9df9ce72bdd9b559197fd3989e4d108cd71ff30806b75541c072c34", - "dist/2022-08-20/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.gz": "82e7f9cd8409e9eeb89166c8ff047910e24a45d65712cc4bef883bb5ccbeb51d", - "dist/2022-08-20/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.xz": "9e0da808f7a3c03b10b309b2a1d934e447bef877adbe78b8d5f9485b2464bb32", - "dist/2022-08-20/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.gz": "31841de97f5f7fef456205ab14b7cb568b7edd202f31fc8a4465105ab59ed413", - "dist/2022-08-20/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.xz": "bc55f15780a850f2fa19fa26d39edce194745235d6f209d21b86a2ab7924c4dd", - "dist/2022-08-20/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.gz": "bdb86ba6b1dfe3359823aa2be3ff1b945d7a34c21383fb2b2ec6f06122ef5587", - "dist/2022-08-20/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.xz": "1df7664bd1f32e1a9b5d37a4eaaaac54ca7b71853edfed4b0ece2e256f17290b", - "dist/2022-08-20/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.gz": "67727084e37de55a4cfa4ad2c1f3a834ef49379f949b50440aeb53d65c6dfc36", - "dist/2022-08-20/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.xz": "820fdce7d561b7e0118b25093cf639eab304ed29852921286f0cbda62e3e8752", - "dist/2022-08-20/rustfmt-nightly-s390x-unknown-linux-gnu.tar.gz": "8cf01738cb6e7450753000737c6b33acf7d433d32b28f6b278d6efb9513c4464", - "dist/2022-08-20/rustfmt-nightly-s390x-unknown-linux-gnu.tar.xz": "3bb194f2d770934580d063b7f0939cea231dbd280a4df062f0309c3dcbcd1d32", - "dist/2022-08-20/rustfmt-nightly-x86_64-apple-darwin.tar.gz": "95a42b3a88d411d7c2567f8532bf86d3bd8ee57ff2a5254c147f08502f5488a9", - "dist/2022-08-20/rustfmt-nightly-x86_64-apple-darwin.tar.xz": "ed885440a7a03d81dfc6ba206c37afdcd4480368a11143805ca12d8df583172d", - "dist/2022-08-20/rustfmt-nightly-x86_64-pc-windows-gnu.tar.gz": "2d6aa369242b820621cddc095f833eb5bf9dda9127dbcea179d730b2e1fc0d09", - "dist/2022-08-20/rustfmt-nightly-x86_64-pc-windows-gnu.tar.xz": "49291adffb00f8f25e9dadfb8e8f530d6a151479e8024de4b0b42c52c7a21f7e", - "dist/2022-08-20/rustfmt-nightly-x86_64-pc-windows-msvc.tar.gz": "a61ebb7b049b8a8c8440acc7e8698896a3143c0e1f8b1c29084f680e12087d9b", - "dist/2022-08-20/rustfmt-nightly-x86_64-pc-windows-msvc.tar.xz": "8bde3268496729d1f5178863859fdad77fa94f85887b0c129e0517226e3bdfb4", - "dist/2022-08-20/rustfmt-nightly-x86_64-unknown-freebsd.tar.gz": "08f4bcd90bc01fea5e0c6238d40fb59bd1160e6635b401f908c046e6446d2183", - "dist/2022-08-20/rustfmt-nightly-x86_64-unknown-freebsd.tar.xz": "a13ad331d827666d8631b4b30a51b1b69de0a90e9cfecc1e8bfb559d52144353", - "dist/2022-08-20/rustfmt-nightly-x86_64-unknown-illumos.tar.gz": "2c7c0607392a0d2cf517cc4fcb726f443c85c26b7deca0f10cbc555de56d20d3", - "dist/2022-08-20/rustfmt-nightly-x86_64-unknown-illumos.tar.xz": "bbd31f2bd64b4cc2e11c0936787bb44d792d20ec303e3b55efd53e0bd8efe88c", - "dist/2022-08-20/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.gz": "27703699164e10526a32a6920eb8d0b71e3572d423defecd81cd6b24c2c5134a", - "dist/2022-08-20/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.xz": "e4d388af9bdfee7bb6470a4467e7743a9b7827cd9d4219174fd424c18204a6b6", - "dist/2022-08-20/rustfmt-nightly-x86_64-unknown-linux-musl.tar.gz": "e090c6410f3ded22065097b5839a80d1ca6c80a7657ca28b88244fe119977371", - "dist/2022-08-20/rustfmt-nightly-x86_64-unknown-linux-musl.tar.xz": "a00a785d87e64660165b56489f6709c0d0280ae728782356a3274e8c0be48c36", - "dist/2022-08-20/rustfmt-nightly-x86_64-unknown-netbsd.tar.gz": "ab9736c80331f0febe42a0e1f29d758327c4c8035954111370ff2c568c784fe4", - "dist/2022-08-20/rustfmt-nightly-x86_64-unknown-netbsd.tar.xz": "ca8127aeae4e84a208ce9a5cdd04c497894e62c226c8bccd00713c1a41f99ddd" + "dist/2022-09-20/cargo-beta-aarch64-apple-darwin.tar.gz": "3186f69cc7efaf3f933ad77798ddf58bf11c0719dc1dec53fadc502a236ef753", + "dist/2022-09-20/cargo-beta-aarch64-apple-darwin.tar.xz": "5ad195346a21a80c700ca08223060ea66298fe8e4cbac19148d14b92a9319b01", + "dist/2022-09-20/cargo-beta-aarch64-pc-windows-msvc.tar.gz": "6a7647d761ce3adba9d4ceff2e6c1929e9d96d767961a7a062f41ec09a1abb85", + "dist/2022-09-20/cargo-beta-aarch64-pc-windows-msvc.tar.xz": "13566a68dd2000fb33a990c21b62b82e77d1bd1f3384152f439cf96318f07f3e", + "dist/2022-09-20/cargo-beta-aarch64-unknown-linux-gnu.tar.gz": "cc698fe69e27a077c6d2aa8dc7319847b1ecd78ad4e3519161957c7cab90c592", + "dist/2022-09-20/cargo-beta-aarch64-unknown-linux-gnu.tar.xz": "1cd369b8ab90e85da78784cf08a92aee87f0804b448676637ee48cb3409dc026", + "dist/2022-09-20/cargo-beta-aarch64-unknown-linux-musl.tar.gz": "856170acebfd7900448fe02bd835d633b2930e2401c4211d72e5dd8c38943606", + "dist/2022-09-20/cargo-beta-aarch64-unknown-linux-musl.tar.xz": "5bbc32a426071c84d39395c64e1f9cfe0db29ab10c255c2a8a8f748b624cdb7a", + "dist/2022-09-20/cargo-beta-arm-unknown-linux-gnueabi.tar.gz": "50518c889d2408a7edf524c0340c8ff6881fd14f505dca0d419deefdb94c3afb", + "dist/2022-09-20/cargo-beta-arm-unknown-linux-gnueabi.tar.xz": "8143057e446c169e614c153ffbe2428e94404af96d06b1d3103028f695388211", + "dist/2022-09-20/cargo-beta-arm-unknown-linux-gnueabihf.tar.gz": "987064edfdb30dde07ef9b2cbd072f66ca042bf95ae724909cafbc13bcf69885", + "dist/2022-09-20/cargo-beta-arm-unknown-linux-gnueabihf.tar.xz": "253161f50a399818a77360f97443ef818dfca3d384e86048655b08c8a799bafc", + "dist/2022-09-20/cargo-beta-armv7-unknown-linux-gnueabihf.tar.gz": "7b9a0feee8f3e1e3c58df38f947904d76006c938a2395650e094337ede9918e9", + "dist/2022-09-20/cargo-beta-armv7-unknown-linux-gnueabihf.tar.xz": "2194b642b8ed595b8534ded204a72f910215c8f42482ac64644f784a3b2ae8b3", + "dist/2022-09-20/cargo-beta-i686-pc-windows-gnu.tar.gz": "7cc2c490988dd1ae095198664317cb0b5c8071fc31bf49aed1eca21eb2766cd8", + "dist/2022-09-20/cargo-beta-i686-pc-windows-gnu.tar.xz": "32641252e12cdadf0a232b43103fc56af621a48056864ff2ee9a034dd2da8f1f", + "dist/2022-09-20/cargo-beta-i686-pc-windows-msvc.tar.gz": "32581e6bf22e7d2c7a147a87158161e3fa07f46ec0252e632a3bafb824382a28", + "dist/2022-09-20/cargo-beta-i686-pc-windows-msvc.tar.xz": "a9a68905a4540389d28e40cc2137cf2fcca77c425089cd99072a34ba15e3ab6a", + "dist/2022-09-20/cargo-beta-i686-unknown-linux-gnu.tar.gz": "b5d9ecd7be4ab25919cd0731bb28a2612965943c5ccedf35ac09c169ed2c97db", + "dist/2022-09-20/cargo-beta-i686-unknown-linux-gnu.tar.xz": "387f7d95d04503293f708f65821f55878449eb5a0efe3344005dca18b84e6563", + "dist/2022-09-20/cargo-beta-mips-unknown-linux-gnu.tar.gz": "f8fbf21aac677276cdf246748d59d183e566bfcacabcd3eab6f19d6c857193ef", + "dist/2022-09-20/cargo-beta-mips-unknown-linux-gnu.tar.xz": "70e561d77632d1463839a8ea9cb72ff49afb61dbba95fa321bdba74be384b21f", + "dist/2022-09-20/cargo-beta-mips64-unknown-linux-gnuabi64.tar.gz": "e81b5a5fc70a1f7ed5920a3860b1259a2cecd9a1d981f2a564cd936de53ecf8a", + "dist/2022-09-20/cargo-beta-mips64-unknown-linux-gnuabi64.tar.xz": "ef9de44d1d37812bfeb67b353f1e308bf46d62c9fe191980de3a62fbfe5167a4", + "dist/2022-09-20/cargo-beta-mips64el-unknown-linux-gnuabi64.tar.gz": "68c1cd309775626f19431f7dbb73789b17ee629b588e05bf0231313913cb6a8a", + "dist/2022-09-20/cargo-beta-mips64el-unknown-linux-gnuabi64.tar.xz": "db290a98987c8bd527f1efe9ff09055fdce8eea0673d2c5eba0640649396b8d0", + "dist/2022-09-20/cargo-beta-mipsel-unknown-linux-gnu.tar.gz": "f4a7da60f164c03bd274f8c98b58a524d7a73476c726e2ef5695f2be950421c7", + "dist/2022-09-20/cargo-beta-mipsel-unknown-linux-gnu.tar.xz": "8fc46e05ba0830eec88e1d764b02fb9a4836883fd180800a8edd3a4cf0acbdae", + "dist/2022-09-20/cargo-beta-powerpc-unknown-linux-gnu.tar.gz": "5f528af9436bfa31d559544220fcb59001a90bff18363390f7fab82f259defde", + "dist/2022-09-20/cargo-beta-powerpc-unknown-linux-gnu.tar.xz": "502d6da5158075cd997833314f9ca7a527aecc8e28c9e26ee9796c2e9ac91cf5", + "dist/2022-09-20/cargo-beta-powerpc64-unknown-linux-gnu.tar.gz": "16a7b922fa6c6019541e859386dbd38e64507d951376c847f83c6b983c72b417", + "dist/2022-09-20/cargo-beta-powerpc64-unknown-linux-gnu.tar.xz": "7f3e361f9bfcdb5fd765f86ed372e00df62af4ae5714d9a2b3324f3929518677", + "dist/2022-09-20/cargo-beta-powerpc64le-unknown-linux-gnu.tar.gz": "f38265c64d6ac34d4632f38368d910bd9471aaf8736595623126cb53e810e307", + "dist/2022-09-20/cargo-beta-powerpc64le-unknown-linux-gnu.tar.xz": "99e7f3795aea0abb019b80b1f35aa8e1638fee35e548424ca52fd23c5bf82c71", + "dist/2022-09-20/cargo-beta-riscv64gc-unknown-linux-gnu.tar.gz": "bb9e89b65fca9a1fad5293e8a52b27331f08e9660237c0b1e7f750064d45ab1d", + "dist/2022-09-20/cargo-beta-riscv64gc-unknown-linux-gnu.tar.xz": "ea81188084da2f2771a1d9414c20065a19544b1af0e56dc71eae7ca00ff72708", + "dist/2022-09-20/cargo-beta-s390x-unknown-linux-gnu.tar.gz": "745577c8c52065d84cedd32608ca0e17f1a46bb86b4d619cd01785486dc99480", + "dist/2022-09-20/cargo-beta-s390x-unknown-linux-gnu.tar.xz": "85944275d5d05943c89ebf8e487bee35ed8586aa9f1903f83490c12ba74ad8cf", + "dist/2022-09-20/cargo-beta-x86_64-apple-darwin.tar.gz": "6c3f841c718404d4917353c7fefee7491df62d7456633bfb99dc850a49aab285", + "dist/2022-09-20/cargo-beta-x86_64-apple-darwin.tar.xz": "0c5a5c3ceec9fcf3b8dbb9fd10172251622e873671049b042b55ede34b8797a8", + "dist/2022-09-20/cargo-beta-x86_64-pc-windows-gnu.tar.gz": "385a01c7a11a5f51253e8182d82763295037d625e7bcf27d54b5f0349cea488c", + "dist/2022-09-20/cargo-beta-x86_64-pc-windows-gnu.tar.xz": "fe498e30198a43586be82c6fbd794093299eddba51fd668d81aed88bef0471ae", + "dist/2022-09-20/cargo-beta-x86_64-pc-windows-msvc.tar.gz": "3ee6926fd5f491eecf574aba631d09d97a9332b936eb7bb0ab348ac3fa02db02", + "dist/2022-09-20/cargo-beta-x86_64-pc-windows-msvc.tar.xz": "d15a8c24d04b308b91d9114b583087e2a13e75920a1837a78fe330cf6892ce4e", + "dist/2022-09-20/cargo-beta-x86_64-unknown-freebsd.tar.gz": "89368ca5eae65a569ae98e66834e93b240ef43a007e02e768ae9bbd5de4a4cf6", + "dist/2022-09-20/cargo-beta-x86_64-unknown-freebsd.tar.xz": "20b46e126c900892d576e972e39409c9009bafa4b3c159e624179d77afa912a9", + "dist/2022-09-20/cargo-beta-x86_64-unknown-illumos.tar.gz": "1712fd404274c993b95aa44dea6b9ff3b0f9857d8d1646e0cbf454d3386f5e32", + "dist/2022-09-20/cargo-beta-x86_64-unknown-illumos.tar.xz": "bd3f848d22bfa19060d459167b6154cc79070e0066f8da79587390fb92404288", + "dist/2022-09-20/cargo-beta-x86_64-unknown-linux-gnu.tar.gz": "0e5869b406dbaab0ef123459a93d4d6a34e85e9bd72d8a206bef69aac9e84d5c", + "dist/2022-09-20/cargo-beta-x86_64-unknown-linux-gnu.tar.xz": "5b0b255fb82d0e751187c6cc6b64298ca014ef86782984ef9e57a0b2ab373f24", + "dist/2022-09-20/cargo-beta-x86_64-unknown-linux-musl.tar.gz": "09dcaeb783d7c57aa8c708295cf46bdcb3873a20ca30794b3c1a8797b2cc9476", + "dist/2022-09-20/cargo-beta-x86_64-unknown-linux-musl.tar.xz": "918ca6c81e9e19f9d84d80e508af0050f2ec2ce2d0d0aa40cd3afd524d69917b", + "dist/2022-09-20/cargo-beta-x86_64-unknown-netbsd.tar.gz": "e66e3ecf93bad48573cf34ed44d508908370a8cc0c2764001cddbef022fb6e73", + "dist/2022-09-20/cargo-beta-x86_64-unknown-netbsd.tar.xz": "03514df0f9f2193824e227c19b84f282d7cb90145206bcfa21cf4f8223047462", + "dist/2022-09-20/rust-std-beta-aarch64-apple-darwin.tar.gz": "7a6a03adcf6481d90d39e929f99a50ed170e98fe61c3fae5264c3aa4d99530ca", + "dist/2022-09-20/rust-std-beta-aarch64-apple-darwin.tar.xz": "ccc8d4fb07a0a9c57b60d05bcf6d076a8b3cdb397930182ebfe99a2e5cd629da", + "dist/2022-09-20/rust-std-beta-aarch64-apple-ios-sim.tar.gz": "3e70853d9fbc3dab4a39303b2281ad63d36a9ae2fd8d6bb7d96f184644e20531", + "dist/2022-09-20/rust-std-beta-aarch64-apple-ios-sim.tar.xz": "59bb5bb6cd8d7269bfd29a952cd26280f5091fb24af4e7bf10cd59b80323d85a", + "dist/2022-09-20/rust-std-beta-aarch64-apple-ios.tar.gz": "da321d56c24e6c2aa326cc082912498c27231f0f0fea27ab925807108d6f329e", + "dist/2022-09-20/rust-std-beta-aarch64-apple-ios.tar.xz": "21e78983abd4523ac9efb0405734ebfd6c8c09b9cc89b9d052b1a58bb7ab798c", + "dist/2022-09-20/rust-std-beta-aarch64-fuchsia.tar.gz": "dd64a476c35b1a6aefed6bcc756cb4562a60ec0277e5661241018678d7a04268", + "dist/2022-09-20/rust-std-beta-aarch64-fuchsia.tar.xz": "bcbb6f3457c9b6e1c9109094536445ff208e78b5a24485af6de580ba7e279861", + "dist/2022-09-20/rust-std-beta-aarch64-linux-android.tar.gz": "63ab6db951f5cefbd1ab1661ffbac9749fec8d4165047dfbcb76b7dcb1468e48", + "dist/2022-09-20/rust-std-beta-aarch64-linux-android.tar.xz": "f3e89fe21779ecd8373280f38e29db8941c0836cba7314414d854ba685e075e4", + "dist/2022-09-20/rust-std-beta-aarch64-pc-windows-msvc.tar.gz": "fa187421633e7ca45948258e804fd4a8177070b9a4b964ac95231018cd5e724c", + "dist/2022-09-20/rust-std-beta-aarch64-pc-windows-msvc.tar.xz": "af981f04545aca6d3fe301a22773ff38077e8c8d437b862a3d7f1e8040bfaebc", + "dist/2022-09-20/rust-std-beta-aarch64-unknown-linux-gnu.tar.gz": "22fb1351c35e4d5b12d043cdf1de51a13176fc60518fa89226f3af9dc2e727b6", + "dist/2022-09-20/rust-std-beta-aarch64-unknown-linux-gnu.tar.xz": "690a7880a563138bbd583b537ddb80bd738d8fceb4cab083bc8bbd1fa1ee2f99", + "dist/2022-09-20/rust-std-beta-aarch64-unknown-linux-musl.tar.gz": "2d5135344f76decf74633d95e2fc98c416093ca962cac608564abf600ff117bc", + "dist/2022-09-20/rust-std-beta-aarch64-unknown-linux-musl.tar.xz": "8f63623f1e0cae99c5d1c4bb1c636fb773ed06dc1d33a251c9253278f7bc1300", + "dist/2022-09-20/rust-std-beta-aarch64-unknown-none-softfloat.tar.gz": "105123c48c7e0946872b8ca0fcc897c2a1fcccb9b71b1805eca01e713a509c0e", + "dist/2022-09-20/rust-std-beta-aarch64-unknown-none-softfloat.tar.xz": "9c9ec824e1db607bfac14ce8a5d1e73aeb8670e655acb4577a8f6ee783202aeb", + "dist/2022-09-20/rust-std-beta-aarch64-unknown-none.tar.gz": "b25fb3d1c41e193b724469898efe9d0f5d282de06d5224ae573c8870ccb5ed4d", + "dist/2022-09-20/rust-std-beta-aarch64-unknown-none.tar.xz": "4f87a8fc869f80072ad2a07896e50ee97b3412badeb69bb37f67ef47ff0d00d5", + "dist/2022-09-20/rust-std-beta-arm-linux-androideabi.tar.gz": "9ee992110e4bcf9a00bec8635cbe5bbeb241d2fb6b567060fa0507406708c8dd", + "dist/2022-09-20/rust-std-beta-arm-linux-androideabi.tar.xz": "aa5981a138a103843462a5a6987fcf0c7c335a5896517505d2e54fb288d7af1e", + "dist/2022-09-20/rust-std-beta-arm-unknown-linux-gnueabi.tar.gz": "854d0d7c9932d4533d642e663ffa465741a3d0ec400a2c4b74324debaa0da27f", + "dist/2022-09-20/rust-std-beta-arm-unknown-linux-gnueabi.tar.xz": "83b7b2dc823608777dc0e2f290fb5a2f8e6e35f4930ce2170309c14a54f136b3", + "dist/2022-09-20/rust-std-beta-arm-unknown-linux-gnueabihf.tar.gz": "9c84cc8ff79098be62011d572cd928faa4cf76c9c3e94060babc042073f3b7a1", + "dist/2022-09-20/rust-std-beta-arm-unknown-linux-gnueabihf.tar.xz": "b34a7bdd0ddac9e8b4ea8e1db8d86389c623a6629edbbd0052f890df75465fa6", + "dist/2022-09-20/rust-std-beta-arm-unknown-linux-musleabi.tar.gz": "49ddce546458f47683928fe341f5eacaec11c3c5a378ce8802c4b97425100905", + "dist/2022-09-20/rust-std-beta-arm-unknown-linux-musleabi.tar.xz": "e64130a854017b921a086749550fe92339cef0890ee645acbe23a30f5169a8ad", + "dist/2022-09-20/rust-std-beta-arm-unknown-linux-musleabihf.tar.gz": "770bab36bd3bbc07739f0cc89c09689189edf7518e740f794be9aa7aed0917f5", + "dist/2022-09-20/rust-std-beta-arm-unknown-linux-musleabihf.tar.xz": "b390f1111f5566b37d3f9384126a6d3dd0cdf9468dea19747394cdaae1c87c7c", + "dist/2022-09-20/rust-std-beta-armebv7r-none-eabi.tar.gz": "de22ffe26c7ef21d316933618b37c832353a7e5a1fb8b84af7bca98626fbc78e", + "dist/2022-09-20/rust-std-beta-armebv7r-none-eabi.tar.xz": "82b77c48fdb685b63bea0d40437d5dcee41500cec0360e393511b2c69d2c7381", + "dist/2022-09-20/rust-std-beta-armebv7r-none-eabihf.tar.gz": "94d427c65134e1e208f662acb3eb65a455016e3bed162bc4fcea9c6455e0474e", + "dist/2022-09-20/rust-std-beta-armebv7r-none-eabihf.tar.xz": "cdd71383ec150dbb2514a48300344a8547d7fee2c797e693cd7803354c5fca13", + "dist/2022-09-20/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.gz": "0241f8f9ffd00c02860158da46e20290d2ba563f93e8fa22324da2b87c347a0d", + "dist/2022-09-20/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.xz": "a780eb139416f2383f16fa63e72e56f0a77c67d2ac2f10f803802660e8ca30bc", + "dist/2022-09-20/rust-std-beta-armv5te-unknown-linux-musleabi.tar.gz": "1628e0c7a8cd8fb2b90db0e3d30f0d36768dbdeca640af967a14b9031d2d4c3f", + "dist/2022-09-20/rust-std-beta-armv5te-unknown-linux-musleabi.tar.xz": "4b06bbd8a0ae240bb19c93b54bd9da3bfe6c3f37a70d2b73dfcc9d1eff8fdaae", + "dist/2022-09-20/rust-std-beta-armv7-linux-androideabi.tar.gz": "9aaeffdd99e9dedb2bffa79adef2096ef29b48ffd2681ede2ea8d63179082f89", + "dist/2022-09-20/rust-std-beta-armv7-linux-androideabi.tar.xz": "d1d0ae4718eb43d4759cbe14a90b422edf0f451c8cb8624368800eff0f05c13e", + "dist/2022-09-20/rust-std-beta-armv7-unknown-linux-gnueabi.tar.gz": "5cf573ce6729200cc211924e45796a9aaf85001272a8690803944dbc91b5a2fb", + "dist/2022-09-20/rust-std-beta-armv7-unknown-linux-gnueabi.tar.xz": "51cecc72479f18c94620b2b022b89403e8ba519e36cb7a6f8c208a9ab6adb17c", + "dist/2022-09-20/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.gz": "c6e6962438e0a8ebdc7a7c74712d75642acfeb8c4b0753354a7d3b64da6948cc", + "dist/2022-09-20/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.xz": "4b812cfa63c380448b0e2ca2e03cfad73ba9951080eff1f76feaee25f67bdf39", + "dist/2022-09-20/rust-std-beta-armv7-unknown-linux-musleabi.tar.gz": "89cdaf10019fc3ddb83ca1848adf8ac3411820a9095dc337b9a962f1e58be058", + "dist/2022-09-20/rust-std-beta-armv7-unknown-linux-musleabi.tar.xz": "e21ac9106eae28b25270f6c1ce70e2c94273919c9c72d22f0fe3ad0b8f0a57f0", + "dist/2022-09-20/rust-std-beta-armv7-unknown-linux-musleabihf.tar.gz": "e218b7e7d148379411502023d6ede2831d76e29d5d2427d030f916a0c14c8ffa", + "dist/2022-09-20/rust-std-beta-armv7-unknown-linux-musleabihf.tar.xz": "2797698cf0f218c17eb22f43f806663723f9c89084fdc08d40adbbcde5a79f88", + "dist/2022-09-20/rust-std-beta-armv7a-none-eabi.tar.gz": "1d5c29d803cb8ef005baf44ca6a0b1fccc4227ab3585046f0d69cbf153be10d7", + "dist/2022-09-20/rust-std-beta-armv7a-none-eabi.tar.xz": "50259e9b9672baf54e176c252e9068cf020c4a79a825bafc5ee21fb46b9af815", + "dist/2022-09-20/rust-std-beta-armv7r-none-eabi.tar.gz": "805fc5ae72249f27ddbdd8afdc188b4f67dfe51822eb813e681259da51dbc75c", + "dist/2022-09-20/rust-std-beta-armv7r-none-eabi.tar.xz": "75151349dc9b6fd3b3a78d38827e517adc6935356bae0c5bc93bae62e1759db8", + "dist/2022-09-20/rust-std-beta-armv7r-none-eabihf.tar.gz": "ad4e0347c3e9b3f4936f26798ae2a8c502a4599c3357baf0b0a4cc3516c471bf", + "dist/2022-09-20/rust-std-beta-armv7r-none-eabihf.tar.xz": "4de3e5a729597473759b2db1f7e2ab633c98bb1d8125de6f458fe3bd0ee7d8c7", + "dist/2022-09-20/rust-std-beta-asmjs-unknown-emscripten.tar.gz": "0b3c92539f3aec14501e09db3aa02854ef98fb4dc89721306798ea163041e669", + "dist/2022-09-20/rust-std-beta-asmjs-unknown-emscripten.tar.xz": "26deacf11e62187673718ea8805b23dc2dd352efdedc11b396e117637a96ceae", + "dist/2022-09-20/rust-std-beta-i586-pc-windows-msvc.tar.gz": "a11ca7a7f67e225365423a704d7139d3c9193699493f1f193d579c126d492475", + "dist/2022-09-20/rust-std-beta-i586-pc-windows-msvc.tar.xz": "08d8aad1d608d2ff626f4e7e4300a31fc3f96c0ef1e5bd0ec179b98d4194fca9", + "dist/2022-09-20/rust-std-beta-i586-unknown-linux-gnu.tar.gz": "3524e1ba92b9ccd1fcfd40a6018efa697d63177cc0a8c9cd016be833aff371f4", + "dist/2022-09-20/rust-std-beta-i586-unknown-linux-gnu.tar.xz": "a6df83285ba5732eca9adf3f39d0a4087249b29cd0c33ee2272f68930df43191", + "dist/2022-09-20/rust-std-beta-i586-unknown-linux-musl.tar.gz": "6951d7aecd555a0dc485f57ad16703af65315c464aebcf73171bbda2273dba0a", + "dist/2022-09-20/rust-std-beta-i586-unknown-linux-musl.tar.xz": "f07c4a267740e46a4013b130e9d1e10492e45dc0226a08f5c909076ade466737", + "dist/2022-09-20/rust-std-beta-i686-linux-android.tar.gz": "dd47fbd29b3b025388352fafe693f25e43c1287f69c2185fecfb0d60e13a7fc3", + "dist/2022-09-20/rust-std-beta-i686-linux-android.tar.xz": "0eebd41330762a4bad438c40f134601e59a7b73043952b2e090a801adff41727", + "dist/2022-09-20/rust-std-beta-i686-pc-windows-gnu.tar.gz": "58cd47de74c201bfed62a8980c2447f97e7c129726d3d28c2140d880fa6d7975", + "dist/2022-09-20/rust-std-beta-i686-pc-windows-gnu.tar.xz": "7fd68f0f9eea4d8256132af2f2c269c58a278b757888e591716a553b87ffcf8c", + "dist/2022-09-20/rust-std-beta-i686-pc-windows-msvc.tar.gz": "816ef343a7ed908706d8f4e7cb915787a4e27c2390cc7c3f6e2210f3ad7c4cda", + "dist/2022-09-20/rust-std-beta-i686-pc-windows-msvc.tar.xz": "2475326f3d32e8ae309750c1639cdc6cce3474fb5d4820b31b46c9c12401b63e", + "dist/2022-09-20/rust-std-beta-i686-unknown-freebsd.tar.gz": "24a897b9916bcd4ad775d96f9751b06663eed599086d0665b83dd4c16af871ab", + "dist/2022-09-20/rust-std-beta-i686-unknown-freebsd.tar.xz": "959725ac2f49d1944c53846d920ab4e8769976d4025bc32bc63e5372b751a8de", + "dist/2022-09-20/rust-std-beta-i686-unknown-linux-gnu.tar.gz": "35eb28ff2d3b383ac1b34bf6eded87f824ef93eb2c2d12c300b136c7c735ced7", + "dist/2022-09-20/rust-std-beta-i686-unknown-linux-gnu.tar.xz": "31085015fbfa608e6d0828a367d84b48679c6a33d55ae32affe37307818b1086", + "dist/2022-09-20/rust-std-beta-i686-unknown-linux-musl.tar.gz": "ef294d01caeba013cc3173b5fab5daac4f0c64e57410f778f2891dff03f23875", + "dist/2022-09-20/rust-std-beta-i686-unknown-linux-musl.tar.xz": "4ad7915a9e54f7d911864adbc097941a9c051e0c97c8eee1c04158a5755e4e4a", + "dist/2022-09-20/rust-std-beta-mips-unknown-linux-gnu.tar.gz": "cd8e8fe2af17def5bf19a8a0993317af5c33833de850a489ef2dee54c61dbca7", + "dist/2022-09-20/rust-std-beta-mips-unknown-linux-gnu.tar.xz": "f2f95555e3564f7b16bcde9ae4c6a30752900519fba68304c4f74b7e508bacc3", + "dist/2022-09-20/rust-std-beta-mips-unknown-linux-musl.tar.gz": "7d42b6d7f028c637f7f9a2f0c14fde880e00098bf4141289620232a263fa8eb0", + "dist/2022-09-20/rust-std-beta-mips-unknown-linux-musl.tar.xz": "50dc97ba9ce28d4252f03f78e23bc05a702d5c1c5ad67b70a358406419f25721", + "dist/2022-09-20/rust-std-beta-mips64-unknown-linux-gnuabi64.tar.gz": "7c14decb2404c616319c99415f65c1383264151f3802ffedfdff4962db310828", + "dist/2022-09-20/rust-std-beta-mips64-unknown-linux-gnuabi64.tar.xz": "230849a3b6dff89671bf94c73391eee43107c81ff65c795eb1c9f30b9bb52176", + "dist/2022-09-20/rust-std-beta-mips64-unknown-linux-muslabi64.tar.gz": "0a63c8f568d9ef12b75b9bcd53faf727bc029b4a1268c53fef913e58be94eff7", + "dist/2022-09-20/rust-std-beta-mips64-unknown-linux-muslabi64.tar.xz": "5b1020d65f651cd1778448618bca55906eef981842b73c18be1b5ec785d6bf06", + "dist/2022-09-20/rust-std-beta-mips64el-unknown-linux-gnuabi64.tar.gz": "3f747d83397942c88ad79a7bde1f98a57d0b416620f08ab57edb64f3b101f493", + "dist/2022-09-20/rust-std-beta-mips64el-unknown-linux-gnuabi64.tar.xz": "babdc0c87bdc8146fc6645da34776be98575019eacb95529c00060f8afcbb1f4", + "dist/2022-09-20/rust-std-beta-mips64el-unknown-linux-muslabi64.tar.gz": "f0bc0b5fddf7ff8251fefa4068fdb623b47bbd1e81c2c732ce2304e4ce78bb20", + "dist/2022-09-20/rust-std-beta-mips64el-unknown-linux-muslabi64.tar.xz": "33e3cc3766f941f3668a93240d627c7357b22a13facff5937821d92a21afe444", + "dist/2022-09-20/rust-std-beta-mipsel-unknown-linux-gnu.tar.gz": "33ae5fdfab257ddb004eb80ff1a8d0351675df06b97951d5c47071ac8b18ba9a", + "dist/2022-09-20/rust-std-beta-mipsel-unknown-linux-gnu.tar.xz": "9f16e21c54944afe83a5e1a3e489a2dcad947f367cbb17c6ffcfd2c503e03f25", + "dist/2022-09-20/rust-std-beta-mipsel-unknown-linux-musl.tar.gz": "065f8929bef2ff2ec0067c788fe64e0a08af0f5e11ac5d67e29e5225557d6d9a", + "dist/2022-09-20/rust-std-beta-mipsel-unknown-linux-musl.tar.xz": "c3c54ba9dfee447e33d76ba8060bb9b6081103fa6809ad77c3221ea064ed3fc8", + "dist/2022-09-20/rust-std-beta-nvptx64-nvidia-cuda.tar.gz": "5627e25a24792131e8c0a1c605908bd56ab5a55614b8e17c23233fdc14d25e81", + "dist/2022-09-20/rust-std-beta-nvptx64-nvidia-cuda.tar.xz": "3ee1b5228665f2d5d7ac500d6fa6a2d0fd771eaafb5c393419713a11bf8d0875", + "dist/2022-09-20/rust-std-beta-powerpc-unknown-linux-gnu.tar.gz": "cbf922bba400e798cd32e5404a804400f79ed03ba5cc433173eac96ba9e06976", + "dist/2022-09-20/rust-std-beta-powerpc-unknown-linux-gnu.tar.xz": "bc573b0012568f0bf397870660f7527697b1c65e1a7387d2419c6f63ba001bdd", + "dist/2022-09-20/rust-std-beta-powerpc64-unknown-linux-gnu.tar.gz": "917b948988edd4e5c5e441102f55b1541318d47c0cd5d958a69ddc6fbfda84d1", + "dist/2022-09-20/rust-std-beta-powerpc64-unknown-linux-gnu.tar.xz": "23e45711ce82b6baf9d27d909d8fe4bc6a5f32c91dfbc280708abfe5c362bc89", + "dist/2022-09-20/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.gz": "448710ce6f3e72d0831ae882fa37196685a28dacb6f0f499370fc2882427044f", + "dist/2022-09-20/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.xz": "831bc2bcb21ab9fe82fc64eb377d6d80b47198dc82677b7bd630d89819914e20", + "dist/2022-09-20/rust-std-beta-riscv32i-unknown-none-elf.tar.gz": "14a61cc3d6740a9033c6570264e6c9356120235f42e5ded8ebec1d592f17b47f", + "dist/2022-09-20/rust-std-beta-riscv32i-unknown-none-elf.tar.xz": "c73aa37081b4248324a459b48378b4a412a3561a12bad3ae064c8336ec862dd6", + "dist/2022-09-20/rust-std-beta-riscv32imac-unknown-none-elf.tar.gz": "f78a367b9977471dae06fffd6049f03585e826fe648a2d1d8ee20ff19dfc913f", + "dist/2022-09-20/rust-std-beta-riscv32imac-unknown-none-elf.tar.xz": "e8ef0dfd9d7df08fcdb7136619d8b9cd31435e0de130f87c799117dba9614a54", + "dist/2022-09-20/rust-std-beta-riscv32imc-unknown-none-elf.tar.gz": "a7cd118c91f4de3a1e1c5d9326080bf39661f708c675272cf697ab9675001705", + "dist/2022-09-20/rust-std-beta-riscv32imc-unknown-none-elf.tar.xz": "58023f2bd169455d97537aca228749e9a980e18d72f67ae8c0caff4ad2d4fd64", + "dist/2022-09-20/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.gz": "726efb0f7cbac9d13deac41d0937ce5f707d8e858b3bf9096c40fd41b2663d4a", + "dist/2022-09-20/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.xz": "73395ddaa22a91a1de120704f22d86b0624de52af773755046ec809b76b88954", + "dist/2022-09-20/rust-std-beta-riscv64gc-unknown-none-elf.tar.gz": "2504e53a04ab1360309dd9e733798a94fa3a92cc575148073dc4870bb26367e9", + "dist/2022-09-20/rust-std-beta-riscv64gc-unknown-none-elf.tar.xz": "f182ac3b6222a333d73f3f612fb31f9d19d4e03456e16b0967cb55d1292ec05a", + "dist/2022-09-20/rust-std-beta-riscv64imac-unknown-none-elf.tar.gz": "9612105b0d40225d54f6b02bcf75e0d7d232331fa22a24de4895f97519dfd6a6", + "dist/2022-09-20/rust-std-beta-riscv64imac-unknown-none-elf.tar.xz": "448b0cd5cc35096e0fd51a7cb1948e87b7c46eafe665dbfda802a4947e08665a", + "dist/2022-09-20/rust-std-beta-s390x-unknown-linux-gnu.tar.gz": "72459d840371f7203e15622a82ccb5e3559db52934445943fc41b11a58b07302", + "dist/2022-09-20/rust-std-beta-s390x-unknown-linux-gnu.tar.xz": "39ca5b49d6e909c81deb8c7391e01da9ef51cabea55fa55dc16cf654abb089a1", + "dist/2022-09-20/rust-std-beta-sparc64-unknown-linux-gnu.tar.gz": "ff74af39ca1446f06f891beb22f1e24fb0b450d97c889dc2e27e0f53fc19b26f", + "dist/2022-09-20/rust-std-beta-sparc64-unknown-linux-gnu.tar.xz": "f56aa4d390eb4b25aa51685ee773b589ebc87bbed7495a07d8af0d3b3cc7c715", + "dist/2022-09-20/rust-std-beta-sparcv9-sun-solaris.tar.gz": "df727ef09f0549051ff5b4fcd04cb22d4244cea85f97e43880e563c45b558cd6", + "dist/2022-09-20/rust-std-beta-sparcv9-sun-solaris.tar.xz": "f575d16acc0a8cc5b96e038d828ac023c302e38efed271d5101a885d3af35cfc", + "dist/2022-09-20/rust-std-beta-thumbv6m-none-eabi.tar.gz": "838be75f56d84d88ab01b0897d9b166b6ea26c527705df2d2a7368968439505f", + "dist/2022-09-20/rust-std-beta-thumbv6m-none-eabi.tar.xz": "b5b33e2de72e71ef5024fb50f0f6e91f32b4747f666aa7069e695b15119a1963", + "dist/2022-09-20/rust-std-beta-thumbv7em-none-eabi.tar.gz": "dbaffcc17215c4342a40c049a9538be44837bcf86a7d65fb2c877f831beca337", + "dist/2022-09-20/rust-std-beta-thumbv7em-none-eabi.tar.xz": "14fabdf3f4cda3bdb3ac139c95d31c2a20e3a88cd9f83e803f9c9bd6e3f9f83a", + "dist/2022-09-20/rust-std-beta-thumbv7em-none-eabihf.tar.gz": "3acc833a086a9b46db81cbf03fcf2dc366a4b3d32eaeedcc2deee8ceea31449a", + "dist/2022-09-20/rust-std-beta-thumbv7em-none-eabihf.tar.xz": "f6cf227b6da03855f1624bb325bd802b8ae6b15d7bbfbfbf8b9de1a74aedb6fe", + "dist/2022-09-20/rust-std-beta-thumbv7m-none-eabi.tar.gz": "e5054ca1e295709654b214847691f4fa9f031104725632dc056853382e74e733", + "dist/2022-09-20/rust-std-beta-thumbv7m-none-eabi.tar.xz": "b44f0462a5f44e762653fecd816dcd5ba5a2f9d8dd3efcec259b250f3af5237d", + "dist/2022-09-20/rust-std-beta-thumbv7neon-linux-androideabi.tar.gz": "4fb8000ce077d346d85005343284f56ae936eac334c72cb8c170dbe810aad740", + "dist/2022-09-20/rust-std-beta-thumbv7neon-linux-androideabi.tar.xz": "77955483882897980f4365bdc71fca9f39d675ff210519702b9cf3f2a6bcc2a8", + "dist/2022-09-20/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.gz": "566b9ea01182e6c7e3844911ed08fe5eb1d848c3de89d4f123d80fd70ff37ddd", + "dist/2022-09-20/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.xz": "33cc9c12d909bd4166be8570e27da8c1884ac1ce82d9548e16d926d9885ff62d", + "dist/2022-09-20/rust-std-beta-thumbv8m.base-none-eabi.tar.gz": "62a345ea2aa55b1a02053e7c49988c5f14d6b90d487b9c4916e40ad31957d1f5", + "dist/2022-09-20/rust-std-beta-thumbv8m.base-none-eabi.tar.xz": "37fd80af2188d837e870d3c8399767be15070344fc87d2b37b5126095252afc5", + "dist/2022-09-20/rust-std-beta-thumbv8m.main-none-eabi.tar.gz": "32a10d7eaaf2189d74700187fbc8c2ebde08b5efa06440c2b4f65fb85eac3ecc", + "dist/2022-09-20/rust-std-beta-thumbv8m.main-none-eabi.tar.xz": "dae8d6deecc5277be729803ed55dc134c1ef5bae49fa0fe7ea4f0eee9d7d19fb", + "dist/2022-09-20/rust-std-beta-thumbv8m.main-none-eabihf.tar.gz": "44457f84d46ccd201771cdae9520caebf813d3283b08f73fabab59b52b485a98", + "dist/2022-09-20/rust-std-beta-thumbv8m.main-none-eabihf.tar.xz": "1e5bcc82a403c1c4c5fa41fa78de9aa4378a2901e3170d9542eb3b21d130e36a", + "dist/2022-09-20/rust-std-beta-wasm32-unknown-emscripten.tar.gz": "b7d31d0ec6fd1355d1323555ec8d1cb4b9f30bab32a75d0d8efaf465ab2aedcc", + "dist/2022-09-20/rust-std-beta-wasm32-unknown-emscripten.tar.xz": "a25b5c180ca97d074d563c6fe1d826db23eba9212d12cb3d60d39b7841a5618d", + "dist/2022-09-20/rust-std-beta-wasm32-unknown-unknown.tar.gz": "31aeed83d12732c40e51cf59a3dd8dd1fe7ba2ed047cab65f8bfca8c72d158ed", + "dist/2022-09-20/rust-std-beta-wasm32-unknown-unknown.tar.xz": "28757fc2c5304b3110b2358d252fb4aaa8d811999bd9881e118bc71b0e6b01a3", + "dist/2022-09-20/rust-std-beta-wasm32-wasi.tar.gz": "b69ecad8480c2d33b854ba3387a0563df53546b8a2b55639fa20d1c104f35050", + "dist/2022-09-20/rust-std-beta-wasm32-wasi.tar.xz": "a09185a76891928cc65e4139373df6f22fd0060388ccc4530cc0be5310f8aaa7", + "dist/2022-09-20/rust-std-beta-x86_64-apple-darwin.tar.gz": "97f5a3dd01a7b5efe44662f2376826c184d212754c730bfaa21cd03235676142", + "dist/2022-09-20/rust-std-beta-x86_64-apple-darwin.tar.xz": "131b37e9d3c2335fb51427a7e0ab43362efccf90a4e001ef52e54aa221634eb8", + "dist/2022-09-20/rust-std-beta-x86_64-apple-ios.tar.gz": "d900fc396731c95a57d43519a109202cd2ed8e574df300cd6124c6390d1584a3", + "dist/2022-09-20/rust-std-beta-x86_64-apple-ios.tar.xz": "694dc51239481fe8f5ec2291b62435e0a7622591f2709ea4709749c7d8c01db3", + "dist/2022-09-20/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.gz": "c2fad6b25e33e4e52fab6d20b6e1bbf78f230e9b387f260b48f940bff67386f5", + "dist/2022-09-20/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.xz": "c3fe305a1082cbf1f5bbdaab5a94c0ad88037a4f99e556cf06ff1270a806f437", + "dist/2022-09-20/rust-std-beta-x86_64-fuchsia.tar.gz": "75b5aaf5206953d16a418c83f6e6d21a0adcbb0c81b5c1a8f467f3e5aa33c038", + "dist/2022-09-20/rust-std-beta-x86_64-fuchsia.tar.xz": "7fc38dbfb7833e9b6336f4aa38706a92e1922231ee875100e16274c571110757", + "dist/2022-09-20/rust-std-beta-x86_64-linux-android.tar.gz": "bc4a42ffc51bc3be27907a73de98fe4c8cf3b205fd1e7c75a9cb3bd30bcc5fbb", + "dist/2022-09-20/rust-std-beta-x86_64-linux-android.tar.xz": "68e02875090c7d382e8b21d0102712e7c9d583d657b6c51b4f939e3a9b7f884c", + "dist/2022-09-20/rust-std-beta-x86_64-pc-solaris.tar.gz": "11edbb1de67f00263f31635bdf006966143aa18423f574cb64ef966301a0fe3a", + "dist/2022-09-20/rust-std-beta-x86_64-pc-solaris.tar.xz": "44743e8f113e3e5bc7ce66902533f6ac59538f8f61fa6ab6c311bbf2ebe75e43", + "dist/2022-09-20/rust-std-beta-x86_64-pc-windows-gnu.tar.gz": "a705945830b23a25f272600470d687a1a9f5d4f8a01c5fed9e495a444b2aa9ee", + "dist/2022-09-20/rust-std-beta-x86_64-pc-windows-gnu.tar.xz": "9e4a045a2e0f754ec6afd897f1bcb66bccfc2b5bb91f141fa8d3d47723eb6090", + "dist/2022-09-20/rust-std-beta-x86_64-pc-windows-msvc.tar.gz": "910de4547c1112170b0981fecfc926cff4c47cc622648b83fea9f79c171cb05a", + "dist/2022-09-20/rust-std-beta-x86_64-pc-windows-msvc.tar.xz": "f9be82ac8c5f64c17cfbf0270b8f71ec71e6b3ba7c9521980a73d6f848f6014c", + "dist/2022-09-20/rust-std-beta-x86_64-sun-solaris.tar.gz": "e1097c0bd31baa61902be4a8a47a674faa15466ce9352213cf7808f50d5854ff", + "dist/2022-09-20/rust-std-beta-x86_64-sun-solaris.tar.xz": "82866dc52808549acd683d5b7c47fe97c992ea70cb6fff941007960a25f3b645", + "dist/2022-09-20/rust-std-beta-x86_64-unknown-freebsd.tar.gz": "2b7c60a6b830d557a6df8865bc8dd658c84037a5893b11db8e11dadb527b5d6f", + "dist/2022-09-20/rust-std-beta-x86_64-unknown-freebsd.tar.xz": "14787b285c55ab885d1360897849882eac861f36029cc72ec9819d035998ee9f", + "dist/2022-09-20/rust-std-beta-x86_64-unknown-illumos.tar.gz": "4bfdf27eb12af6c4df132603a111ae26f4d06846af366a38e594e66c092373d5", + "dist/2022-09-20/rust-std-beta-x86_64-unknown-illumos.tar.xz": "66b602046eaa83cf2b69bc75af4dd11dbc5d0c6878537d0af451d17121fdbbe9", + "dist/2022-09-20/rust-std-beta-x86_64-unknown-linux-gnu.tar.gz": "78d12361e71630978928896a63e6cf7e3e866c09de761029b4e8e959850ac025", + "dist/2022-09-20/rust-std-beta-x86_64-unknown-linux-gnu.tar.xz": "d55f9cb4a8c47fc5d0123cedf622b94b33f57a59022129e31f451e1b80f1815e", + "dist/2022-09-20/rust-std-beta-x86_64-unknown-linux-gnux32.tar.gz": "74bbecb0f35ad8a1aae65fb09ef21e38bfbe6d5b4c6b1d741832eb8f40eb4b1f", + "dist/2022-09-20/rust-std-beta-x86_64-unknown-linux-gnux32.tar.xz": "135f19e88ac0fb7ed02072c82a17f0d12abaf40055efd0a6b43bbbbc9c4445cd", + "dist/2022-09-20/rust-std-beta-x86_64-unknown-linux-musl.tar.gz": "0b3abb866d7b82bc5add9fa01d59b9223d2124d69dfd78a13a4dfcc17196f510", + "dist/2022-09-20/rust-std-beta-x86_64-unknown-linux-musl.tar.xz": "ec5989076c015e5b7d1a307ecb19f2ed12df7b5e2836d3b410f3743f9066683d", + "dist/2022-09-20/rust-std-beta-x86_64-unknown-netbsd.tar.gz": "1e236c2ad7aa296aa389751ce64d1cecf86053d23126e1211da71674603e6900", + "dist/2022-09-20/rust-std-beta-x86_64-unknown-netbsd.tar.xz": "de43876b381f7b91f7a8e1d1df5b92a3d60b22a62333f9a645f3e6055e91be3b", + "dist/2022-09-20/rust-std-beta-x86_64-unknown-none.tar.gz": "568e95b842c3d8f9f733fc3b5b59a8c673d200b4d16d5db36ce24ee355e18c1d", + "dist/2022-09-20/rust-std-beta-x86_64-unknown-none.tar.xz": "557727f83c7998b9349bb2c05f5ac5fcb2f0bef28e55f27b165fb7a2d9347396", + "dist/2022-09-20/rust-std-beta-x86_64-unknown-redox.tar.gz": "e3c00ab70a0a69a9567bc525cc283318186521a6d57ccf4a42e2eb640ed50ce6", + "dist/2022-09-20/rust-std-beta-x86_64-unknown-redox.tar.xz": "757f2208edb49f23adf702a34b093551f0e193f6a6cd8c24b2cf4f199f77b2dd", + "dist/2022-09-20/rustc-beta-aarch64-apple-darwin.tar.gz": "a036bf0b4d0c8ab907ef2cb8cf8eacff41f7b82d519a2988a529c3d926539ee8", + "dist/2022-09-20/rustc-beta-aarch64-apple-darwin.tar.xz": "3c49210d4b867cefb4050507104b2672fc70e15f42615ced22469831b34b3267", + "dist/2022-09-20/rustc-beta-aarch64-pc-windows-msvc.tar.gz": "21fefdaa0b70d7f4839751926ce102e19164a373e4d310c0f0b3655f3adbff47", + "dist/2022-09-20/rustc-beta-aarch64-pc-windows-msvc.tar.xz": "7c88775b4efbb2416deb2b0d9ba86d5178d34059b18165b276658973f29d5971", + "dist/2022-09-20/rustc-beta-aarch64-unknown-linux-gnu.tar.gz": "99e30eb1612fd18b42a1b89602f448788ddcbbac2430577fc963a2c0c4708c55", + "dist/2022-09-20/rustc-beta-aarch64-unknown-linux-gnu.tar.xz": "385eaeb8f260a187ef828904e5267551062210543614dbf98d1c1e392853b913", + "dist/2022-09-20/rustc-beta-aarch64-unknown-linux-musl.tar.gz": "8f3b377a74c586cc8f7cc165eac0794bec560e04c885ae552af4e5cf42490a1b", + "dist/2022-09-20/rustc-beta-aarch64-unknown-linux-musl.tar.xz": "2fb2add792a9377cbe86aaedec389d023c35343ef801a97a2392f323e92c386f", + "dist/2022-09-20/rustc-beta-arm-unknown-linux-gnueabi.tar.gz": "658ec925f51b2a5da9ab8cb193c33c05cc294915d8c0c5a2e93f9ade383375df", + "dist/2022-09-20/rustc-beta-arm-unknown-linux-gnueabi.tar.xz": "75d19b64530691739654763b89468a7101457d638da04e25f549078594b67b68", + "dist/2022-09-20/rustc-beta-arm-unknown-linux-gnueabihf.tar.gz": "c167fb9f352fed99d427094a5c2b96da0486f30ccb4188756def7c232083319a", + "dist/2022-09-20/rustc-beta-arm-unknown-linux-gnueabihf.tar.xz": "ec1c19536b6fc3020ccfff727bddc934f89da0592797d49bf7149e96f7175451", + "dist/2022-09-20/rustc-beta-armv7-unknown-linux-gnueabihf.tar.gz": "05c5e668d5b40db5cd18b21192d8f0f1401d2304f715eff08ff49c3c97d740dc", + "dist/2022-09-20/rustc-beta-armv7-unknown-linux-gnueabihf.tar.xz": "ad620c5de3ae9a0b30b3c49dc89bfcd08a061da01f004a724ad5400efd4a7189", + "dist/2022-09-20/rustc-beta-i686-pc-windows-gnu.tar.gz": "2be9e0f5fe27b7085f65d32cb20875392bdcb177c582c58d1df842b316dcb9c5", + "dist/2022-09-20/rustc-beta-i686-pc-windows-gnu.tar.xz": "5841c0f4558d24ccd0c4e6996e399fe3ff13d5d1ffb2bda38bab6d60020fa649", + "dist/2022-09-20/rustc-beta-i686-pc-windows-msvc.tar.gz": "a19c5330c111ad4b19a724b22dc3381eb9f05a85bf9299dd13eefabbf6499504", + "dist/2022-09-20/rustc-beta-i686-pc-windows-msvc.tar.xz": "902811dec71e36989af12c8dc15b79759e5cf4e2250841bad2b9db2eb94195a1", + "dist/2022-09-20/rustc-beta-i686-unknown-linux-gnu.tar.gz": "36474bb89e67bc867cb7a4a5101d00be221d7a8b6a625535a5b2a74f505d5af4", + "dist/2022-09-20/rustc-beta-i686-unknown-linux-gnu.tar.xz": "4329562f89817b02e3eac219ad3051d9de5fab89e0678d91378c02a90fea7d59", + "dist/2022-09-20/rustc-beta-mips-unknown-linux-gnu.tar.gz": "bb7f5c8abc99d07a337eaeb3c1dc3861a4f148c364f58b039886f43abf6a7d01", + "dist/2022-09-20/rustc-beta-mips-unknown-linux-gnu.tar.xz": "0b02a4d1aac7c9d4b38fd760937020975e5de209ad23b7285cceae7992449d47", + "dist/2022-09-20/rustc-beta-mips64-unknown-linux-gnuabi64.tar.gz": "7ceae3da1fb1f865df3315ca450ec3cb4657086dd61c7a47879f98188aa38100", + "dist/2022-09-20/rustc-beta-mips64-unknown-linux-gnuabi64.tar.xz": "5a5273ed85d3012b8067dbc3e93f1af105e4cd80ed8055daade24f43dfb41977", + "dist/2022-09-20/rustc-beta-mips64el-unknown-linux-gnuabi64.tar.gz": "dbd12a141765f29be2a602531db7f9a02bc32617635448f602befc90f1a574c3", + "dist/2022-09-20/rustc-beta-mips64el-unknown-linux-gnuabi64.tar.xz": "e3abf34a09040149f8725ed1fca6e9c412c4cf290f9424541a819f0e2aa363b2", + "dist/2022-09-20/rustc-beta-mipsel-unknown-linux-gnu.tar.gz": "e13b7057525302dc3585a71461aa022ea0c059c0b0069fec44f86549eea94d18", + "dist/2022-09-20/rustc-beta-mipsel-unknown-linux-gnu.tar.xz": "b7bedce1d0ce44b4014e10122201c10443c0e8ced80084a6ebf1add1dbd3236f", + "dist/2022-09-20/rustc-beta-powerpc-unknown-linux-gnu.tar.gz": "fa738ae0d068e85044d2fce10f6a8bebe7b608630b9b7a822b2d7b84c6c59002", + "dist/2022-09-20/rustc-beta-powerpc-unknown-linux-gnu.tar.xz": "b53d773465368d9484cd36063d7ff202c1ca8d18422b4f6727cba54beb88f4bf", + "dist/2022-09-20/rustc-beta-powerpc64-unknown-linux-gnu.tar.gz": "9fad6a7ae30e5ccb4f0779ffdd117f6cb30e6c5f6efd5247c208f9ee3296a27f", + "dist/2022-09-20/rustc-beta-powerpc64-unknown-linux-gnu.tar.xz": "e8a92259aa371d350dc29171467c3e99fc178b636343ca82188c7b602a39ab58", + "dist/2022-09-20/rustc-beta-powerpc64le-unknown-linux-gnu.tar.gz": "5b64e0924a705e267177c8d80970f510487de350dda47cbc9bb758ec1b212a17", + "dist/2022-09-20/rustc-beta-powerpc64le-unknown-linux-gnu.tar.xz": "f6ca5a88f0ea25521e1135100cc7404547ffbbc4422b3c9a06177c94d7871ef4", + "dist/2022-09-20/rustc-beta-riscv64gc-unknown-linux-gnu.tar.gz": "8db27ac2a1b8322f529428ee7278347263a9ff71101d37bfb04056137f63de78", + "dist/2022-09-20/rustc-beta-riscv64gc-unknown-linux-gnu.tar.xz": "2475866ff4afe38755a27ffde9c09302066d0c936a4778883fee9a37c1b59f31", + "dist/2022-09-20/rustc-beta-s390x-unknown-linux-gnu.tar.gz": "4cd81c652fd3e59cbdd42872f2e37bdcc1fa61a550eb8ffed7783e7ad3350577", + "dist/2022-09-20/rustc-beta-s390x-unknown-linux-gnu.tar.xz": "1f8529e51192433d1a281484072f94d910ff81161efef230e6a2be82765f6f26", + "dist/2022-09-20/rustc-beta-x86_64-apple-darwin.tar.gz": "430311100511fe9fe176f01030b78fa8160840bf4d9b4ed798a2a7fe089b4f7c", + "dist/2022-09-20/rustc-beta-x86_64-apple-darwin.tar.xz": "57be1bb1dc7d7d0f0479d11e36d6315a9d19eb0102610b7f1dbd5151fe6ff5c2", + "dist/2022-09-20/rustc-beta-x86_64-pc-windows-gnu.tar.gz": "826f3f6839c4e18e6d58a32de8f067bb57be2fb2c6cdf74f55d55ef76f5c5e21", + "dist/2022-09-20/rustc-beta-x86_64-pc-windows-gnu.tar.xz": "5f8b9704071e6b372a5c67a29bcb9ba5978ffdedd62e057680aaba17dfc91ba1", + "dist/2022-09-20/rustc-beta-x86_64-pc-windows-msvc.tar.gz": "06a29a85bfce9981504f1630c5f3ea86171948080a93d8dadb4a306dd678af80", + "dist/2022-09-20/rustc-beta-x86_64-pc-windows-msvc.tar.xz": "36c2944aa3db18dfa1632c7b52c67e6bad9effb03960af8cbf82fdf32924019b", + "dist/2022-09-20/rustc-beta-x86_64-unknown-freebsd.tar.gz": "c20829efb9888d8097c9f5f472598b06868bf918a9d033d4b6fd031323878492", + "dist/2022-09-20/rustc-beta-x86_64-unknown-freebsd.tar.xz": "515b35360865016b7efe6f973730ce4c66021df0edeed8eb490b69f4bf50006d", + "dist/2022-09-20/rustc-beta-x86_64-unknown-illumos.tar.gz": "e63231ee48425687c97c654faba961a1b12379696459f284b6a4ea7ea52fb2af", + "dist/2022-09-20/rustc-beta-x86_64-unknown-illumos.tar.xz": "fae9048709741bcd21f4dc2ad8119576ba8dbe6b6442e79a443c207a4c52cc47", + "dist/2022-09-20/rustc-beta-x86_64-unknown-linux-gnu.tar.gz": "3785a8837c6fdf230b79992e4a3fd6a8b6faa269461bf908e427ffbd59728adb", + "dist/2022-09-20/rustc-beta-x86_64-unknown-linux-gnu.tar.xz": "a238209d54c2f9fea99a18bf43c4c0ae9bbc9cb10075e63d77af131728d64892", + "dist/2022-09-20/rustc-beta-x86_64-unknown-linux-musl.tar.gz": "520ba16bf1b892f5c3d3fd6c1ba695ff48e0babd4ed5be97615887589e60c204", + "dist/2022-09-20/rustc-beta-x86_64-unknown-linux-musl.tar.xz": "4251abe5dde29e9d2ffd7560e7f8eeb5c1b4ad6078b27896f63fcad5db6dabeb", + "dist/2022-09-20/rustc-beta-x86_64-unknown-netbsd.tar.gz": "ccdde196a376d8f06d3457a1b6d85b4b3692acc9e4bd055fb93dcb217ecd4494", + "dist/2022-09-20/rustc-beta-x86_64-unknown-netbsd.tar.xz": "22f5defadc7b4b4231315b420b6ee102c188a03381580feb7e22b75e16661017", + "dist/2022-09-20/rustfmt-nightly-aarch64-apple-darwin.tar.gz": "8fead022ff05d4112e4cf7e637a459651dc793d9c38f1e823437f6c0c1bf6791", + "dist/2022-09-20/rustfmt-nightly-aarch64-apple-darwin.tar.xz": "5e5f06c2c7a0567bb096b676ecde4bc87cd56c1a60d5e99feb0ac0b679280e1a", + "dist/2022-09-20/rustfmt-nightly-aarch64-pc-windows-msvc.tar.gz": "f365e910e58e962526bc2ffc01b47ea7b99b2be199baeed82e3bb0609147994b", + "dist/2022-09-20/rustfmt-nightly-aarch64-pc-windows-msvc.tar.xz": "3e8a10a285b3c248691e20090d2805d0aabdfc0555a5463bc472899fba085759", + "dist/2022-09-20/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.gz": "4316414f83c30535f0c46efba5fd011755f4afa6cc3440b39e8ec154ae451b69", + "dist/2022-09-20/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.xz": "f3bf1d0198db6efb751fd61d096615d09dec94a2732b028728d74a3513e9bc47", + "dist/2022-09-20/rustfmt-nightly-aarch64-unknown-linux-musl.tar.gz": "d0f4c30d1ed5144ce0a2931290cb730efa5616375ff846692faba0f04b2fed4a", + "dist/2022-09-20/rustfmt-nightly-aarch64-unknown-linux-musl.tar.xz": "3c20a791400f994ea5ae681700e9bd1773b9203821a5458448a038b70fe98794", + "dist/2022-09-20/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.gz": "587eabfb4ab41ec7fc1f344f8d8674feb1787cb402dbc10754c43eb9352233f6", + "dist/2022-09-20/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.xz": "0f5c05ce846c42f4afd9127fa5bc0af070e7a03911ed93630177d6304ec66fe9", + "dist/2022-09-20/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.gz": "dfcab7b0d9b93e1ce639a7a1b9774a41e1e70b67fb91814393531476e7ff6d97", + "dist/2022-09-20/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.xz": "aa66edb8208b73e3dc939ce82afb78b9104022427fc2278a50ca004c54b1fd5e", + "dist/2022-09-20/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.gz": "9d31be70cf5aa67219bf85e303651b928e89f54831a14ad004ef606291206991", + "dist/2022-09-20/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.xz": "8b1249489bbf015af1865ddeb83560fbbc52ca84937e14a2ae928eb4fa854322", + "dist/2022-09-20/rustfmt-nightly-i686-pc-windows-gnu.tar.gz": "4154363e7fc7888088ba020c7454a2e0ea75a64e01532ccc709dba3a16c48d78", + "dist/2022-09-20/rustfmt-nightly-i686-pc-windows-gnu.tar.xz": "48ba35bdfe87b78428fde9b7ff6fbd7682d7f94113b874e8308bd3c5e734154c", + "dist/2022-09-20/rustfmt-nightly-i686-pc-windows-msvc.tar.gz": "bf42294f1c3053b8ff6dcf13219056a5e83fb0680e5e53621c626f825f2f11c6", + "dist/2022-09-20/rustfmt-nightly-i686-pc-windows-msvc.tar.xz": "a08b27ac0b47af60618f07d884320e80665eab550536e19828b5fe139a59499d", + "dist/2022-09-20/rustfmt-nightly-i686-unknown-linux-gnu.tar.gz": "748c42c63c3363d820b132a96bd95cd5203c5f808fb4885710065b9c609ae183", + "dist/2022-09-20/rustfmt-nightly-i686-unknown-linux-gnu.tar.xz": "a2bfe3e12d0ecb5881a749a3d11652d45efcd9ee3647ea7c6b6cbc94071e34e4", + "dist/2022-09-20/rustfmt-nightly-mips-unknown-linux-gnu.tar.gz": "a26f46c9d777ca55db8ef595219aea45c3ff7547ee7cfe07d01b9535dc00e1dd", + "dist/2022-09-20/rustfmt-nightly-mips-unknown-linux-gnu.tar.xz": "d3ba043430fb0177023d4028c90a797d9b469d4c2fb2c539bb52e2dd070723cb", + "dist/2022-09-20/rustfmt-nightly-mips64-unknown-linux-gnuabi64.tar.gz": "1f7b83d238dcd63de150d5fe457b8c04347626a583f049cac7989644787c2432", + "dist/2022-09-20/rustfmt-nightly-mips64-unknown-linux-gnuabi64.tar.xz": "25f682b00e0362c16cb8d9879854d0a9781dd7a1e0f980a0c5064fad3764e8ef", + "dist/2022-09-20/rustfmt-nightly-mips64el-unknown-linux-gnuabi64.tar.gz": "09aaccf92485ad1d69623410f947b264835236d20472f974e348015bb8d2353f", + "dist/2022-09-20/rustfmt-nightly-mips64el-unknown-linux-gnuabi64.tar.xz": "cff865ff4979885f158af7b437ebe67ea2645489a6067abd97eeaa97b57041d8", + "dist/2022-09-20/rustfmt-nightly-mipsel-unknown-linux-gnu.tar.gz": "1ca400758f5e44fa8ed01d8fc6d5622259cde42597fe80dc5e0e1b4129270c77", + "dist/2022-09-20/rustfmt-nightly-mipsel-unknown-linux-gnu.tar.xz": "bd71382043ea4e934640a60660169d8785af453415d88945066bd6b8a42b0099", + "dist/2022-09-20/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.gz": "86feeca2cb543476419583bc1b10dbf8d91afd25ac77a9f04f789aff4f34e3e6", + "dist/2022-09-20/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.xz": "2ce655da2899200f9e4a331a45f005f4faea11cfdf5b74397a68d376dab88bf9", + "dist/2022-09-20/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.gz": "ed7e14c85bb1dd2900991775e812c56a76891a70dbea013bff06f73e7d1beaba", + "dist/2022-09-20/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.xz": "09710d4622fd7a9695d3907be6433c69f2ff590415fab776a05ba74ea5be63a9", + "dist/2022-09-20/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.gz": "02da320a5aac0eaffa83cd49b37d0cbcecab7686cef166f30dd5ed02fa9cb023", + "dist/2022-09-20/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.xz": "1f4465079a5493ec23f433cae4af3f633885b38f6ba7693387ccd355010b955e", + "dist/2022-09-20/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.gz": "a9a3bdba43897b0ab44c54537ce80fc969c378480348af715e293403b55b83be", + "dist/2022-09-20/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.xz": "2d58863182dac199cde47e12d3d92a64b5d068afc7e97e1047ae8b369fbe6df9", + "dist/2022-09-20/rustfmt-nightly-s390x-unknown-linux-gnu.tar.gz": "002667d802f1ff1224318c2090caaa3eefd18dabd1bcd40ad957b0c09acd047a", + "dist/2022-09-20/rustfmt-nightly-s390x-unknown-linux-gnu.tar.xz": "a34aa6451cf5faf985967ec5df78a41b21ae317bba7f8836e09f87571a7f9c16", + "dist/2022-09-20/rustfmt-nightly-x86_64-apple-darwin.tar.gz": "8950773a8433fcc68f16c1e07210c3cf07c9e9240df92b0a90c67ca285d932f8", + "dist/2022-09-20/rustfmt-nightly-x86_64-apple-darwin.tar.xz": "1ce5bb4a0a3490f95037a1512f4b5539c65bfdc5d7f6d42005019345bedb71e8", + "dist/2022-09-20/rustfmt-nightly-x86_64-pc-windows-gnu.tar.gz": "cdbef502285d5eec5788299354f391a2263858d630466cd1cc6d48748aefb1af", + "dist/2022-09-20/rustfmt-nightly-x86_64-pc-windows-gnu.tar.xz": "d5e04d0abda5e8ec429794a58f6404a6b95cc66cb218a52299c3bfaf1ec35485", + "dist/2022-09-20/rustfmt-nightly-x86_64-pc-windows-msvc.tar.gz": "d1ec51e70918e4f50463839eb86528582424d69eecc6af5cd07987621acc713e", + "dist/2022-09-20/rustfmt-nightly-x86_64-pc-windows-msvc.tar.xz": "64a108e60c1ff0e1c004d63e13a8180e5b266382e8434aa94eaff3c654158e51", + "dist/2022-09-20/rustfmt-nightly-x86_64-unknown-freebsd.tar.gz": "d439ce2780177b3123de9a4c6727ea19831a215d19363d12b0bcc3bc19fc5074", + "dist/2022-09-20/rustfmt-nightly-x86_64-unknown-freebsd.tar.xz": "851adf8da102068b4195a78ba587e168b7c4471b5a2e66451385a503362d091d", + "dist/2022-09-20/rustfmt-nightly-x86_64-unknown-illumos.tar.gz": "7bad988696f60f49c0ab1929f8cfe843effaa455ab1d20b002dadd1e10bc4ded", + "dist/2022-09-20/rustfmt-nightly-x86_64-unknown-illumos.tar.xz": "8bee32774f9af0b6f382640592b65d4187401a59bd3bea4a139e2dc43471bc0c", + "dist/2022-09-20/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.gz": "16a3ff01a6bc471da2195c7e8d0a6623b911d956db388b66e39096a7c81ae1d4", + "dist/2022-09-20/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.xz": "721115ea0ec7902f74d203eaadc71c79c4489caf9a23b0a81c513fddce5fb9b2", + "dist/2022-09-20/rustfmt-nightly-x86_64-unknown-linux-musl.tar.gz": "9042aba5f18ef575cff2e106c34b707d8fe013f4140e4a066ce80f2103563809", + "dist/2022-09-20/rustfmt-nightly-x86_64-unknown-linux-musl.tar.xz": "9106ee07a9f173ae845ae2b5ce30798e15deffd46149430ec5aacceaed7848b8", + "dist/2022-09-20/rustfmt-nightly-x86_64-unknown-netbsd.tar.gz": "9acb78526c40efdfa0087373d802b30b75238e4c46e0bb18262e16416be49b4b", + "dist/2022-09-20/rustfmt-nightly-x86_64-unknown-netbsd.tar.xz": "c7a73c5b9034417998800dabb08ba71e12713a299457381a4437ea454cead1bd" } } From 3975d55d9888392cd738708b914442de9ac2bff5 Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Tue, 20 Sep 2022 15:41:42 +0200 Subject: [PATCH 259/586] remove cfg(bootstrap) --- compiler/rustc_ast/src/ast.rs | 1 - compiler/rustc_ast/src/lib.rs | 2 - compiler/rustc_ast_lowering/src/lib.rs | 1 - compiler/rustc_ast_passes/src/lib.rs | 1 - compiler/rustc_attr/src/lib.rs | 1 - compiler/rustc_borrowck/src/lib.rs | 1 - compiler/rustc_builtin_macros/src/lib.rs | 1 - compiler/rustc_codegen_llvm/src/lib.rs | 1 - compiler/rustc_codegen_ssa/src/lib.rs | 1 - .../rustc_const_eval/src/interpret/operand.rs | 2 +- .../rustc_const_eval/src/interpret/place.rs | 2 - compiler/rustc_const_eval/src/lib.rs | 1 - compiler/rustc_data_structures/src/lib.rs | 1 - compiler/rustc_driver/src/lib.rs | 1 - compiler/rustc_errors/src/lib.rs | 3 +- compiler/rustc_expand/src/lib.rs | 1 - compiler/rustc_hir/src/hir.rs | 5 - compiler/rustc_hir/src/lib.rs | 1 - compiler/rustc_incremental/src/lib.rs | 1 - compiler/rustc_index/src/lib.rs | 1 - compiler/rustc_infer/src/lib.rs | 2 - compiler/rustc_interface/src/lib.rs | 1 - compiler/rustc_lint/src/lib.rs | 2 +- compiler/rustc_macros/src/lib.rs | 1 - compiler/rustc_metadata/src/lib.rs | 2 - compiler/rustc_middle/src/lib.rs | 2 - compiler/rustc_middle/src/mir/syntax.rs | 1 - compiler/rustc_middle/src/thir.rs | 4 - compiler/rustc_mir_build/src/lib.rs | 1 - compiler/rustc_mir_dataflow/src/lib.rs | 1 - compiler/rustc_mir_transform/src/lib.rs | 1 - compiler/rustc_monomorphize/src/lib.rs | 1 - compiler/rustc_parse/src/lib.rs | 1 - compiler/rustc_passes/src/lib.rs | 1 - compiler/rustc_privacy/src/lib.rs | 1 - compiler/rustc_query_system/src/lib.rs | 1 - compiler/rustc_resolve/src/lib.rs | 1 - compiler/rustc_save_analysis/src/lib.rs | 1 - compiler/rustc_serialize/src/lib.rs | 1 - compiler/rustc_session/src/lib.rs | 1 - compiler/rustc_span/src/lib.rs | 1 - compiler/rustc_target/src/lib.rs | 1 - compiler/rustc_trait_selection/src/lib.rs | 2 - compiler/rustc_traits/src/lib.rs | 1 - compiler/rustc_ty_utils/src/lib.rs | 1 - compiler/rustc_typeck/src/lib.rs | 2 - library/alloc/src/boxed.rs | 14 - library/alloc/src/boxed/thin.rs | 2 - .../alloc/src/collections/btree/map/entry.rs | 1 - library/alloc/src/collections/mod.rs | 1 - library/alloc/src/ffi/c_str.rs | 3 - library/alloc/src/lib.rs | 7 +- library/alloc/src/string.rs | 3 - library/alloc/src/sync.rs | 1 - library/core/src/alloc/layout.rs | 2 - library/core/src/alloc/mod.rs | 2 - library/core/src/array/mod.rs | 2 - library/core/src/char/decode.rs | 2 - library/core/src/char/mod.rs | 2 - library/core/src/convert/mod.rs | 2 - library/core/src/intrinsics.rs | 65 -- library/core/src/lib.rs | 1 - library/core/src/marker.rs | 2 +- library/core/src/mem/transmutability.rs | 4 +- library/core/src/num/error.rs | 3 - library/core/src/num/mod.rs | 2 - library/core/src/ops/generator.rs | 1 - library/core/src/ops/try_trait.rs | 84 +- library/core/src/ptr/const_ptr.rs | 1 - library/core/src/ptr/mut_ptr.rs | 1 - library/core/src/str/error.rs | 3 - library/core/src/str/mod.rs | 1 - library/std/src/collections/hash/map.rs | 2 - library/std/src/error.rs | 1023 ----------------- library/std/src/io/error.rs | 1 - library/std/src/lib.rs | 8 +- library/std/src/rt.rs | 5 +- src/librustdoc/clean/types.rs | 1 - src/librustdoc/lib.rs | 2 - src/test/mir-opt/issue-101867.rs | 1 - src/test/ui/let-else/const-fn.rs | 1 - src/tools/clippy/clippy_dev/src/lib.rs | 1 - src/tools/clippy/clippy_lints/src/lib.rs | 1 - src/tools/clippy/clippy_utils/src/lib.rs | 1 - 84 files changed, 15 insertions(+), 1308 deletions(-) diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 6c514c75a500c..0efde1e7b2124 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -3046,7 +3046,6 @@ mod size_asserts { static_assert_size!(Block, 48); static_assert_size!(Expr, 104); static_assert_size!(ExprKind, 72); - #[cfg(not(bootstrap))] static_assert_size!(Fn, 184); static_assert_size!(ForeignItem, 96); static_assert_size!(ForeignItemKind, 24); diff --git a/compiler/rustc_ast/src/lib.rs b/compiler/rustc_ast/src/lib.rs index bd7a85b07a09e..eeb7e56e2b124 100644 --- a/compiler/rustc_ast/src/lib.rs +++ b/compiler/rustc_ast/src/lib.rs @@ -13,9 +13,7 @@ #![feature(const_default_impls)] #![feature(const_trait_impl)] #![feature(if_let_guard)] -#![cfg_attr(bootstrap, feature(label_break_value))] #![feature(let_chains)] -#![cfg_attr(bootstrap, feature(let_else))] #![feature(min_specialization)] #![feature(negative_impls)] #![feature(slice_internals)] diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 186c10065f306..275ceed30d7da 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -32,7 +32,6 @@ #![feature(box_patterns)] #![feature(let_chains)] -#![cfg_attr(bootstrap, feature(let_else))] #![feature(never_type)] #![recursion_limit = "256"] #![allow(rustc::potential_query_instability)] diff --git a/compiler/rustc_ast_passes/src/lib.rs b/compiler/rustc_ast_passes/src/lib.rs index 8aa9d57f046a9..f58fffc917200 100644 --- a/compiler/rustc_ast_passes/src/lib.rs +++ b/compiler/rustc_ast_passes/src/lib.rs @@ -9,7 +9,6 @@ #![feature(if_let_guard)] #![feature(iter_is_partitioned)] #![feature(let_chains)] -#![cfg_attr(bootstrap, feature(let_else))] #![recursion_limit = "256"] #[macro_use] diff --git a/compiler/rustc_attr/src/lib.rs b/compiler/rustc_attr/src/lib.rs index 52e65a9c7743d..4580ffcc6d8be 100644 --- a/compiler/rustc_attr/src/lib.rs +++ b/compiler/rustc_attr/src/lib.rs @@ -5,7 +5,6 @@ //! to this crate. #![feature(let_chains)] -#![cfg_attr(bootstrap, feature(let_else))] #![deny(rustc::untranslatable_diagnostic)] #![deny(rustc::diagnostic_outside_of_impl)] diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 6b90f2daeea3c..a83840e10998a 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -3,7 +3,6 @@ #![allow(rustc::potential_query_instability)] #![feature(box_patterns)] #![feature(let_chains)] -#![cfg_attr(bootstrap, feature(let_else))] #![feature(min_specialization)] #![feature(never_type)] #![feature(rustc_attrs)] diff --git a/compiler/rustc_builtin_macros/src/lib.rs b/compiler/rustc_builtin_macros/src/lib.rs index 8aeb3b82a9cd0..0de27d3d4070e 100644 --- a/compiler/rustc_builtin_macros/src/lib.rs +++ b/compiler/rustc_builtin_macros/src/lib.rs @@ -9,7 +9,6 @@ #![feature(if_let_guard)] #![feature(is_sorted)] #![feature(let_chains)] -#![cfg_attr(bootstrap, feature(let_else))] #![feature(proc_macro_internals)] #![feature(proc_macro_quote)] #![recursion_limit = "256"] diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs index 42c65e04e3b6b..15bfa8430460f 100644 --- a/compiler/rustc_codegen_llvm/src/lib.rs +++ b/compiler/rustc_codegen_llvm/src/lib.rs @@ -7,7 +7,6 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![feature(hash_raw_entry)] #![feature(let_chains)] -#![cfg_attr(bootstrap, feature(let_else))] #![feature(extern_types)] #![feature(once_cell)] #![feature(iter_intersperse)] diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs index e736b2aba9c14..3ef9a634e1857 100644 --- a/compiler/rustc_codegen_ssa/src/lib.rs +++ b/compiler/rustc_codegen_ssa/src/lib.rs @@ -1,7 +1,6 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![feature(box_patterns)] #![feature(try_blocks)] -#![cfg_attr(bootstrap, feature(let_else))] #![feature(once_cell)] #![feature(associated_type_bounds)] #![feature(strict_provenance)] diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs index dc5305aabcf89..510adde62962b 100644 --- a/compiler/rustc_const_eval/src/interpret/operand.rs +++ b/compiler/rustc_const_eval/src/interpret/operand.rs @@ -784,7 +784,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } // Some nodes are used a lot. Make sure they don't unintentionally get bigger. -#[cfg(all(target_arch = "x86_64", target_pointer_width = "64", not(bootstrap)))] +#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] mod size_asserts { use super::*; use rustc_data_structures::static_assert_size; diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs index bc1aa43b73a99..7a01b85381a3f 100644 --- a/compiler/rustc_const_eval/src/interpret/place.rs +++ b/compiler/rustc_const_eval/src/interpret/place.rs @@ -890,8 +890,6 @@ mod size_asserts { static_assert_size!(MemPlaceMeta, 24); static_assert_size!(MemPlace, 40); static_assert_size!(MPlaceTy<'_>, 64); - #[cfg(not(bootstrap))] static_assert_size!(Place, 40); - #[cfg(not(bootstrap))] static_assert_size!(PlaceTy<'_>, 64); } diff --git a/compiler/rustc_const_eval/src/lib.rs b/compiler/rustc_const_eval/src/lib.rs index 9f47d302a0c3d..7c4c7db1035b4 100644 --- a/compiler/rustc_const_eval/src/lib.rs +++ b/compiler/rustc_const_eval/src/lib.rs @@ -10,7 +10,6 @@ Rust MIR: a lowered representation of Rust. #![feature(decl_macro)] #![feature(exact_size_is_empty)] #![feature(let_chains)] -#![cfg_attr(bootstrap, feature(let_else))] #![feature(map_try_insert)] #![feature(min_specialization)] #![feature(slice_ptr_get)] diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs index 56f7823efe0c2..467ac401d086b 100644 --- a/compiler/rustc_data_structures/src/lib.rs +++ b/compiler/rustc_data_structures/src/lib.rs @@ -13,7 +13,6 @@ #![feature(cell_leak)] #![feature(control_flow_enum)] #![feature(extend_one)] -#![cfg_attr(bootstrap, feature(let_else))] #![feature(hash_raw_entry)] #![feature(hasher_prefixfree_extras)] #![feature(maybe_uninit_uninit_array)] diff --git a/compiler/rustc_driver/src/lib.rs b/compiler/rustc_driver/src/lib.rs index c768935eb6238..fcd49f5d01567 100644 --- a/compiler/rustc_driver/src/lib.rs +++ b/compiler/rustc_driver/src/lib.rs @@ -5,7 +5,6 @@ //! This API is completely unstable and subject to change. #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] -#![cfg_attr(bootstrap, feature(let_else))] #![feature(once_cell)] #![recursion_limit = "256"] #![allow(rustc::potential_query_instability)] diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index b44cf352233e3..4d262ae0f5ec8 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -7,7 +7,6 @@ #![feature(if_let_guard)] #![feature(adt_const_params)] #![feature(let_chains)] -#![cfg_attr(bootstrap, feature(let_else))] #![feature(never_type)] #![feature(result_option_inspect)] #![feature(rustc_attrs)] @@ -69,7 +68,7 @@ pub type PResult<'a, T> = Result>; // (See also the comment on `DiagnosticBuilder`'s `diagnostic` field.) #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] rustc_data_structures::static_assert_size!(PResult<'_, ()>, 16); -#[cfg(all(target_arch = "x86_64", target_pointer_width = "64", not(bootstrap)))] +#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] rustc_data_structures::static_assert_size!(PResult<'_, bool>, 16); #[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, Encodable, Decodable)] diff --git a/compiler/rustc_expand/src/lib.rs b/compiler/rustc_expand/src/lib.rs index ffc9abe64d2ea..b34de94fb7db4 100644 --- a/compiler/rustc_expand/src/lib.rs +++ b/compiler/rustc_expand/src/lib.rs @@ -3,7 +3,6 @@ #![feature(associated_type_defaults)] #![feature(if_let_guard)] #![feature(let_chains)] -#![cfg_attr(bootstrap, feature(let_else))] #![feature(macro_metavar_expr)] #![feature(proc_macro_diagnostic)] #![feature(proc_macro_internals)] diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 018b7cc5d9dfe..c1948052e3c51 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -3520,14 +3520,11 @@ mod size_asserts { static_assert_size!(FnDecl<'_>, 40); static_assert_size!(ForeignItem<'_>, 72); static_assert_size!(ForeignItemKind<'_>, 40); - #[cfg(not(bootstrap))] static_assert_size!(GenericArg<'_>, 24); static_assert_size!(GenericBound<'_>, 48); static_assert_size!(Generics<'_>, 56); static_assert_size!(Impl<'_>, 80); - #[cfg(not(bootstrap))] static_assert_size!(ImplItem<'_>, 80); - #[cfg(not(bootstrap))] static_assert_size!(ImplItemKind<'_>, 32); static_assert_size!(Item<'_>, 80); static_assert_size!(ItemKind<'_>, 48); @@ -3540,9 +3537,7 @@ mod size_asserts { static_assert_size!(QPath<'_>, 24); static_assert_size!(Stmt<'_>, 32); static_assert_size!(StmtKind<'_>, 16); - #[cfg(not(bootstrap))] static_assert_size!(TraitItem<'_>, 88); - #[cfg(not(bootstrap))] static_assert_size!(TraitItemKind<'_>, 48); static_assert_size!(Ty<'_>, 48); static_assert_size!(TyKind<'_>, 32); diff --git a/compiler/rustc_hir/src/lib.rs b/compiler/rustc_hir/src/lib.rs index 556ff1cc48e4d..1c4aa420c9bf9 100644 --- a/compiler/rustc_hir/src/lib.rs +++ b/compiler/rustc_hir/src/lib.rs @@ -5,7 +5,6 @@ #![feature(associated_type_defaults)] #![feature(closure_track_caller)] #![feature(const_btree_len)] -#![cfg_attr(bootstrap, feature(let_else))] #![feature(once_cell)] #![feature(min_specialization)] #![feature(never_type)] diff --git a/compiler/rustc_incremental/src/lib.rs b/compiler/rustc_incremental/src/lib.rs index 2c9e21f769fb1..83dd9a67e61bc 100644 --- a/compiler/rustc_incremental/src/lib.rs +++ b/compiler/rustc_incremental/src/lib.rs @@ -2,7 +2,6 @@ #![deny(missing_docs)] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] -#![cfg_attr(bootstrap, feature(let_else))] #![recursion_limit = "256"] #![allow(rustc::potential_query_instability)] diff --git a/compiler/rustc_index/src/lib.rs b/compiler/rustc_index/src/lib.rs index a00d7bd680147..9753fb355308c 100644 --- a/compiler/rustc_index/src/lib.rs +++ b/compiler/rustc_index/src/lib.rs @@ -3,7 +3,6 @@ #![feature(allow_internal_unstable)] #![feature(bench_black_box)] #![feature(extend_one)] -#![cfg_attr(bootstrap, feature(let_else))] #![feature(min_specialization)] #![feature(new_uninit)] #![feature(step_trait)] diff --git a/compiler/rustc_infer/src/lib.rs b/compiler/rustc_infer/src/lib.rs index 909a597e22135..b91c098ab03db 100644 --- a/compiler/rustc_infer/src/lib.rs +++ b/compiler/rustc_infer/src/lib.rs @@ -17,9 +17,7 @@ #![feature(box_patterns)] #![feature(control_flow_enum)] #![feature(extend_one)] -#![cfg_attr(bootstrap, feature(label_break_value))] #![feature(let_chains)] -#![cfg_attr(bootstrap, feature(let_else))] #![feature(if_let_guard)] #![feature(min_specialization)] #![feature(never_type)] diff --git a/compiler/rustc_interface/src/lib.rs b/compiler/rustc_interface/src/lib.rs index 41cd7b0e9b1d6..a41a749ee68e5 100644 --- a/compiler/rustc_interface/src/lib.rs +++ b/compiler/rustc_interface/src/lib.rs @@ -1,5 +1,4 @@ #![feature(box_patterns)] -#![cfg_attr(bootstrap, feature(let_else))] #![feature(internal_output_capture)] #![feature(thread_spawn_unchecked)] #![feature(once_cell)] diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index 752a751f6bcf5..4408f68dd63f3 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -34,7 +34,7 @@ #![feature(iter_intersperse)] #![feature(iter_order_by)] #![feature(let_chains)] -#![cfg_attr(bootstrap, feature(let_else))] +#![feature(min_specialization)] #![feature(never_type)] #![recursion_limit = "256"] diff --git a/compiler/rustc_macros/src/lib.rs b/compiler/rustc_macros/src/lib.rs index 8fd23ee5ced99..36bda3e0f6bb2 100644 --- a/compiler/rustc_macros/src/lib.rs +++ b/compiler/rustc_macros/src/lib.rs @@ -1,5 +1,4 @@ #![feature(allow_internal_unstable)] -#![cfg_attr(bootstrap, feature(let_else))] #![feature(never_type)] #![feature(proc_macro_diagnostic)] #![feature(proc_macro_span)] diff --git a/compiler/rustc_metadata/src/lib.rs b/compiler/rustc_metadata/src/lib.rs index 6f5604b7e11f0..98cf6fef54a8f 100644 --- a/compiler/rustc_metadata/src/lib.rs +++ b/compiler/rustc_metadata/src/lib.rs @@ -2,10 +2,8 @@ #![feature(decl_macro)] #![feature(drain_filter)] #![feature(generators)] -#![cfg_attr(bootstrap, feature(generic_associated_types))] #![feature(iter_from_generator)] #![feature(let_chains)] -#![cfg_attr(bootstrap, feature(let_else))] #![feature(once_cell)] #![feature(proc_macro_internals)] #![feature(macro_metavar_expr)] diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs index 01b9277b98362..a180706e1cf0f 100644 --- a/compiler/rustc_middle/src/lib.rs +++ b/compiler/rustc_middle/src/lib.rs @@ -31,7 +31,6 @@ #![feature(discriminant_kind)] #![feature(exhaustive_patterns)] #![feature(get_mut_unchecked)] -#![cfg_attr(bootstrap, feature(generic_associated_types))] #![feature(if_let_guard)] #![feature(map_first_last)] #![feature(negative_impls)] @@ -40,7 +39,6 @@ #![feature(new_uninit)] #![feature(once_cell)] #![feature(let_chains)] -#![cfg_attr(bootstrap, feature(let_else))] #![feature(min_specialization)] #![feature(trusted_len)] #![feature(type_alias_impl_trait)] diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index 568d63fb06217..ee8377d1987c1 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -1242,7 +1242,6 @@ pub enum BinOp { mod size_asserts { use super::*; // These are in alphabetical order, which is easy to maintain. - #[cfg(not(bootstrap))] static_assert_size!(AggregateKind<'_>, 40); static_assert_size!(Operand<'_>, 24); static_assert_size!(Place<'_>, 16); diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs index 86b4150505fd9..84374a25ed85e 100644 --- a/compiler/rustc_middle/src/thir.rs +++ b/compiler/rustc_middle/src/thir.rs @@ -852,12 +852,8 @@ mod size_asserts { static_assert_size!(Block, 56); static_assert_size!(Expr<'_>, 64); static_assert_size!(ExprKind<'_>, 40); - #[cfg(not(bootstrap))] static_assert_size!(Pat<'_>, 72); - #[cfg(not(bootstrap))] static_assert_size!(PatKind<'_>, 56); - #[cfg(not(bootstrap))] static_assert_size!(Stmt<'_>, 48); - #[cfg(not(bootstrap))] static_assert_size!(StmtKind<'_>, 40); } diff --git a/compiler/rustc_mir_build/src/lib.rs b/compiler/rustc_mir_build/src/lib.rs index 0c0a2fe9c9ed6..8236b1528c0ec 100644 --- a/compiler/rustc_mir_build/src/lib.rs +++ b/compiler/rustc_mir_build/src/lib.rs @@ -6,7 +6,6 @@ #![feature(control_flow_enum)] #![feature(if_let_guard)] #![feature(let_chains)] -#![cfg_attr(bootstrap, feature(let_else))] #![feature(min_specialization)] #![feature(once_cell)] #![recursion_limit = "256"] diff --git a/compiler/rustc_mir_dataflow/src/lib.rs b/compiler/rustc_mir_dataflow/src/lib.rs index b45c32ee986b6..b471d04fd606f 100644 --- a/compiler/rustc_mir_dataflow/src/lib.rs +++ b/compiler/rustc_mir_dataflow/src/lib.rs @@ -1,7 +1,6 @@ #![feature(associated_type_defaults)] #![feature(box_patterns)] #![feature(exact_size_is_empty)] -#![cfg_attr(bootstrap, feature(let_else))] #![feature(min_specialization)] #![feature(once_cell)] #![feature(stmt_expr_attributes)] diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index e6fc85595714b..2230c3399f0f8 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -1,7 +1,6 @@ #![allow(rustc::potential_query_instability)] #![feature(box_patterns)] #![feature(let_chains)] -#![cfg_attr(bootstrap, feature(let_else))] #![feature(map_try_insert)] #![feature(min_specialization)] #![feature(never_type)] diff --git a/compiler/rustc_monomorphize/src/lib.rs b/compiler/rustc_monomorphize/src/lib.rs index ba6ce9fd40f63..42781bd25f05b 100644 --- a/compiler/rustc_monomorphize/src/lib.rs +++ b/compiler/rustc_monomorphize/src/lib.rs @@ -1,6 +1,5 @@ #![feature(array_windows)] #![feature(control_flow_enum)] -#![cfg_attr(bootstrap, feature(let_else))] #![recursion_limit = "256"] #![allow(rustc::potential_query_instability)] #![deny(rustc::untranslatable_diagnostic)] diff --git a/compiler/rustc_parse/src/lib.rs b/compiler/rustc_parse/src/lib.rs index a37327f42942a..06245380927c3 100644 --- a/compiler/rustc_parse/src/lib.rs +++ b/compiler/rustc_parse/src/lib.rs @@ -4,7 +4,6 @@ #![feature(box_patterns)] #![feature(if_let_guard)] #![feature(let_chains)] -#![cfg_attr(bootstrap, feature(let_else))] #![feature(never_type)] #![feature(rustc_attrs)] #![recursion_limit = "256"] diff --git a/compiler/rustc_passes/src/lib.rs b/compiler/rustc_passes/src/lib.rs index 39ebb8db21cbc..6e621b7eb5eb0 100644 --- a/compiler/rustc_passes/src/lib.rs +++ b/compiler/rustc_passes/src/lib.rs @@ -8,7 +8,6 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![feature(iter_intersperse)] #![feature(let_chains)] -#![cfg_attr(bootstrap, feature(let_else))] #![feature(map_try_insert)] #![feature(min_specialization)] #![feature(try_blocks)] diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 728674472505c..41d5f54b3664f 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -1,7 +1,6 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![feature(associated_type_defaults)] #![feature(control_flow_enum)] -#![cfg_attr(bootstrap, feature(let_else))] #![feature(rustc_private)] #![feature(try_blocks)] #![recursion_limit = "256"] diff --git a/compiler/rustc_query_system/src/lib.rs b/compiler/rustc_query_system/src/lib.rs index 5987651322af7..8f6da73d1f2d2 100644 --- a/compiler/rustc_query_system/src/lib.rs +++ b/compiler/rustc_query_system/src/lib.rs @@ -1,7 +1,6 @@ #![feature(assert_matches)] #![feature(core_intrinsics)] #![feature(hash_raw_entry)] -#![cfg_attr(bootstrap, feature(let_else))] #![feature(min_specialization)] #![feature(extern_types)] #![allow(rustc::potential_query_instability)] diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 54a7f416ce64c..583030b0e5048 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -12,7 +12,6 @@ #![feature(if_let_guard)] #![feature(iter_intersperse)] #![feature(let_chains)] -#![cfg_attr(bootstrap, feature(let_else))] #![feature(never_type)] #![recursion_limit = "256"] #![allow(rustdoc::private_intra_doc_links)] diff --git a/compiler/rustc_save_analysis/src/lib.rs b/compiler/rustc_save_analysis/src/lib.rs index 1a3511a1dc8bc..ad7aca3cb9494 100644 --- a/compiler/rustc_save_analysis/src/lib.rs +++ b/compiler/rustc_save_analysis/src/lib.rs @@ -1,6 +1,5 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![feature(if_let_guard)] -#![cfg_attr(bootstrap, feature(let_else))] #![recursion_limit = "256"] #![allow(rustc::potential_query_instability)] #![feature(never_type)] diff --git a/compiler/rustc_serialize/src/lib.rs b/compiler/rustc_serialize/src/lib.rs index fa9c7bd54c395..1f8d2336c4e58 100644 --- a/compiler/rustc_serialize/src/lib.rs +++ b/compiler/rustc_serialize/src/lib.rs @@ -14,7 +14,6 @@ Core encoding and decoding interfaces. #![feature(min_specialization)] #![feature(core_intrinsics)] #![feature(maybe_uninit_slice)] -#![cfg_attr(bootstrap, feature(let_else))] #![feature(new_uninit)] #![feature(allocator_api)] #![cfg_attr(test, feature(test))] diff --git a/compiler/rustc_session/src/lib.rs b/compiler/rustc_session/src/lib.rs index f6bab775e76b3..39e871f532c49 100644 --- a/compiler/rustc_session/src/lib.rs +++ b/compiler/rustc_session/src/lib.rs @@ -1,6 +1,5 @@ #![feature(if_let_guard)] #![feature(let_chains)] -#![cfg_attr(bootstrap, feature(let_else))] #![feature(min_specialization)] #![feature(never_type)] #![feature(once_cell)] diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index 366fd9d2cd1c3..f8df416971593 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -15,7 +15,6 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![feature(array_windows)] -#![cfg_attr(bootstrap, feature(let_else))] #![feature(if_let_guard)] #![feature(negative_impls)] #![feature(min_specialization)] diff --git a/compiler/rustc_target/src/lib.rs b/compiler/rustc_target/src/lib.rs index a7deab9d2efc8..aaba0d7f093ae 100644 --- a/compiler/rustc_target/src/lib.rs +++ b/compiler/rustc_target/src/lib.rs @@ -11,7 +11,6 @@ #![feature(assert_matches)] #![feature(associated_type_bounds)] #![feature(exhaustive_patterns)] -#![cfg_attr(bootstrap, feature(let_else))] #![feature(min_specialization)] #![feature(never_type)] #![feature(rustc_attrs)] diff --git a/compiler/rustc_trait_selection/src/lib.rs b/compiler/rustc_trait_selection/src/lib.rs index d35f74974fdd9..5d52aa0752301 100644 --- a/compiler/rustc_trait_selection/src/lib.rs +++ b/compiler/rustc_trait_selection/src/lib.rs @@ -16,9 +16,7 @@ #![feature(control_flow_enum)] #![feature(drain_filter)] #![feature(hash_drain_filter)] -#![cfg_attr(bootstrap, feature(label_break_value))] #![feature(let_chains)] -#![cfg_attr(bootstrap, feature(let_else))] #![feature(if_let_guard)] #![feature(never_type)] #![feature(type_alias_impl_trait)] diff --git a/compiler/rustc_traits/src/lib.rs b/compiler/rustc_traits/src/lib.rs index 2d39e973ed9bb..0da28737f69bc 100644 --- a/compiler/rustc_traits/src/lib.rs +++ b/compiler/rustc_traits/src/lib.rs @@ -3,7 +3,6 @@ #![deny(rustc::untranslatable_diagnostic)] #![deny(rustc::diagnostic_outside_of_impl)] -#![cfg_attr(bootstrap, feature(let_else))] #![recursion_limit = "256"] #[macro_use] diff --git a/compiler/rustc_ty_utils/src/lib.rs b/compiler/rustc_ty_utils/src/lib.rs index 8524e57cb58a3..10c18789f7476 100644 --- a/compiler/rustc_ty_utils/src/lib.rs +++ b/compiler/rustc_ty_utils/src/lib.rs @@ -6,7 +6,6 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![feature(control_flow_enum)] -#![cfg_attr(bootstrap, feature(let_else))] #![feature(never_type)] #![feature(box_patterns)] #![recursion_limit = "256"] diff --git a/compiler/rustc_typeck/src/lib.rs b/compiler/rustc_typeck/src/lib.rs index b1ce972e1d682..1859473166a78 100644 --- a/compiler/rustc_typeck/src/lib.rs +++ b/compiler/rustc_typeck/src/lib.rs @@ -64,9 +64,7 @@ This API is completely unstable and subject to change. #![feature(if_let_guard)] #![feature(is_sorted)] #![feature(iter_intersperse)] -#![cfg_attr(bootstrap, feature(label_break_value))] #![feature(let_chains)] -#![cfg_attr(bootstrap, feature(let_else))] #![feature(min_specialization)] #![feature(never_type)] #![feature(once_cell)] diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index 0aff1323f976e..f651cb0217698 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -151,7 +151,6 @@ use core::async_iter::AsyncIterator; use core::borrow; use core::cmp::Ordering; use core::convert::{From, TryFrom}; -#[cfg(not(bootstrap))] use core::error::Error; use core::fmt; use core::future::Future; @@ -176,7 +175,6 @@ use crate::borrow::Cow; use crate::raw_vec::RawVec; #[cfg(not(no_global_oom_handling))] use crate::str::from_boxed_utf8_unchecked; -#[cfg(not(bootstrap))] #[cfg(not(no_global_oom_handling))] use crate::string::String; #[cfg(not(no_global_oom_handling))] @@ -2090,7 +2088,6 @@ impl AsyncIterator for Box { } } -#[cfg(not(bootstrap))] impl dyn Error { #[inline] #[stable(feature = "error_downcast", since = "1.3.0")] @@ -2108,7 +2105,6 @@ impl dyn Error { } } -#[cfg(not(bootstrap))] impl dyn Error + Send { #[inline] #[stable(feature = "error_downcast", since = "1.3.0")] @@ -2123,7 +2119,6 @@ impl dyn Error + Send { } } -#[cfg(not(bootstrap))] impl dyn Error + Send + Sync { #[inline] #[stable(feature = "error_downcast", since = "1.3.0")] @@ -2138,7 +2133,6 @@ impl dyn Error + Send + Sync { } } -#[cfg(not(bootstrap))] #[cfg(not(no_global_oom_handling))] #[stable(feature = "rust1", since = "1.0.0")] impl<'a, E: Error + 'a> From for Box { @@ -2172,7 +2166,6 @@ impl<'a, E: Error + 'a> From for Box { } } -#[cfg(not(bootstrap))] #[cfg(not(no_global_oom_handling))] #[stable(feature = "rust1", since = "1.0.0")] impl<'a, E: Error + Send + Sync + 'a> From for Box { @@ -2212,7 +2205,6 @@ impl<'a, E: Error + Send + Sync + 'a> From for Box for Box { @@ -2257,7 +2249,6 @@ impl From for Box { } } -#[cfg(not(bootstrap))] #[cfg(not(no_global_oom_handling))] #[stable(feature = "string_box_error", since = "1.6.0")] impl From for Box { @@ -2280,7 +2271,6 @@ impl From for Box { } } -#[cfg(not(bootstrap))] #[cfg(not(no_global_oom_handling))] #[stable(feature = "rust1", since = "1.0.0")] impl<'a> From<&str> for Box { @@ -2305,7 +2295,6 @@ impl<'a> From<&str> for Box { } } -#[cfg(not(bootstrap))] #[cfg(not(no_global_oom_handling))] #[stable(feature = "string_box_error", since = "1.6.0")] impl From<&str> for Box { @@ -2328,7 +2317,6 @@ impl From<&str> for Box { } } -#[cfg(not(bootstrap))] #[cfg(not(no_global_oom_handling))] #[stable(feature = "cow_box_error", since = "1.22.0")] impl<'a, 'b> From> for Box { @@ -2351,7 +2339,6 @@ impl<'a, 'b> From> for Box { } } -#[cfg(not(bootstrap))] #[cfg(not(no_global_oom_handling))] #[stable(feature = "cow_box_error", since = "1.22.0")] impl<'a> From> for Box { @@ -2373,7 +2360,6 @@ impl<'a> From> for Box { } } -#[cfg(not(bootstrap))] #[stable(feature = "box_error", since = "1.8.0")] impl core::error::Error for Box { #[allow(deprecated, deprecated_in_future)] diff --git a/library/alloc/src/boxed/thin.rs b/library/alloc/src/boxed/thin.rs index 0a20c74b00fdc..c477c44906c97 100644 --- a/library/alloc/src/boxed/thin.rs +++ b/library/alloc/src/boxed/thin.rs @@ -2,7 +2,6 @@ // https://github.com/matthieu-m/rfc2580/blob/b58d1d3cba0d4b5e859d3617ea2d0943aaa31329/examples/thin.rs // by matthieu-m use crate::alloc::{self, Layout, LayoutError}; -#[cfg(not(bootstrap))] use core::error::Error; use core::fmt::{self, Debug, Display, Formatter}; use core::marker::PhantomData; @@ -274,7 +273,6 @@ impl WithHeader { } } -#[cfg(not(bootstrap))] #[unstable(feature = "thin_box", issue = "92791")] impl Error for ThinBox { fn source(&self) -> Option<&(dyn Error + 'static)> { diff --git a/library/alloc/src/collections/btree/map/entry.rs b/library/alloc/src/collections/btree/map/entry.rs index cd7cdc1920719..370b58864af8f 100644 --- a/library/alloc/src/collections/btree/map/entry.rs +++ b/library/alloc/src/collections/btree/map/entry.rs @@ -133,7 +133,6 @@ impl<'a, K: Debug + Ord, V: Debug, A: Allocator + Clone> fmt::Display } } -#[cfg(not(bootstrap))] #[unstable(feature = "map_try_insert", issue = "82766")] impl<'a, K: core::fmt::Debug + Ord, V: core::fmt::Debug> core::error::Error for crate::collections::btree_map::OccupiedError<'a, K, V> diff --git a/library/alloc/src/collections/mod.rs b/library/alloc/src/collections/mod.rs index 21d0def0866ed..161a375736c65 100644 --- a/library/alloc/src/collections/mod.rs +++ b/library/alloc/src/collections/mod.rs @@ -153,6 +153,5 @@ trait SpecExtend { fn spec_extend(&mut self, iter: I); } -#[cfg(not(bootstrap))] #[stable(feature = "try_reserve", since = "1.57.0")] impl core::error::Error for TryReserveError {} diff --git a/library/alloc/src/ffi/c_str.rs b/library/alloc/src/ffi/c_str.rs index aede6d54c6c17..11bd4c4dc1ba8 100644 --- a/library/alloc/src/ffi/c_str.rs +++ b/library/alloc/src/ffi/c_str.rs @@ -1122,7 +1122,6 @@ impl CStr { } } -#[cfg(not(bootstrap))] #[stable(feature = "rust1", since = "1.0.0")] impl core::error::Error for NulError { #[allow(deprecated)] @@ -1131,11 +1130,9 @@ impl core::error::Error for NulError { } } -#[cfg(not(bootstrap))] #[stable(feature = "cstring_from_vec_with_nul", since = "1.58.0")] impl core::error::Error for FromVecWithNulError {} -#[cfg(not(bootstrap))] #[stable(feature = "cstring_into", since = "1.7.0")] impl core::error::Error for IntoStringError { #[allow(deprecated)] diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index de58f22daae78..7fde8f670a231 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -114,8 +114,8 @@ #![feature(const_waker)] #![feature(cstr_from_bytes_until_nul)] #![feature(dispatch_from_dyn)] -#![cfg_attr(not(bootstrap), feature(error_generic_member_access))] -#![cfg_attr(not(bootstrap), feature(error_in_core))] +#![feature(error_generic_member_access)] +#![feature(error_in_core)] #![feature(exact_size_is_empty)] #![feature(extend_one)] #![feature(fmt_internals)] @@ -132,7 +132,7 @@ #![feature(nonnull_slice_from_raw_parts)] #![feature(pattern)] #![feature(pointer_byte_offsets)] -#![cfg_attr(not(bootstrap), feature(provide_any))] +#![feature(provide_any)] #![feature(ptr_internals)] #![feature(ptr_metadata)] #![feature(ptr_sub_ptr)] @@ -173,7 +173,6 @@ #![cfg_attr(not(test), feature(generator_trait))] #![feature(hashmap_internals)] #![feature(lang_items)] -#![cfg_attr(bootstrap, feature(let_else))] #![feature(min_specialization)] #![feature(negative_impls)] #![feature(never_type)] diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs index f2448396ce8db..983376a282be5 100644 --- a/library/alloc/src/string.rs +++ b/library/alloc/src/string.rs @@ -44,7 +44,6 @@ #[cfg(not(no_global_oom_handling))] use core::char::{decode_utf16, REPLACEMENT_CHARACTER}; -#[cfg(not(bootstrap))] use core::error::Error; use core::fmt; use core::hash; @@ -1941,7 +1940,6 @@ impl fmt::Display for FromUtf16Error { } } -#[cfg(not(bootstrap))] #[stable(feature = "rust1", since = "1.0.0")] impl Error for FromUtf8Error { #[allow(deprecated)] @@ -1950,7 +1948,6 @@ impl Error for FromUtf8Error { } } -#[cfg(not(bootstrap))] #[stable(feature = "rust1", since = "1.0.0")] impl Error for FromUtf16Error { #[allow(deprecated)] diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index 4377edeee8710..a5322953d4921 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -2764,7 +2764,6 @@ fn data_offset_align(align: usize) -> usize { layout.size() + layout.padding_needed_for(align) } -#[cfg(not(bootstrap))] #[stable(feature = "arc_error", since = "1.52.0")] impl core::error::Error for Arc { #[allow(deprecated, deprecated_in_future)] diff --git a/library/core/src/alloc/layout.rs b/library/core/src/alloc/layout.rs index f03502429ab21..5bb44b4085962 100644 --- a/library/core/src/alloc/layout.rs +++ b/library/core/src/alloc/layout.rs @@ -5,7 +5,6 @@ // Your performance intuition is useless. Run perf. use crate::cmp; -#[cfg(not(bootstrap))] use crate::error::Error; use crate::fmt; use crate::mem::{self, ValidAlign}; @@ -463,7 +462,6 @@ pub type LayoutErr = LayoutError; #[derive(Clone, PartialEq, Eq, Debug)] pub struct LayoutError; -#[cfg(not(bootstrap))] #[stable(feature = "alloc_layout", since = "1.28.0")] impl Error for LayoutError {} diff --git a/library/core/src/alloc/mod.rs b/library/core/src/alloc/mod.rs index 615531574786b..a4bf6a853a650 100644 --- a/library/core/src/alloc/mod.rs +++ b/library/core/src/alloc/mod.rs @@ -21,7 +21,6 @@ pub use self::layout::LayoutErr; #[stable(feature = "alloc_layout_error", since = "1.50.0")] pub use self::layout::LayoutError; -#[cfg(not(bootstrap))] use crate::error::Error; use crate::fmt; use crate::ptr::{self, NonNull}; @@ -34,7 +33,6 @@ use crate::ptr::{self, NonNull}; #[derive(Copy, Clone, PartialEq, Eq, Debug)] pub struct AllocError; -#[cfg(not(bootstrap))] #[unstable( feature = "allocator_api", reason = "the precise API and guarantees it provides may be tweaked.", diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs index 36e89a95fd212..b82bbf2267a96 100644 --- a/library/core/src/array/mod.rs +++ b/library/core/src/array/mod.rs @@ -7,7 +7,6 @@ use crate::borrow::{Borrow, BorrowMut}; use crate::cmp::Ordering; use crate::convert::{Infallible, TryFrom}; -#[cfg(not(bootstrap))] use crate::error::Error; use crate::fmt; use crate::hash::{self, Hash}; @@ -121,7 +120,6 @@ impl fmt::Display for TryFromSliceError { } } -#[cfg(not(bootstrap))] #[stable(feature = "try_from", since = "1.34.0")] impl Error for TryFromSliceError { #[allow(deprecated)] diff --git a/library/core/src/char/decode.rs b/library/core/src/char/decode.rs index dc8ea66cc6d0e..11f1c30f6d559 100644 --- a/library/core/src/char/decode.rs +++ b/library/core/src/char/decode.rs @@ -1,6 +1,5 @@ //! UTF-8 and UTF-16 decoding iterators -#[cfg(not(bootstrap))] use crate::error::Error; use crate::fmt; @@ -124,7 +123,6 @@ impl fmt::Display for DecodeUtf16Error { } } -#[cfg(not(bootstrap))] #[stable(feature = "decode_utf16", since = "1.9.0")] impl Error for DecodeUtf16Error { #[allow(deprecated)] diff --git a/library/core/src/char/mod.rs b/library/core/src/char/mod.rs index 72d63ac4b4b41..b34a7121631c1 100644 --- a/library/core/src/char/mod.rs +++ b/library/core/src/char/mod.rs @@ -38,7 +38,6 @@ pub use self::methods::encode_utf16_raw; #[unstable(feature = "char_internals", reason = "exposed only for libstd", issue = "none")] pub use self::methods::encode_utf8_raw; -#[cfg(not(bootstrap))] use crate::error::Error; use crate::fmt::{self, Write}; use crate::iter::FusedIterator; @@ -587,6 +586,5 @@ impl fmt::Display for TryFromCharError { } } -#[cfg(not(bootstrap))] #[stable(feature = "u8_from_char", since = "1.59.0")] impl Error for TryFromCharError {} diff --git a/library/core/src/convert/mod.rs b/library/core/src/convert/mod.rs index 0480704a6d6fa..c42adda8da545 100644 --- a/library/core/src/convert/mod.rs +++ b/library/core/src/convert/mod.rs @@ -34,7 +34,6 @@ #![stable(feature = "rust1", since = "1.0.0")] -#[cfg(not(bootstrap))] use crate::error::Error; use crate::fmt; use crate::hash::{Hash, Hasher}; @@ -724,7 +723,6 @@ impl fmt::Display for Infallible { } } -#[cfg(not(bootstrap))] #[stable(feature = "str_parse_error2", since = "1.8.0")] impl Error for Infallible { fn description(&self) -> &str { diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index 11c75e2c91241..12b43da5a4280 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -54,8 +54,6 @@ )] #![allow(missing_docs)] -#[cfg(bootstrap)] -use crate::marker::Destruct; use crate::marker::DiscriminantKind; use crate::mem; @@ -1297,7 +1295,6 @@ extern "rust-intrinsic" { /// any safety invariants. /// /// Consider using [`pointer::mask`] instead. - #[cfg(not(bootstrap))] pub fn ptr_mask(ptr: *const T, mask: usize) -> *const T; /// Equivalent to the appropriate `llvm.memcpy.p0i8.0i8.*` intrinsic, with @@ -2022,17 +2019,8 @@ extern "rust-intrinsic" { /// Therefore, implementations must not require the user to uphold /// any safety invariants. #[rustc_const_unstable(feature = "const_raw_ptr_comparison", issue = "53020")] - #[cfg(not(bootstrap))] pub fn ptr_guaranteed_cmp(ptr: *const T, other: *const T) -> u8; - #[rustc_const_unstable(feature = "const_raw_ptr_comparison", issue = "53020")] - #[cfg(bootstrap)] - pub fn ptr_guaranteed_eq(ptr: *const T, other: *const T) -> bool; - - #[rustc_const_unstable(feature = "const_raw_ptr_comparison", issue = "53020")] - #[cfg(bootstrap)] - pub fn ptr_guaranteed_ne(ptr: *const T, other: *const T) -> bool; - /// Allocates a block of memory at compile time. /// At runtime, just returns a null pointer. /// @@ -2143,7 +2131,6 @@ extern "rust-intrinsic" { /// `unreachable_unchecked` is actually being reached. The bug is in *crate A*, /// which violates the principle that a `const fn` must behave the same at /// compile-time and at run-time. The unsafe code in crate B is fine. - #[cfg(not(bootstrap))] #[rustc_const_unstable(feature = "const_eval_select", issue = "none")] pub fn const_eval_select(arg: ARG, called_in_const: F, called_at_rt: G) -> RET where @@ -2216,16 +2203,6 @@ pub(crate) fn is_nonoverlapping(src: *const T, dst: *const T, count: usize) - diff >= size } -#[cfg(bootstrap)] -pub const fn ptr_guaranteed_cmp(a: *const (), b: *const ()) -> u8 { - match (ptr_guaranteed_eq(a, b), ptr_guaranteed_ne(a, b)) { - (false, false) => 2, - (true, false) => 1, - (false, true) => 0, - (true, true) => unreachable!(), - } -} - /// Copies `count * size_of::()` bytes from `src` to `dst`. The source /// and destination must *not* overlap. /// @@ -2484,45 +2461,3 @@ pub const unsafe fn write_bytes(dst: *mut T, val: u8, count: usize) { write_bytes(dst, val, count) } } - -#[cfg(bootstrap)] -#[unstable( - feature = "const_eval_select", - issue = "none", - reason = "const_eval_select will never be stable" -)] -#[rustc_const_unstable(feature = "const_eval_select", issue = "none")] -#[lang = "const_eval_select"] -#[rustc_do_not_const_check] -#[inline] -pub const unsafe fn const_eval_select( - arg: ARG, - _called_in_const: F, - called_at_rt: G, -) -> RET -where - F: ~const FnOnce, - G: FnOnce + ~const Destruct, -{ - called_at_rt.call_once(arg) -} - -#[cfg(bootstrap)] -#[unstable( - feature = "const_eval_select", - issue = "none", - reason = "const_eval_select will never be stable" -)] -#[rustc_const_unstable(feature = "const_eval_select", issue = "none")] -#[lang = "const_eval_select_ct"] -pub const unsafe fn const_eval_select_ct( - arg: ARG, - called_in_const: F, - _called_at_rt: G, -) -> RET -where - F: ~const FnOnce, - G: FnOnce + ~const Destruct, -{ - called_in_const.call_once(arg) -} diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index a48290ea08ef0..5690b5256e88c 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -310,7 +310,6 @@ pub mod clone; pub mod cmp; pub mod convert; pub mod default; -#[cfg(not(bootstrap))] pub mod error; pub mod marker; pub mod ops; diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs index 40a7b69619305..5cb5e4458cc68 100644 --- a/library/core/src/marker.rs +++ b/library/core/src/marker.rs @@ -806,7 +806,7 @@ pub trait Destruct {} /// The implementation of this trait is built-in and cannot be implemented /// for any user type. #[unstable(feature = "tuple_trait", issue = "none")] -#[cfg_attr(not(bootstrap), lang = "tuple_trait")] +#[lang = "tuple_trait"] #[rustc_on_unimplemented(message = "`{Self}` is not a tuple")] pub trait Tuple {} diff --git a/library/core/src/mem/transmutability.rs b/library/core/src/mem/transmutability.rs index 87a378631050a..3b98efff2938a 100644 --- a/library/core/src/mem/transmutability.rs +++ b/library/core/src/mem/transmutability.rs @@ -4,7 +4,7 @@ /// any value of type `Self` are safely transmutable into a value of type `Dst`, in a given `Context`, /// notwithstanding whatever safety checks you have asked the compiler to [`Assume`] are satisfied. #[unstable(feature = "transmutability", issue = "99571")] -#[cfg_attr(not(bootstrap), lang = "transmute_trait")] +#[lang = "transmute_trait"] #[rustc_on_unimplemented( message = "`{Src}` cannot be safely transmuted into `{Self}` in the defining scope of `{Context}`.", label = "`{Src}` cannot be safely transmuted into `{Self}` in the defining scope of `{Context}`." @@ -17,7 +17,7 @@ where /// What transmutation safety conditions shall the compiler assume that *you* are checking? #[unstable(feature = "transmutability", issue = "99571")] -#[cfg_attr(not(bootstrap), lang = "transmute_opts")] +#[lang = "transmute_opts"] #[derive(PartialEq, Eq, Clone, Copy, Debug)] pub struct Assume { /// When `true`, the compiler assumes that *you* are ensuring (either dynamically or statically) that diff --git a/library/core/src/num/error.rs b/library/core/src/num/error.rs index 1f6b40e5df554..768dd87816df7 100644 --- a/library/core/src/num/error.rs +++ b/library/core/src/num/error.rs @@ -1,7 +1,6 @@ //! Error types for conversion to integral types. use crate::convert::Infallible; -#[cfg(not(bootstrap))] use crate::error::Error; use crate::fmt; @@ -147,7 +146,6 @@ impl fmt::Display for ParseIntError { } } -#[cfg(not(bootstrap))] #[stable(feature = "rust1", since = "1.0.0")] impl Error for ParseIntError { #[allow(deprecated)] @@ -156,7 +154,6 @@ impl Error for ParseIntError { } } -#[cfg(not(bootstrap))] #[stable(feature = "try_from", since = "1.34.0")] impl Error for TryFromIntError { #[allow(deprecated)] diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs index dd4409198e39b..c0be235c120bf 100644 --- a/library/core/src/num/mod.rs +++ b/library/core/src/num/mod.rs @@ -3,7 +3,6 @@ #![stable(feature = "rust1", since = "1.0.0")] use crate::ascii; -#[cfg(not(bootstrap))] use crate::error::Error; use crate::intrinsics; use crate::mem; @@ -59,7 +58,6 @@ pub use wrapping::Wrapping; #[cfg(not(no_fp_fmt_parse))] pub use dec2flt::ParseFloatError; -#[cfg(not(bootstrap))] #[cfg(not(no_fp_fmt_parse))] #[stable(feature = "rust1", since = "1.0.0")] impl Error for ParseFloatError { diff --git a/library/core/src/ops/generator.rs b/library/core/src/ops/generator.rs index 3ebd6f8cdbdc0..fee4beb1e84bb 100644 --- a/library/core/src/ops/generator.rs +++ b/library/core/src/ops/generator.rs @@ -83,7 +83,6 @@ pub trait Generator { /// `return` statement or implicitly as the last expression of a generator /// literal. For example futures would use this as `Result` as it /// represents a completed future. - #[cfg_attr(bootstrap, lang = "generator_return")] type Return; /// Resumes the execution of this generator. diff --git a/library/core/src/ops/try_trait.rs b/library/core/src/ops/try_trait.rs index 4d0d4e12adbf8..33df9e6c5cd48 100644 --- a/library/core/src/ops/try_trait.rs +++ b/library/core/src/ops/try_trait.rs @@ -223,7 +223,7 @@ pub trait Try: ~const FromResidual { /// Every `Try` type needs to be recreatable from its own associated /// `Residual` type, but can also have additional `FromResidual` implementations /// to support interconversion with other `Try` types. -#[cfg_attr(not(bootstrap), rustc_on_unimplemented( +#[rustc_on_unimplemented( on( all( from_desugaring = "QuestionMark", @@ -302,87 +302,7 @@ pub trait Try: ~const FromResidual { label = "cannot use the `?` operator in {ItemContext} that returns `{Self}`", parent_label = "this function should return `Result` or `Option` to accept `?`" ), -))] -#[cfg_attr(bootstrap, rustc_on_unimplemented( - on( - all( - from_desugaring = "QuestionMark", - _Self = "std::result::Result", - R = "std::option::Option" - ), - message = "the `?` operator can only be used on `Result`s, not `Option`s, \ - in {ItemContext} that returns `Result`", - label = "use `.ok_or(...)?` to provide an error compatible with `{Self}`", - enclosing_scope = "this function returns a `Result`" - ), - on( - all( - from_desugaring = "QuestionMark", - _Self = "std::result::Result", - ), - // There's a special error message in the trait selection code for - // `From` in `?`, so this is not shown for result-in-result errors, - // and thus it can be phrased more strongly than `ControlFlow`'s. - message = "the `?` operator can only be used on `Result`s \ - in {ItemContext} that returns `Result`", - label = "this `?` produces `{R}`, which is incompatible with `{Self}`", - enclosing_scope = "this function returns a `Result`" - ), - on( - all( - from_desugaring = "QuestionMark", - _Self = "std::option::Option", - R = "std::result::Result", - ), - message = "the `?` operator can only be used on `Option`s, not `Result`s, \ - in {ItemContext} that returns `Option`", - label = "use `.ok()?` if you want to discard the `{R}` error information", - enclosing_scope = "this function returns an `Option`" - ), - on( - all( - from_desugaring = "QuestionMark", - _Self = "std::option::Option", - ), - // `Option`-in-`Option` always works, as there's only one possible - // residual, so this can also be phrased strongly. - message = "the `?` operator can only be used on `Option`s \ - in {ItemContext} that returns `Option`", - label = "this `?` produces `{R}`, which is incompatible with `{Self}`", - enclosing_scope = "this function returns an `Option`" - ), - on( - all( - from_desugaring = "QuestionMark", - _Self = "std::ops::ControlFlow", - R = "std::ops::ControlFlow", - ), - message = "the `?` operator in {ItemContext} that returns `ControlFlow` \ - can only be used on other `ControlFlow`s (with the same Break type)", - label = "this `?` produces `{R}`, which is incompatible with `{Self}`", - enclosing_scope = "this function returns a `ControlFlow`", - note = "unlike `Result`, there's no `From`-conversion performed for `ControlFlow`" - ), - on( - all( - from_desugaring = "QuestionMark", - _Self = "std::ops::ControlFlow", - // `R` is not a `ControlFlow`, as that case was matched previously - ), - message = "the `?` operator can only be used on `ControlFlow`s \ - in {ItemContext} that returns `ControlFlow`", - label = "this `?` produces `{R}`, which is incompatible with `{Self}`", - enclosing_scope = "this function returns a `ControlFlow`", - ), - on( - all(from_desugaring = "QuestionMark"), - message = "the `?` operator can only be used in {ItemContext} \ - that returns `Result` or `Option` \ - (or another type that implements `{FromResidual}`)", - label = "cannot use the `?` operator in {ItemContext} that returns `{Self}`", - enclosing_scope = "this function should return `Result` or `Option` to accept `?`" - ), -))] +)] #[rustc_diagnostic_item = "FromResidual"] #[unstable(feature = "try_trait_v2", issue = "84277")] #[const_trait] diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index 43e883b8bf718..d898108be580f 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -568,7 +568,6 @@ impl *const T { /// /// For non-`Sized` pointees this operation changes only the data pointer, /// leaving the metadata untouched. - #[cfg(not(bootstrap))] #[unstable(feature = "ptr_mask", issue = "98290")] #[must_use = "returns a new pointer rather than modifying its argument"] #[inline(always)] diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index e277b8181754e..543ab826c4eb9 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -584,7 +584,6 @@ impl *mut T { /// /// For non-`Sized` pointees this operation changes only the data pointer, /// leaving the metadata untouched. - #[cfg(not(bootstrap))] #[unstable(feature = "ptr_mask", issue = "98290")] #[must_use = "returns a new pointer rather than modifying its argument"] #[inline(always)] diff --git a/library/core/src/str/error.rs b/library/core/src/str/error.rs index 343889b6999fa..a11b5add42ebf 100644 --- a/library/core/src/str/error.rs +++ b/library/core/src/str/error.rs @@ -1,6 +1,5 @@ //! Defines utf8 error type. -#[cfg(not(bootstrap))] use crate::error::Error; use crate::fmt; @@ -124,7 +123,6 @@ impl fmt::Display for Utf8Error { } } -#[cfg(not(bootstrap))] #[stable(feature = "rust1", since = "1.0.0")] impl Error for Utf8Error { #[allow(deprecated)] @@ -148,7 +146,6 @@ impl fmt::Display for ParseBoolError { } } -#[cfg(not(bootstrap))] #[stable(feature = "rust1", since = "1.0.0")] impl Error for ParseBoolError { #[allow(deprecated)] diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs index f673aa2a44b10..fbc0fc397a5df 100644 --- a/library/core/src/str/mod.rs +++ b/library/core/src/str/mod.rs @@ -2642,5 +2642,4 @@ impl_fn_for_zst! { } #[stable(feature = "rust1", since = "1.0.0")] -#[cfg(not(bootstrap))] impl !crate::error::Error for &str {} diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs index 9845d1faf9aa1..d2db4bb7a46f5 100644 --- a/library/std/src/collections/hash/map.rs +++ b/library/std/src/collections/hash/map.rs @@ -9,7 +9,6 @@ use crate::borrow::Borrow; use crate::cell::Cell; use crate::collections::TryReserveError; use crate::collections::TryReserveErrorKind; -#[cfg(not(bootstrap))] use crate::error::Error; use crate::fmt::{self, Debug}; #[allow(deprecated)] @@ -2160,7 +2159,6 @@ impl<'a, K: Debug, V: Debug> fmt::Display for OccupiedError<'a, K, V> { } } -#[cfg(not(bootstrap))] #[unstable(feature = "map_try_insert", issue = "82766")] impl<'a, K: fmt::Debug, V: fmt::Debug> Error for OccupiedError<'a, K, V> { #[allow(deprecated)] diff --git a/library/std/src/error.rs b/library/std/src/error.rs index e45059595362f..05f8fd8de327f 100644 --- a/library/std/src/error.rs +++ b/library/std/src/error.rs @@ -4,242 +4,12 @@ #[cfg(test)] mod tests; -#[cfg(bootstrap)] -use core::array; -#[cfg(bootstrap)] -use core::convert::Infallible; - -#[cfg(bootstrap)] -use crate::alloc::{AllocError, LayoutError}; -#[cfg(bootstrap)] -use crate::any::Demand; -#[cfg(bootstrap)] -use crate::any::{Provider, TypeId}; use crate::backtrace::Backtrace; -#[cfg(bootstrap)] -use crate::borrow::Cow; -#[cfg(bootstrap)] -use crate::cell; -#[cfg(bootstrap)] -use crate::char; -#[cfg(bootstrap)] -use crate::fmt::Debug; -#[cfg(bootstrap)] -use crate::fmt::Display; use crate::fmt::{self, Write}; -#[cfg(bootstrap)] -use crate::io; -#[cfg(bootstrap)] -use crate::mem::transmute; -#[cfg(bootstrap)] -use crate::num; -#[cfg(bootstrap)] -use crate::str; -#[cfg(bootstrap)] -use crate::string; -#[cfg(bootstrap)] -use crate::sync::Arc; -#[cfg(bootstrap)] -use crate::time; -#[cfg(not(bootstrap))] #[stable(feature = "rust1", since = "1.0.0")] pub use core::error::Error; -/// `Error` is a trait representing the basic expectations for error values, -/// i.e., values of type `E` in [`Result`]. -/// -/// Errors must describe themselves through the [`Display`] and [`Debug`] -/// traits. Error messages are typically concise lowercase sentences without -/// trailing punctuation: -/// -/// ``` -/// let err = "NaN".parse::().unwrap_err(); -/// assert_eq!(err.to_string(), "invalid digit found in string"); -/// ``` -/// -/// Errors may provide cause information. [`Error::source()`] is generally -/// used when errors cross "abstraction boundaries". If one module must report -/// an error that is caused by an error from a lower-level module, it can allow -/// accessing that error via [`Error::source()`]. This makes it possible for the -/// high-level module to provide its own errors while also revealing some of the -/// implementation for debugging. -#[stable(feature = "rust1", since = "1.0.0")] -#[cfg_attr(not(test), rustc_diagnostic_item = "Error")] -#[cfg(bootstrap)] -pub trait Error: Debug + Display { - /// The lower-level source of this error, if any. - /// - /// # Examples - /// - /// ``` - /// use std::error::Error; - /// use std::fmt; - /// - /// #[derive(Debug)] - /// struct SuperError { - /// source: SuperErrorSideKick, - /// } - /// - /// impl fmt::Display for SuperError { - /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - /// write!(f, "SuperError is here!") - /// } - /// } - /// - /// impl Error for SuperError { - /// fn source(&self) -> Option<&(dyn Error + 'static)> { - /// Some(&self.source) - /// } - /// } - /// - /// #[derive(Debug)] - /// struct SuperErrorSideKick; - /// - /// impl fmt::Display for SuperErrorSideKick { - /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - /// write!(f, "SuperErrorSideKick is here!") - /// } - /// } - /// - /// impl Error for SuperErrorSideKick {} - /// - /// fn get_super_error() -> Result<(), SuperError> { - /// Err(SuperError { source: SuperErrorSideKick }) - /// } - /// - /// fn main() { - /// match get_super_error() { - /// Err(e) => { - /// println!("Error: {e}"); - /// println!("Caused by: {}", e.source().unwrap()); - /// } - /// _ => println!("No error"), - /// } - /// } - /// ``` - #[stable(feature = "error_source", since = "1.30.0")] - fn source(&self) -> Option<&(dyn Error + 'static)> { - None - } - - /// Gets the `TypeId` of `self`. - #[doc(hidden)] - #[unstable( - feature = "error_type_id", - reason = "this is memory-unsafe to override in user code", - issue = "60784" - )] - fn type_id(&self, _: private::Internal) -> TypeId - where - Self: 'static, - { - TypeId::of::() - } - - /// ``` - /// if let Err(e) = "xc".parse::() { - /// // Print `e` itself, no need for description(). - /// eprintln!("Error: {e}"); - /// } - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[deprecated(since = "1.42.0", note = "use the Display impl or to_string()")] - fn description(&self) -> &str { - "description() is deprecated; use Display" - } - - #[stable(feature = "rust1", since = "1.0.0")] - #[deprecated( - since = "1.33.0", - note = "replaced by Error::source, which can support downcasting" - )] - #[allow(missing_docs)] - fn cause(&self) -> Option<&dyn Error> { - self.source() - } - - /// Provides type based access to context intended for error reports. - /// - /// Used in conjunction with [`Demand::provide_value`] and [`Demand::provide_ref`] to extract - /// references to member variables from `dyn Error` trait objects. - /// - /// # Example - /// - /// ```rust - /// #![feature(provide_any)] - /// #![feature(error_generic_member_access)] - /// use core::fmt; - /// use core::any::Demand; - /// - /// #[derive(Debug)] - /// struct MyBacktrace { - /// // ... - /// } - /// - /// impl MyBacktrace { - /// fn new() -> MyBacktrace { - /// // ... - /// # MyBacktrace {} - /// } - /// } - /// - /// #[derive(Debug)] - /// struct SourceError { - /// // ... - /// } - /// - /// impl fmt::Display for SourceError { - /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - /// write!(f, "Example Source Error") - /// } - /// } - /// - /// impl std::error::Error for SourceError {} - /// - /// #[derive(Debug)] - /// struct Error { - /// source: SourceError, - /// backtrace: MyBacktrace, - /// } - /// - /// impl fmt::Display for Error { - /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - /// write!(f, "Example Error") - /// } - /// } - /// - /// impl std::error::Error for Error { - /// fn provide<'a>(&'a self, demand: &mut Demand<'a>) { - /// demand - /// .provide_ref::(&self.backtrace) - /// .provide_ref::(&self.source); - /// } - /// } - /// - /// fn main() { - /// let backtrace = MyBacktrace::new(); - /// let source = SourceError {}; - /// let error = Error { source, backtrace }; - /// let dyn_error = &error as &dyn std::error::Error; - /// let backtrace_ref = dyn_error.request_ref::().unwrap(); - /// - /// assert!(core::ptr::eq(&error.backtrace, backtrace_ref)); - /// } - /// ``` - #[unstable(feature = "error_generic_member_access", issue = "99301")] - #[allow(unused_variables)] - fn provide<'a>(&'a self, demand: &mut Demand<'a>) {} -} - -#[cfg(bootstrap)] -#[unstable(feature = "error_generic_member_access", issue = "99301")] -impl<'b> Provider for dyn Error + 'b { - fn provide<'a>(&'a self, demand: &mut Demand<'a>) { - self.provide(demand) - } -} - mod private { // This is a hack to prevent `type_id` from being overridden by `Error` // implementations, since that can enable unsound downcasting. @@ -248,799 +18,6 @@ mod private { pub struct Internal; } -#[cfg(bootstrap)] -#[stable(feature = "rust1", since = "1.0.0")] -impl<'a, E: Error + 'a> From for Box { - /// Converts a type of [`Error`] into a box of dyn [`Error`]. - /// - /// # Examples - /// - /// ``` - /// use std::error::Error; - /// use std::fmt; - /// use std::mem; - /// - /// #[derive(Debug)] - /// struct AnError; - /// - /// impl fmt::Display for AnError { - /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - /// write!(f, "An error") - /// } - /// } - /// - /// impl Error for AnError {} - /// - /// let an_error = AnError; - /// assert!(0 == mem::size_of_val(&an_error)); - /// let a_boxed_error = Box::::from(an_error); - /// assert!(mem::size_of::>() == mem::size_of_val(&a_boxed_error)) - /// ``` - fn from(err: E) -> Box { - Box::new(err) - } -} - -#[cfg(bootstrap)] -#[stable(feature = "rust1", since = "1.0.0")] -impl<'a, E: Error + Send + Sync + 'a> From for Box { - /// Converts a type of [`Error`] + [`Send`] + [`Sync`] into a box of - /// dyn [`Error`] + [`Send`] + [`Sync`]. - /// - /// # Examples - /// - /// ``` - /// use std::error::Error; - /// use std::fmt; - /// use std::mem; - /// - /// #[derive(Debug)] - /// struct AnError; - /// - /// impl fmt::Display for AnError { - /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - /// write!(f, "An error") - /// } - /// } - /// - /// impl Error for AnError {} - /// - /// unsafe impl Send for AnError {} - /// - /// unsafe impl Sync for AnError {} - /// - /// let an_error = AnError; - /// assert!(0 == mem::size_of_val(&an_error)); - /// let a_boxed_error = Box::::from(an_error); - /// assert!( - /// mem::size_of::>() == mem::size_of_val(&a_boxed_error)) - /// ``` - fn from(err: E) -> Box { - Box::new(err) - } -} - -#[cfg(bootstrap)] -#[stable(feature = "rust1", since = "1.0.0")] -impl From for Box { - /// Converts a [`String`] into a box of dyn [`Error`] + [`Send`] + [`Sync`]. - /// - /// # Examples - /// - /// ``` - /// use std::error::Error; - /// use std::mem; - /// - /// let a_string_error = "a string error".to_string(); - /// let a_boxed_error = Box::::from(a_string_error); - /// assert!( - /// mem::size_of::>() == mem::size_of_val(&a_boxed_error)) - /// ``` - #[inline] - fn from(err: String) -> Box { - struct StringError(String); - - impl Error for StringError { - #[allow(deprecated)] - fn description(&self) -> &str { - &self.0 - } - } - - impl Display for StringError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - Display::fmt(&self.0, f) - } - } - - // Purposefully skip printing "StringError(..)" - impl Debug for StringError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - Debug::fmt(&self.0, f) - } - } - - Box::new(StringError(err)) - } -} - -#[cfg(bootstrap)] -#[stable(feature = "string_box_error", since = "1.6.0")] -impl From for Box { - /// Converts a [`String`] into a box of dyn [`Error`]. - /// - /// # Examples - /// - /// ``` - /// use std::error::Error; - /// use std::mem; - /// - /// let a_string_error = "a string error".to_string(); - /// let a_boxed_error = Box::::from(a_string_error); - /// assert!(mem::size_of::>() == mem::size_of_val(&a_boxed_error)) - /// ``` - fn from(str_err: String) -> Box { - let err1: Box = From::from(str_err); - let err2: Box = err1; - err2 - } -} - -#[cfg(bootstrap)] -#[stable(feature = "rust1", since = "1.0.0")] -impl<'a> From<&str> for Box { - /// Converts a [`str`] into a box of dyn [`Error`] + [`Send`] + [`Sync`]. - /// - /// [`str`]: prim@str - /// - /// # Examples - /// - /// ``` - /// use std::error::Error; - /// use std::mem; - /// - /// let a_str_error = "a str error"; - /// let a_boxed_error = Box::::from(a_str_error); - /// assert!( - /// mem::size_of::>() == mem::size_of_val(&a_boxed_error)) - /// ``` - #[inline] - fn from(err: &str) -> Box { - From::from(String::from(err)) - } -} - -#[cfg(bootstrap)] -#[stable(feature = "string_box_error", since = "1.6.0")] -impl From<&str> for Box { - /// Converts a [`str`] into a box of dyn [`Error`]. - /// - /// [`str`]: prim@str - /// - /// # Examples - /// - /// ``` - /// use std::error::Error; - /// use std::mem; - /// - /// let a_str_error = "a str error"; - /// let a_boxed_error = Box::::from(a_str_error); - /// assert!(mem::size_of::>() == mem::size_of_val(&a_boxed_error)) - /// ``` - fn from(err: &str) -> Box { - From::from(String::from(err)) - } -} - -#[cfg(bootstrap)] -#[stable(feature = "cow_box_error", since = "1.22.0")] -impl<'a, 'b> From> for Box { - /// Converts a [`Cow`] into a box of dyn [`Error`] + [`Send`] + [`Sync`]. - /// - /// # Examples - /// - /// ``` - /// use std::error::Error; - /// use std::mem; - /// use std::borrow::Cow; - /// - /// let a_cow_str_error = Cow::from("a str error"); - /// let a_boxed_error = Box::::from(a_cow_str_error); - /// assert!( - /// mem::size_of::>() == mem::size_of_val(&a_boxed_error)) - /// ``` - fn from(err: Cow<'b, str>) -> Box { - From::from(String::from(err)) - } -} - -#[cfg(bootstrap)] -#[stable(feature = "cow_box_error", since = "1.22.0")] -impl<'a> From> for Box { - /// Converts a [`Cow`] into a box of dyn [`Error`]. - /// - /// # Examples - /// - /// ``` - /// use std::error::Error; - /// use std::mem; - /// use std::borrow::Cow; - /// - /// let a_cow_str_error = Cow::from("a str error"); - /// let a_boxed_error = Box::::from(a_cow_str_error); - /// assert!(mem::size_of::>() == mem::size_of_val(&a_boxed_error)) - /// ``` - fn from(err: Cow<'a, str>) -> Box { - From::from(String::from(err)) - } -} - -#[cfg(bootstrap)] -#[unstable(feature = "never_type", issue = "35121")] -impl Error for ! {} - -#[cfg(bootstrap)] -#[unstable( - feature = "allocator_api", - reason = "the precise API and guarantees it provides may be tweaked.", - issue = "32838" -)] -impl Error for AllocError {} - -#[cfg(bootstrap)] -#[stable(feature = "alloc_layout", since = "1.28.0")] -impl Error for LayoutError {} - -#[cfg(bootstrap)] -#[stable(feature = "rust1", since = "1.0.0")] -impl Error for str::ParseBoolError { - #[allow(deprecated)] - fn description(&self) -> &str { - "failed to parse bool" - } -} - -#[cfg(bootstrap)] -#[stable(feature = "rust1", since = "1.0.0")] -impl Error for str::Utf8Error { - #[allow(deprecated)] - fn description(&self) -> &str { - "invalid utf-8: corrupt contents" - } -} - -#[cfg(bootstrap)] -#[stable(feature = "rust1", since = "1.0.0")] -impl Error for num::ParseIntError { - #[allow(deprecated)] - fn description(&self) -> &str { - self.__description() - } -} - -#[cfg(bootstrap)] -#[stable(feature = "try_from", since = "1.34.0")] -impl Error for num::TryFromIntError { - #[allow(deprecated)] - fn description(&self) -> &str { - self.__description() - } -} - -#[cfg(bootstrap)] -#[stable(feature = "try_from", since = "1.34.0")] -impl Error for array::TryFromSliceError { - #[allow(deprecated)] - fn description(&self) -> &str { - self.__description() - } -} - -#[cfg(bootstrap)] -#[stable(feature = "rust1", since = "1.0.0")] -impl Error for num::ParseFloatError { - #[allow(deprecated)] - fn description(&self) -> &str { - self.__description() - } -} - -#[cfg(bootstrap)] -#[stable(feature = "rust1", since = "1.0.0")] -impl Error for string::FromUtf8Error { - #[allow(deprecated)] - fn description(&self) -> &str { - "invalid utf-8" - } -} - -#[cfg(bootstrap)] -#[stable(feature = "rust1", since = "1.0.0")] -impl Error for string::FromUtf16Error { - #[allow(deprecated)] - fn description(&self) -> &str { - "invalid utf-16" - } -} - -#[cfg(bootstrap)] -#[stable(feature = "str_parse_error2", since = "1.8.0")] -impl Error for Infallible { - fn description(&self) -> &str { - match *self {} - } -} - -#[cfg(bootstrap)] -#[stable(feature = "decode_utf16", since = "1.9.0")] -impl Error for char::DecodeUtf16Error { - #[allow(deprecated)] - fn description(&self) -> &str { - "unpaired surrogate found" - } -} - -#[cfg(bootstrap)] -#[stable(feature = "u8_from_char", since = "1.59.0")] -impl Error for char::TryFromCharError {} - -#[cfg(bootstrap)] -#[unstable(feature = "map_try_insert", issue = "82766")] -impl<'a, K: Debug + Ord, V: Debug> Error - for crate::collections::btree_map::OccupiedError<'a, K, V> -{ - #[allow(deprecated)] - fn description(&self) -> &str { - "key already exists" - } -} - -#[cfg(bootstrap)] -#[unstable(feature = "map_try_insert", issue = "82766")] -impl<'a, K: Debug, V: Debug> Error for crate::collections::hash_map::OccupiedError<'a, K, V> { - #[allow(deprecated)] - fn description(&self) -> &str { - "key already exists" - } -} - -#[cfg(bootstrap)] -#[stable(feature = "box_error", since = "1.8.0")] -impl Error for Box { - #[allow(deprecated, deprecated_in_future)] - fn description(&self) -> &str { - Error::description(&**self) - } - - #[allow(deprecated)] - fn cause(&self) -> Option<&dyn Error> { - Error::cause(&**self) - } - - fn source(&self) -> Option<&(dyn Error + 'static)> { - Error::source(&**self) - } -} - -#[cfg(bootstrap)] -#[unstable(feature = "thin_box", issue = "92791")] -impl crate::error::Error for crate::boxed::ThinBox { - fn source(&self) -> Option<&(dyn crate::error::Error + 'static)> { - use core::ops::Deref; - self.deref().source() - } -} - -#[cfg(bootstrap)] -#[stable(feature = "error_by_ref", since = "1.51.0")] -impl<'a, T: Error + ?Sized> Error for &'a T { - #[allow(deprecated, deprecated_in_future)] - fn description(&self) -> &str { - Error::description(&**self) - } - - #[allow(deprecated)] - fn cause(&self) -> Option<&dyn Error> { - Error::cause(&**self) - } - - fn source(&self) -> Option<&(dyn Error + 'static)> { - Error::source(&**self) - } - - fn provide<'b>(&'b self, demand: &mut Demand<'b>) { - Error::provide(&**self, demand); - } -} - -#[cfg(bootstrap)] -#[stable(feature = "arc_error", since = "1.52.0")] -impl Error for Arc { - #[allow(deprecated, deprecated_in_future)] - fn description(&self) -> &str { - Error::description(&**self) - } - - #[allow(deprecated)] - fn cause(&self) -> Option<&dyn Error> { - Error::cause(&**self) - } - - fn source(&self) -> Option<&(dyn Error + 'static)> { - Error::source(&**self) - } - - fn provide<'a>(&'a self, demand: &mut Demand<'a>) { - Error::provide(&**self, demand); - } -} - -#[cfg(bootstrap)] -#[stable(feature = "fmt_error", since = "1.11.0")] -impl Error for fmt::Error { - #[allow(deprecated)] - fn description(&self) -> &str { - "an error occurred when formatting an argument" - } -} - -#[cfg(bootstrap)] -#[stable(feature = "try_borrow", since = "1.13.0")] -impl Error for cell::BorrowError { - #[allow(deprecated)] - fn description(&self) -> &str { - "already mutably borrowed" - } -} - -#[cfg(bootstrap)] -#[stable(feature = "try_borrow", since = "1.13.0")] -impl Error for cell::BorrowMutError { - #[allow(deprecated)] - fn description(&self) -> &str { - "already borrowed" - } -} - -#[cfg(bootstrap)] -#[stable(feature = "try_from", since = "1.34.0")] -impl Error for char::CharTryFromError { - #[allow(deprecated)] - fn description(&self) -> &str { - "converted integer out of range for `char`" - } -} - -#[cfg(bootstrap)] -#[stable(feature = "char_from_str", since = "1.20.0")] -impl Error for char::ParseCharError { - #[allow(deprecated)] - fn description(&self) -> &str { - self.__description() - } -} - -#[cfg(bootstrap)] -#[stable(feature = "try_reserve", since = "1.57.0")] -impl Error for alloc::collections::TryReserveError {} - -#[cfg(bootstrap)] -#[unstable(feature = "duration_checked_float", issue = "83400")] -impl Error for time::FromFloatSecsError {} - -#[cfg(bootstrap)] -#[stable(feature = "rust1", since = "1.0.0")] -impl Error for alloc::ffi::NulError { - #[allow(deprecated)] - fn description(&self) -> &str { - "nul byte found in data" - } -} - -#[cfg(bootstrap)] -#[stable(feature = "rust1", since = "1.0.0")] -impl From for io::Error { - /// Converts a [`alloc::ffi::NulError`] into a [`io::Error`]. - fn from(_: alloc::ffi::NulError) -> io::Error { - io::const_io_error!(io::ErrorKind::InvalidInput, "data provided contains a nul byte") - } -} - -#[cfg(bootstrap)] -#[stable(feature = "frombyteswithnulerror_impls", since = "1.17.0")] -impl Error for core::ffi::FromBytesWithNulError { - #[allow(deprecated)] - fn description(&self) -> &str { - self.__description() - } -} - -#[cfg(bootstrap)] -#[unstable(feature = "cstr_from_bytes_until_nul", issue = "95027")] -impl Error for core::ffi::FromBytesUntilNulError {} - -#[cfg(bootstrap)] -#[stable(feature = "cstring_from_vec_with_nul", since = "1.58.0")] -impl Error for alloc::ffi::FromVecWithNulError {} - -#[cfg(bootstrap)] -#[stable(feature = "cstring_into", since = "1.7.0")] -impl Error for alloc::ffi::IntoStringError { - #[allow(deprecated)] - fn description(&self) -> &str { - "C string contained non-utf8 bytes" - } - - fn source(&self) -> Option<&(dyn Error + 'static)> { - Some(self.__source()) - } -} - -#[cfg(bootstrap)] -impl<'a> dyn Error + 'a { - /// Request a reference of type `T` as context about this error. - #[unstable(feature = "error_generic_member_access", issue = "99301")] - pub fn request_ref(&'a self) -> Option<&'a T> { - core::any::request_ref(self) - } - - /// Request a value of type `T` as context about this error. - #[unstable(feature = "error_generic_member_access", issue = "99301")] - pub fn request_value(&'a self) -> Option { - core::any::request_value(self) - } -} - -// Copied from `any.rs`. -#[cfg(bootstrap)] -impl dyn Error + 'static { - /// Returns `true` if the inner type is the same as `T`. - #[stable(feature = "error_downcast", since = "1.3.0")] - #[inline] - pub fn is(&self) -> bool { - // Get `TypeId` of the type this function is instantiated with. - let t = TypeId::of::(); - - // Get `TypeId` of the type in the trait object (`self`). - let concrete = self.type_id(private::Internal); - - // Compare both `TypeId`s on equality. - t == concrete - } - - /// Returns some reference to the inner value if it is of type `T`, or - /// `None` if it isn't. - #[stable(feature = "error_downcast", since = "1.3.0")] - #[inline] - pub fn downcast_ref(&self) -> Option<&T> { - if self.is::() { - unsafe { Some(&*(self as *const dyn Error as *const T)) } - } else { - None - } - } - - /// Returns some mutable reference to the inner value if it is of type `T`, or - /// `None` if it isn't. - #[stable(feature = "error_downcast", since = "1.3.0")] - #[inline] - pub fn downcast_mut(&mut self) -> Option<&mut T> { - if self.is::() { - unsafe { Some(&mut *(self as *mut dyn Error as *mut T)) } - } else { - None - } - } -} - -#[cfg(bootstrap)] -impl dyn Error + 'static + Send { - /// Forwards to the method defined on the type `dyn Error`. - #[stable(feature = "error_downcast", since = "1.3.0")] - #[inline] - pub fn is(&self) -> bool { - ::is::(self) - } - - /// Forwards to the method defined on the type `dyn Error`. - #[stable(feature = "error_downcast", since = "1.3.0")] - #[inline] - pub fn downcast_ref(&self) -> Option<&T> { - ::downcast_ref::(self) - } - - /// Forwards to the method defined on the type `dyn Error`. - #[stable(feature = "error_downcast", since = "1.3.0")] - #[inline] - pub fn downcast_mut(&mut self) -> Option<&mut T> { - ::downcast_mut::(self) - } - - /// Request a reference of type `T` as context about this error. - #[unstable(feature = "error_generic_member_access", issue = "99301")] - pub fn request_ref(&self) -> Option<&T> { - ::request_ref(self) - } - - /// Request a value of type `T` as context about this error. - #[unstable(feature = "error_generic_member_access", issue = "99301")] - pub fn request_value(&self) -> Option { - ::request_value(self) - } -} - -#[cfg(bootstrap)] -impl dyn Error + 'static + Send + Sync { - /// Forwards to the method defined on the type `dyn Error`. - #[stable(feature = "error_downcast", since = "1.3.0")] - #[inline] - pub fn is(&self) -> bool { - ::is::(self) - } - - /// Forwards to the method defined on the type `dyn Error`. - #[stable(feature = "error_downcast", since = "1.3.0")] - #[inline] - pub fn downcast_ref(&self) -> Option<&T> { - ::downcast_ref::(self) - } - - /// Forwards to the method defined on the type `dyn Error`. - #[stable(feature = "error_downcast", since = "1.3.0")] - #[inline] - pub fn downcast_mut(&mut self) -> Option<&mut T> { - ::downcast_mut::(self) - } - - /// Request a reference of type `T` as context about this error. - #[unstable(feature = "error_generic_member_access", issue = "99301")] - pub fn request_ref(&self) -> Option<&T> { - ::request_ref(self) - } - - /// Request a value of type `T` as context about this error. - #[unstable(feature = "error_generic_member_access", issue = "99301")] - pub fn request_value(&self) -> Option { - ::request_value(self) - } -} - -#[cfg(bootstrap)] -impl dyn Error { - #[inline] - #[stable(feature = "error_downcast", since = "1.3.0")] - /// Attempts to downcast the box to a concrete type. - pub fn downcast(self: Box) -> Result, Box> { - if self.is::() { - unsafe { - let raw: *mut dyn Error = Box::into_raw(self); - Ok(Box::from_raw(raw as *mut T)) - } - } else { - Err(self) - } - } - - /// Returns an iterator starting with the current error and continuing with - /// recursively calling [`Error::source`]. - /// - /// If you want to omit the current error and only use its sources, - /// use `skip(1)`. - /// - /// # Examples - /// - /// ``` - /// #![feature(error_iter)] - /// use std::error::Error; - /// use std::fmt; - /// - /// #[derive(Debug)] - /// struct A; - /// - /// #[derive(Debug)] - /// struct B(Option>); - /// - /// impl fmt::Display for A { - /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - /// write!(f, "A") - /// } - /// } - /// - /// impl fmt::Display for B { - /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - /// write!(f, "B") - /// } - /// } - /// - /// impl Error for A {} - /// - /// impl Error for B { - /// fn source(&self) -> Option<&(dyn Error + 'static)> { - /// self.0.as_ref().map(|e| e.as_ref()) - /// } - /// } - /// - /// let b = B(Some(Box::new(A))); - /// - /// // let err : Box = b.into(); // or - /// let err = &b as &(dyn Error); - /// - /// let mut iter = err.sources(); - /// - /// assert_eq!("B".to_string(), iter.next().unwrap().to_string()); - /// assert_eq!("A".to_string(), iter.next().unwrap().to_string()); - /// assert!(iter.next().is_none()); - /// assert!(iter.next().is_none()); - /// ``` - #[unstable(feature = "error_iter", issue = "58520")] - #[inline] - pub fn sources(&self) -> Sources<'_> { - // You may think this method would be better in the Error trait, and you'd be right. - // Unfortunately that doesn't work, not because of the object safety rules but because we - // save a reference to self in Sources below as a trait object. If this method was - // declared in Error, then self would have the type &T where T is some concrete type which - // implements Error. We would need to coerce self to have type &dyn Error, but that requires - // that Self has a known size (i.e., Self: Sized). We can't put that bound on Error - // since that would forbid Error trait objects, and we can't put that bound on the method - // because that means the method can't be called on trait objects (we'd also need the - // 'static bound, but that isn't allowed because methods with bounds on Self other than - // Sized are not object-safe). Requiring an Unsize bound is not backwards compatible. - - Sources { current: Some(self) } - } -} - -/// An iterator over an [`Error`] and its sources. -/// -/// If you want to omit the initial error and only process -/// its sources, use `skip(1)`. -#[unstable(feature = "error_iter", issue = "58520")] -#[derive(Clone, Debug)] -#[cfg(bootstrap)] -pub struct Sources<'a> { - current: Option<&'a (dyn Error + 'static)>, -} - -#[cfg(bootstrap)] -#[unstable(feature = "error_iter", issue = "58520")] -impl<'a> Iterator for Sources<'a> { - type Item = &'a (dyn Error + 'static); - - fn next(&mut self) -> Option { - let current = self.current; - self.current = self.current.and_then(Error::source); - current - } -} - -#[cfg(bootstrap)] -impl dyn Error + Send { - #[inline] - #[stable(feature = "error_downcast", since = "1.3.0")] - /// Attempts to downcast the box to a concrete type. - pub fn downcast(self: Box) -> Result, Box> { - let err: Box = self; - ::downcast(err).map_err(|s| unsafe { - // Reapply the `Send` marker. - transmute::, Box>(s) - }) - } -} - -#[cfg(bootstrap)] -impl dyn Error + Send + Sync { - #[inline] - #[stable(feature = "error_downcast", since = "1.3.0")] - /// Attempts to downcast the box to a concrete type. - pub fn downcast(self: Box) -> Result, Box> { - let err: Box = self; - ::downcast(err).map_err(|s| unsafe { - // Reapply the `Send + Sync` marker. - transmute::, Box>(s) - }) - } -} - /// An error reporter that prints an error and its sources. /// /// Report also exposes configuration options for formatting the error sources, either entirely on a diff --git a/library/std/src/io/error.rs b/library/std/src/io/error.rs index 29b09fcc5274e..feb3fb989a7ac 100644 --- a/library/std/src/io/error.rs +++ b/library/std/src/io/error.rs @@ -76,7 +76,6 @@ impl fmt::Debug for Error { } } -#[cfg(not(bootstrap))] #[stable(feature = "rust1", since = "1.0.0")] impl From for Error { /// Converts a [`alloc::ffi::NulError`] into a [`Error`]. diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 3131dd4726984..c2b7a4d8648d0 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -252,10 +252,8 @@ #![feature(dropck_eyepatch)] #![feature(exhaustive_patterns)] #![feature(intra_doc_pointers)] -#![cfg_attr(bootstrap, feature(label_break_value))] #![feature(lang_items)] #![feature(let_chains)] -#![cfg_attr(bootstrap, feature(let_else))] #![feature(linkage)] #![feature(link_cfg)] #![feature(min_specialization)] @@ -282,9 +280,9 @@ #![feature(cstr_internals)] #![feature(duration_checked_float)] #![feature(duration_constants)] -#![cfg_attr(not(bootstrap), feature(error_generic_member_access))] -#![cfg_attr(not(bootstrap), feature(error_in_core))] -#![cfg_attr(not(bootstrap), feature(error_iter))] +#![feature(error_generic_member_access)] +#![feature(error_in_core)] +#![feature(error_iter)] #![feature(exact_size_is_empty)] #![feature(exclusive_wrapper)] #![feature(extend_one)] diff --git a/library/std/src/rt.rs b/library/std/src/rt.rs index 98f6cc7aa3ea1..b8bcdbece0af3 100644 --- a/library/std/src/rt.rs +++ b/library/std/src/rt.rs @@ -160,15 +160,12 @@ fn lang_start( main: fn() -> T, argc: isize, argv: *const *const u8, - #[cfg(not(bootstrap))] sigpipe: u8, + sigpipe: u8, ) -> isize { let Ok(v) = lang_start_internal( &move || crate::sys_common::backtrace::__rust_begin_short_backtrace(main).report().to_i32(), argc, argv, - #[cfg(bootstrap)] - 2, // Temporary inlining of sigpipe::DEFAULT until bootstrap stops being special - #[cfg(not(bootstrap))] sigpipe, ); v diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index f973fd0889ebc..f06d2cf108de3 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -2535,7 +2535,6 @@ mod size_asserts { // These are in alphabetical order, which is easy to maintain. static_assert_size!(Crate, 72); // frequently moved by-value static_assert_size!(DocFragment, 32); - #[cfg(not(bootstrap))] static_assert_size!(GenericArg, 56); static_assert_size!(GenericArgs, 32); static_assert_size!(GenericParamDef, 56); diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 23ad0c30f21ed..23e3de45fa510 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -9,14 +9,12 @@ #![feature(control_flow_enum)] #![feature(drain_filter)] #![feature(let_chains)] -#![cfg_attr(bootstrap, feature(let_else))] #![feature(test)] #![feature(never_type)] #![feature(once_cell)] #![feature(type_ascription)] #![feature(iter_intersperse)] #![feature(type_alias_impl_trait)] -#![cfg_attr(bootstrap, feature(generic_associated_types))] #![recursion_limit = "256"] #![warn(rustc::internal)] #![allow(clippy::collapsible_if, clippy::collapsible_else_if)] diff --git a/src/test/mir-opt/issue-101867.rs b/src/test/mir-opt/issue-101867.rs index 931396e2171f0..fcbe5a2b90a97 100644 --- a/src/test/mir-opt/issue-101867.rs +++ b/src/test/mir-opt/issue-101867.rs @@ -1,4 +1,3 @@ -#![cfg_attr(bootstrap, feature(let_else))] // EMIT_MIR issue_101867.main.mir_map.0.mir fn main() { diff --git a/src/test/ui/let-else/const-fn.rs b/src/test/ui/let-else/const-fn.rs index 336b0b4b72ad5..a3921b8033fc0 100644 --- a/src/test/ui/let-else/const-fn.rs +++ b/src/test/ui/let-else/const-fn.rs @@ -1,7 +1,6 @@ // run-pass // issue #101932 -#![cfg_attr(bootstrap, feature(let_else))] const fn foo(a: Option) -> i32 { let Some(a) = a else { diff --git a/src/tools/clippy/clippy_dev/src/lib.rs b/src/tools/clippy/clippy_dev/src/lib.rs index 54c7456a2a3b0..80bb83af43b19 100644 --- a/src/tools/clippy/clippy_dev/src/lib.rs +++ b/src/tools/clippy/clippy_dev/src/lib.rs @@ -1,5 +1,4 @@ #![feature(let_chains)] -#![cfg_attr(bootstrap, feature(let_else))] #![feature(once_cell)] #![feature(rustc_private)] #![cfg_attr(feature = "deny-warnings", deny(warnings))] diff --git a/src/tools/clippy/clippy_lints/src/lib.rs b/src/tools/clippy/clippy_lints/src/lib.rs index 298566cb5b625..00bf6445c12d2 100644 --- a/src/tools/clippy/clippy_lints/src/lib.rs +++ b/src/tools/clippy/clippy_lints/src/lib.rs @@ -5,7 +5,6 @@ #![feature(drain_filter)] #![feature(iter_intersperse)] #![feature(let_chains)] -#![cfg_attr(bootstrap, feature(let_else))] #![feature(lint_reasons)] #![feature(never_type)] #![feature(once_cell)] diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index 9343cf457b341..b1abd3b04c929 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -3,7 +3,6 @@ #![feature(control_flow_enum)] #![feature(let_chains)] #![feature(lint_reasons)] -#![cfg_attr(bootstrap, feature(let_else))] #![feature(once_cell)] #![feature(rustc_private)] #![recursion_limit = "512"] From 79ad2d59957c8ebe13a742472dfa55d5141cb84f Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Tue, 20 Sep 2022 17:02:26 +0200 Subject: [PATCH 260/586] fix check_cfg --- src/bootstrap/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 572adeb6420eb..c83490316b657 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -198,6 +198,7 @@ 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::Codegen), "parallel_compiler", None), (Some(Mode::Std), "stdarch_intel_sde", None), (Some(Mode::Std), "no_fp_fmt_parse", None), (Some(Mode::Std), "no_global_oom_handling", None), From e78507d97d8b3a31607c733bab45af1bc7e818fe Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Wed, 21 Sep 2022 09:24:00 +0200 Subject: [PATCH 261/586] applease tidy --- src/test/mir-opt/issue-101867.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/test/mir-opt/issue-101867.rs b/src/test/mir-opt/issue-101867.rs index fcbe5a2b90a97..8a357eb799514 100644 --- a/src/test/mir-opt/issue-101867.rs +++ b/src/test/mir-opt/issue-101867.rs @@ -1,4 +1,3 @@ - // EMIT_MIR issue_101867.main.mir_map.0.mir fn main() { let x: Option = Some(1); From 81cfb14d998e54c5a05c79cf95fba1fd2c8ac1db Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Wed, 21 Sep 2022 15:15:17 +0200 Subject: [PATCH 262/586] fix line number in expected test output --- src/test/mir-opt/issue_101867.main.mir_map.0.mir | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/mir-opt/issue_101867.main.mir_map.0.mir b/src/test/mir-opt/issue_101867.main.mir_map.0.mir index 98501ac8c9d84..ae2e4c02dd634 100644 --- a/src/test/mir-opt/issue_101867.main.mir_map.0.mir +++ b/src/test/mir-opt/issue_101867.main.mir_map.0.mir @@ -1,8 +1,8 @@ // MIR for `main` 0 mir_map | User Type Annotations -| 0: user_ty: Canonical { max_universe: U0, variables: [], value: Ty(std::option::Option) }, span: $DIR/issue-101867.rs:5:12: 5:22, inferred_ty: std::option::Option -| 1: user_ty: Canonical { max_universe: U0, variables: [], value: Ty(std::option::Option) }, span: $DIR/issue-101867.rs:5:12: 5:22, inferred_ty: std::option::Option +| 0: user_ty: Canonical { max_universe: U0, variables: [], value: Ty(std::option::Option) }, span: $DIR/issue-101867.rs:3:12: 5:22, inferred_ty: std::option::Option +| 1: user_ty: Canonical { max_universe: U0, variables: [], value: Ty(std::option::Option) }, span: $DIR/issue-101867.rs:3:12: 5:22, inferred_ty: std::option::Option | fn main() -> () { let mut _0: (); // return place in scope 0 at $DIR/issue-101867.rs:+0:11: +0:11 From f7b0c858a5c50946537abf053549b3df98b7f76a Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Fri, 23 Sep 2022 10:40:36 +0200 Subject: [PATCH 263/586] actually fix line number --- src/test/mir-opt/issue_101867.main.mir_map.0.mir | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/mir-opt/issue_101867.main.mir_map.0.mir b/src/test/mir-opt/issue_101867.main.mir_map.0.mir index ae2e4c02dd634..42a9e5587603d 100644 --- a/src/test/mir-opt/issue_101867.main.mir_map.0.mir +++ b/src/test/mir-opt/issue_101867.main.mir_map.0.mir @@ -1,8 +1,8 @@ // MIR for `main` 0 mir_map | User Type Annotations -| 0: user_ty: Canonical { max_universe: U0, variables: [], value: Ty(std::option::Option) }, span: $DIR/issue-101867.rs:3:12: 5:22, inferred_ty: std::option::Option -| 1: user_ty: Canonical { max_universe: U0, variables: [], value: Ty(std::option::Option) }, span: $DIR/issue-101867.rs:3:12: 5:22, inferred_ty: std::option::Option +| 0: user_ty: Canonical { max_universe: U0, variables: [], value: Ty(std::option::Option) }, span: $DIR/issue-101867.rs:3:12: 3:22, inferred_ty: std::option::Option +| 1: user_ty: Canonical { max_universe: U0, variables: [], value: Ty(std::option::Option) }, span: $DIR/issue-101867.rs:3:12: 3:22, inferred_ty: std::option::Option | fn main() -> () { let mut _0: (); // return place in scope 0 at $DIR/issue-101867.rs:+0:11: +0:11 From 475aeab79e7d9b0fcdc4fef7bc13e98772d24a94 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 25 Sep 2022 23:58:33 +0200 Subject: [PATCH 264/586] Improve code example for Option::unwrap_or_default --- library/core/src/option.rs | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/library/core/src/option.rs b/library/core/src/option.rs index ed7703befcfa3..4a93df4591b7a 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -834,20 +834,12 @@ impl Option { /// /// # Examples /// - /// Converts a string to an integer, turning poorly-formed strings - /// into 0 (the default value for integers). [`parse`] converts - /// a string to any other type that implements [`FromStr`], returning - /// [`None`] on error. - /// /// ``` - /// let good_year_from_input = "1909"; - /// let bad_year_from_input = "190blarg"; - /// // Result::ok() converts a Result to an Option - /// let good_year = good_year_from_input.parse().ok().unwrap_or_default(); - /// let bad_year = bad_year_from_input.parse().ok().unwrap_or_default(); + /// let x: Option = None; + /// let y: Option = Some(12); /// - /// assert_eq!(1909, good_year); - /// assert_eq!(0, bad_year); + /// assert_eq!(x.unwrap_or_default(), 0); + /// assert_eq!(y.unwrap_or_default(), 12); /// ``` /// /// [default value]: Default::default From 0919c945929f1cccc84fac44b982132ba2262a17 Mon Sep 17 00:00:00 2001 From: Florian Bartels Date: Mon, 26 Sep 2022 12:38:14 +0200 Subject: [PATCH 265/586] Get rid of long exclude-list for Windows-only tests --- src/test/ui/abi/x86stdcall.rs | 26 +++++--------------------- src/test/ui/abi/x86stdcall2.rs | 12 +++--------- 2 files changed, 8 insertions(+), 30 deletions(-) diff --git a/src/test/ui/abi/x86stdcall.rs b/src/test/ui/abi/x86stdcall.rs index 868923e593243..d1cf1319fb090 100644 --- a/src/test/ui/abi/x86stdcall.rs +++ b/src/test/ui/abi/x86stdcall.rs @@ -1,17 +1,15 @@ // run-pass -// ignore-wasm32-bare no libc to test ffi with -// ignore-sgx no libc +// only-windows // GetLastError doesn't seem to work with stack switching #[cfg(windows)] mod kernel32 { - extern "system" { - pub fn SetLastError(err: usize); - pub fn GetLastError() -> usize; - } + extern "system" { + pub fn SetLastError(err: usize); + pub fn GetLastError() -> usize; + } } - #[cfg(windows)] pub fn main() { unsafe { @@ -22,17 +20,3 @@ pub fn main() { assert_eq!(expected, actual); } } - -#[cfg(any(target_os = "android", - target_os = "dragonfly", - target_os = "emscripten", - target_os = "freebsd", - target_os = "fuchsia", - target_os = "illumos", - target_os = "linux", - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd", - target_os = "solaris", - target_os = "vxworks"))] -pub fn main() { } diff --git a/src/test/ui/abi/x86stdcall2.rs b/src/test/ui/abi/x86stdcall2.rs index 563e3aba6326c..4d508ecb2422e 100644 --- a/src/test/ui/abi/x86stdcall2.rs +++ b/src/test/ui/abi/x86stdcall2.rs @@ -1,4 +1,5 @@ // run-pass +// only-windows #![allow(non_camel_case_types)] pub type HANDLE = usize; @@ -7,20 +8,16 @@ pub type SIZE_T = u32; pub type LPVOID = usize; pub type BOOL = u8; -#[cfg(windows)] mod kernel32 { - use super::{HANDLE, DWORD, SIZE_T, LPVOID, BOOL}; + use super::{BOOL, DWORD, HANDLE, LPVOID, SIZE_T}; extern "system" { pub fn GetProcessHeap() -> HANDLE; - pub fn HeapAlloc(hHeap: HANDLE, dwFlags: DWORD, dwBytes: SIZE_T) - -> LPVOID; + pub fn HeapAlloc(hHeap: HANDLE, dwFlags: DWORD, dwBytes: SIZE_T) -> LPVOID; pub fn HeapFree(hHeap: HANDLE, dwFlags: DWORD, lpMem: LPVOID) -> BOOL; } } - -#[cfg(windows)] pub fn main() { let heap = unsafe { kernel32::GetProcessHeap() }; let mem = unsafe { kernel32::HeapAlloc(heap, 0, 100) }; @@ -28,6 +25,3 @@ pub fn main() { let res = unsafe { kernel32::HeapFree(heap, 0, mem) }; assert!(res != 0); } - -#[cfg(not(windows))] -pub fn main() { } From 932f930d279c1d974538bee1f8879b3007f97c99 Mon Sep 17 00:00:00 2001 From: lcnr Date: Mon, 26 Sep 2022 12:41:12 +0200 Subject: [PATCH 266/586] remove outdated coherence hack --- .../src/traits/select/mod.rs | 33 ------------------- 1 file changed, 33 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 5e32a27cdb1da..8d2a90503b6b4 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -35,7 +35,6 @@ use rustc_middle::mir::interpret::ErrorHandled; use rustc_middle::ty::abstract_const::NotConstEvaluatable; use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams}; use rustc_middle::ty::fold::BottomUpFolder; -use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::relate::TypeRelation; use rustc_middle::ty::SubstsRef; use rustc_middle::ty::{self, EarlyBinder, PolyProjectionPredicate, ToPolyTraitRef, ToPredicate}; @@ -914,38 +913,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let unbound_input_types = stack.fresh_trait_pred.skip_binder().trait_ref.substs.types().any(|ty| ty.is_fresh()); - if stack.obligation.polarity() != ty::ImplPolarity::Negative { - // This check was an imperfect workaround for a bug in the old - // intercrate mode; it should be removed when that goes away. - if unbound_input_types && self.intercrate { - debug!("evaluate_stack --> unbound argument, intercrate --> ambiguous",); - // Heuristics: show the diagnostics when there are no candidates in crate. - if self.intercrate_ambiguity_causes.is_some() { - debug!("evaluate_stack: intercrate_ambiguity_causes is some"); - if let Ok(candidate_set) = self.assemble_candidates(stack) { - if !candidate_set.ambiguous && candidate_set.vec.is_empty() { - let trait_ref = stack.obligation.predicate.skip_binder().trait_ref; - let self_ty = trait_ref.self_ty(); - let cause = with_no_trimmed_paths!({ - IntercrateAmbiguityCause::DownstreamCrate { - trait_desc: trait_ref.print_only_trait_path().to_string(), - self_desc: if self_ty.has_concrete_skeleton() { - Some(self_ty.to_string()) - } else { - None - }, - } - }); - - debug!(?cause, "evaluate_stack: pushing cause"); - self.intercrate_ambiguity_causes.as_mut().unwrap().insert(cause); - } - } - } - return Ok(EvaluatedToAmbig); - } - } - if unbound_input_types && stack.iter().skip(1).any(|prev| { stack.obligation.param_env == prev.obligation.param_env From f20c882b8b65f09701ef937b765e93e76682a298 Mon Sep 17 00:00:00 2001 From: David Wood Date: Fri, 23 Sep 2022 12:49:02 +0100 Subject: [PATCH 267/586] macros: support diagnostic derive on enums Signed-off-by: David Wood --- .../src/diagnostics/diagnostic.rs | 157 +++++--------- .../src/diagnostics/diagnostic_builder.rs | 204 ++++++++++-------- .../src/diagnostics/subdiagnostic.rs | 26 +-- .../rustc_macros/src/diagnostics/utils.rs | 85 ++++++-- .../session-diagnostic/diagnostic-derive.rs | 22 +- .../diagnostic-derive.stderr | 185 ++++++++-------- 6 files changed, 371 insertions(+), 308 deletions(-) diff --git a/compiler/rustc_macros/src/diagnostics/diagnostic.rs b/compiler/rustc_macros/src/diagnostics/diagnostic.rs index 3b8d9594eb91a..b9a283552f75f 100644 --- a/compiler/rustc_macros/src/diagnostics/diagnostic.rs +++ b/compiler/rustc_macros/src/diagnostics/diagnostic.rs @@ -2,10 +2,9 @@ use crate::diagnostics::diagnostic_builder::{DiagnosticDeriveBuilder, DiagnosticDeriveKind}; use crate::diagnostics::error::{span_err, DiagnosticDeriveError}; -use crate::diagnostics::utils::{build_field_mapping, SetOnce}; +use crate::diagnostics::utils::SetOnce; use proc_macro2::TokenStream; use quote::quote; -use syn::spanned::Spanned; use synstructure::Structure; /// The central struct for constructing the `into_diagnostic` method from an annotated struct. @@ -18,13 +17,7 @@ pub(crate) struct DiagnosticDerive<'a> { impl<'a> DiagnosticDerive<'a> { pub(crate) fn new(diag: syn::Ident, handler: syn::Ident, structure: Structure<'a>) -> Self { Self { - builder: DiagnosticDeriveBuilder { - diag, - fields: build_field_mapping(&structure), - kind: DiagnosticDeriveKind::Diagnostic, - code: None, - slug: None, - }, + builder: DiagnosticDeriveBuilder { diag, kind: DiagnosticDeriveKind::Diagnostic }, handler, structure, } @@ -33,52 +26,35 @@ impl<'a> DiagnosticDerive<'a> { pub(crate) fn into_tokens(self) -> TokenStream { let DiagnosticDerive { mut structure, handler, mut builder } = self; - let ast = structure.ast(); - let implementation = { - if let syn::Data::Struct(..) = ast.data { - let preamble = builder.preamble(&structure); - let (attrs, args) = builder.body(&mut structure); - - let span = ast.span().unwrap(); - let diag = &builder.diag; - let init = match builder.slug.value() { - None => { - span_err(span, "diagnostic slug not specified") - .help(&format!( - "specify the slug as the first argument to the `#[diag(...)]` attribute, \ - such as `#[diag(typeck::example_error)]`", - )) - .emit(); - return DiagnosticDeriveError::ErrorHandled.to_compile_error(); - } - Some(slug) => { - quote! { - let mut #diag = #handler.struct_diagnostic(rustc_errors::fluent::#slug); - } - } - }; - - quote! { - #init - #preamble - match self { - #attrs - } - match self { - #args + let implementation = builder.each_variant(&mut structure, |mut builder, variant| { + let preamble = builder.preamble(&variant); + let body = builder.body(&variant); + + let diag = &builder.parent.diag; + let init = match builder.slug.value_ref() { + None => { + span_err(builder.span, "diagnostic slug not specified") + .help(&format!( + "specify the slug as the first argument to the `#[diag(...)]` \ + attribute, such as `#[diag(typeck::example_error)]`", + )) + .emit(); + return DiagnosticDeriveError::ErrorHandled.to_compile_error(); + } + Some(slug) => { + quote! { + let mut #diag = #handler.struct_diagnostic(rustc_errors::fluent::#slug); } - #diag } - } else { - span_err( - ast.span().unwrap(), - "`#[derive(Diagnostic)]` can only be used on structs", - ) - .emit(); + }; - DiagnosticDeriveError::ErrorHandled.to_compile_error() + quote! { + #init + #preamble + #body + #diag } - }; + }); structure.gen_impl(quote! { gen impl<'__diagnostic_handler_sess, G> @@ -107,13 +83,7 @@ pub(crate) struct LintDiagnosticDerive<'a> { impl<'a> LintDiagnosticDerive<'a> { pub(crate) fn new(diag: syn::Ident, structure: Structure<'a>) -> Self { Self { - builder: DiagnosticDeriveBuilder { - diag, - fields: build_field_mapping(&structure), - kind: DiagnosticDeriveKind::LintDiagnostic, - code: None, - slug: None, - }, + builder: DiagnosticDeriveBuilder { diag, kind: DiagnosticDeriveKind::LintDiagnostic }, structure, } } @@ -121,54 +91,35 @@ impl<'a> LintDiagnosticDerive<'a> { pub(crate) fn into_tokens(self) -> TokenStream { let LintDiagnosticDerive { mut structure, mut builder } = self; - let ast = structure.ast(); - let implementation = { - if let syn::Data::Struct(..) = ast.data { - let preamble = builder.preamble(&structure); - let (attrs, args) = builder.body(&mut structure); - - let diag = &builder.diag; - let span = ast.span().unwrap(); - let init = match builder.slug.value() { - None => { - span_err(span, "diagnostic slug not specified") - .help(&format!( - "specify the slug as the first argument to the attribute, such as \ - `#[diag(typeck::example_error)]`", - )) - .emit(); - return DiagnosticDeriveError::ErrorHandled.to_compile_error(); - } - Some(slug) => { - quote! { - let mut #diag = #diag.build(rustc_errors::fluent::#slug); - } - } - }; - - let implementation = quote! { - #init - #preamble - match self { - #attrs - } - match self { - #args + let implementation = builder.each_variant(&mut structure, |mut builder, variant| { + let preamble = builder.preamble(&variant); + let body = builder.body(&variant); + + let diag = &builder.parent.diag; + let init = match builder.slug.value_ref() { + None => { + span_err(builder.span, "diagnostic slug not specified") + .help(&format!( + "specify the slug as the first argument to the attribute, such as \ + `#[diag(typeck::example_error)]`", + )) + .emit(); + return DiagnosticDeriveError::ErrorHandled.to_compile_error(); + } + Some(slug) => { + quote! { + let mut #diag = #diag.build(rustc_errors::fluent::#slug); } - #diag.emit(); - }; - - implementation - } else { - span_err( - ast.span().unwrap(), - "`#[derive(LintDiagnostic)]` can only be used on structs", - ) - .emit(); + } + }; - DiagnosticDeriveError::ErrorHandled.to_compile_error() + quote! { + #init + #preamble + #body + #diag.emit(); } - }; + }); let diag = &builder.diag; structure.gen_impl(quote! { diff --git a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs index 2aa292bbce2b6..38bd986f76fb9 100644 --- a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs +++ b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs @@ -1,22 +1,20 @@ #![deny(unused_must_use)] -use super::error::throw_invalid_nested_attr; -use super::utils::{SpannedOption, SubdiagnosticKind}; use crate::diagnostics::error::{ - invalid_nested_attr, span_err, throw_invalid_attr, throw_span_err, DiagnosticDeriveError, + invalid_nested_attr, span_err, throw_invalid_attr, throw_invalid_nested_attr, throw_span_err, + DiagnosticDeriveError, }; use crate::diagnostics::utils::{ - report_error_if_not_applied_to_span, report_type_error, type_is_unit, type_matches_path, - FieldInfo, FieldInnerTy, HasFieldMap, SetOnce, + bind_style_of_field, build_field_mapping, report_error_if_not_applied_to_span, + report_type_error, should_generate_set_arg, type_is_unit, type_matches_path, FieldInfo, + FieldInnerTy, FieldMap, HasFieldMap, SetOnce, SpannedOption, SubdiagnosticKind, }; use proc_macro2::{Ident, Span, TokenStream}; use quote::{format_ident, quote}; -use std::collections::HashMap; use syn::{ - parse_quote, spanned::Spanned, Attribute, Field, Meta, MetaList, MetaNameValue, NestedMeta, - Path, Type, + parse_quote, spanned::Spanned, Attribute, Meta, MetaList, MetaNameValue, NestedMeta, Path, Type, }; -use synstructure::{BindingInfo, Structure}; +use synstructure::{BindingInfo, Structure, VariantInfo}; /// What kind of diagnostic is being derived - a fatal/error/warning or a lint? #[derive(Copy, Clone, PartialEq, Eq)] @@ -25,19 +23,30 @@ pub(crate) enum DiagnosticDeriveKind { LintDiagnostic, } -/// Tracks persistent information required for building up individual calls to diagnostic methods -/// for generated diagnostic derives - both `Diagnostic` for fatal/errors/warnings and -/// `LintDiagnostic` for lints. +/// Tracks persistent information required for the entire type when building up individual calls to +/// diagnostic methods for generated diagnostic derives - both `Diagnostic` for +/// fatal/errors/warnings and `LintDiagnostic` for lints. pub(crate) struct DiagnosticDeriveBuilder { /// The identifier to use for the generated `DiagnosticBuilder` instance. pub diag: syn::Ident, + /// Kind of diagnostic that should be derived. + pub kind: DiagnosticDeriveKind, +} + +/// Tracks persistent information required for a specific variant when building up individual calls +/// to diagnostic methods for generated diagnostic derives - both `Diagnostic` for +/// fatal/errors/warnings and `LintDiagnostic` for lints. +pub(crate) struct DiagnosticDeriveVariantBuilder<'parent> { + /// The parent builder for the entire type. + pub parent: &'parent DiagnosticDeriveBuilder, + + /// Span of the struct or the enum variant. + pub span: proc_macro::Span, /// Store a map of field name to its corresponding field. This is built on construction of the /// derive builder. - pub fields: HashMap, + pub field_map: FieldMap, - /// Kind of diagnostic that should be derived. - pub kind: DiagnosticDeriveKind, /// Slug is a mandatory part of the struct attribute as corresponds to the Fluent message that /// has the actual diagnostic message. pub slug: SpannedOption, @@ -46,15 +55,82 @@ pub(crate) struct DiagnosticDeriveBuilder { pub code: SpannedOption<()>, } -impl HasFieldMap for DiagnosticDeriveBuilder { +impl<'a> HasFieldMap for DiagnosticDeriveVariantBuilder<'a> { fn get_field_binding(&self, field: &String) -> Option<&TokenStream> { - self.fields.get(field) + self.field_map.get(field) } } impl DiagnosticDeriveBuilder { - pub fn preamble<'s>(&mut self, structure: &Structure<'s>) -> TokenStream { + /// Call `f` for the struct or for each variant of the enum, returning a `TokenStream` with the + /// tokens from `f` wrapped in an `match` expression. Emits errors for use of derive on unions + /// or attributes on the type itself when input is an enum. + pub fn each_variant<'s, F>(&mut self, structure: &mut Structure<'s>, f: F) -> TokenStream + where + F: for<'a, 'v> Fn(DiagnosticDeriveVariantBuilder<'a>, &VariantInfo<'v>) -> TokenStream, + { let ast = structure.ast(); + let span = ast.span().unwrap(); + match ast.data { + syn::Data::Struct(..) | syn::Data::Enum(..) => (), + syn::Data::Union(..) => { + span_err(span, "diagnostic derives can only be used on structs and enums"); + } + } + + if matches!(ast.data, syn::Data::Enum(..)) { + for attr in &ast.attrs { + span_err( + attr.span().unwrap(), + "unsupported type attribute for diagnostic derive enum", + ) + .emit(); + } + } + + for variant in structure.variants_mut() { + // First, change the binding style of each field based on the code that will be + // generated for the field - e.g. `set_arg` calls needs by-move bindings, whereas + // `set_primary_span` only needs by-ref. + variant.bind_with(|bi| bind_style_of_field(bi.ast()).0); + + // Then, perform a stable sort on bindings which generates code for by-ref bindings + // before code generated for by-move bindings. Any code generated for the by-ref + // bindings which creates a reference to the by-move fields will happen before the + // by-move bindings move those fields and make them inaccessible. + variant.bindings_mut().sort_by_cached_key(|bi| bind_style_of_field(bi.ast())); + } + + let variants = structure.each_variant(|variant| { + let span = match structure.ast().data { + syn::Data::Struct(..) => span, + // There isn't a good way to get the span of the variant, so the variant's + // name will need to do. + _ => variant.ast().ident.span().unwrap(), + }; + let builder = DiagnosticDeriveVariantBuilder { + parent: &self, + span, + field_map: build_field_mapping(variant), + slug: None, + code: None, + }; + f(builder, variant) + }); + + quote! { + match self { + #variants + } + } + } +} + +impl<'a> DiagnosticDeriveVariantBuilder<'a> { + /// Generates calls to `code` and similar functions based on the attributes on the type or + /// variant. + pub fn preamble<'s>(&mut self, variant: &VariantInfo<'s>) -> TokenStream { + let ast = variant.ast(); let attrs = &ast.attrs; let preamble = attrs.iter().map(|attr| { self.generate_structure_code_for_attr(attr).unwrap_or_else(|v| v.to_compile_error()) @@ -65,68 +141,24 @@ impl DiagnosticDeriveBuilder { } } - pub fn body<'s>(&mut self, structure: &mut Structure<'s>) -> (TokenStream, TokenStream) { - // Keep track of which fields need to be handled with a by-move binding. - let mut needs_moved = std::collections::HashSet::new(); - - // Generates calls to `span_label` and similar functions based on the attributes - // on fields. Code for suggestions uses formatting machinery and the value of - // other fields - because any given field can be referenced multiple times, it - // should be accessed through a borrow. When passing fields to `add_subdiagnostic` - // or `set_arg` (which happens below) for Fluent, we want to move the data, so that - // has to happen in a separate pass over the fields. - let attrs = structure - .clone() - .filter(|field_binding| { - let ast = &field_binding.ast(); - !self.needs_move(ast) || { - needs_moved.insert(field_binding.binding.clone()); - false - } - }) - .each(|field_binding| self.generate_field_attrs_code(field_binding)); - - structure.bind_with(|_| synstructure::BindStyle::Move); - // When a field has attributes like `#[label]` or `#[note]` then it doesn't - // need to be passed as an argument to the diagnostic. But when a field has no - // attributes or a `#[subdiagnostic]` attribute then it must be passed as an - // argument to the diagnostic so that it can be referred to by Fluent messages. - let args = structure - .filter(|field_binding| needs_moved.contains(&field_binding.binding)) - .each(|field_binding| self.generate_field_attrs_code(field_binding)); - - (attrs, args) - } - - /// Returns `true` if `field` should generate a `set_arg` call rather than any other diagnostic - /// call (like `span_label`). - fn should_generate_set_arg(&self, field: &Field) -> bool { - field.attrs.is_empty() - } - - /// Returns `true` if `field` needs to have code generated in the by-move branch of the - /// generated derive rather than the by-ref branch. - fn needs_move(&self, field: &Field) -> bool { - let generates_set_arg = self.should_generate_set_arg(field); - let is_multispan = type_matches_path(&field.ty, &["rustc_errors", "MultiSpan"]); - // FIXME(davidtwco): better support for one field needing to be in the by-move and - // by-ref branches. - let is_subdiagnostic = field - .attrs - .iter() - .map(|attr| attr.path.segments.last().unwrap().ident.to_string()) - .any(|attr| attr == "subdiagnostic"); - - // `set_arg` calls take their argument by-move.. - generates_set_arg - // If this is a `MultiSpan` field then it needs to be moved to be used by any - // attribute.. - || is_multispan - // If this a `#[subdiagnostic]` then it needs to be moved as the other diagnostic is - // unlikely to be `Copy`.. - || is_subdiagnostic + /// Generates calls to `span_label` and similar functions based on the attributes on fields or + /// calls to `set_arg` when no attributes are present. + /// + /// Expects use of `Self::each_variant` which will have sorted bindings so that by-ref bindings + /// (which may create references to by-move bindings) have their code generated first - + /// necessary as code for suggestions uses formatting machinery and the value of other fields + /// (any given field can be referenced multiple times, so must be accessed through a borrow); + /// and when passing fields to `add_subdiagnostic` or `set_arg` for Fluent, fields must be + /// accessed by-move. + pub fn body<'s>(&mut self, variant: &VariantInfo<'s>) -> TokenStream { + let mut body = quote! {}; + for binding in variant.bindings() { + body.extend(self.generate_field_attrs_code(binding)); + } + body } + /// Parse a `SubdiagnosticKind` from an `Attribute`. fn parse_subdiag_attribute( &self, attr: &Attribute, @@ -158,7 +190,7 @@ impl DiagnosticDeriveBuilder { &mut self, attr: &Attribute, ) -> Result { - let diag = &self.diag; + let diag = &self.parent.diag; let name = attr.path.segments.last().unwrap().ident.to_string(); let name = name.as_str(); @@ -246,8 +278,8 @@ impl DiagnosticDeriveBuilder { let field = binding_info.ast(); let field_binding = &binding_info.binding; - if self.should_generate_set_arg(&field) { - let diag = &self.diag; + if should_generate_set_arg(&field) { + let diag = &self.parent.diag; let ident = field.ident.as_ref().unwrap(); return quote! { #diag.set_arg( @@ -257,7 +289,7 @@ impl DiagnosticDeriveBuilder { }; } - let needs_move = self.needs_move(&field); + let needs_move = bind_style_of_field(&field).is_move(); let inner_ty = FieldInnerTy::from_type(&field.ty); field @@ -303,7 +335,7 @@ impl DiagnosticDeriveBuilder { info: FieldInfo<'_>, binding: TokenStream, ) -> Result { - let diag = &self.diag; + let diag = &self.parent.diag; let meta = attr.parse_meta()?; if let Meta::Path(_) = meta { @@ -316,7 +348,7 @@ impl DiagnosticDeriveBuilder { // `set_arg` call will not be generated. return Ok(quote! {}); } - "primary_span" => match self.kind { + "primary_span" => match self.parent.kind { DiagnosticDeriveKind::Diagnostic => { report_error_if_not_applied_to_span(attr, &info)?; @@ -390,7 +422,7 @@ impl DiagnosticDeriveBuilder { kind: &Ident, fluent_attr_identifier: Path, ) -> TokenStream { - let diag = &self.diag; + let diag = &self.parent.diag; let fn_name = format_ident!("span_{}", kind); quote! { #diag.#fn_name( @@ -403,7 +435,7 @@ impl DiagnosticDeriveBuilder { /// Adds a subdiagnostic by generating a `diag.span_$kind` call with the current slug /// and `fluent_attr_identifier`. fn add_subdiagnostic(&self, kind: &Ident, fluent_attr_identifier: Path) -> TokenStream { - let diag = &self.diag; + let diag = &self.parent.diag; quote! { #diag.#kind(rustc_errors::fluent::#fluent_attr_identifier); } diff --git a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs index 6545ae086b158..adb4902ebc172 100644 --- a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs +++ b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs @@ -1,21 +1,19 @@ #![deny(unused_must_use)] use crate::diagnostics::error::{ - span_err, throw_invalid_attr, throw_invalid_nested_attr, throw_span_err, DiagnosticDeriveError, + invalid_attr, span_err, throw_invalid_attr, throw_invalid_nested_attr, throw_span_err, + DiagnosticDeriveError, }; use crate::diagnostics::utils::{ - report_error_if_not_applied_to_applicability, report_error_if_not_applied_to_span, FieldInfo, - FieldInnerTy, HasFieldMap, SetOnce, + build_field_mapping, report_error_if_not_applied_to_applicability, + report_error_if_not_applied_to_span, FieldInfo, FieldInnerTy, FieldMap, HasFieldMap, SetOnce, + SpannedOption, SubdiagnosticKind, }; use proc_macro2::TokenStream; use quote::{format_ident, quote}; -use std::collections::HashMap; use syn::{spanned::Spanned, Attribute, Meta, MetaList, MetaNameValue, NestedMeta, Path}; use synstructure::{BindingInfo, Structure, VariantInfo}; -use super::error::invalid_attr; -use super::utils::{SpannedOption, SubdiagnosticKind}; - /// The central struct for constructing the `add_to_diagnostic` method from an annotated struct. pub(crate) struct SubdiagnosticDerive<'a> { structure: Structure<'a>, @@ -55,21 +53,11 @@ impl<'a> SubdiagnosticDerive<'a> { structure.bind_with(|_| synstructure::BindStyle::Move); let variants_ = structure.each_variant(|variant| { - // Build the mapping of field names to fields. This allows attributes to peek - // values from other fields. - let mut fields_map = HashMap::new(); - for binding in variant.bindings() { - let field = binding.ast(); - if let Some(ident) = &field.ident { - fields_map.insert(ident.to_string(), quote! { #binding }); - } - } - let mut builder = SubdiagnosticDeriveBuilder { diag: &diag, variant, span, - fields: fields_map, + fields: build_field_mapping(variant), span_field: None, applicability: None, has_suggestion_parts: false, @@ -111,7 +99,7 @@ struct SubdiagnosticDeriveBuilder<'a> { /// Store a map of field name to its corresponding field. This is built on construction of the /// derive builder. - fields: HashMap, + fields: FieldMap, /// Identifier for the binding to the `#[primary_span]` field. span_field: SpannedOption, diff --git a/compiler/rustc_macros/src/diagnostics/utils.rs b/compiler/rustc_macros/src/diagnostics/utils.rs index a31bda9ca0def..162699c286872 100644 --- a/compiler/rustc_macros/src/diagnostics/utils.rs +++ b/compiler/rustc_macros/src/diagnostics/utils.rs @@ -4,12 +4,13 @@ use crate::diagnostics::error::{ use proc_macro::Span; use proc_macro2::TokenStream; use quote::{format_ident, quote, ToTokens}; +use std::cmp::Ordering; use std::collections::{BTreeSet, HashMap}; use std::fmt; use std::str::FromStr; -use syn::{spanned::Spanned, Attribute, Meta, Type, TypeTuple}; +use syn::{spanned::Spanned, Attribute, Field, Meta, Type, TypeTuple}; use syn::{MetaList, MetaNameValue, NestedMeta, Path}; -use synstructure::{BindingInfo, Structure}; +use synstructure::{BindStyle, BindingInfo, VariantInfo}; use super::error::invalid_nested_attr; @@ -210,6 +211,8 @@ impl SetOnce for SpannedOption { } } +pub(super) type FieldMap = HashMap; + pub(crate) trait HasFieldMap { /// Returns the binding for the field with the given name, if it exists on the type. fn get_field_binding(&self, field: &String) -> Option<&TokenStream>; @@ -360,18 +363,13 @@ impl quote::ToTokens for Applicability { /// Build the mapping of field names to fields. This allows attributes to peek values from /// other fields. -pub(crate) fn build_field_mapping<'a>(structure: &Structure<'a>) -> HashMap { - let mut fields_map = HashMap::new(); - - let ast = structure.ast(); - if let syn::Data::Struct(syn::DataStruct { fields, .. }) = &ast.data { - for field in fields.iter() { - if let Some(ident) = &field.ident { - fields_map.insert(ident.to_string(), quote! { &self.#ident }); - } +pub(super) fn build_field_mapping<'v>(variant: &VariantInfo<'v>) -> HashMap { + let mut fields_map = FieldMap::new(); + for binding in variant.bindings() { + if let Some(ident) = &binding.ast().ident { + fields_map.insert(ident.to_string(), quote! { #binding }); } } - fields_map } @@ -621,3 +619,66 @@ impl quote::IdentFragment for SubdiagnosticKind { None } } + +/// Wrapper around `synstructure::BindStyle` which implements `Ord`. +#[derive(PartialEq, Eq)] +pub(super) struct OrderedBindStyle(pub(super) BindStyle); + +impl OrderedBindStyle { + /// Is `BindStyle::Move` or `BindStyle::MoveMut`? + pub(super) fn is_move(&self) -> bool { + matches!(self.0, BindStyle::Move | BindStyle::MoveMut) + } +} + +impl Ord for OrderedBindStyle { + fn cmp(&self, other: &Self) -> Ordering { + match (self.is_move(), other.is_move()) { + // If both `self` and `other` are the same, then ordering is equal. + (true, true) | (false, false) => Ordering::Equal, + // If `self` is not a move then it should be considered less than `other` (so that + // references are sorted first). + (false, _) => Ordering::Less, + // If `self` is a move then it must be greater than `other` (again, so that references + // are sorted first). + (true, _) => Ordering::Greater, + } + } +} + +impl PartialOrd for OrderedBindStyle { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +/// Returns `true` if `field` should generate a `set_arg` call rather than any other diagnostic +/// call (like `span_label`). +pub(super) fn should_generate_set_arg(field: &Field) -> bool { + field.attrs.is_empty() +} + +/// Returns `true` if `field` needs to have code generated in the by-move branch of the +/// generated derive rather than the by-ref branch. +pub(super) fn bind_style_of_field(field: &Field) -> OrderedBindStyle { + let generates_set_arg = should_generate_set_arg(field); + let is_multispan = type_matches_path(&field.ty, &["rustc_errors", "MultiSpan"]); + // FIXME(davidtwco): better support for one field needing to be in the by-move and + // by-ref branches. + let is_subdiagnostic = field + .attrs + .iter() + .map(|attr| attr.path.segments.last().unwrap().ident.to_string()) + .any(|attr| attr == "subdiagnostic"); + + // `set_arg` calls take their argument by-move.. + let needs_move = generates_set_arg + // If this is a `MultiSpan` field then it needs to be moved to be used by any + // attribute.. + || is_multispan + // If this a `#[subdiagnostic]` then it needs to be moved as the other diagnostic is + // unlikely to be `Copy`.. + || is_subdiagnostic; + + OrderedBindStyle(if needs_move { BindStyle::Move } else { BindStyle::Ref }) +} diff --git a/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs b/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs index ad481c14bab8d..cf04e05095f0a 100644 --- a/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs +++ b/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs @@ -37,10 +37,12 @@ struct HelloWarn {} #[derive(Diagnostic)] #[diag(typeck::ambiguous_lifetime_bound, code = "E0123")] -//~^ ERROR `#[derive(Diagnostic)]` can only be used on structs +//~^ ERROR unsupported type attribute for diagnostic derive enum enum DiagnosticOnEnum { Foo, +//~^ ERROR diagnostic slug not specified Bar, +//~^ ERROR diagnostic slug not specified } #[derive(Diagnostic)] @@ -651,3 +653,21 @@ struct LabelOnStruct { #[primary_span] suggestion: Span, } + +#[derive(Diagnostic)] +enum ExampleEnum { + #[diag(typeck::ambiguous_lifetime_bound)] + Foo { + #[primary_span] + sp: Span, + #[note] + note_sp: Span, + }, + #[diag(typeck::ambiguous_lifetime_bound)] + Bar { + #[primary_span] + sp: Span, + }, + #[diag(typeck::ambiguous_lifetime_bound)] + Baz, +} diff --git a/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr b/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr index 9919b12beaf0a..68602640a24f2 100644 --- a/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr +++ b/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr @@ -1,28 +1,39 @@ -error: `#[derive(Diagnostic)]` can only be used on structs +error: unsupported type attribute for diagnostic derive enum --> $DIR/diagnostic-derive.rs:39:1 | -LL | / #[diag(typeck::ambiguous_lifetime_bound, code = "E0123")] -LL | | -LL | | enum DiagnosticOnEnum { -LL | | Foo, -LL | | Bar, -LL | | } - | |_^ +LL | #[diag(typeck::ambiguous_lifetime_bound, code = "E0123")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: diagnostic slug not specified + --> $DIR/diagnostic-derive.rs:42:5 + | +LL | Foo, + | ^^^ + | + = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(typeck::example_error)]` + +error: diagnostic slug not specified + --> $DIR/diagnostic-derive.rs:44:5 + | +LL | Bar, + | ^^^ + | + = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(typeck::example_error)]` error: `#[diag = ...]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:48:1 + --> $DIR/diagnostic-derive.rs:50:1 | LL | #[diag = "E0123"] | ^^^^^^^^^^^^^^^^^ error: `#[nonsense(...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:53:1 + --> $DIR/diagnostic-derive.rs:55:1 | LL | #[nonsense(typeck::ambiguous_lifetime_bound, code = "E0123")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: diagnostic slug not specified - --> $DIR/diagnostic-derive.rs:53:1 + --> $DIR/diagnostic-derive.rs:55:1 | LL | / #[nonsense(typeck::ambiguous_lifetime_bound, code = "E0123")] LL | | @@ -34,7 +45,7 @@ LL | | struct InvalidStructAttr {} = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(typeck::example_error)]` error: `#[diag("...")]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:60:8 + --> $DIR/diagnostic-derive.rs:62:8 | LL | #[diag("E0123")] | ^^^^^^^ @@ -42,7 +53,7 @@ LL | #[diag("E0123")] = help: a diagnostic slug is required as the first argument error: diagnostic slug not specified - --> $DIR/diagnostic-derive.rs:60:1 + --> $DIR/diagnostic-derive.rs:62:1 | LL | / #[diag("E0123")] LL | | @@ -53,7 +64,7 @@ LL | | struct InvalidLitNestedAttr {} = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(typeck::example_error)]` error: `#[diag(nonsense(...))]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:71:8 + --> $DIR/diagnostic-derive.rs:73:8 | LL | #[diag(nonsense("foo"), code = "E0123", slug = "foo")] | ^^^^^^^^^^^^^^^ @@ -61,7 +72,7 @@ LL | #[diag(nonsense("foo"), code = "E0123", slug = "foo")] = help: a diagnostic slug is required as the first argument error: diagnostic slug not specified - --> $DIR/diagnostic-derive.rs:71:1 + --> $DIR/diagnostic-derive.rs:73:1 | LL | / #[diag(nonsense("foo"), code = "E0123", slug = "foo")] LL | | @@ -72,7 +83,7 @@ LL | | struct InvalidNestedStructAttr1 {} = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(typeck::example_error)]` error: `#[diag(nonsense = ...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:77:8 + --> $DIR/diagnostic-derive.rs:79:8 | LL | #[diag(nonsense = "...", code = "E0123", slug = "foo")] | ^^^^^^^^^^^^^^^^ @@ -80,7 +91,7 @@ LL | #[diag(nonsense = "...", code = "E0123", slug = "foo")] = help: only `code` is a valid nested attributes following the slug error: `#[diag(slug = ...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:77:42 + --> $DIR/diagnostic-derive.rs:79:42 | LL | #[diag(nonsense = "...", code = "E0123", slug = "foo")] | ^^^^^^^^^^^^ @@ -88,7 +99,7 @@ LL | #[diag(nonsense = "...", code = "E0123", slug = "foo")] = help: only `code` is a valid nested attributes following the slug error: diagnostic slug not specified - --> $DIR/diagnostic-derive.rs:77:1 + --> $DIR/diagnostic-derive.rs:79:1 | LL | / #[diag(nonsense = "...", code = "E0123", slug = "foo")] LL | | @@ -100,13 +111,13 @@ LL | | struct InvalidNestedStructAttr2 {} = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(typeck::example_error)]` error: `#[diag(nonsense = ...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:84:8 + --> $DIR/diagnostic-derive.rs:86:8 | LL | #[diag(nonsense = 4, code = "E0123", slug = "foo")] | ^^^^^^^^^^^^ error: `#[diag(slug = ...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:84:38 + --> $DIR/diagnostic-derive.rs:86:38 | LL | #[diag(nonsense = 4, code = "E0123", slug = "foo")] | ^^^^^^^^^^^^ @@ -114,7 +125,7 @@ LL | #[diag(nonsense = 4, code = "E0123", slug = "foo")] = help: only `code` is a valid nested attributes following the slug error: diagnostic slug not specified - --> $DIR/diagnostic-derive.rs:84:1 + --> $DIR/diagnostic-derive.rs:86:1 | LL | / #[diag(nonsense = 4, code = "E0123", slug = "foo")] LL | | @@ -126,7 +137,7 @@ LL | | struct InvalidNestedStructAttr3 {} = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(typeck::example_error)]` error: `#[diag(slug = ...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:91:58 + --> $DIR/diagnostic-derive.rs:93:58 | LL | #[diag(typeck::ambiguous_lifetime_bound, code = "E0123", slug = "foo")] | ^^^^^^^^^^^^ @@ -134,49 +145,49 @@ LL | #[diag(typeck::ambiguous_lifetime_bound, code = "E0123", slug = "foo")] = help: only `code` is a valid nested attributes following the slug error: `#[suggestion = ...]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:98:5 + --> $DIR/diagnostic-derive.rs:100:5 | LL | #[suggestion = "bar"] | ^^^^^^^^^^^^^^^^^^^^^ error: specified multiple times - --> $DIR/diagnostic-derive.rs:105:8 + --> $DIR/diagnostic-derive.rs:107:8 | LL | #[diag(typeck::ambiguous_lifetime_bound, code = "E0456")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: previously specified here - --> $DIR/diagnostic-derive.rs:104:8 + --> $DIR/diagnostic-derive.rs:106:8 | LL | #[diag(typeck::ambiguous_lifetime_bound, code = "E0123")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: specified multiple times - --> $DIR/diagnostic-derive.rs:105:49 + --> $DIR/diagnostic-derive.rs:107:49 | LL | #[diag(typeck::ambiguous_lifetime_bound, code = "E0456")] | ^^^^^^^ | note: previously specified here - --> $DIR/diagnostic-derive.rs:104:49 + --> $DIR/diagnostic-derive.rs:106:49 | LL | #[diag(typeck::ambiguous_lifetime_bound, code = "E0123")] | ^^^^^^^ error: specified multiple times - --> $DIR/diagnostic-derive.rs:111:65 + --> $DIR/diagnostic-derive.rs:113:65 | LL | #[diag(typeck::ambiguous_lifetime_bound, code = "E0456", code = "E0457")] | ^^^^^^^ | note: previously specified here - --> $DIR/diagnostic-derive.rs:111:49 + --> $DIR/diagnostic-derive.rs:113:49 | LL | #[diag(typeck::ambiguous_lifetime_bound, code = "E0456", code = "E0457")] | ^^^^^^^ error: `#[diag(typeck::ambiguous_lifetime_bound)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:116:42 + --> $DIR/diagnostic-derive.rs:118:42 | LL | #[diag(typeck::ambiguous_lifetime_bound, typeck::ambiguous_lifetime_bound, code = "E0456")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -184,7 +195,7 @@ LL | #[diag(typeck::ambiguous_lifetime_bound, typeck::ambiguous_lifetime_bound, = help: diagnostic slug must be the first argument error: diagnostic slug not specified - --> $DIR/diagnostic-derive.rs:121:1 + --> $DIR/diagnostic-derive.rs:123:1 | LL | struct KindNotProvided {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -192,7 +203,7 @@ LL | struct KindNotProvided {} = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(typeck::example_error)]` error: diagnostic slug not specified - --> $DIR/diagnostic-derive.rs:124:1 + --> $DIR/diagnostic-derive.rs:126:1 | LL | / #[diag(code = "E0456")] LL | | @@ -202,31 +213,31 @@ LL | | struct SlugNotProvided {} = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(typeck::example_error)]` error: the `#[primary_span]` attribute can only be applied to fields of type `Span` or `MultiSpan` - --> $DIR/diagnostic-derive.rs:135:5 + --> $DIR/diagnostic-derive.rs:137:5 | LL | #[primary_span] | ^^^^^^^^^^^^^^^ error: `#[nonsense]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:143:5 + --> $DIR/diagnostic-derive.rs:145:5 | LL | #[nonsense] | ^^^^^^^^^^^ error: the `#[label(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan` - --> $DIR/diagnostic-derive.rs:160:5 + --> $DIR/diagnostic-derive.rs:162:5 | LL | #[label(typeck::label)] | ^^^^^^^^^^^^^^^^^^^^^^^ error: `name` doesn't refer to a field on this type - --> $DIR/diagnostic-derive.rs:168:45 + --> $DIR/diagnostic-derive.rs:170:45 | LL | #[suggestion(typeck::suggestion, code = "{name}")] | ^^^^^^^^ error: invalid format string: expected `'}'` but string was terminated - --> $DIR/diagnostic-derive.rs:173:16 + --> $DIR/diagnostic-derive.rs:175:16 | LL | #[derive(Diagnostic)] | - ^ expected `'}'` in format string @@ -237,7 +248,7 @@ LL | #[derive(Diagnostic)] = note: this error originates in the derive macro `Diagnostic` (in Nightly builds, run with -Z macro-backtrace for more info) error: invalid format string: unmatched `}` found - --> $DIR/diagnostic-derive.rs:183:15 + --> $DIR/diagnostic-derive.rs:185:15 | LL | #[derive(Diagnostic)] | ^ unmatched `}` in format string @@ -246,19 +257,19 @@ LL | #[derive(Diagnostic)] = note: this error originates in the derive macro `Diagnostic` (in Nightly builds, run with -Z macro-backtrace for more info) error: the `#[label(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan` - --> $DIR/diagnostic-derive.rs:203:5 + --> $DIR/diagnostic-derive.rs:205:5 | LL | #[label(typeck::label)] | ^^^^^^^^^^^^^^^^^^^^^^^ error: suggestion without `code = "..."` - --> $DIR/diagnostic-derive.rs:221:5 + --> $DIR/diagnostic-derive.rs:223:5 | LL | #[suggestion(typeck::suggestion)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: `#[suggestion(nonsense = ...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:229:18 + --> $DIR/diagnostic-derive.rs:231:18 | LL | #[suggestion(nonsense = "bar")] | ^^^^^^^^^^^^^^^^ @@ -266,13 +277,13 @@ LL | #[suggestion(nonsense = "bar")] = help: only `code` and `applicability` are valid nested attributes error: suggestion without `code = "..."` - --> $DIR/diagnostic-derive.rs:229:5 + --> $DIR/diagnostic-derive.rs:231:5 | LL | #[suggestion(nonsense = "bar")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: `#[suggestion(msg = ...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:238:18 + --> $DIR/diagnostic-derive.rs:240:18 | LL | #[suggestion(msg = "bar")] | ^^^^^^^^^^^ @@ -280,13 +291,13 @@ LL | #[suggestion(msg = "bar")] = help: only `code` and `applicability` are valid nested attributes error: suggestion without `code = "..."` - --> $DIR/diagnostic-derive.rs:238:5 + --> $DIR/diagnostic-derive.rs:240:5 | LL | #[suggestion(msg = "bar")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: wrong field type for suggestion - --> $DIR/diagnostic-derive.rs:261:5 + --> $DIR/diagnostic-derive.rs:263:5 | LL | / #[suggestion(typeck::suggestion, code = "This is suggested code")] LL | | @@ -296,55 +307,55 @@ LL | | suggestion: Applicability, = help: `#[suggestion(...)]` should be applied to fields of type `Span` or `(Span, Applicability)` error: specified multiple times - --> $DIR/diagnostic-derive.rs:277:24 + --> $DIR/diagnostic-derive.rs:279:24 | LL | suggestion: (Span, Span, Applicability), | ^^^^ | note: previously specified here - --> $DIR/diagnostic-derive.rs:277:18 + --> $DIR/diagnostic-derive.rs:279:18 | LL | suggestion: (Span, Span, Applicability), | ^^^^ error: specified multiple times - --> $DIR/diagnostic-derive.rs:285:33 + --> $DIR/diagnostic-derive.rs:287:33 | LL | suggestion: (Applicability, Applicability, Span), | ^^^^^^^^^^^^^ | note: previously specified here - --> $DIR/diagnostic-derive.rs:285:18 + --> $DIR/diagnostic-derive.rs:287:18 | LL | suggestion: (Applicability, Applicability, Span), | ^^^^^^^^^^^^^ error: `#[label = ...]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:292:5 + --> $DIR/diagnostic-derive.rs:294:5 | LL | #[label = "bar"] | ^^^^^^^^^^^^^^^^ error: specified multiple times - --> $DIR/diagnostic-derive.rs:443:52 + --> $DIR/diagnostic-derive.rs:445:52 | LL | #[suggestion(typeck::suggestion, code = "...", applicability = "maybe-incorrect")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: previously specified here - --> $DIR/diagnostic-derive.rs:445:24 + --> $DIR/diagnostic-derive.rs:447:24 | LL | suggestion: (Span, Applicability), | ^^^^^^^^^^^^^ error: invalid applicability - --> $DIR/diagnostic-derive.rs:451:52 + --> $DIR/diagnostic-derive.rs:453:52 | LL | #[suggestion(typeck::suggestion, code = "...", applicability = "batman")] | ^^^^^^^^^^^^^^^^^^^^^^^^ error: `#[label(foo)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:514:28 + --> $DIR/diagnostic-derive.rs:516:28 | LL | #[label(typeck::label, foo)] | ^^^ @@ -352,19 +363,19 @@ LL | #[label(typeck::label, foo)] = help: a diagnostic slug must be the first argument to the attribute error: `#[label(foo = ...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:522:28 + --> $DIR/diagnostic-derive.rs:524:28 | LL | #[label(typeck::label, foo = "...")] | ^^^^^^^^^^^ error: `#[label(foo(...))]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:530:28 + --> $DIR/diagnostic-derive.rs:532:28 | LL | #[label(typeck::label, foo("..."))] | ^^^^^^^^^^ error: `#[primary_span]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:543:5 + --> $DIR/diagnostic-derive.rs:545:5 | LL | #[primary_span] | ^^^^^^^^^^^^^^^ @@ -372,13 +383,13 @@ LL | #[primary_span] = help: the `primary_span` field attribute is not valid for lint diagnostics error: `#[error(...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:563:1 + --> $DIR/diagnostic-derive.rs:565:1 | LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0123")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: diagnostic slug not specified - --> $DIR/diagnostic-derive.rs:563:1 + --> $DIR/diagnostic-derive.rs:565:1 | LL | / #[error(typeck::ambiguous_lifetime_bound, code = "E0123")] LL | | @@ -390,13 +401,13 @@ LL | | struct ErrorAttribute {} = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(typeck::example_error)]` error: `#[warn_(...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:570:1 + --> $DIR/diagnostic-derive.rs:572:1 | LL | #[warn_(typeck::ambiguous_lifetime_bound, code = "E0123")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: diagnostic slug not specified - --> $DIR/diagnostic-derive.rs:570:1 + --> $DIR/diagnostic-derive.rs:572:1 | LL | / #[warn_(typeck::ambiguous_lifetime_bound, code = "E0123")] LL | | @@ -408,13 +419,13 @@ LL | | struct WarnAttribute {} = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(typeck::example_error)]` error: `#[lint(...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:577:1 + --> $DIR/diagnostic-derive.rs:579:1 | LL | #[lint(typeck::ambiguous_lifetime_bound, code = "E0123")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: diagnostic slug not specified - --> $DIR/diagnostic-derive.rs:577:1 + --> $DIR/diagnostic-derive.rs:579:1 | LL | / #[lint(typeck::ambiguous_lifetime_bound, code = "E0123")] LL | | @@ -426,13 +437,13 @@ LL | | struct LintAttributeOnSessionDiag {} = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(typeck::example_error)]` error: `#[lint(...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:584:1 + --> $DIR/diagnostic-derive.rs:586:1 | LL | #[lint(typeck::ambiguous_lifetime_bound, code = "E0123")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: diagnostic slug not specified - --> $DIR/diagnostic-derive.rs:584:1 + --> $DIR/diagnostic-derive.rs:586:1 | LL | / #[lint(typeck::ambiguous_lifetime_bound, code = "E0123")] LL | | @@ -444,19 +455,19 @@ LL | | struct LintAttributeOnLintDiag {} = help: specify the slug as the first argument to the attribute, such as `#[diag(typeck::example_error)]` error: specified multiple times - --> $DIR/diagnostic-derive.rs:593:52 + --> $DIR/diagnostic-derive.rs:595:52 | LL | #[suggestion(typeck::suggestion, code = "...", code = ",,,")] | ^^^^^^^^^^^^ | note: previously specified here - --> $DIR/diagnostic-derive.rs:593:38 + --> $DIR/diagnostic-derive.rs:595:38 | LL | #[suggestion(typeck::suggestion, code = "...", code = ",,,")] | ^^^^^^^^^^^^ error: wrong types for suggestion - --> $DIR/diagnostic-derive.rs:602:24 + --> $DIR/diagnostic-derive.rs:604:24 | LL | suggestion: (Span, usize), | ^^^^^ @@ -464,7 +475,7 @@ LL | suggestion: (Span, usize), = help: `#[suggestion(...)]` on a tuple field must be applied to fields of type `(Span, Applicability)` error: wrong types for suggestion - --> $DIR/diagnostic-derive.rs:610:17 + --> $DIR/diagnostic-derive.rs:612:17 | LL | suggestion: (Span,), | ^^^^^^^ @@ -472,13 +483,13 @@ LL | suggestion: (Span,), = help: `#[suggestion(...)]` on a tuple field must be applied to fields of type `(Span, Applicability)` error: suggestion without `code = "..."` - --> $DIR/diagnostic-derive.rs:617:5 + --> $DIR/diagnostic-derive.rs:619:5 | LL | #[suggestion(typeck::suggestion)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: `#[multipart_suggestion(...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:624:1 + --> $DIR/diagnostic-derive.rs:626:1 | LL | #[multipart_suggestion(typeck::suggestion)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -486,7 +497,7 @@ LL | #[multipart_suggestion(typeck::suggestion)] = help: consider creating a `Subdiagnostic` instead error: `#[multipart_suggestion(...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:627:1 + --> $DIR/diagnostic-derive.rs:629:1 | LL | #[multipart_suggestion()] | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -494,7 +505,7 @@ LL | #[multipart_suggestion()] = help: consider creating a `Subdiagnostic` instead error: `#[multipart_suggestion(...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:631:5 + --> $DIR/diagnostic-derive.rs:633:5 | LL | #[multipart_suggestion(typeck::suggestion)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -502,7 +513,7 @@ LL | #[multipart_suggestion(typeck::suggestion)] = help: consider creating a `Subdiagnostic` instead error: `#[suggestion(...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:639:1 + --> $DIR/diagnostic-derive.rs:641:1 | LL | #[suggestion(typeck::suggestion, code = "...")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -510,7 +521,7 @@ LL | #[suggestion(typeck::suggestion, code = "...")] = help: `#[label]` and `#[suggestion]` can only be applied to fields error: `#[label]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:648:1 + --> $DIR/diagnostic-derive.rs:650:1 | LL | #[label] | ^^^^^^^^ @@ -518,67 +529,67 @@ LL | #[label] = help: `#[label]` and `#[suggestion]` can only be applied to fields error: cannot find attribute `nonsense` in this scope - --> $DIR/diagnostic-derive.rs:53:3 + --> $DIR/diagnostic-derive.rs:55:3 | LL | #[nonsense(typeck::ambiguous_lifetime_bound, code = "E0123")] | ^^^^^^^^ error: cannot find attribute `nonsense` in this scope - --> $DIR/diagnostic-derive.rs:143:7 + --> $DIR/diagnostic-derive.rs:145:7 | LL | #[nonsense] | ^^^^^^^^ error: cannot find attribute `error` in this scope - --> $DIR/diagnostic-derive.rs:563:3 + --> $DIR/diagnostic-derive.rs:565:3 | LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0123")] | ^^^^^ error: cannot find attribute `warn_` in this scope - --> $DIR/diagnostic-derive.rs:570:3 + --> $DIR/diagnostic-derive.rs:572:3 | LL | #[warn_(typeck::ambiguous_lifetime_bound, code = "E0123")] | ^^^^^ help: a built-in attribute with a similar name exists: `warn` error: cannot find attribute `lint` in this scope - --> $DIR/diagnostic-derive.rs:577:3 + --> $DIR/diagnostic-derive.rs:579:3 | LL | #[lint(typeck::ambiguous_lifetime_bound, code = "E0123")] | ^^^^ help: a built-in attribute with a similar name exists: `link` error: cannot find attribute `lint` in this scope - --> $DIR/diagnostic-derive.rs:584:3 + --> $DIR/diagnostic-derive.rs:586:3 | LL | #[lint(typeck::ambiguous_lifetime_bound, code = "E0123")] | ^^^^ help: a built-in attribute with a similar name exists: `link` error: cannot find attribute `multipart_suggestion` in this scope - --> $DIR/diagnostic-derive.rs:624:3 + --> $DIR/diagnostic-derive.rs:626:3 | LL | #[multipart_suggestion(typeck::suggestion)] | ^^^^^^^^^^^^^^^^^^^^ error: cannot find attribute `multipart_suggestion` in this scope - --> $DIR/diagnostic-derive.rs:627:3 + --> $DIR/diagnostic-derive.rs:629:3 | LL | #[multipart_suggestion()] | ^^^^^^^^^^^^^^^^^^^^ error: cannot find attribute `multipart_suggestion` in this scope - --> $DIR/diagnostic-derive.rs:631:7 + --> $DIR/diagnostic-derive.rs:633:7 | LL | #[multipart_suggestion(typeck::suggestion)] | ^^^^^^^^^^^^^^^^^^^^ error[E0425]: cannot find value `nonsense` in module `rustc_errors::fluent` - --> $DIR/diagnostic-derive.rs:66:8 + --> $DIR/diagnostic-derive.rs:68:8 | LL | #[diag(nonsense, code = "E0123")] | ^^^^^^^^ not found in `rustc_errors::fluent` error[E0277]: the trait bound `Hello: IntoDiagnosticArg` is not satisfied - --> $DIR/diagnostic-derive.rs:336:10 + --> $DIR/diagnostic-derive.rs:338:10 | LL | #[derive(Diagnostic)] | ^^^^^^^^^^ the trait `IntoDiagnosticArg` is not implemented for `Hello` @@ -591,7 +602,7 @@ LL | arg: impl IntoDiagnosticArg, | ^^^^^^^^^^^^^^^^^ required by this bound in `DiagnosticBuilder::<'a, G>::set_arg` = note: this error originates in the derive macro `Diagnostic` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 72 previous errors +error: aborting due to 74 previous errors Some errors have detailed explanations: E0277, E0425. For more information about an error, try `rustc --explain E0277`. From 456f4e8d22dfa18de1fc0bafb4455a6b27f92aea Mon Sep 17 00:00:00 2001 From: b-naber Date: Thu, 15 Sep 2022 18:46:40 +0200 Subject: [PATCH 268/586] don't duplicate late-bound region names in print of Binder --- compiler/rustc_middle/src/ty/print/pretty.rs | 80 +++++++++++++------- compiler/rustc_middle/src/ty/sty.rs | 28 +++++++ 2 files changed, 81 insertions(+), 27 deletions(-) diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 99e5722ddad0e..da964077285f4 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -1562,7 +1562,9 @@ pub struct FmtPrinterData<'a, 'tcx> { in_value: bool, pub print_alloc_ids: bool, + // set of all named (non-anonymous) region names used_region_names: FxHashSet, + region_index: usize, binder_depth: usize, printed_type_count: usize, @@ -2118,23 +2120,31 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { where T: Print<'tcx, Self, Output = Self, Error = fmt::Error> + TypeFoldable<'tcx>, { - fn name_by_region_index(index: usize) -> Symbol { - match index { - 0 => Symbol::intern("'r"), - 1 => Symbol::intern("'s"), - i => Symbol::intern(&format!("'t{}", i - 2)), + fn name_by_region_index( + index: usize, + available_names: &mut Vec, + num_available: usize, + ) -> Symbol { + if let Some(name) = available_names.pop() { + name + } else { + Symbol::intern(&format!("'t{}", index - num_available)) } } + debug!("name_all_regions"); + // Replace any anonymous late-bound regions with named // variants, using new unique identifiers, so that we can // clearly differentiate between named and unnamed regions in // the output. We'll probably want to tweak this over time to // decide just how much information to give. if self.binder_depth == 0 { - self.prepare_late_bound_region_info(value); + self.prepare_region_info(value); } + debug!("self.used_region_names: {:?}", &self.used_region_names); + let mut empty = true; let mut start_or_continue = |cx: &mut Self, start: &str, cont: &str| { let w = if empty { @@ -2151,13 +2161,23 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { define_scoped_cx!(self); + let possible_names = vec![Symbol::intern("'t"), Symbol::intern("'s"), Symbol::intern("'r")]; + + let mut available_names = possible_names + .into_iter() + .filter(|name| !self.used_region_names.contains(&name)) + .collect::>(); + debug!(?available_names); + let num_available = available_names.len(); + let mut region_index = self.region_index; - let mut next_name = |this: &Self| loop { - let name = name_by_region_index(region_index); + let mut next_name = |this: &Self| { + let name = name_by_region_index(region_index, &mut available_names, num_available); + debug!(?name); region_index += 1; - if !this.used_region_names.contains(&name) { - break name; - } + assert!(!this.used_region_names.contains(&name)); + + name }; // If we want to print verbosely, then print *all* binders, even if they @@ -2178,6 +2198,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { ty::BrAnon(_) | ty::BrEnv => { start_or_continue(&mut self, "for<", ", "); let name = next_name(&self); + debug!(?name); do_continue(&mut self, name); ty::BrNamed(CRATE_DEF_ID.to_def_id(), name) } @@ -2271,29 +2292,37 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { Ok(inner) } - fn prepare_late_bound_region_info(&mut self, value: &ty::Binder<'tcx, T>) + fn prepare_region_info(&mut self, value: &ty::Binder<'tcx, T>) where T: TypeVisitable<'tcx>, { - struct LateBoundRegionNameCollector<'a, 'tcx> { - used_region_names: &'a mut FxHashSet, + struct RegionNameCollector<'tcx> { + used_region_names: FxHashSet, type_collector: SsoHashSet>, } - impl<'tcx> ty::visit::TypeVisitor<'tcx> for LateBoundRegionNameCollector<'_, 'tcx> { + impl<'tcx> RegionNameCollector<'tcx> { + fn new() -> Self { + RegionNameCollector { + used_region_names: Default::default(), + type_collector: SsoHashSet::new(), + } + } + } + + impl<'tcx> ty::visit::TypeVisitor<'tcx> for RegionNameCollector<'tcx> { type BreakTy = (); fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow { trace!("address: {:p}", r.0.0); - if let ty::ReLateBound(_, ty::BoundRegion { kind: ty::BrNamed(_, name), .. }) = *r { - self.used_region_names.insert(name); - } else if let ty::RePlaceholder(ty::PlaceholderRegion { - name: ty::BrNamed(_, name), - .. - }) = *r - { + + // Collect all named lifetimes. These allow us to prevent duplication + // of already existing lifetime names when introducing names for + // anonymous late-bound regions. + if let Some(name) = r.get_name() { self.used_region_names.insert(name); } + r.super_visit_with(self) } @@ -2309,12 +2338,9 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { } } - self.used_region_names.clear(); - let mut collector = LateBoundRegionNameCollector { - used_region_names: &mut self.used_region_names, - type_collector: SsoHashSet::new(), - }; + let mut collector = RegionNameCollector::new(); value.visit_with(&mut collector); + self.used_region_names = collector.used_region_names; self.region_index = 0; } } diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 258fb2e2f9f11..08fb6a329dffa 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -85,6 +85,17 @@ impl BoundRegionKind { _ => false, } } + + pub fn get_name(&self) -> Option { + if self.is_named() { + match *self { + BoundRegionKind::BrNamed(_, name) => return Some(name), + _ => unreachable!(), + } + } + + None + } } pub trait Article { @@ -1445,6 +1456,23 @@ impl<'tcx> Region<'tcx> { *self.0.0 } + pub fn get_name(self) -> Option { + if self.has_name() { + let name = match *self { + ty::ReEarlyBound(ebr) => Some(ebr.name), + ty::ReLateBound(_, br) => br.kind.get_name(), + ty::ReFree(fr) => fr.bound_region.get_name(), + ty::ReStatic => Some(Symbol::intern("static")), + ty::RePlaceholder(placeholder) => placeholder.name.get_name(), + _ => None, + }; + + return name; + } + + None + } + /// Is this region named by the user? pub fn has_name(self) -> bool { match *self { From 897adb866665997fe8dfb66dc338faba9671577a Mon Sep 17 00:00:00 2001 From: b-naber Date: Sun, 18 Sep 2022 22:02:56 +0200 Subject: [PATCH 269/586] bless tests --- ...arms.float_to_exponential_common.ConstProp.diff | 4 ++-- .../issue_73223.main.SimplifyArmIdentity.diff | 2 +- src/test/mir-opt/issue_99325.main.mir_map.0.mir | 4 ++-- ...ray_casts.SimplifyCfg-elaborate-drops.after.mir | 2 +- .../issue-70935-complex-spans.drop_tracking.stderr | 2 +- .../escape-argument-callee.stderr | 2 +- .../propagate-approximated-ref.stderr | 2 +- ...-approximated-shorter-to-static-no-bound.stderr | 2 +- ...proximated-shorter-to-static-wrong-bound.stderr | 2 +- ...ate-fail-to-approximate-longer-no-bounds.stderr | 2 +- ...-fail-to-approximate-longer-wrong-bounds.stderr | 2 +- src/test/ui/regions/issue-101280.rs | 10 ++++++++++ src/test/ui/regions/issue-101280.stderr | 14 ++++++++++++++ ...gion-lifetime-bounds-on-fns-where-clause.stderr | 2 +- ...iple-lifetime-bounds-on-fns-where-clause.stderr | 4 ++-- .../regions/regions-lifetime-bounds-on-fns.stderr | 2 +- 16 files changed, 41 insertions(+), 17 deletions(-) create mode 100644 src/test/ui/regions/issue-101280.rs create mode 100644 src/test/ui/regions/issue-101280.stderr diff --git a/src/test/mir-opt/funky_arms.float_to_exponential_common.ConstProp.diff b/src/test/mir-opt/funky_arms.float_to_exponential_common.ConstProp.diff index b789ae22974da..340080ede1bd1 100644 --- a/src/test/mir-opt/funky_arms.float_to_exponential_common.ConstProp.diff +++ b/src/test/mir-opt/funky_arms.float_to_exponential_common.ConstProp.diff @@ -100,7 +100,7 @@ _0 = float_to_exponential_common_exact::(move _11, move _12, move _13, move _14, move _17) -> bb7; // scope 3 at $DIR/funky_arms.rs:+15:9: +15:87 // mir::Constant // + span: $DIR/funky_arms.rs:26:9: 26:42 - // + literal: Const { ty: for<'r, 's, 't0> fn(&'r mut Formatter<'s>, &'t0 T, Sign, u32, bool) -> Result<(), std::fmt::Error> {float_to_exponential_common_exact::}, val: Value() } + // + literal: Const { ty: for<'r, 's, 't> fn(&'r mut Formatter<'s>, &'t T, Sign, u32, bool) -> Result<(), std::fmt::Error> {float_to_exponential_common_exact::}, val: Value() } } bb7: { @@ -125,7 +125,7 @@ _0 = float_to_exponential_common_shortest::(move _18, move _19, move _20, move _21) -> bb9; // scope 2 at $DIR/funky_arms.rs:+17:9: +17:68 // mir::Constant // + span: $DIR/funky_arms.rs:28:9: 28:45 - // + literal: Const { ty: for<'r, 's, 't0> fn(&'r mut Formatter<'s>, &'t0 T, Sign, bool) -> Result<(), std::fmt::Error> {float_to_exponential_common_shortest::}, val: Value() } + // + literal: Const { ty: for<'r, 's, 't> fn(&'r mut Formatter<'s>, &'t T, Sign, bool) -> Result<(), std::fmt::Error> {float_to_exponential_common_shortest::}, val: Value() } } bb9: { diff --git a/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.diff b/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.diff index 533907e704093..b19e8a8918ef5 100644 --- a/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.diff +++ b/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.diff @@ -139,7 +139,7 @@ _21 = core::panicking::assert_failed::(const core::panicking::AssertKind::Eq, move _23, move _25, move _27); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL // mir::Constant // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL - // + literal: Const { ty: for<'r, 's, 't0> fn(core::panicking::AssertKind, &'r i32, &'s i32, Option>) -> ! {core::panicking::assert_failed::}, val: Value() } + // + literal: Const { ty: for<'r, 's, 't> fn(core::panicking::AssertKind, &'r i32, &'s i32, Option>) -> ! {core::panicking::assert_failed::}, val: Value() } // mir::Constant // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL // + literal: Const { ty: core::panicking::AssertKind, val: Value(Scalar(0x00)) } diff --git a/src/test/mir-opt/issue_99325.main.mir_map.0.mir b/src/test/mir-opt/issue_99325.main.mir_map.0.mir index 6f58bb1b47fe4..ab701486a6bd9 100644 --- a/src/test/mir-opt/issue_99325.main.mir_map.0.mir +++ b/src/test/mir-opt/issue_99325.main.mir_map.0.mir @@ -132,7 +132,7 @@ fn main() -> () { _16 = core::panicking::assert_failed::<&[u8], &[u8; 4]>(move _17, move _18, move _20, move _22) -> bb19; // scope 2 at $SRC_DIR/core/src/macros/mod.rs:LL:COL // mir::Constant // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL - // + literal: Const { ty: for<'r, 's, 't0> fn(core::panicking::AssertKind, &'r &[u8], &'s &[u8; 4], Option>) -> ! {core::panicking::assert_failed::<&[u8], &[u8; 4]>}, val: Value() } + // + literal: Const { ty: for<'r, 's, 't> fn(core::panicking::AssertKind, &'r &[u8], &'s &[u8; 4], Option>) -> ! {core::panicking::assert_failed::<&[u8], &[u8; 4]>}, val: Value() } } bb4: { @@ -241,7 +241,7 @@ fn main() -> () { _37 = core::panicking::assert_failed::<&[u8], &[u8; 4]>(move _38, move _39, move _41, move _43) -> bb19; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL // mir::Constant // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL - // + literal: Const { ty: for<'r, 's, 't0> fn(core::panicking::AssertKind, &'r &[u8], &'s &[u8; 4], Option>) -> ! {core::panicking::assert_failed::<&[u8], &[u8; 4]>}, val: Value() } + // + literal: Const { ty: for<'r, 's, 't> fn(core::panicking::AssertKind, &'r &[u8], &'s &[u8; 4], Option>) -> ! {core::panicking::assert_failed::<&[u8], &[u8; 4]>}, val: Value() } } bb13: { diff --git a/src/test/mir-opt/retag.array_casts.SimplifyCfg-elaborate-drops.after.mir b/src/test/mir-opt/retag.array_casts.SimplifyCfg-elaborate-drops.after.mir index 318b241fa737a..448b465db23f6 100644 --- a/src/test/mir-opt/retag.array_casts.SimplifyCfg-elaborate-drops.after.mir +++ b/src/test/mir-opt/retag.array_casts.SimplifyCfg-elaborate-drops.after.mir @@ -180,7 +180,7 @@ fn array_casts() -> () { _28 = core::panicking::assert_failed::(move _29, move _30, move _32, move _34); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL // mir::Constant // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL - // + literal: Const { ty: for<'r, 's, 't0> fn(core::panicking::AssertKind, &'r usize, &'s usize, Option>) -> ! {core::panicking::assert_failed::}, val: Value() } + // + literal: Const { ty: for<'r, 's, 't> fn(core::panicking::AssertKind, &'r usize, &'s usize, Option>) -> ! {core::panicking::assert_failed::}, val: Value() } } bb4: { diff --git a/src/test/ui/async-await/issue-70935-complex-spans.drop_tracking.stderr b/src/test/ui/async-await/issue-70935-complex-spans.drop_tracking.stderr index 198de7bf79f36..8fba766bc8704 100644 --- a/src/test/ui/async-await/issue-70935-complex-spans.drop_tracking.stderr +++ b/src/test/ui/async-await/issue-70935-complex-spans.drop_tracking.stderr @@ -18,7 +18,7 @@ LL | async fn baz(_c: impl FnMut() -> T) where T: Future { | ___________________________________________________________________^ LL | | } | |_^ - = note: required because it captures the following types: `ResumeTy`, `impl for<'r, 's, 't0> Future`, `()` + = note: required because it captures the following types: `ResumeTy`, `impl for<'r, 's, 't> Future`, `()` note: required because it's used within this `async` block --> $DIR/issue-70935-complex-spans.rs:16:16 | diff --git a/src/test/ui/nll/closure-requirements/escape-argument-callee.stderr b/src/test/ui/nll/closure-requirements/escape-argument-callee.stderr index 59b848ea85ce1..66c99bcdfed0c 100644 --- a/src/test/ui/nll/closure-requirements/escape-argument-callee.stderr +++ b/src/test/ui/nll/closure-requirements/escape-argument-callee.stderr @@ -6,7 +6,7 @@ LL | let mut closure = expect_sig(|p, y| *p = y); | = note: defining type: test::{closure#0} with closure substs [ i16, - for<'r, 's, 't0> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) mut &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) i32, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrNamed('t0) }) i32)), + for<'r, 's, 't> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) mut &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) i32, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrNamed('t) }) i32)), (), ] diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-ref.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-ref.stderr index 435a5353340da..ca4c1a1ee7e76 100644 --- a/src/test/ui/nll/closure-requirements/propagate-approximated-ref.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-approximated-ref.stderr @@ -6,7 +6,7 @@ LL | establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y | = note: defining type: supply::{closure#0} with closure substs [ i16, - for<'r, 's, 't0, 't1, 't2, 't3> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrNamed('t0) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrNamed('t1) }) &'_#2r u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrNamed('t2) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 5, kind: BrNamed('t3) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrNamed('t1) }) u32>)), + for<'r, 's, 't, 't0, 't1, 't2> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrNamed('t) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrNamed('t0) }) &'_#2r u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrNamed('t1) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 5, kind: BrNamed('t2) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrNamed('t0) }) u32>)), (), ] = note: late-bound region is '_#3r diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr index c95907ea75e5a..42404412bf990 100644 --- a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr @@ -6,7 +6,7 @@ LL | establish_relationships(&cell_a, &cell_b, |_outlives, x, y| { | = note: defining type: supply::{closure#0} with closure substs [ i16, - for<'r, 's, 't0, 't1, 't2> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrNamed('t0) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrNamed('t1) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrNamed('t2) }) u32>)), + for<'r, 's, 't, 't0, 't1> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrNamed('t) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrNamed('t0) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrNamed('t1) }) u32>)), (), ] = note: late-bound region is '_#2r diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr index db58d9d6f1a3c..c74430ea3fc2b 100644 --- a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr @@ -6,7 +6,7 @@ LL | establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y | = note: defining type: supply::{closure#0} with closure substs [ i16, - for<'r, 's, 't0, 't1, 't2, 't3> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrNamed('t0) }) std::cell::Cell<&'_#2r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrNamed('t1) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrNamed('t2) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 5, kind: BrNamed('t3) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrNamed('t1) }) u32>)), + for<'r, 's, 't, 't0, 't1, 't2> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrNamed('t) }) std::cell::Cell<&'_#2r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrNamed('t0) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrNamed('t1) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 5, kind: BrNamed('t2) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrNamed('t0) }) u32>)), (), ] = note: late-bound region is '_#3r diff --git a/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr index e6f88de4ee8d9..1e161757222f2 100644 --- a/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr @@ -6,7 +6,7 @@ LL | establish_relationships(&cell_a, &cell_b, |_outlives, x, y| { | = note: defining type: supply::{closure#0} with closure substs [ i16, - for<'r, 's, 't0, 't1, 't2> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) &'_#1r u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrNamed('t0) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrNamed('t1) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrNamed('t2) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) u32>)), + for<'r, 's, 't, 't0, 't1> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) &'_#1r u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrNamed('t) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrNamed('t0) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrNamed('t1) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) u32>)), (), ] = note: late-bound region is '_#2r diff --git a/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr index 5f5fce77137c1..622113a875bd6 100644 --- a/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr @@ -6,7 +6,7 @@ LL | establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y | = note: defining type: supply::{closure#0} with closure substs [ i16, - for<'r, 's, 't0, 't1, 't2, 't3> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) &'_#1r u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrNamed('t0) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrNamed('t1) }) &'_#2r u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrNamed('t2) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 5, kind: BrNamed('t3) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrNamed('t1) }) u32>)), + for<'r, 's, 't, 't0, 't1, 't2> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) &'_#1r u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrNamed('t) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrNamed('t0) }) &'_#2r u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrNamed('t1) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 5, kind: BrNamed('t2) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrNamed('t0) }) u32>)), (), ] = note: late-bound region is '_#3r diff --git a/src/test/ui/regions/issue-101280.rs b/src/test/ui/regions/issue-101280.rs new file mode 100644 index 0000000000000..29f158366f026 --- /dev/null +++ b/src/test/ui/regions/issue-101280.rs @@ -0,0 +1,10 @@ +use std::cell::Cell; + +type Ty = for<'r> fn(Cell<(&'r i32, &'r i32)>); + +fn f<'r>(f: fn(Cell<(&'r i32, &i32)>)) -> Ty { + f + //~^ ERROR mismatched types +} + +fn main() {} diff --git a/src/test/ui/regions/issue-101280.stderr b/src/test/ui/regions/issue-101280.stderr new file mode 100644 index 0000000000000..3ce08966326d0 --- /dev/null +++ b/src/test/ui/regions/issue-101280.stderr @@ -0,0 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/issue-101280.rs:6:5 + | +LL | fn f<'r>(f: fn(Cell<(&'r i32, &i32)>)) -> Ty { + | -- expected `for<'r> fn(Cell<(&'r i32, &'r i32)>)` because of return type +LL | f + | ^ one type is more general than the other + | + = note: expected fn pointer `for<'r> fn(Cell<(&'r i32, &'r i32)>)` + found fn pointer `for<'s> fn(Cell<(&'r i32, &'s i32)>)` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/regions/region-lifetime-bounds-on-fns-where-clause.stderr b/src/test/ui/regions/region-lifetime-bounds-on-fns-where-clause.stderr index 48f2e1a2fa212..20c0c9f4514d7 100644 --- a/src/test/ui/regions/region-lifetime-bounds-on-fns-where-clause.stderr +++ b/src/test/ui/regions/region-lifetime-bounds-on-fns-where-clause.stderr @@ -4,7 +4,7 @@ error[E0308]: mismatched types LL | let _: fn(&mut &isize, &mut &isize) = a; | ^ one type is more general than the other | - = note: expected fn pointer `for<'r, 's, 't0, 't1> fn(&'r mut &'s isize, &'t0 mut &'t1 isize)` + = note: expected fn pointer `for<'r, 's, 't, 't0> fn(&'r mut &'s isize, &'t mut &'t0 isize)` found fn item `for<'r, 's> fn(&'r mut &isize, &'s mut &isize) {a::<'_, '_>}` error: aborting due to previous error diff --git a/src/test/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.stderr b/src/test/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.stderr index 36f40cd9a0f62..676b0904ebfa4 100644 --- a/src/test/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.stderr +++ b/src/test/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.stderr @@ -4,8 +4,8 @@ error[E0308]: mismatched types LL | let _: fn(&mut &isize, &mut &isize, &mut &isize) = a; | ^ one type is more general than the other | - = note: expected fn pointer `for<'r, 's, 't0, 't1, 't2, 't3> fn(&'r mut &'s isize, &'t0 mut &'t1 isize, &'t2 mut &'t3 isize)` - found fn item `for<'r, 's, 't0> fn(&'r mut &isize, &'s mut &isize, &'t0 mut &isize) {a::<'_, '_, '_>}` + = note: expected fn pointer `for<'r, 's, 't, 't0, 't1, 't2> fn(&'r mut &'s isize, &'t mut &'t0 isize, &'t1 mut &'t2 isize)` + found fn item `for<'r, 's, 't> fn(&'r mut &isize, &'s mut &isize, &'t mut &isize) {a::<'_, '_, '_>}` error: aborting due to previous error diff --git a/src/test/ui/regions/regions-lifetime-bounds-on-fns.stderr b/src/test/ui/regions/regions-lifetime-bounds-on-fns.stderr index a0daf58c6b57b..e02bed707dca4 100644 --- a/src/test/ui/regions/regions-lifetime-bounds-on-fns.stderr +++ b/src/test/ui/regions/regions-lifetime-bounds-on-fns.stderr @@ -4,7 +4,7 @@ error[E0308]: mismatched types LL | let _: fn(&mut &isize, &mut &isize) = a; | ^ one type is more general than the other | - = note: expected fn pointer `for<'r, 's, 't0, 't1> fn(&'r mut &'s isize, &'t0 mut &'t1 isize)` + = note: expected fn pointer `for<'r, 's, 't, 't0> fn(&'r mut &'s isize, &'t mut &'t0 isize)` found fn item `for<'r, 's> fn(&'r mut &isize, &'s mut &isize) {a::<'_, '_>}` error: aborting due to previous error From 6118ee343f5ebbea657337a5dceb9ded40fde117 Mon Sep 17 00:00:00 2001 From: b-naber Date: Wed, 21 Sep 2022 17:57:30 +0200 Subject: [PATCH 270/586] address review --- compiler/rustc_middle/src/ty/print/pretty.rs | 5 +++-- compiler/rustc_middle/src/ty/sty.rs | 2 +- ...primitives.{impl#0}-clone.InstCombine.diff | 6 +++--- ...motion_extern_static.BAR.PromoteTemps.diff | 2 +- ...motion_extern_static.FOO.PromoteTemps.diff | 2 +- ..._line_doc_comment_2.DeduplicateBlocks.diff | 2 +- .../derefer_complex_case.main.Derefer.diff | 2 +- .../simple.nrvo.DestinationPropagation.diff | 4 ++-- ...float_to_exponential_common.ConstProp.diff | 8 ++++---- src/test/mir-opt/inline/cycle.f.Inline.diff | 2 +- .../inline/dyn_trait.get_query.Inline.diff | 6 +++--- .../inline/dyn_trait.mk_cycle.Inline.diff | 2 +- .../dyn_trait.try_execute_query.Inline.diff | 4 ++-- .../inline/inline_generator.main.Inline.diff | 2 +- .../inline/inline_retag.bar.Inline.after.mir | 6 +++--- .../inline/inline_shims.clone.Inline.diff | 2 +- .../inline_trait_method.test.Inline.after.mir | 2 +- ...line_trait_method_2.test2.Inline.after.mir | 2 +- .../inline/issue_78442.bar.Inline.diff | 2 +- .../inline/issue_78442.bar.RevealAll.diff | 4 ++-- .../issue_73223.main.SimplifyArmIdentity.diff | 2 +- .../mir-opt/issue_91633.bar.mir_map.0.mir | 2 +- .../mir-opt/issue_91633.foo.mir_map.0.mir | 2 +- .../mir-opt/issue_91633.hey.mir_map.0.mir | 2 +- .../mir-opt/issue_99325.main.mir_map.0.mir | 8 ++++---- ...trinsics.discriminant.LowerIntrinsics.diff | 8 ++++---- ...er_slice_len.bound.LowerSliceLenCalls.diff | 2 +- ..._after_call.main.ElaborateDrops.before.mir | 2 +- .../nrvo_simple.nrvo.RenameReturnPlace.diff | 4 ++-- ...age_markers.main.RemoveStorageMarkers.diff | 2 +- ...asts.SimplifyCfg-elaborate-drops.after.mir | 2 +- ...place.Test.SimplifyCfg-make_shim.after.mir | 2 +- ...main.SimplifyCfg-elaborate-drops.after.mir | 10 +++++----- ...Vec_i32_.AddMovesForPackedDrops.before.mir | 2 +- src/test/pretty/issue-4264.pp | 2 +- .../anonymous-higher-ranked-lifetime.stderr | 20 +++++++++---------- ...e-70935-complex-spans.drop_tracking.stderr | 2 +- src/test/ui/binop/issue-77910-1.rs | 2 +- src/test/ui/binop/issue-77910-1.stderr | 10 +++++----- src/test/ui/binop/issue-77910-2.stderr | 4 ++-- .../expect-fn-supply-fn.stderr | 6 +++--- .../ui/closures/closure-reform-bad.stderr | 2 +- src/test/ui/compare-method/issue-90444.stderr | 6 +++--- .../bugs/issue-88382.stderr | 4 ++-- .../issue-30786.stderr | 10 +++++----- .../issue-46989.stderr | 2 +- .../normalize-under-binder/issue-71955.stderr | 16 +++++++-------- .../normalize-under-binder/issue-85455.rs | 2 +- .../normalize-under-binder/issue-85455.stderr | 6 +++--- src/test/ui/hygiene/impl_items.rs | 2 +- src/test/ui/hygiene/impl_items.stderr | 2 +- ...plicit-hrtb-without-dyn.edition2015.stderr | 4 ++-- ...plicit-hrtb-without-dyn.edition2021.stderr | 4 ++-- .../generic-with-implicit-hrtb-without-dyn.rs | 2 +- src/test/ui/issues/issue-18919.stderr | 4 ++-- src/test/ui/issues/issue-24322.stderr | 4 ++-- src/test/ui/issues/issue-40000.stderr | 4 ++-- src/test/ui/issues/issue-57362-2.stderr | 6 +++--- src/test/ui/lifetimes/issue-79187-2.stderr | 2 +- src/test/ui/lifetimes/issue-79187.stderr | 2 +- .../lifetime-errors/issue_74400.stderr | 2 +- .../ui/lifetimes/re-empty-in-error.stderr | 2 +- .../closure-arg-type-mismatch.stderr | 2 +- .../mismatched_types/closure-mismatch.stderr | 2 +- .../ui/mismatched_types/fn-variance-1.stderr | 4 ++-- .../ui/mismatched_types/issue-36053-2.stderr | 4 ++-- .../escape-argument-callee.stderr | 2 +- .../escape-argument.stderr | 2 +- ...pagate-approximated-fail-no-postdom.stderr | 2 +- .../propagate-approximated-ref.stderr | 2 +- ...er-to-static-comparing-against-free.stderr | 4 ++-- ...oximated-shorter-to-static-no-bound.stderr | 2 +- ...mated-shorter-to-static-wrong-bound.stderr | 2 +- .../propagate-approximated-val.stderr | 2 +- .../propagate-despite-same-free-region.stderr | 2 +- ...ail-to-approximate-longer-no-bounds.stderr | 2 +- ...-to-approximate-longer-wrong-bounds.stderr | 2 +- .../return-wrong-bound-region.stderr | 2 +- .../issue-57642-higher-ranked-subtype.stderr | 10 +++++----- src/test/ui/nll/issue-97997.stderr | 4 ++-- .../impl-fn-ignore-binder-via-bottom.stderr | 6 +++--- .../nll/relate_tys/universe-violation.stderr | 2 +- ...ram-closure-approximate-lower-bound.stderr | 4 ++-- .../associated-item-privacy-inherent.rs | 6 +++--- .../associated-item-privacy-inherent.stderr | 6 +++--- .../privacy/associated-item-privacy-trait.rs | 6 +++--- .../associated-item-privacy-trait.stderr | 6 +++--- .../ui/privacy/private-inferred-type-3.rs | 2 +- .../ui/privacy/private-inferred-type-3.stderr | 2 +- src/test/ui/privacy/private-inferred-type.rs | 2 +- .../ui/privacy/private-inferred-type.stderr | 2 +- src/test/ui/regions/issue-101280.stderr | 2 +- ...lifetime-bounds-on-fns-where-clause.stderr | 4 ++-- ...lifetime-bounds-on-fns-where-clause.stderr | 4 ++-- ...ons-fn-subtyping-return-static-fail.stderr | 2 +- .../regions-lifetime-bounds-on-fns.stderr | 4 ++-- src/test/ui/rfc1623-2.stderr | 2 +- .../fn-or-tuple-struct-without-args.stderr | 8 ++++---- src/test/ui/suggestions/issue-101984.stderr | 4 ++-- .../ui/suggestions/return-closures.stderr | 2 +- src/test/ui/symbol-names/impl1.legacy.stderr | 2 +- src/test/ui/symbol-names/impl1.rs | 4 ++-- src/test/ui/symbol-names/impl1.v0.stderr | 2 +- .../check-trait-object-bounds-2.stderr | 2 +- .../issue-57611-trait-alias.stderr | 2 +- .../unboxed-closures-unsafe-extern-fn.stderr | 12 +++++------ .../unboxed-closures-wrong-abi.stderr | 18 ++++++++--------- ...d-closures-wrong-arg-type-extern-fn.stderr | 6 +++--- 108 files changed, 214 insertions(+), 213 deletions(-) diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index da964077285f4..70efa748846ab 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -2128,7 +2128,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { if let Some(name) = available_names.pop() { name } else { - Symbol::intern(&format!("'t{}", index - num_available)) + Symbol::intern(&format!("'z{}", index - num_available)) } } @@ -2161,7 +2161,8 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { define_scoped_cx!(self); - let possible_names = vec![Symbol::intern("'t"), Symbol::intern("'s"), Symbol::intern("'r")]; + let possible_names = + ('a'..='z').rev().map(|s| Symbol::intern(&format!("'{s}"))).collect::>(); let mut available_names = possible_names .into_iter() diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 08fb6a329dffa..f4f4bb37c1acc 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -1462,7 +1462,7 @@ impl<'tcx> Region<'tcx> { ty::ReEarlyBound(ebr) => Some(ebr.name), ty::ReLateBound(_, br) => br.kind.get_name(), ty::ReFree(fr) => fr.bound_region.get_name(), - ty::ReStatic => Some(Symbol::intern("static")), + ty::ReStatic => Some(kw::StaticLifetime), ty::RePlaceholder(placeholder) => placeholder.name.get_name(), _ => None, }; diff --git a/src/test/mir-opt/combine_clone_of_primitives.{impl#0}-clone.InstCombine.diff b/src/test/mir-opt/combine_clone_of_primitives.{impl#0}-clone.InstCombine.diff index bde2f04fac9f0..6f01553eef6da 100644 --- a/src/test/mir-opt/combine_clone_of_primitives.{impl#0}-clone.InstCombine.diff +++ b/src/test/mir-opt/combine_clone_of_primitives.{impl#0}-clone.InstCombine.diff @@ -24,7 +24,7 @@ _2 = ::clone(move _3) -> bb1; // scope 0 at $DIR/combine_clone_of_primitives.rs:8:5: 8:9 // mir::Constant // + span: $DIR/combine_clone_of_primitives.rs:8:5: 8:9 - // + literal: Const { ty: for<'r> fn(&'r T) -> T {::clone}, val: Value() } + // + literal: Const { ty: for<'a> fn(&'a T) -> T {::clone}, val: Value() } } bb1: { @@ -37,7 +37,7 @@ - _5 = ::clone(move _6) -> [return: bb2, unwind: bb4]; // scope 0 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11 - // mir::Constant - // + span: $DIR/combine_clone_of_primitives.rs:9:5: 9:11 -- // + literal: Const { ty: for<'r> fn(&'r u64) -> u64 {::clone}, val: Value() } +- // + literal: Const { ty: for<'a> fn(&'a u64) -> u64 {::clone}, val: Value() } + _6 = _7; // scope 0 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11 + _5 = (*_6); // scope 0 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11 + goto -> bb2; // scope 0 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11 @@ -53,7 +53,7 @@ - _8 = <[f32; 3] as Clone>::clone(move _9) -> [return: bb3, unwind: bb4]; // scope 0 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16 - // mir::Constant - // + span: $DIR/combine_clone_of_primitives.rs:10:5: 10:16 -- // + literal: Const { ty: for<'r> fn(&'r [f32; 3]) -> [f32; 3] {<[f32; 3] as Clone>::clone}, val: Value() } +- // + literal: Const { ty: for<'a> fn(&'a [f32; 3]) -> [f32; 3] {<[f32; 3] as Clone>::clone}, val: Value() } + _9 = _10; // scope 0 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16 + _8 = (*_9); // scope 0 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16 + goto -> bb3; // scope 0 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16 diff --git a/src/test/mir-opt/const_promotion_extern_static.BAR.PromoteTemps.diff b/src/test/mir-opt/const_promotion_extern_static.BAR.PromoteTemps.diff index 248abb8fd0e5b..f8a7c687e124a 100644 --- a/src/test/mir-opt/const_promotion_extern_static.BAR.PromoteTemps.diff +++ b/src/test/mir-opt/const_promotion_extern_static.BAR.PromoteTemps.diff @@ -33,7 +33,7 @@ _0 = core::slice::::as_ptr(move _1) -> [return: bb1, unwind: bb2]; // scope 0 at $DIR/const-promotion-extern-static.rs:+0:31: +0:44 // mir::Constant // + span: $DIR/const-promotion-extern-static.rs:9:36: 9:42 - // + literal: Const { ty: for<'r> fn(&'r [&i32]) -> *const &i32 {core::slice::::as_ptr}, val: Value() } + // + literal: Const { ty: for<'a> fn(&'a [&i32]) -> *const &i32 {core::slice::::as_ptr}, val: Value() } } bb1: { diff --git a/src/test/mir-opt/const_promotion_extern_static.FOO.PromoteTemps.diff b/src/test/mir-opt/const_promotion_extern_static.FOO.PromoteTemps.diff index 8ce895fe72b00..e938ca28af5d6 100644 --- a/src/test/mir-opt/const_promotion_extern_static.FOO.PromoteTemps.diff +++ b/src/test/mir-opt/const_promotion_extern_static.FOO.PromoteTemps.diff @@ -35,7 +35,7 @@ _0 = core::slice::::as_ptr(move _1) -> [return: bb1, unwind: bb2]; // scope 0 at $DIR/const-promotion-extern-static.rs:+0:31: +0:55 // mir::Constant // + span: $DIR/const-promotion-extern-static.rs:13:47: 13:53 - // + literal: Const { ty: for<'r> fn(&'r [&i32]) -> *const &i32 {core::slice::::as_ptr}, val: Value() } + // + literal: Const { ty: for<'a> fn(&'a [&i32]) -> *const &i32 {core::slice::::as_ptr}, val: Value() } } bb1: { 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 53f977de5d6ad..995611f0e9664 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 @@ -20,7 +20,7 @@ _2 = core::str::::as_bytes(move _3) -> bb1; // scope 0 at $DIR/deduplicate_blocks.rs:+1:11: +1:23 // mir::Constant // + span: $DIR/deduplicate_blocks.rs:5:13: 5:21 - // + literal: Const { ty: for<'r> fn(&'r str) -> &'r [u8] {core::str::::as_bytes}, val: Value() } + // + literal: Const { ty: for<'a> fn(&'a str) -> &'a [u8] {core::str::::as_bytes}, val: Value() } } bb1: { diff --git a/src/test/mir-opt/derefer_complex_case.main.Derefer.diff b/src/test/mir-opt/derefer_complex_case.main.Derefer.diff index 1e1c80aad34e7..713d56c383613 100644 --- a/src/test/mir-opt/derefer_complex_case.main.Derefer.diff +++ b/src/test/mir-opt/derefer_complex_case.main.Derefer.diff @@ -56,7 +56,7 @@ _7 = as Iterator>::next(move _8) -> bb3; // scope 1 at $DIR/derefer_complex_case.rs:+1:17: +1:26 // mir::Constant // + span: $DIR/derefer_complex_case.rs:6:17: 6:26 - // + literal: Const { ty: for<'r> fn(&'r mut std::slice::Iter<'_, i32>) -> Option< as Iterator>::Item> { as Iterator>::next}, val: Value() } + // + literal: Const { ty: for<'a> fn(&'a mut std::slice::Iter<'_, i32>) -> Option< as Iterator>::Item> { as Iterator>::next}, val: Value() } } bb3: { diff --git a/src/test/mir-opt/dest-prop/simple.nrvo.DestinationPropagation.diff b/src/test/mir-opt/dest-prop/simple.nrvo.DestinationPropagation.diff index a20a172af1bbc..80b09ed5f8d35 100644 --- a/src/test/mir-opt/dest-prop/simple.nrvo.DestinationPropagation.diff +++ b/src/test/mir-opt/dest-prop/simple.nrvo.DestinationPropagation.diff @@ -1,12 +1,12 @@ - // MIR for `nrvo` before DestinationPropagation + // MIR for `nrvo` after DestinationPropagation - fn nrvo(_1: for<'r> fn(&'r mut [u8; 1024])) -> [u8; 1024] { + fn nrvo(_1: for<'a> fn(&'a mut [u8; 1024])) -> [u8; 1024] { debug init => _1; // in scope 0 at $DIR/simple.rs:+0:9: +0:13 let mut _0: [u8; 1024]; // return place in scope 0 at $DIR/simple.rs:+0:39: +0:49 let mut _2: [u8; 1024]; // in scope 0 at $DIR/simple.rs:+1:9: +1:16 let _3: (); // in scope 0 at $DIR/simple.rs:+2:5: +2:19 - let mut _4: for<'r> fn(&'r mut [u8; 1024]); // in scope 0 at $DIR/simple.rs:+2:5: +2:9 + let mut _4: for<'a> fn(&'a mut [u8; 1024]); // in scope 0 at $DIR/simple.rs:+2:5: +2:9 let mut _5: &mut [u8; 1024]; // in scope 0 at $DIR/simple.rs:+2:10: +2:18 let mut _6: &mut [u8; 1024]; // in scope 0 at $DIR/simple.rs:+2:10: +2:18 scope 1 { diff --git a/src/test/mir-opt/funky_arms.float_to_exponential_common.ConstProp.diff b/src/test/mir-opt/funky_arms.float_to_exponential_common.ConstProp.diff index 340080ede1bd1..e83a358b7258b 100644 --- a/src/test/mir-opt/funky_arms.float_to_exponential_common.ConstProp.diff +++ b/src/test/mir-opt/funky_arms.float_to_exponential_common.ConstProp.diff @@ -41,7 +41,7 @@ _4 = Formatter::<'_>::sign_plus(move _5) -> bb1; // scope 0 at $DIR/funky_arms.rs:+4:22: +4:37 // mir::Constant // + span: $DIR/funky_arms.rs:15:26: 15:35 - // + literal: Const { ty: for<'r> fn(&'r Formatter<'_>) -> bool {Formatter::<'_>::sign_plus}, val: Value() } + // + literal: Const { ty: for<'a> fn(&'a Formatter<'_>) -> bool {Formatter::<'_>::sign_plus}, val: Value() } } bb1: { @@ -69,7 +69,7 @@ _7 = Formatter::<'_>::precision(move _8) -> bb5; // scope 3 at $DIR/funky_arms.rs:+13:30: +13:45 // mir::Constant // + span: $DIR/funky_arms.rs:24:34: 24:43 - // + literal: Const { ty: for<'r> fn(&'r Formatter<'_>) -> Option {Formatter::<'_>::precision}, val: Value() } + // + literal: Const { ty: for<'a> fn(&'a Formatter<'_>) -> Option {Formatter::<'_>::precision}, val: Value() } } bb5: { @@ -100,7 +100,7 @@ _0 = float_to_exponential_common_exact::(move _11, move _12, move _13, move _14, move _17) -> bb7; // scope 3 at $DIR/funky_arms.rs:+15:9: +15:87 // mir::Constant // + span: $DIR/funky_arms.rs:26:9: 26:42 - // + literal: Const { ty: for<'r, 's, 't> fn(&'r mut Formatter<'s>, &'t T, Sign, u32, bool) -> Result<(), std::fmt::Error> {float_to_exponential_common_exact::}, val: Value() } + // + literal: Const { ty: for<'a, 'b, 'c> fn(&'a mut Formatter<'b>, &'c T, Sign, u32, bool) -> Result<(), std::fmt::Error> {float_to_exponential_common_exact::}, val: Value() } } bb7: { @@ -125,7 +125,7 @@ _0 = float_to_exponential_common_shortest::(move _18, move _19, move _20, move _21) -> bb9; // scope 2 at $DIR/funky_arms.rs:+17:9: +17:68 // mir::Constant // + span: $DIR/funky_arms.rs:28:9: 28:45 - // + literal: Const { ty: for<'r, 's, 't> fn(&'r mut Formatter<'s>, &'t T, Sign, bool) -> Result<(), std::fmt::Error> {float_to_exponential_common_shortest::}, val: Value() } + // + literal: Const { ty: for<'a, 'b, 'c> fn(&'a mut Formatter<'b>, &'c T, Sign, bool) -> Result<(), std::fmt::Error> {float_to_exponential_common_shortest::}, val: Value() } } bb9: { diff --git a/src/test/mir-opt/inline/cycle.f.Inline.diff b/src/test/mir-opt/inline/cycle.f.Inline.diff index 40fdd1cdb19c9..75ea69a42eb59 100644 --- a/src/test/mir-opt/inline/cycle.f.Inline.diff +++ b/src/test/mir-opt/inline/cycle.f.Inline.diff @@ -17,7 +17,7 @@ _2 = >::call(move _3, move _4) -> [return: bb1, unwind: bb3]; // scope 0 at $DIR/cycle.rs:+1:5: +1:8 // mir::Constant // + span: $DIR/cycle.rs:6:5: 6:6 - // + literal: Const { ty: for<'r> extern "rust-call" fn(&'r impl Fn(), ()) -> >::Output {>::call}, val: Value() } + // + literal: Const { ty: for<'a> extern "rust-call" fn(&'a impl Fn(), ()) -> >::Output {>::call}, val: Value() } } bb1: { diff --git a/src/test/mir-opt/inline/dyn_trait.get_query.Inline.diff b/src/test/mir-opt/inline/dyn_trait.get_query.Inline.diff index 4b50ba9501c1a..1e95b5b29ff4e 100644 --- a/src/test/mir-opt/inline/dyn_trait.get_query.Inline.diff +++ b/src/test/mir-opt/inline/dyn_trait.get_query.Inline.diff @@ -28,7 +28,7 @@ // mir::Constant // + span: $DIR/dyn-trait.rs:33:13: 33:21 // + user_ty: UserType(0) - // + literal: Const { ty: for<'r> fn(&'r T) -> &'r ::C {::cache::}, val: Value() } + // + literal: Const { ty: for<'a> fn(&'a T) -> &'a ::C {::cache::}, val: Value() } } bb1: { @@ -46,9 +46,9 @@ + _0 = ::V> as Cache>::store_nocache(move _7) -> bb2; // scope 3 at $DIR/dyn-trait.rs:21:5: 21:22 // mir::Constant - // + span: $DIR/dyn-trait.rs:34:5: 34:22 -- // + literal: Const { ty: for<'r> fn(&'r ::C) {try_execute_query::<::C>}, val: Value() } +- // + literal: Const { ty: for<'a> fn(&'a ::C) {try_execute_query::<::C>}, val: Value() } + // + span: $DIR/dyn-trait.rs:21:7: 21:20 -+ // + literal: Const { ty: for<'r> fn(&'r dyn Cache::V>) {::V> as Cache>::store_nocache}, val: Value() } ++ // + literal: Const { ty: for<'a> fn(&'a dyn Cache::V>) {::V> as Cache>::store_nocache}, val: Value() } } bb2: { diff --git a/src/test/mir-opt/inline/dyn_trait.mk_cycle.Inline.diff b/src/test/mir-opt/inline/dyn_trait.mk_cycle.Inline.diff index 994930ef4cf6f..7421db4d063af 100644 --- a/src/test/mir-opt/inline/dyn_trait.mk_cycle.Inline.diff +++ b/src/test/mir-opt/inline/dyn_trait.mk_cycle.Inline.diff @@ -12,7 +12,7 @@ _0 = as Cache>::store_nocache(move _2) -> bb1; // scope 0 at $DIR/dyn-trait.rs:+1:5: +1:22 // mir::Constant // + span: $DIR/dyn-trait.rs:21:7: 21:20 - // + literal: Const { ty: for<'r> fn(&'r dyn Cache) { as Cache>::store_nocache}, val: Value() } + // + literal: Const { ty: for<'a> fn(&'a dyn Cache) { as Cache>::store_nocache}, val: Value() } } bb1: { diff --git a/src/test/mir-opt/inline/dyn_trait.try_execute_query.Inline.diff b/src/test/mir-opt/inline/dyn_trait.try_execute_query.Inline.diff index 58c05b9f564df..e6e783744227e 100644 --- a/src/test/mir-opt/inline/dyn_trait.try_execute_query.Inline.diff +++ b/src/test/mir-opt/inline/dyn_trait.try_execute_query.Inline.diff @@ -23,9 +23,9 @@ + _0 = ::V> as Cache>::store_nocache(move _4) -> bb1; // scope 1 at $DIR/dyn-trait.rs:21:5: 21:22 // mir::Constant - // + span: $DIR/dyn-trait.rs:27:5: 27:13 -- // + literal: Const { ty: for<'r> fn(&'r (dyn Cache::V> + 'r)) {mk_cycle::<::V>}, val: Value() } +- // + literal: Const { ty: for<'a> fn(&'a (dyn Cache::V> + 'a)) {mk_cycle::<::V>}, val: Value() } + // + span: $DIR/dyn-trait.rs:21:7: 21:20 -+ // + literal: Const { ty: for<'r> fn(&'r dyn Cache::V>) {::V> as Cache>::store_nocache}, val: Value() } ++ // + literal: Const { ty: for<'a> fn(&'a dyn Cache::V>) {::V> as Cache>::store_nocache}, val: Value() } } bb1: { 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 0b992e3c32ad1..3fd8aad723880 100644 --- a/src/test/mir-opt/inline/inline_generator.main.Inline.diff +++ b/src/test/mir-opt/inline/inline_generator.main.Inline.diff @@ -70,7 +70,7 @@ - _1 = <[generator@$DIR/inline-generator.rs:15:5: 15:8] as Generator>::resume(move _2, const false) -> [return: bb3, unwind: bb4]; // scope 0 at $DIR/inline-generator.rs:+1:14: +1:46 - // mir::Constant - // + span: $DIR/inline-generator.rs:9:33: 9:39 -- // + literal: Const { ty: for<'r> fn(Pin<&'r mut [generator@$DIR/inline-generator.rs:15:5: 15:8]>, bool) -> GeneratorState<<[generator@$DIR/inline-generator.rs:15:5: 15:8] as Generator>::Yield, <[generator@$DIR/inline-generator.rs:15:5: 15:8] as Generator>::Return> {<[generator@$DIR/inline-generator.rs:15:5: 15:8] as Generator>::resume}, val: Value() } +- // + literal: Const { ty: for<'a> fn(Pin<&'a mut [generator@$DIR/inline-generator.rs:15:5: 15:8]>, bool) -> GeneratorState<<[generator@$DIR/inline-generator.rs:15:5: 15:8] as Generator>::Yield, <[generator@$DIR/inline-generator.rs:15:5: 15:8] as Generator>::Return> {<[generator@$DIR/inline-generator.rs:15:5: 15:8] as Generator>::resume}, val: Value() } + StorageLive(_7); // scope 0 at $DIR/inline-generator.rs:+1:14: +1:46 + _7 = const false; // scope 0 at $DIR/inline-generator.rs:+1:14: +1:46 + StorageLive(_10); // scope 0 at $DIR/inline-generator.rs:+1:14: +1:46 diff --git a/src/test/mir-opt/inline/inline_retag.bar.Inline.after.mir b/src/test/mir-opt/inline/inline_retag.bar.Inline.after.mir index cabc1a92024fc..169e7f5c5d936 100644 --- a/src/test/mir-opt/inline/inline_retag.bar.Inline.after.mir +++ b/src/test/mir-opt/inline/inline_retag.bar.Inline.after.mir @@ -2,8 +2,8 @@ fn bar() -> bool { let mut _0: bool; // return place in scope 0 at $DIR/inline-retag.rs:+0:13: +0:17 - let _1: for<'r, 's> fn(&'r i32, &'s i32) -> bool {foo}; // in scope 0 at $DIR/inline-retag.rs:+1:9: +1:10 - let mut _2: for<'r, 's> fn(&'r i32, &'s i32) -> bool {foo}; // in scope 0 at $DIR/inline-retag.rs:+2:5: +2:6 + let _1: for<'a, 'b> fn(&'a i32, &'b i32) -> bool {foo}; // in scope 0 at $DIR/inline-retag.rs:+1:9: +1:10 + let mut _2: for<'a, 'b> fn(&'a i32, &'b i32) -> bool {foo}; // in scope 0 at $DIR/inline-retag.rs:+2:5: +2:6 let mut _3: &i32; // in scope 0 at $DIR/inline-retag.rs:+2:7: +2:9 let _4: &i32; // in scope 0 at $DIR/inline-retag.rs:+2:7: +2:9 let _5: i32; // in scope 0 at $DIR/inline-retag.rs:+2:8: +2:9 @@ -27,7 +27,7 @@ fn bar() -> bool { _1 = foo; // scope 0 at $DIR/inline-retag.rs:+1:13: +1:16 // mir::Constant // + span: $DIR/inline-retag.rs:11:13: 11:16 - // + literal: Const { ty: for<'r, 's> fn(&'r i32, &'s i32) -> bool {foo}, val: Value() } + // + literal: Const { ty: for<'a, 'b> fn(&'a i32, &'b i32) -> bool {foo}, val: Value() } StorageLive(_2); // scope 1 at $DIR/inline-retag.rs:+2:5: +2:6 _2 = _1; // scope 1 at $DIR/inline-retag.rs:+2:5: +2:6 StorageLive(_3); // scope 1 at $DIR/inline-retag.rs:+2:7: +2:9 diff --git a/src/test/mir-opt/inline/inline_shims.clone.Inline.diff b/src/test/mir-opt/inline/inline_shims.clone.Inline.diff index 25ca05893b2ee..d691e90b7dac6 100644 --- a/src/test/mir-opt/inline/inline_shims.clone.Inline.diff +++ b/src/test/mir-opt/inline/inline_shims.clone.Inline.diff @@ -14,7 +14,7 @@ - _0 = ::clone(move _2) -> bb1; // scope 0 at $DIR/inline-shims.rs:+1:5: +1:14 - // mir::Constant - // + span: $DIR/inline-shims.rs:6:7: 6:12 -- // + literal: Const { ty: for<'r> fn(&'r fn(A, B)) -> fn(A, B) {::clone}, val: Value() } +- // + literal: Const { ty: for<'a> fn(&'a fn(A, B)) -> fn(A, B) {::clone}, val: Value() } - } - - bb1: { diff --git a/src/test/mir-opt/inline/inline_trait_method.test.Inline.after.mir b/src/test/mir-opt/inline/inline_trait_method.test.Inline.after.mir index ed95edd16ce79..89eefc2926911 100644 --- a/src/test/mir-opt/inline/inline_trait_method.test.Inline.after.mir +++ b/src/test/mir-opt/inline/inline_trait_method.test.Inline.after.mir @@ -11,7 +11,7 @@ fn test(_1: &dyn X) -> u32 { _0 = ::y(move _2) -> bb1; // scope 0 at $DIR/inline-trait-method.rs:+1:5: +1:10 // mir::Constant // + span: $DIR/inline-trait-method.rs:9:7: 9:8 - // + literal: Const { ty: for<'r> fn(&'r dyn X) -> u32 {::y}, val: Value() } + // + literal: Const { ty: for<'a> fn(&'a dyn X) -> u32 {::y}, val: Value() } } bb1: { diff --git a/src/test/mir-opt/inline/inline_trait_method_2.test2.Inline.after.mir b/src/test/mir-opt/inline/inline_trait_method_2.test2.Inline.after.mir index b8896430d221a..3d05869fa513e 100644 --- a/src/test/mir-opt/inline/inline_trait_method_2.test2.Inline.after.mir +++ b/src/test/mir-opt/inline/inline_trait_method_2.test2.Inline.after.mir @@ -21,7 +21,7 @@ fn test2(_1: &dyn X) -> bool { _0 = ::y(move _4) -> bb1; // scope 1 at $DIR/inline-trait-method_2.rs:10:5: 10:10 // mir::Constant // + span: $DIR/inline-trait-method_2.rs:10:7: 10:8 - // + literal: Const { ty: for<'r> fn(&'r dyn X) -> bool {::y}, val: Value() } + // + literal: Const { ty: for<'a> fn(&'a dyn X) -> bool {::y}, val: Value() } } bb1: { 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 c16dfdf395ecc..4186650dfabe0 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 @@ - _2 = >::call(move _3, move _5) -> [return: bb2, unwind: bb4]; // scope 0 at $DIR/issue-78442.rs:+4:5: +4:17 - // 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() } +- // + literal: Const { ty: for<'a> extern "rust-call" fn(&'a fn() {foo}, ()) -> >::Output {>::call}, val: Value() } + _2 = move (*_3)() -> [return: bb5, unwind: bb3]; // scope 1 at $SRC_DIR/core/src/ops/function.rs:LL:COL } 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 0faa522cbaa9c..24e9a3df15acd 100644 --- a/src/test/mir-opt/inline/issue_78442.bar.RevealAll.diff +++ b/src/test/mir-opt/inline/issue_78442.bar.RevealAll.diff @@ -29,8 +29,8 @@ + _2 = >::call(move _3, move _5) -> [return: bb2, unwind: bb4]; // scope 0 at $DIR/issue-78442.rs:+4:5: +4: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() } -+ // + literal: Const { ty: for<'r> extern "rust-call" fn(&'r fn() {foo}, ()) -> >::Output {>::call}, val: Value() } +- // + literal: Const { ty: for<'a> extern "rust-call" fn(&'a impl Fn(), ()) -> >::Output {>::call}, val: Value() } ++ // + literal: Const { ty: for<'a> extern "rust-call" fn(&'a fn() {foo}, ()) -> >::Output {>::call}, val: Value() } } bb2: { diff --git a/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.diff b/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.diff index b19e8a8918ef5..269e4e3261751 100644 --- a/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.diff +++ b/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.diff @@ -139,7 +139,7 @@ _21 = core::panicking::assert_failed::(const core::panicking::AssertKind::Eq, move _23, move _25, move _27); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL // mir::Constant // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL - // + literal: Const { ty: for<'r, 's, 't> fn(core::panicking::AssertKind, &'r i32, &'s i32, Option>) -> ! {core::panicking::assert_failed::}, val: Value() } + // + literal: Const { ty: for<'a, 'b, 'c> fn(core::panicking::AssertKind, &'a i32, &'b i32, Option>) -> ! {core::panicking::assert_failed::}, val: Value() } // mir::Constant // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL // + literal: Const { ty: core::panicking::AssertKind, val: Value(Scalar(0x00)) } diff --git a/src/test/mir-opt/issue_91633.bar.mir_map.0.mir b/src/test/mir-opt/issue_91633.bar.mir_map.0.mir index f5092d2ac9238..625f6c7361ac8 100644 --- a/src/test/mir-opt/issue_91633.bar.mir_map.0.mir +++ b/src/test/mir-opt/issue_91633.bar.mir_map.0.mir @@ -15,7 +15,7 @@ fn bar(_1: Box<[T]>) -> () { _2 = <[T] as Index>::index(move _3, const 0_usize) -> [return: bb1, unwind: bb3]; // scope 0 at $DIR/issue-91633.rs:+4:14: +4:19 // mir::Constant // + span: $DIR/issue-91633.rs:15:14: 15:19 - // + literal: Const { ty: for<'r> fn(&'r [T], usize) -> &'r <[T] as Index>::Output {<[T] as Index>::index}, val: Value() } + // + literal: Const { ty: for<'a> fn(&'a [T], usize) -> &'a <[T] as Index>::Output {<[T] as Index>::index}, val: Value() } } bb1: { diff --git a/src/test/mir-opt/issue_91633.foo.mir_map.0.mir b/src/test/mir-opt/issue_91633.foo.mir_map.0.mir index 2e8b0feedd3f9..9903e203a2312 100644 --- a/src/test/mir-opt/issue_91633.foo.mir_map.0.mir +++ b/src/test/mir-opt/issue_91633.foo.mir_map.0.mir @@ -27,7 +27,7 @@ fn foo(_1: Box<[T]>) -> T { _2 = ::clone(move _3) -> [return: bb2, unwind: bb5]; // scope 0 at $DIR/issue-91633.rs:+2:14: +2:27 // mir::Constant // + span: $DIR/issue-91633.rs:28:20: 28:25 - // + literal: Const { ty: for<'r> fn(&'r T) -> T {::clone}, val: Value() } + // + literal: Const { ty: for<'a> fn(&'a T) -> T {::clone}, val: Value() } } bb2: { diff --git a/src/test/mir-opt/issue_91633.hey.mir_map.0.mir b/src/test/mir-opt/issue_91633.hey.mir_map.0.mir index 74f4a5a976116..37c3b3fcacafb 100644 --- a/src/test/mir-opt/issue_91633.hey.mir_map.0.mir +++ b/src/test/mir-opt/issue_91633.hey.mir_map.0.mir @@ -17,7 +17,7 @@ fn hey(_1: &[T]) -> () { _3 = <[T] as Index>::index(move _4, const 0_usize) -> [return: bb1, unwind: bb2]; // scope 0 at $DIR/issue-91633.rs:+4:15: +4:20 // mir::Constant // + span: $DIR/issue-91633.rs:7:15: 7:20 - // + literal: Const { ty: for<'r> fn(&'r [T], usize) -> &'r <[T] as Index>::Output {<[T] as Index>::index}, val: Value() } + // + literal: Const { ty: for<'a> fn(&'a [T], usize) -> &'a <[T] as Index>::Output {<[T] as Index>::index}, val: Value() } } bb1: { diff --git a/src/test/mir-opt/issue_99325.main.mir_map.0.mir b/src/test/mir-opt/issue_99325.main.mir_map.0.mir index ab701486a6bd9..165efa9df4118 100644 --- a/src/test/mir-opt/issue_99325.main.mir_map.0.mir +++ b/src/test/mir-opt/issue_99325.main.mir_map.0.mir @@ -101,7 +101,7 @@ fn main() -> () { _11 = <&[u8] as PartialEq<&[u8; 4]>>::eq(move _12, move _13) -> [return: bb2, unwind: bb19]; // scope 1 at $SRC_DIR/core/src/macros/mod.rs:LL:COL // mir::Constant // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL - // + literal: Const { ty: for<'r, 's> fn(&'r &[u8], &'s &[u8; 4]) -> bool {<&[u8] as PartialEq<&[u8; 4]>>::eq}, val: Value() } + // + literal: Const { ty: for<'a, 'b> fn(&'a &[u8], &'b &[u8; 4]) -> bool {<&[u8] as PartialEq<&[u8; 4]>>::eq}, val: Value() } } bb2: { @@ -132,7 +132,7 @@ fn main() -> () { _16 = core::panicking::assert_failed::<&[u8], &[u8; 4]>(move _17, move _18, move _20, move _22) -> bb19; // scope 2 at $SRC_DIR/core/src/macros/mod.rs:LL:COL // mir::Constant // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL - // + literal: Const { ty: for<'r, 's, 't> fn(core::panicking::AssertKind, &'r &[u8], &'s &[u8; 4], Option>) -> ! {core::panicking::assert_failed::<&[u8], &[u8; 4]>}, val: Value() } + // + literal: Const { ty: for<'a, 'b, 'c> fn(core::panicking::AssertKind, &'a &[u8], &'b &[u8; 4], Option>) -> ! {core::panicking::assert_failed::<&[u8], &[u8; 4]>}, val: Value() } } bb4: { @@ -210,7 +210,7 @@ fn main() -> () { _32 = <&[u8] as PartialEq<&[u8; 4]>>::eq(move _33, move _34) -> [return: bb11, unwind: bb19]; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL // mir::Constant // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL - // + literal: Const { ty: for<'r, 's> fn(&'r &[u8], &'s &[u8; 4]) -> bool {<&[u8] as PartialEq<&[u8; 4]>>::eq}, val: Value() } + // + literal: Const { ty: for<'a, 'b> fn(&'a &[u8], &'b &[u8; 4]) -> bool {<&[u8] as PartialEq<&[u8; 4]>>::eq}, val: Value() } } bb11: { @@ -241,7 +241,7 @@ fn main() -> () { _37 = core::panicking::assert_failed::<&[u8], &[u8; 4]>(move _38, move _39, move _41, move _43) -> bb19; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL // mir::Constant // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL - // + literal: Const { ty: for<'r, 's, 't> fn(core::panicking::AssertKind, &'r &[u8], &'s &[u8; 4], Option>) -> ! {core::panicking::assert_failed::<&[u8], &[u8; 4]>}, val: Value() } + // + literal: Const { ty: for<'a, 'b, 'c> fn(core::panicking::AssertKind, &'a &[u8], &'b &[u8; 4], Option>) -> ! {core::panicking::assert_failed::<&[u8], &[u8; 4]>}, val: Value() } } bb13: { diff --git a/src/test/mir-opt/lower_intrinsics.discriminant.LowerIntrinsics.diff b/src/test/mir-opt/lower_intrinsics.discriminant.LowerIntrinsics.diff index a648e5d672dc8..d962ef8cb12dc 100644 --- a/src/test/mir-opt/lower_intrinsics.discriminant.LowerIntrinsics.diff +++ b/src/test/mir-opt/lower_intrinsics.discriminant.LowerIntrinsics.diff @@ -32,7 +32,7 @@ - _2 = discriminant_value::(move _3) -> bb1; // scope 0 at $DIR/lower_intrinsics.rs:+1:5: +1:45 - // mir::Constant - // + span: $DIR/lower_intrinsics.rs:49:5: 49:41 -- // + literal: Const { ty: for<'r> extern "rust-intrinsic" fn(&'r T) -> ::Discriminant {discriminant_value::}, val: Value() } +- // + literal: Const { ty: for<'a> extern "rust-intrinsic" fn(&'a T) -> ::Discriminant {discriminant_value::}, val: Value() } + _2 = discriminant((*_3)); // scope 0 at $DIR/lower_intrinsics.rs:+1:5: +1:45 + goto -> bb1; // scope 0 at $DIR/lower_intrinsics.rs:+1:5: +1:45 } @@ -53,7 +53,7 @@ - _5 = discriminant_value::(move _6) -> bb2; // scope 0 at $DIR/lower_intrinsics.rs:+2:5: +2:45 - // mir::Constant - // + span: $DIR/lower_intrinsics.rs:50:5: 50:41 -- // + literal: Const { ty: for<'r> extern "rust-intrinsic" fn(&'r i32) -> ::Discriminant {discriminant_value::}, val: Value() } +- // + literal: Const { ty: for<'a> extern "rust-intrinsic" fn(&'a i32) -> ::Discriminant {discriminant_value::}, val: Value() } + _5 = discriminant((*_6)); // scope 0 at $DIR/lower_intrinsics.rs:+2:5: +2:45 + goto -> bb2; // scope 0 at $DIR/lower_intrinsics.rs:+2:5: +2:45 } @@ -74,7 +74,7 @@ - _9 = discriminant_value::<()>(move _10) -> bb3; // scope 0 at $DIR/lower_intrinsics.rs:+3:5: +3:46 - // mir::Constant - // + span: $DIR/lower_intrinsics.rs:51:5: 51:41 -- // + literal: Const { ty: for<'r> extern "rust-intrinsic" fn(&'r ()) -> <() as DiscriminantKind>::Discriminant {discriminant_value::<()>}, val: Value() } +- // + literal: Const { ty: for<'a> extern "rust-intrinsic" fn(&'a ()) -> <() as DiscriminantKind>::Discriminant {discriminant_value::<()>}, val: Value() } + _9 = discriminant((*_10)); // scope 0 at $DIR/lower_intrinsics.rs:+3:5: +3:46 + goto -> bb3; // scope 0 at $DIR/lower_intrinsics.rs:+3:5: +3:46 } @@ -95,7 +95,7 @@ - _13 = discriminant_value::(move _14) -> bb4; // scope 0 at $DIR/lower_intrinsics.rs:+4:5: +4:48 - // mir::Constant - // + span: $DIR/lower_intrinsics.rs:52:5: 52:41 -- // + literal: Const { ty: for<'r> extern "rust-intrinsic" fn(&'r E) -> ::Discriminant {discriminant_value::}, val: Value() } +- // + literal: Const { ty: for<'a> extern "rust-intrinsic" fn(&'a E) -> ::Discriminant {discriminant_value::}, val: Value() } + _13 = discriminant((*_14)); // scope 0 at $DIR/lower_intrinsics.rs:+4:5: +4:48 + goto -> bb4; // scope 0 at $DIR/lower_intrinsics.rs:+4:5: +4:48 } diff --git a/src/test/mir-opt/lower_slice_len.bound.LowerSliceLenCalls.diff b/src/test/mir-opt/lower_slice_len.bound.LowerSliceLenCalls.diff index 46fccba56f7c8..5f5d6e68fdc17 100644 --- a/src/test/mir-opt/lower_slice_len.bound.LowerSliceLenCalls.diff +++ b/src/test/mir-opt/lower_slice_len.bound.LowerSliceLenCalls.diff @@ -23,7 +23,7 @@ - _5 = core::slice::::len(move _6) -> bb1; // scope 0 at $DIR/lower_slice_len.rs:+1:16: +1:27 - // mir::Constant - // + span: $DIR/lower_slice_len.rs:5:22: 5:25 -- // + literal: Const { ty: for<'r> fn(&'r [u8]) -> usize {core::slice::::len}, val: Value() } +- // + literal: Const { ty: for<'a> fn(&'a [u8]) -> usize {core::slice::::len}, val: Value() } + _5 = Len((*_6)); // scope 0 at $DIR/lower_slice_len.rs:+1:16: +1:27 + goto -> bb1; // scope 0 at $DIR/lower_slice_len.rs:+1:16: +1:27 } diff --git a/src/test/mir-opt/no_spurious_drop_after_call.main.ElaborateDrops.before.mir b/src/test/mir-opt/no_spurious_drop_after_call.main.ElaborateDrops.before.mir index 25c6e3060069d..963e7cde6567b 100644 --- a/src/test/mir-opt/no_spurious_drop_after_call.main.ElaborateDrops.before.mir +++ b/src/test/mir-opt/no_spurious_drop_after_call.main.ElaborateDrops.before.mir @@ -20,7 +20,7 @@ fn main() -> () { _2 = ::to_string(move _3) -> bb1; // scope 0 at $DIR/no-spurious-drop-after-call.rs:+1:20: +1:34 // mir::Constant // + span: $DIR/no-spurious-drop-after-call.rs:9:23: 9:32 - // + literal: Const { ty: for<'r> fn(&'r str) -> String {::to_string}, val: Value() } + // + literal: Const { ty: for<'a> fn(&'a str) -> String {::to_string}, val: Value() } } bb1: { diff --git a/src/test/mir-opt/nrvo_simple.nrvo.RenameReturnPlace.diff b/src/test/mir-opt/nrvo_simple.nrvo.RenameReturnPlace.diff index 9e89bd9fb9631..ce35f920bf627 100644 --- a/src/test/mir-opt/nrvo_simple.nrvo.RenameReturnPlace.diff +++ b/src/test/mir-opt/nrvo_simple.nrvo.RenameReturnPlace.diff @@ -1,13 +1,13 @@ - // MIR for `nrvo` before RenameReturnPlace + // MIR for `nrvo` after RenameReturnPlace - fn nrvo(_1: for<'r> fn(&'r mut [u8; 1024])) -> [u8; 1024] { + fn nrvo(_1: for<'a> fn(&'a mut [u8; 1024])) -> [u8; 1024] { debug init => _1; // in scope 0 at $DIR/nrvo-simple.rs:+0:9: +0:13 - let mut _0: [u8; 1024]; // return place in scope 0 at $DIR/nrvo-simple.rs:+0:39: +0:49 + let mut _0: [u8; 1024]; // return place in scope 0 at $DIR/nrvo-simple.rs:+1:9: +1:16 let mut _2: [u8; 1024]; // in scope 0 at $DIR/nrvo-simple.rs:+1:9: +1:16 let _3: (); // in scope 0 at $DIR/nrvo-simple.rs:+2:5: +2:19 - let mut _4: for<'r> fn(&'r mut [u8; 1024]); // in scope 0 at $DIR/nrvo-simple.rs:+2:5: +2:9 + let mut _4: for<'a> fn(&'a mut [u8; 1024]); // in scope 0 at $DIR/nrvo-simple.rs:+2:5: +2:9 let mut _5: &mut [u8; 1024]; // in scope 0 at $DIR/nrvo-simple.rs:+2:10: +2:18 let mut _6: &mut [u8; 1024]; // in scope 0 at $DIR/nrvo-simple.rs:+2:10: +2:18 scope 1 { 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 99667aabdaee2..188aa55649069 100644 --- a/src/test/mir-opt/remove_storage_markers.main.RemoveStorageMarkers.diff +++ b/src/test/mir-opt/remove_storage_markers.main.RemoveStorageMarkers.diff @@ -57,7 +57,7 @@ _7 = as Iterator>::next(move _8) -> bb3; // scope 2 at $DIR/remove_storage_markers.rs:+2:14: +2:19 // mir::Constant // + span: $DIR/remove_storage_markers.rs:10:14: 10:19 - // + literal: Const { ty: for<'r> fn(&'r mut std::ops::Range) -> Option< as Iterator>::Item> { as Iterator>::next}, val: Value() } + // + literal: Const { ty: for<'a> fn(&'a mut std::ops::Range) -> Option< as Iterator>::Item> { as Iterator>::next}, val: Value() } } bb3: { diff --git a/src/test/mir-opt/retag.array_casts.SimplifyCfg-elaborate-drops.after.mir b/src/test/mir-opt/retag.array_casts.SimplifyCfg-elaborate-drops.after.mir index 448b465db23f6..fe57e32a7acc2 100644 --- a/src/test/mir-opt/retag.array_casts.SimplifyCfg-elaborate-drops.after.mir +++ b/src/test/mir-opt/retag.array_casts.SimplifyCfg-elaborate-drops.after.mir @@ -180,7 +180,7 @@ fn array_casts() -> () { _28 = core::panicking::assert_failed::(move _29, move _30, move _32, move _34); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL // mir::Constant // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL - // + literal: Const { ty: for<'r, 's, 't> fn(core::panicking::AssertKind, &'r usize, &'s usize, Option>) -> ! {core::panicking::assert_failed::}, val: Value() } + // + literal: Const { ty: for<'a, 'b, 'c> fn(core::panicking::AssertKind, &'a usize, &'b usize, Option>) -> ! {core::panicking::assert_failed::}, val: Value() } } bb4: { diff --git a/src/test/mir-opt/retag.core.ptr-drop_in_place.Test.SimplifyCfg-make_shim.after.mir b/src/test/mir-opt/retag.core.ptr-drop_in_place.Test.SimplifyCfg-make_shim.after.mir index 84f674db2d154..cdc413c568f18 100644 --- a/src/test/mir-opt/retag.core.ptr-drop_in_place.Test.SimplifyCfg-make_shim.after.mir +++ b/src/test/mir-opt/retag.core.ptr-drop_in_place.Test.SimplifyCfg-make_shim.after.mir @@ -11,7 +11,7 @@ fn std::ptr::drop_in_place(_1: *mut Test) -> () { _3 = ::drop(move _2) -> bb1; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 // mir::Constant // + span: $SRC_DIR/core/src/ptr/mod.rs:LL:COL - // + literal: Const { ty: for<'r> fn(&'r mut Test) {::drop}, val: Value() } + // + literal: Const { ty: for<'a> fn(&'a mut Test) {::drop}, val: Value() } } bb1: { diff --git a/src/test/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.mir b/src/test/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.mir index 7212de52fc378..81225b44ebf9f 100644 --- a/src/test/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.mir +++ b/src/test/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.mir @@ -11,7 +11,7 @@ fn main() -> () { let mut _9: &mut i32; // in scope 0 at $DIR/retag.rs:+4:19: +4:20 let mut _12: *mut i32; // in scope 0 at $DIR/retag.rs:+7:18: +7:29 let mut _14: [closure@main::{closure#0}]; // in scope 0 at $DIR/retag.rs:+11:31: +14:6 - let mut _16: for<'r> fn(&'r i32) -> &'r i32; // in scope 0 at $DIR/retag.rs:+15:14: +15:15 + let mut _16: for<'a> fn(&'a i32) -> &'a i32; // in scope 0 at $DIR/retag.rs:+15:14: +15:15 let mut _17: &i32; // in scope 0 at $DIR/retag.rs:+15:16: +15:18 let _18: &i32; // in scope 0 at $DIR/retag.rs:+15:16: +15:18 let _19: &i32; // in scope 0 at $DIR/retag.rs:+18:5: +18:24 @@ -25,7 +25,7 @@ fn main() -> () { scope 1 { debug x => _1; // in scope 1 at $DIR/retag.rs:+1:9: +1:14 let _3: &mut i32; // in scope 1 at $DIR/retag.rs:+3:13: +3:14 - let _13: for<'r> fn(&'r i32) -> &'r i32; // in scope 1 at $DIR/retag.rs:+11:9: +11:10 + let _13: for<'a> fn(&'a i32) -> &'a i32; // in scope 1 at $DIR/retag.rs:+11:9: +11:10 scope 2 { debug v => _3; // in scope 2 at $DIR/retag.rs:+3:13: +3:14 let _8: &mut i32; // in scope 2 at $DIR/retag.rs:+4:13: +4:14 @@ -75,7 +75,7 @@ fn main() -> () { _3 = Test::foo(move _4, move _6) -> [return: bb1, unwind: bb8]; // scope 1 at $DIR/retag.rs:+3:17: +3:36 // mir::Constant // + span: $DIR/retag.rs:33:25: 33:28 - // + literal: Const { ty: for<'r, 'x> fn(&'r Test, &'x mut i32) -> &'x mut i32 {Test::foo}, val: Value() } + // + literal: Const { ty: for<'a, 'x> fn(&'a Test, &'x mut i32) -> &'x mut i32 {Test::foo}, val: Value() } } bb1: { @@ -114,7 +114,7 @@ fn main() -> () { StorageLive(_14); // scope 1 at $DIR/retag.rs:+11:31: +14:6 Deinit(_14); // scope 1 at $DIR/retag.rs:+11:31: +14:6 Retag(_14); // scope 1 at $DIR/retag.rs:+11:31: +14:6 - _13 = move _14 as for<'r> fn(&'r i32) -> &'r i32 (Pointer(ClosureFnPointer(Normal))); // scope 1 at $DIR/retag.rs:+11:31: +14:6 + _13 = move _14 as for<'a> fn(&'a i32) -> &'a i32 (Pointer(ClosureFnPointer(Normal))); // scope 1 at $DIR/retag.rs:+11:31: +14:6 StorageDead(_14); // scope 1 at $DIR/retag.rs:+11:47: +11:48 StorageLive(_15); // scope 6 at $DIR/retag.rs:+15:9: +15:11 StorageLive(_16); // scope 6 at $DIR/retag.rs:+15:14: +15:15 @@ -154,7 +154,7 @@ fn main() -> () { _19 = Test::foo_shr(move _20, move _22) -> [return: bb4, unwind: bb7]; // scope 7 at $DIR/retag.rs:+18:5: +18:24 // mir::Constant // + span: $DIR/retag.rs:48:13: 48:20 - // + literal: Const { ty: for<'r, 'x> fn(&'r Test, &'x i32) -> &'x i32 {Test::foo_shr}, val: Value() } + // + literal: Const { ty: for<'a, 'x> fn(&'a Test, &'x i32) -> &'x i32 {Test::foo_shr}, val: Value() } } bb4: { diff --git a/src/test/mir-opt/unusual_item_types.core.ptr-drop_in_place.Vec_i32_.AddMovesForPackedDrops.before.mir b/src/test/mir-opt/unusual_item_types.core.ptr-drop_in_place.Vec_i32_.AddMovesForPackedDrops.before.mir index 7ffd242e0dc3b..ed9f3bdbdf4d6 100644 --- a/src/test/mir-opt/unusual_item_types.core.ptr-drop_in_place.Vec_i32_.AddMovesForPackedDrops.before.mir +++ b/src/test/mir-opt/unusual_item_types.core.ptr-drop_in_place.Vec_i32_.AddMovesForPackedDrops.before.mir @@ -34,6 +34,6 @@ fn std::ptr::drop_in_place(_1: *mut Vec) -> () { _3 = as Drop>::drop(move _2) -> [return: bb5, unwind: bb4]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 // mir::Constant // + span: $SRC_DIR/core/src/ptr/mod.rs:LL:COL - // + literal: Const { ty: for<'r> fn(&'r mut Vec) { as Drop>::drop}, val: Value() } + // + literal: Const { ty: for<'a> fn(&'a mut Vec) { as Drop>::drop}, val: Value() } } } diff --git a/src/test/pretty/issue-4264.pp b/src/test/pretty/issue-4264.pp index 10958a7727c4b..18e6d75b1d5ad 100644 --- a/src/test/pretty/issue-4264.pp +++ b/src/test/pretty/issue-4264.pp @@ -32,7 +32,7 @@ ({ let res = ((::alloc::fmt::format as - for<'r> fn(Arguments<'r>) -> String {format})(((::core::fmt::Arguments::new_v1 + for<'a> fn(Arguments<'a>) -> String {format})(((::core::fmt::Arguments::new_v1 as fn(&[&'static str], &[ArgumentV1<'_>]) -> Arguments<'_> {Arguments::<'_>::new_v1})((&([("test" as &str)] as [&str; 1]) as &[&str; 1]), diff --git a/src/test/ui/anonymous-higher-ranked-lifetime.stderr b/src/test/ui/anonymous-higher-ranked-lifetime.stderr index 1a0a5fdf4eb23..bf5f642ca823d 100644 --- a/src/test/ui/anonymous-higher-ranked-lifetime.stderr +++ b/src/test/ui/anonymous-higher-ranked-lifetime.stderr @@ -6,7 +6,7 @@ LL | f1(|_: (), _: ()| {}); | | | expected due to this | - = note: expected closure signature `for<'r, 's> fn(&'r (), &'s ()) -> _` + = note: expected closure signature `for<'a, 'b> fn(&'a (), &'b ()) -> _` found closure signature `fn((), ()) -> _` note: required by a bound in `f1` --> $DIR/anonymous-higher-ranked-lifetime.rs:16:25 @@ -22,7 +22,7 @@ LL | f2(|_: (), _: ()| {}); | | | expected due to this | - = note: expected closure signature `for<'a, 'r> fn(&'a (), &'r ()) -> _` + = note: expected closure signature `for<'a, 'b> fn(&'a (), &'b ()) -> _` found closure signature `fn((), ()) -> _` note: required by a bound in `f2` --> $DIR/anonymous-higher-ranked-lifetime.rs:17:25 @@ -38,7 +38,7 @@ LL | f3(|_: (), _: ()| {}); | | | expected due to this | - = note: expected closure signature `for<'r> fn(&(), &'r ()) -> _` + = note: expected closure signature `for<'a> fn(&(), &'a ()) -> _` found closure signature `fn((), ()) -> _` note: required by a bound in `f3` --> $DIR/anonymous-higher-ranked-lifetime.rs:18:29 @@ -54,7 +54,7 @@ LL | f4(|_: (), _: ()| {}); | | | expected due to this | - = note: expected closure signature `for<'r, 's> fn(&'s (), &'r ()) -> _` + = note: expected closure signature `for<'r, 'a> fn(&'a (), &'r ()) -> _` found closure signature `fn((), ()) -> _` note: required by a bound in `f4` --> $DIR/anonymous-higher-ranked-lifetime.rs:19:25 @@ -86,7 +86,7 @@ LL | g1(|_: (), _: ()| {}); | | | expected due to this | - = note: expected closure signature `for<'r> fn(&'r (), Box<(dyn for<'r> Fn(&'r ()) + 'static)>) -> _` + = note: expected closure signature `for<'a> fn(&'a (), Box<(dyn for<'a> Fn(&'a ()) + 'static)>) -> _` found closure signature `fn((), ()) -> _` note: required by a bound in `g1` --> $DIR/anonymous-higher-ranked-lifetime.rs:23:25 @@ -102,7 +102,7 @@ LL | g2(|_: (), _: ()| {}); | | | expected due to this | - = note: expected closure signature `for<'r> fn(&'r (), for<'r> fn(&'r ())) -> _` + = note: expected closure signature `for<'a> fn(&'a (), for<'a> fn(&'a ())) -> _` found closure signature `fn((), ()) -> _` note: required by a bound in `g2` --> $DIR/anonymous-higher-ranked-lifetime.rs:24:25 @@ -118,7 +118,7 @@ LL | g3(|_: (), _: ()| {}); | | | expected due to this | - = note: expected closure signature `for<'s> fn(&'s (), Box<(dyn for<'r> Fn(&'r ()) + 'static)>) -> _` + = note: expected closure signature `for<'s> fn(&'s (), Box<(dyn for<'a> Fn(&'a ()) + 'static)>) -> _` found closure signature `fn((), ()) -> _` note: required by a bound in `g3` --> $DIR/anonymous-higher-ranked-lifetime.rs:25:25 @@ -134,7 +134,7 @@ LL | g4(|_: (), _: ()| {}); | | | expected due to this | - = note: expected closure signature `for<'s> fn(&'s (), for<'r> fn(&'r ())) -> _` + = note: expected closure signature `for<'a> fn(&'a (), for<'r> fn(&'r ())) -> _` found closure signature `fn((), ()) -> _` note: required by a bound in `g4` --> $DIR/anonymous-higher-ranked-lifetime.rs:26:25 @@ -150,7 +150,7 @@ LL | h1(|_: (), _: (), _: (), _: ()| {}); | | | expected due to this | - = note: expected closure signature `for<'r, 's> fn(&'r (), Box<(dyn for<'r> Fn(&'r ()) + 'static)>, &'s (), for<'r, 's> fn(&'r (), &'s ())) -> _` + = note: expected closure signature `for<'a, 'b> fn(&'a (), Box<(dyn for<'a> Fn(&'a ()) + 'static)>, &'b (), for<'a, 'b> fn(&'a (), &'b ())) -> _` found closure signature `fn((), (), (), ()) -> _` note: required by a bound in `h1` --> $DIR/anonymous-higher-ranked-lifetime.rs:29:25 @@ -166,7 +166,7 @@ LL | h2(|_: (), _: (), _: (), _: ()| {}); | | | expected due to this | - = note: expected closure signature `for<'t0, 'r> fn(&'r (), Box<(dyn for<'r> Fn(&'r ()) + 'static)>, &'t0 (), for<'r, 's> fn(&'r (), &'s ())) -> _` + = note: expected closure signature `for<'t0, 'a> fn(&'a (), Box<(dyn for<'a> Fn(&'a ()) + 'static)>, &'t0 (), for<'a, 'b> fn(&'a (), &'b ())) -> _` found closure signature `fn((), (), (), ()) -> _` note: required by a bound in `h2` --> $DIR/anonymous-higher-ranked-lifetime.rs:30:25 diff --git a/src/test/ui/async-await/issue-70935-complex-spans.drop_tracking.stderr b/src/test/ui/async-await/issue-70935-complex-spans.drop_tracking.stderr index 8fba766bc8704..85f7d1dd6748b 100644 --- a/src/test/ui/async-await/issue-70935-complex-spans.drop_tracking.stderr +++ b/src/test/ui/async-await/issue-70935-complex-spans.drop_tracking.stderr @@ -18,7 +18,7 @@ LL | async fn baz(_c: impl FnMut() -> T) where T: Future { | ___________________________________________________________________^ LL | | } | |_^ - = note: required because it captures the following types: `ResumeTy`, `impl for<'r, 's, 't> Future`, `()` + = note: required because it captures the following types: `ResumeTy`, `impl for<'a, 'b, 'c> Future`, `()` note: required because it's used within this `async` block --> $DIR/issue-70935-complex-spans.rs:16:16 | diff --git a/src/test/ui/binop/issue-77910-1.rs b/src/test/ui/binop/issue-77910-1.rs index d786e33585984..95bbd6a60ec86 100644 --- a/src/test/ui/binop/issue-77910-1.rs +++ b/src/test/ui/binop/issue-77910-1.rs @@ -7,5 +7,5 @@ fn main() { // we shouldn't ice with the bound var here. assert_eq!(foo, y); //~^ ERROR binary operation `==` cannot be applied to type - //~| ERROR `for<'r> fn(&'r i32) -> &'r i32 {foo}` doesn't implement `Debug` + //~| ERROR `for<'a> fn(&'a i32) -> &'a i32 {foo}` doesn't implement `Debug` } diff --git a/src/test/ui/binop/issue-77910-1.stderr b/src/test/ui/binop/issue-77910-1.stderr index 097a14f26f868..9c7bf6228be6e 100644 --- a/src/test/ui/binop/issue-77910-1.stderr +++ b/src/test/ui/binop/issue-77910-1.stderr @@ -1,24 +1,24 @@ -error[E0369]: binary operation `==` cannot be applied to type `for<'r> fn(&'r i32) -> &'r i32 {foo}` +error[E0369]: binary operation `==` cannot be applied to type `for<'a> fn(&'a i32) -> &'a i32 {foo}` --> $DIR/issue-77910-1.rs:8:5 | LL | assert_eq!(foo, y); | ^^^^^^^^^^^^^^^^^^ | | - | for<'r> fn(&'r i32) -> &'r i32 {foo} + | for<'a> fn(&'a i32) -> &'a i32 {foo} | _ | = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0277]: `for<'r> fn(&'r i32) -> &'r i32 {foo}` doesn't implement `Debug` +error[E0277]: `for<'a> fn(&'a i32) -> &'a i32 {foo}` doesn't implement `Debug` --> $DIR/issue-77910-1.rs:8:5 | LL | fn foo(s: &i32) -> &i32 { | --- consider calling this function ... LL | assert_eq!(foo, y); - | ^^^^^^^^^^^^^^^^^^ `for<'r> fn(&'r i32) -> &'r i32 {foo}` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | ^^^^^^^^^^^^^^^^^^ `for<'a> fn(&'a i32) -> &'a i32 {foo}` cannot be formatted using `{:?}` because it doesn't implement `Debug` | - = help: the trait `Debug` is not implemented for fn item `for<'r> fn(&'r i32) -> &'r i32 {foo}` + = help: the trait `Debug` is not implemented for fn item `for<'a> fn(&'a i32) -> &'a i32 {foo}` = help: use parentheses to call the function: `foo(s)` = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/binop/issue-77910-2.stderr b/src/test/ui/binop/issue-77910-2.stderr index a334bd8562593..b3856b6ae1681 100644 --- a/src/test/ui/binop/issue-77910-2.stderr +++ b/src/test/ui/binop/issue-77910-2.stderr @@ -1,10 +1,10 @@ -error[E0369]: binary operation `==` cannot be applied to type `for<'r> fn(&'r i32) -> &'r i32 {foo}` +error[E0369]: binary operation `==` cannot be applied to type `for<'a> fn(&'a i32) -> &'a i32 {foo}` --> $DIR/issue-77910-2.rs:7:12 | LL | if foo == y {} | --- ^^ - _ | | - | for<'r> fn(&'r i32) -> &'r i32 {foo} + | for<'a> fn(&'a i32) -> &'a i32 {foo} | help: use parentheses to call this function | diff --git a/src/test/ui/closure-expected-type/expect-fn-supply-fn.stderr b/src/test/ui/closure-expected-type/expect-fn-supply-fn.stderr index 284fc1c21f5f9..e6ddc60689779 100644 --- a/src/test/ui/closure-expected-type/expect-fn-supply-fn.stderr +++ b/src/test/ui/closure-expected-type/expect-fn-supply-fn.stderr @@ -26,7 +26,7 @@ LL | with_closure_expecting_fn_with_free_region(|x: fn(&u32), y| {}); | ^ one type is more general than the other | = note: expected fn pointer `fn(&u32)` - found fn pointer `for<'r> fn(&'r u32)` + found fn pointer `for<'a> fn(&'a u32)` error[E0308]: mismatched types --> $DIR/expect-fn-supply-fn.rs:39:50 @@ -34,7 +34,7 @@ error[E0308]: mismatched types LL | with_closure_expecting_fn_with_bound_region(|x: fn(&'x u32), y| {}); | ^ one type is more general than the other | - = note: expected fn pointer `for<'r> fn(&'r u32)` + = note: expected fn pointer `for<'a> fn(&'a u32)` found fn pointer `fn(&u32)` error[E0308]: mismatched types @@ -43,7 +43,7 @@ error[E0308]: mismatched types LL | with_closure_expecting_fn_with_bound_region(|x: Foo<'_>, y| { | ^ one type is more general than the other | - = note: expected fn pointer `for<'r> fn(&'r u32)` + = note: expected fn pointer `for<'a> fn(&'a u32)` found fn pointer `fn(&u32)` error: aborting due to 5 previous errors diff --git a/src/test/ui/closures/closure-reform-bad.stderr b/src/test/ui/closures/closure-reform-bad.stderr index 9dfff8499fddd..4c40f70b9d0a8 100644 --- a/src/test/ui/closures/closure-reform-bad.stderr +++ b/src/test/ui/closures/closure-reform-bad.stderr @@ -8,7 +8,7 @@ LL | call_bare(f) | | | arguments to this function are incorrect | - = note: expected fn pointer `for<'r> fn(&'r str)` + = note: expected fn pointer `for<'a> fn(&'a str)` found closure `[closure@$DIR/closure-reform-bad.rs:10:13: 10:22]` note: closures can only be coerced to `fn` types if they do not capture any variables --> $DIR/closure-reform-bad.rs:10:43 diff --git a/src/test/ui/compare-method/issue-90444.stderr b/src/test/ui/compare-method/issue-90444.stderr index 84bbec0623fd8..ee63f34b799a5 100644 --- a/src/test/ui/compare-method/issue-90444.stderr +++ b/src/test/ui/compare-method/issue-90444.stderr @@ -5,10 +5,10 @@ LL | fn from(_: fn((), (), &mut ())) -> Self { | ^^^^^^^^^^^^^^^^^^^ | | | types differ in mutability - | help: change the parameter type to match the trait: `for<'r> fn((), (), &'r ())` + | help: change the parameter type to match the trait: `for<'a> fn((), (), &'a ())` | - = note: expected fn pointer `fn(for<'r> fn((), (), &'r ())) -> A` - found fn pointer `fn(for<'r> fn((), (), &'r mut ())) -> A` + = note: expected fn pointer `fn(for<'a> fn((), (), &'a ())) -> A` + found fn pointer `fn(for<'a> fn((), (), &'a mut ())) -> A` error[E0053]: method `from` has an incompatible type for trait --> $DIR/issue-90444.rs:11:16 diff --git a/src/test/ui/generic-associated-types/bugs/issue-88382.stderr b/src/test/ui/generic-associated-types/bugs/issue-88382.stderr index c5fd58096b7fd..a9a70bb7130cb 100644 --- a/src/test/ui/generic-associated-types/bugs/issue-88382.stderr +++ b/src/test/ui/generic-associated-types/bugs/issue-88382.stderr @@ -9,8 +9,8 @@ LL | do_something(SomeImplementation(), test); LL | fn test<'a, I: Iterable>(_: &mut I::Iterator<'a>) {} | ------------------------------------------------- found signature defined here | - = note: expected function signature `for<'r> fn(&'r mut std::iter::Empty) -> _` - found function signature `for<'a, 'r> fn(&'r mut <_ as Iterable>::Iterator<'a>) -> _` + = note: expected function signature `for<'a> fn(&'a mut std::iter::Empty) -> _` + found function signature `for<'a, 'b> fn(&'b mut <_ as Iterable>::Iterator<'a>) -> _` note: required by a bound in `do_something` --> $DIR/issue-88382.rs:20:48 | diff --git a/src/test/ui/higher-rank-trait-bounds/issue-30786.stderr b/src/test/ui/higher-rank-trait-bounds/issue-30786.stderr index ffe3d7b81f51e..c1e235441d65d 100644 --- a/src/test/ui/higher-rank-trait-bounds/issue-30786.stderr +++ b/src/test/ui/higher-rank-trait-bounds/issue-30786.stderr @@ -19,7 +19,7 @@ note: the following trait bounds were not satisfied: LL | impl StreamExt for T where for<'a> &'a mut T: Stream {} | --------- - ^^^^^^ unsatisfied trait bound introduced here -error[E0599]: the method `countx` exists for struct `Filter fn(&'r u64) -> &'r u64 {identity::}>, [closure@$DIR/issue-30786.rs:129:30: 129:37]>`, but its trait bounds were not satisfied +error[E0599]: the method `countx` exists for struct `Filter fn(&'a u64) -> &'a u64 {identity::}>, [closure@$DIR/issue-30786.rs:129:30: 129:37]>`, but its trait bounds were not satisfied --> $DIR/issue-30786.rs:130:24 | LL | pub struct Filter { @@ -29,12 +29,12 @@ LL | pub struct Filter { | doesn't satisfy `_: StreamExt` ... LL | let count = filter.countx(); - | ^^^^^^ method cannot be called on `Filter fn(&'r u64) -> &'r u64 {identity::}>, [closure@$DIR/issue-30786.rs:129:30: 129:37]>` due to unsatisfied trait bounds + | ^^^^^^ method cannot be called on `Filter fn(&'a u64) -> &'a u64 {identity::}>, [closure@$DIR/issue-30786.rs:129:30: 129:37]>` due to unsatisfied trait bounds | note: the following trait bounds were not satisfied: - `&'a mut &Filter fn(&'r u64) -> &'r u64 {identity::}>, [closure@$DIR/issue-30786.rs:129:30: 129:37]>: Stream` - `&'a mut &mut Filter fn(&'r u64) -> &'r u64 {identity::}>, [closure@$DIR/issue-30786.rs:129:30: 129:37]>: Stream` - `&'a mut Filter fn(&'r u64) -> &'r u64 {identity::}>, [closure@$DIR/issue-30786.rs:129:30: 129:37]>: Stream` + `&'a mut &Filter fn(&'a u64) -> &'a u64 {identity::}>, [closure@$DIR/issue-30786.rs:129:30: 129:37]>: Stream` + `&'a mut &mut Filter fn(&'a u64) -> &'a u64 {identity::}>, [closure@$DIR/issue-30786.rs:129:30: 129:37]>: Stream` + `&'a mut Filter fn(&'a u64) -> &'a u64 {identity::}>, [closure@$DIR/issue-30786.rs:129:30: 129:37]>: Stream` --> $DIR/issue-30786.rs:96:50 | LL | impl StreamExt for T where for<'a> &'a mut T: Stream {} diff --git a/src/test/ui/higher-rank-trait-bounds/issue-46989.stderr b/src/test/ui/higher-rank-trait-bounds/issue-46989.stderr index 309e1a676edaf..3f874220a2708 100644 --- a/src/test/ui/higher-rank-trait-bounds/issue-46989.stderr +++ b/src/test/ui/higher-rank-trait-bounds/issue-46989.stderr @@ -4,7 +4,7 @@ error: implementation of `Foo` is not general enough LL | assert_foo::(); | ^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough | - = note: `Foo` would have to be implemented for the type `for<'r> fn(&'r i32)` + = note: `Foo` would have to be implemented for the type `for<'a> fn(&'a i32)` = note: ...but `Foo` is actually implemented for the type `fn(&'0 i32)`, for some specific lifetime `'0` error: aborting due to previous error diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-71955.stderr b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-71955.stderr index eebce827d1cae..4ef96cd954106 100644 --- a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-71955.stderr +++ b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-71955.stderr @@ -4,8 +4,8 @@ error[E0308]: mismatched types LL | foo(bar, "string", |s| s.len() == 5); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other | - = note: expected trait `for<'r, 's> FnOnce<(&'r &'s str,)>` - found trait `for<'r> FnOnce<(&'r &str,)>` + = note: expected trait `for<'a, 'b> FnOnce<(&'a &'b str,)>` + found trait `for<'a> FnOnce<(&'a &str,)>` note: this closure does not fulfill the lifetime requirements --> $DIR/issue-71955.rs:45:24 | @@ -23,8 +23,8 @@ error[E0308]: mismatched types LL | foo(bar, "string", |s| s.len() == 5); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other | - = note: expected trait `for<'r, 's> FnOnce<(&'r &'s str,)>` - found trait `for<'r> FnOnce<(&'r &str,)>` + = note: expected trait `for<'a, 'b> FnOnce<(&'a &'b str,)>` + found trait `for<'a> FnOnce<(&'a &str,)>` note: this closure does not fulfill the lifetime requirements --> $DIR/issue-71955.rs:45:24 | @@ -42,8 +42,8 @@ error[E0308]: mismatched types LL | foo(baz, "string", |s| s.0.len() == 5); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other | - = note: expected trait `for<'r, 's> FnOnce<(&'r Wrapper<'s>,)>` - found trait `for<'r> FnOnce<(&'r Wrapper<'_>,)>` + = note: expected trait `for<'a, 'b> FnOnce<(&'a Wrapper<'b>,)>` + found trait `for<'a> FnOnce<(&'a Wrapper<'_>,)>` note: this closure does not fulfill the lifetime requirements --> $DIR/issue-71955.rs:48:24 | @@ -61,8 +61,8 @@ error[E0308]: mismatched types LL | foo(baz, "string", |s| s.0.len() == 5); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other | - = note: expected trait `for<'r, 's> FnOnce<(&'r Wrapper<'s>,)>` - found trait `for<'r> FnOnce<(&'r Wrapper<'_>,)>` + = note: expected trait `for<'a, 'b> FnOnce<(&'a Wrapper<'b>,)>` + found trait `for<'a> FnOnce<(&'a Wrapper<'_>,)>` note: this closure does not fulfill the lifetime requirements --> $DIR/issue-71955.rs:48:24 | diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-85455.rs b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-85455.rs index de9348f539709..c10a0888a4f27 100644 --- a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-85455.rs +++ b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-85455.rs @@ -6,7 +6,7 @@ trait SomeTrait<'a> { fn give_me_ice() { callee:: >::Associated>(); - //~^ ERROR the trait bound `for<'r> T: SomeTrait<'r>` is not satisfied [E0277] + //~^ ERROR the trait bound `for<'a> T: SomeTrait<'a>` is not satisfied [E0277] } fn callee>() { diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-85455.stderr b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-85455.stderr index 6a948a116e03b..25a4f6088deba 100644 --- a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-85455.stderr +++ b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-85455.stderr @@ -1,12 +1,12 @@ -error[E0277]: the trait bound `for<'r> T: SomeTrait<'r>` is not satisfied +error[E0277]: the trait bound `for<'a> T: SomeTrait<'a>` is not satisfied --> $DIR/issue-85455.rs:8:5 | LL | callee:: >::Associated>(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'r> SomeTrait<'r>` is not implemented for `T` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> SomeTrait<'a>` is not implemented for `T` | help: consider restricting type parameter `T` | -LL | fn give_me_ice SomeTrait<'r>>() { +LL | fn give_me_ice SomeTrait<'a>>() { | +++++++++++++++++++++++ error: aborting due to previous error diff --git a/src/test/ui/hygiene/impl_items.rs b/src/test/ui/hygiene/impl_items.rs index 37794c6e0773c..ddb25c06b1b17 100644 --- a/src/test/ui/hygiene/impl_items.rs +++ b/src/test/ui/hygiene/impl_items.rs @@ -9,7 +9,7 @@ mod foo { } pub macro m() { - let _: () = S.f(); //~ ERROR type `for<'r> fn(&'r foo::S) {foo::S::f}` is private + let _: () = S.f(); //~ ERROR type `for<'a> fn(&'a foo::S) {foo::S::f}` is private } } diff --git a/src/test/ui/hygiene/impl_items.stderr b/src/test/ui/hygiene/impl_items.stderr index 523309f432504..46a2500386e0f 100644 --- a/src/test/ui/hygiene/impl_items.stderr +++ b/src/test/ui/hygiene/impl_items.stderr @@ -1,4 +1,4 @@ -error: type `for<'r> fn(&'r foo::S) {foo::S::f}` is private +error: type `for<'a> fn(&'a foo::S) {foo::S::f}` is private --> $DIR/impl_items.rs:12:23 | LL | let _: () = S.f(); diff --git a/src/test/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.edition2015.stderr b/src/test/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.edition2015.stderr index fd2e454e7e455..edf3911e2a097 100644 --- a/src/test/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.edition2015.stderr +++ b/src/test/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.edition2015.stderr @@ -1,8 +1,8 @@ -error[E0277]: the trait bound `(): AsRef<(dyn for<'r> Fn(&'r ()) + 'static)>` is not satisfied +error[E0277]: the trait bound `(): AsRef<(dyn for<'a> Fn(&'a ()) + 'static)>` is not satisfied --> $DIR/generic-with-implicit-hrtb-without-dyn.rs:6:13 | LL | fn ice() -> impl AsRef { - | ^^^^^^^^^^^^^^^^^^^ the trait `AsRef<(dyn for<'r> Fn(&'r ()) + 'static)>` is not implemented for `()` + | ^^^^^^^^^^^^^^^^^^^ the trait `AsRef<(dyn for<'a> Fn(&'a ()) + 'static)>` is not implemented for `()` error: aborting due to previous error diff --git a/src/test/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.edition2021.stderr b/src/test/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.edition2021.stderr index 8f40922732486..88e2520bf4b24 100644 --- a/src/test/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.edition2021.stderr +++ b/src/test/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.edition2021.stderr @@ -9,11 +9,11 @@ help: add `dyn` keyword before this trait LL | fn ice() -> impl AsRef { | +++ -error[E0277]: the trait bound `(): AsRef<(dyn for<'r> Fn(&'r ()) + 'static)>` is not satisfied +error[E0277]: the trait bound `(): AsRef<(dyn for<'a> Fn(&'a ()) + 'static)>` is not satisfied --> $DIR/generic-with-implicit-hrtb-without-dyn.rs:6:13 | LL | fn ice() -> impl AsRef { - | ^^^^^^^^^^^^^^^^^^^ the trait `AsRef<(dyn for<'r> Fn(&'r ()) + 'static)>` is not implemented for `()` + | ^^^^^^^^^^^^^^^^^^^ the trait `AsRef<(dyn for<'a> Fn(&'a ()) + 'static)>` is not implemented for `()` error: aborting due to 2 previous errors diff --git a/src/test/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.rs b/src/test/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.rs index 856dc7a3f5a22..5a922697f6ff9 100644 --- a/src/test/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.rs +++ b/src/test/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.rs @@ -4,7 +4,7 @@ #![allow(warnings)] fn ice() -> impl AsRef { - //~^ ERROR: the trait bound `(): AsRef<(dyn for<'r> Fn(&'r ()) + 'static)>` is not satisfied [E0277] + //~^ ERROR: the trait bound `(): AsRef<(dyn for<'a> Fn(&'a ()) + 'static)>` is not satisfied [E0277] //[edition2021]~| ERROR: trait objects must include the `dyn` keyword [E0782] todo!() } diff --git a/src/test/ui/issues/issue-18919.stderr b/src/test/ui/issues/issue-18919.stderr index d7dbb8299b9ef..b0b03a0eea69e 100644 --- a/src/test/ui/issues/issue-18919.stderr +++ b/src/test/ui/issues/issue-18919.stderr @@ -1,10 +1,10 @@ -error[E0277]: the size for values of type `dyn for<'r> Fn(&'r isize) -> isize` cannot be known at compilation time +error[E0277]: the size for values of type `dyn for<'a> Fn(&'a isize) -> isize` cannot be known at compilation time --> $DIR/issue-18919.rs:3:15 | LL | fn ho_func(f: Option) { | ^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | - = help: the trait `Sized` is not implemented for `dyn for<'r> Fn(&'r isize) -> isize` + = help: the trait `Sized` is not implemented for `dyn for<'a> Fn(&'a isize) -> isize` note: required by a bound in `Option` --> $DIR/issue-18919.rs:7:13 | diff --git a/src/test/ui/issues/issue-24322.stderr b/src/test/ui/issues/issue-24322.stderr index 1a4fab165405d..1e4c8ac7c356c 100644 --- a/src/test/ui/issues/issue-24322.stderr +++ b/src/test/ui/issues/issue-24322.stderr @@ -6,8 +6,8 @@ LL | let x: &fn(&B) -> u32 = &B::func; | | | expected due to this | - = note: expected reference `&for<'r> fn(&'r B) -> u32` - found reference `&for<'r> fn(&'r B) -> u32 {B::func}` + = note: expected reference `&for<'a> fn(&'a B) -> u32` + found reference `&for<'a> fn(&'a B) -> u32 {B::func}` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-40000.stderr b/src/test/ui/issues/issue-40000.stderr index e6f0b5fbfba1d..c41fbb9d2ec1d 100644 --- a/src/test/ui/issues/issue-40000.stderr +++ b/src/test/ui/issues/issue-40000.stderr @@ -4,7 +4,7 @@ error[E0308]: mismatched types LL | foo(bar); | ^^^ one type is more general than the other | - = note: expected trait object `dyn for<'r> Fn(&'r i32)` + = note: expected trait object `dyn for<'a> Fn(&'a i32)` found trait object `dyn Fn(&i32)` error[E0308]: mismatched types @@ -13,7 +13,7 @@ error[E0308]: mismatched types LL | foo(bar); | ^^^ one type is more general than the other | - = note: expected trait object `dyn for<'r> Fn(&'r i32)` + = note: expected trait object `dyn for<'a> Fn(&'a i32)` found trait object `dyn Fn(&i32)` error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-57362-2.stderr b/src/test/ui/issues/issue-57362-2.stderr index 3b6cffeafe4c2..7d08c4643ff2f 100644 --- a/src/test/ui/issues/issue-57362-2.stderr +++ b/src/test/ui/issues/issue-57362-2.stderr @@ -1,11 +1,11 @@ -error[E0599]: the function or associated item `make_g` exists for fn pointer `for<'r> fn(&'r ())`, but its trait bounds were not satisfied +error[E0599]: the function or associated item `make_g` exists for fn pointer `for<'a> fn(&'a ())`, but its trait bounds were not satisfied --> $DIR/issue-57362-2.rs:22:25 | LL | let x = ::make_g(); - | ^^^^^^ function or associated item cannot be called on `for<'r> fn(&'r ())` due to unsatisfied trait bounds + | ^^^^^^ function or associated item cannot be called on `for<'a> fn(&'a ())` due to unsatisfied trait bounds | = note: the following trait bounds were not satisfied: - `for<'r> fn(&'r ()): X` + `for<'a> fn(&'a ()): X` = help: items from traits can only be used if the trait is implemented and in scope note: `X` defines an item `make_g`, perhaps you need to implement it --> $DIR/issue-57362-2.rs:8:1 diff --git a/src/test/ui/lifetimes/issue-79187-2.stderr b/src/test/ui/lifetimes/issue-79187-2.stderr index 9322e617176a1..c5f654b37bf6f 100644 --- a/src/test/ui/lifetimes/issue-79187-2.stderr +++ b/src/test/ui/lifetimes/issue-79187-2.stderr @@ -31,7 +31,7 @@ error[E0308]: mismatched types LL | take_foo(|a| a); | ^^^^^^^^^^^^^^^ one type is more general than the other | - = note: expected trait `for<'r> Fn<(&'r i32,)>` + = note: expected trait `for<'a> Fn<(&'a i32,)>` found trait `Fn<(&i32,)>` note: this closure does not fulfill the lifetime requirements --> $DIR/issue-79187-2.rs:8:14 diff --git a/src/test/ui/lifetimes/issue-79187.stderr b/src/test/ui/lifetimes/issue-79187.stderr index 3e75e7fed2cc1..ee6e7b89d5f0e 100644 --- a/src/test/ui/lifetimes/issue-79187.stderr +++ b/src/test/ui/lifetimes/issue-79187.stderr @@ -4,7 +4,7 @@ error[E0308]: mismatched types LL | thing(f); | ^^^^^^^^ one type is more general than the other | - = note: expected trait `for<'r> FnOnce<(&'r u32,)>` + = note: expected trait `for<'a> FnOnce<(&'a u32,)>` found trait `FnOnce<(&u32,)>` note: this closure does not fulfill the lifetime requirements --> $DIR/issue-79187.rs:4:13 diff --git a/src/test/ui/lifetimes/lifetime-errors/issue_74400.stderr b/src/test/ui/lifetimes/lifetime-errors/issue_74400.stderr index d82b2684cce58..7049f28e2f6eb 100644 --- a/src/test/ui/lifetimes/lifetime-errors/issue_74400.stderr +++ b/src/test/ui/lifetimes/lifetime-errors/issue_74400.stderr @@ -15,7 +15,7 @@ error[E0308]: mismatched types LL | f(data, identity) | ^^^^^^^^^^^^^^^^^ one type is more general than the other | - = note: expected trait `for<'r> Fn<(&'r T,)>` + = note: expected trait `for<'a> Fn<(&'a T,)>` found trait `Fn<(&T,)>` note: the lifetime requirement is introduced here --> $DIR/issue_74400.rs:8:34 diff --git a/src/test/ui/lifetimes/re-empty-in-error.stderr b/src/test/ui/lifetimes/re-empty-in-error.stderr index 72bb0782f4b4f..840707d947081 100644 --- a/src/test/ui/lifetimes/re-empty-in-error.stderr +++ b/src/test/ui/lifetimes/re-empty-in-error.stderr @@ -4,7 +4,7 @@ error: higher-ranked lifetime error LL | foo(&10); | ^^^^^^^^ | - = note: could not prove `for<'b, 'r> &'b (): 'r` + = note: could not prove `for<'b, 'a> &'b (): 'a` error: aborting due to previous error diff --git a/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr b/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr index 71469bfec2d39..92d545b7366e3 100644 --- a/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr +++ b/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr @@ -23,7 +23,7 @@ LL | a.iter().map(|_: &(u16, u16)| 45); | expected due to this | = note: expected closure signature `fn(&(u32, u32)) -> _` - found closure signature `for<'r> fn(&'r (u16, u16)) -> _` + found closure signature `for<'a> fn(&'a (u16, u16)) -> _` note: required by a bound in `map` --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL | diff --git a/src/test/ui/mismatched_types/closure-mismatch.stderr b/src/test/ui/mismatched_types/closure-mismatch.stderr index ef76ec63fdaf8..a7ef8fa08923f 100644 --- a/src/test/ui/mismatched_types/closure-mismatch.stderr +++ b/src/test/ui/mismatched_types/closure-mismatch.stderr @@ -13,7 +13,7 @@ error[E0308]: mismatched types LL | baz(|_| ()); | ^^^^^^^^^^^ one type is more general than the other | - = note: expected trait `for<'r> Fn<(&'r (),)>` + = note: expected trait `for<'a> Fn<(&'a (),)>` found trait `Fn<(&(),)>` note: this closure does not fulfill the lifetime requirements --> $DIR/closure-mismatch.rs:8:9 diff --git a/src/test/ui/mismatched_types/fn-variance-1.stderr b/src/test/ui/mismatched_types/fn-variance-1.stderr index eec6d83fe223c..5794e606eeb93 100644 --- a/src/test/ui/mismatched_types/fn-variance-1.stderr +++ b/src/test/ui/mismatched_types/fn-variance-1.stderr @@ -10,7 +10,7 @@ LL | apply(&3, takes_mut); | required by a bound introduced by this call | = note: expected function signature `fn(&{integer}) -> _` - found function signature `for<'r> fn(&'r mut isize) -> _` + found function signature `for<'a> fn(&'a mut isize) -> _` note: required by a bound in `apply` --> $DIR/fn-variance-1.rs:5:37 | @@ -29,7 +29,7 @@ LL | apply(&mut 3, takes_imm); | required by a bound introduced by this call | = note: expected function signature `fn(&mut {integer}) -> _` - found function signature `for<'r> fn(&'r isize) -> _` + found function signature `for<'a> fn(&'a isize) -> _` note: required by a bound in `apply` --> $DIR/fn-variance-1.rs:5:37 | diff --git a/src/test/ui/mismatched_types/issue-36053-2.stderr b/src/test/ui/mismatched_types/issue-36053-2.stderr index b11ea97d160be..906001ca1e09e 100644 --- a/src/test/ui/mismatched_types/issue-36053-2.stderr +++ b/src/test/ui/mismatched_types/issue-36053-2.stderr @@ -6,8 +6,8 @@ LL | once::<&str>("str").fuse().filter(|a: &str| true).count(); | | | expected due to this | - = note: expected closure signature `for<'r> fn(&'r &str) -> _` - found closure signature `for<'r> fn(&'r str) -> _` + = note: expected closure signature `for<'a> fn(&'a &str) -> _` + found closure signature `for<'a> fn(&'a str) -> _` note: required by a bound in `filter` --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL | diff --git a/src/test/ui/nll/closure-requirements/escape-argument-callee.stderr b/src/test/ui/nll/closure-requirements/escape-argument-callee.stderr index 66c99bcdfed0c..d2d26b23d646e 100644 --- a/src/test/ui/nll/closure-requirements/escape-argument-callee.stderr +++ b/src/test/ui/nll/closure-requirements/escape-argument-callee.stderr @@ -6,7 +6,7 @@ LL | let mut closure = expect_sig(|p, y| *p = y); | = note: defining type: test::{closure#0} with closure substs [ i16, - for<'r, 's, 't> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) mut &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) i32, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrNamed('t) }) i32)), + for<'a, 'b, 'c> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('a) }) mut &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('b) }) i32, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrNamed('c) }) i32)), (), ] diff --git a/src/test/ui/nll/closure-requirements/escape-argument.stderr b/src/test/ui/nll/closure-requirements/escape-argument.stderr index ff4e8e590e5a6..6355d3295247f 100644 --- a/src/test/ui/nll/closure-requirements/escape-argument.stderr +++ b/src/test/ui/nll/closure-requirements/escape-argument.stderr @@ -6,7 +6,7 @@ LL | let mut closure = expect_sig(|p, y| *p = y); | = note: defining type: test::{closure#0} with closure substs [ i16, - for<'r, 's> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) mut &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) i32, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) i32)), + for<'a, 'b> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('a) }) mut &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('b) }) i32, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('b) }) i32)), (), ] diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr index 0d94fca2823e5..5f9724ce3db19 100644 --- a/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr @@ -6,7 +6,7 @@ LL | |_outlives1, _outlives2, _outlives3, x, y| { | = note: defining type: supply::{closure#0} with closure substs [ i16, - for<'r, 's> extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) u32>, std::cell::Cell<&'_#2r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) &'_#3r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) u32>)), + for<'a, 'b> extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('a) }) u32>, std::cell::Cell<&'_#2r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('a) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('b) }) &'_#3r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('a) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('b) }) u32>)), (), ] = note: late-bound region is '_#4r diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-ref.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-ref.stderr index ca4c1a1ee7e76..ec728ebd5adf5 100644 --- a/src/test/ui/nll/closure-requirements/propagate-approximated-ref.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-approximated-ref.stderr @@ -6,7 +6,7 @@ LL | establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y | = note: defining type: supply::{closure#0} with closure substs [ i16, - for<'r, 's, 't, 't0, 't1, 't2> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrNamed('t) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrNamed('t0) }) &'_#2r u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrNamed('t1) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 5, kind: BrNamed('t2) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrNamed('t0) }) u32>)), + for<'a, 'b, 'c, 'd, 'e, 'f> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('a) }) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('b) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrNamed('c) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrNamed('d) }) &'_#2r u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrNamed('e) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('b) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 5, kind: BrNamed('f) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrNamed('d) }) u32>)), (), ] = note: late-bound region is '_#3r diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr index 6aafbe42c496c..01293379700d2 100644 --- a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr @@ -6,7 +6,7 @@ LL | foo(cell, |cell_a, cell_x| { | = note: defining type: case1::{closure#0} with closure substs [ i32, - for<'r> extern "rust-call" fn((std::cell::Cell<&'_#1r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) u32>)), + for<'a> extern "rust-call" fn((std::cell::Cell<&'_#1r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('a) }) u32>)), (), ] @@ -36,7 +36,7 @@ LL | foo(cell, |cell_a, cell_x| { | = note: defining type: case2::{closure#0} with closure substs [ i32, - for<'r> extern "rust-call" fn((std::cell::Cell<&'_#1r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) u32>)), + for<'a> extern "rust-call" fn((std::cell::Cell<&'_#1r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('a) }) u32>)), (), ] = note: number of external vids: 2 diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr index 42404412bf990..ce85b20b344e2 100644 --- a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr @@ -6,7 +6,7 @@ LL | establish_relationships(&cell_a, &cell_b, |_outlives, x, y| { | = note: defining type: supply::{closure#0} with closure substs [ i16, - for<'r, 's, 't, 't0, 't1> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrNamed('t) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrNamed('t0) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrNamed('t1) }) u32>)), + for<'a, 'b, 'c, 'd, 'e> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('a) }) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('b) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrNamed('c) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('b) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrNamed('d) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrNamed('e) }) u32>)), (), ] = note: late-bound region is '_#2r diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr index c74430ea3fc2b..20c7967b78bc9 100644 --- a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr @@ -6,7 +6,7 @@ LL | establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y | = note: defining type: supply::{closure#0} with closure substs [ i16, - for<'r, 's, 't, 't0, 't1, 't2> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrNamed('t) }) std::cell::Cell<&'_#2r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrNamed('t0) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrNamed('t1) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 5, kind: BrNamed('t2) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrNamed('t0) }) u32>)), + for<'a, 'b, 'c, 'd, 'e, 'f> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('a) }) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('b) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrNamed('c) }) std::cell::Cell<&'_#2r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrNamed('d) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrNamed('e) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('b) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 5, kind: BrNamed('f) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrNamed('d) }) u32>)), (), ] = note: late-bound region is '_#3r diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-val.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-val.stderr index be5f1e5ef1a68..f7db5ab1f27a0 100644 --- a/src/test/ui/nll/closure-requirements/propagate-approximated-val.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-approximated-val.stderr @@ -6,7 +6,7 @@ LL | establish_relationships(cell_a, cell_b, |outlives1, outlives2, x, y| { | = note: defining type: test::{closure#0} with closure substs [ i16, - for<'r, 's> extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) &'_#2r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) u32>)), + for<'a, 'b> extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('a) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('b) }) &'_#2r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('a) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('b) }) u32>)), (), ] = note: late-bound region is '_#3r diff --git a/src/test/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr b/src/test/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr index d18db97be5789..3488edc75e102 100644 --- a/src/test/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr @@ -6,7 +6,7 @@ LL | |_outlives1, _outlives2, x, y| { | = note: defining type: supply::{closure#0} with closure substs [ i16, - for<'r, 's> extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) &'_#2r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) u32>)), + for<'a, 'b> extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('a) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('b) }) &'_#2r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('a) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('b) }) u32>)), (), ] = note: late-bound region is '_#3r diff --git a/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr index 1e161757222f2..0dc2d0de98fe7 100644 --- a/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr @@ -6,7 +6,7 @@ LL | establish_relationships(&cell_a, &cell_b, |_outlives, x, y| { | = note: defining type: supply::{closure#0} with closure substs [ i16, - for<'r, 's, 't, 't0, 't1> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) &'_#1r u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrNamed('t) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrNamed('t0) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrNamed('t1) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) u32>)), + for<'a, 'b, 'c, 'd, 'e> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('a) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('b) }) &'_#1r u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrNamed('c) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrNamed('d) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrNamed('e) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('b) }) u32>)), (), ] = note: late-bound region is '_#2r diff --git a/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr index 622113a875bd6..4c9e026ea522c 100644 --- a/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr @@ -6,7 +6,7 @@ LL | establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y | = note: defining type: supply::{closure#0} with closure substs [ i16, - for<'r, 's, 't, 't0, 't1, 't2> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) &'_#1r u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrNamed('t) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrNamed('t0) }) &'_#2r u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrNamed('t1) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 5, kind: BrNamed('t2) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrNamed('t0) }) u32>)), + for<'a, 'b, 'c, 'd, 'e, 'f> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('a) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('b) }) &'_#1r u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrNamed('c) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrNamed('d) }) &'_#2r u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrNamed('e) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('b) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 5, kind: BrNamed('f) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrNamed('d) }) u32>)), (), ] = note: late-bound region is '_#3r diff --git a/src/test/ui/nll/closure-requirements/return-wrong-bound-region.stderr b/src/test/ui/nll/closure-requirements/return-wrong-bound-region.stderr index da89071eabda9..68429142edecd 100644 --- a/src/test/ui/nll/closure-requirements/return-wrong-bound-region.stderr +++ b/src/test/ui/nll/closure-requirements/return-wrong-bound-region.stderr @@ -6,7 +6,7 @@ LL | expect_sig(|a, b| b); // ought to return `a` | = note: defining type: test::{closure#0} with closure substs [ i16, - for<'r, 's> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) i32, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) i32)) -> &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) i32, + for<'a, 'b> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('a) }) i32, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('b) }) i32)) -> &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('a) }) i32, (), ] diff --git a/src/test/ui/nll/issue-57642-higher-ranked-subtype.stderr b/src/test/ui/nll/issue-57642-higher-ranked-subtype.stderr index 0ae6b7c1d7f06..6e96f40c0e0d8 100644 --- a/src/test/ui/nll/issue-57642-higher-ranked-subtype.stderr +++ b/src/test/ui/nll/issue-57642-higher-ranked-subtype.stderr @@ -1,11 +1,11 @@ -error[E0599]: the function or associated item `make_g` exists for fn pointer `for<'r> fn(&'r ())`, but its trait bounds were not satisfied +error[E0599]: the function or associated item `make_g` exists for fn pointer `for<'a> fn(&'a ())`, but its trait bounds were not satisfied --> $DIR/issue-57642-higher-ranked-subtype.rs:31:25 | LL | let x = ::make_g(); - | ^^^^^^ function or associated item cannot be called on `for<'r> fn(&'r ())` due to unsatisfied trait bounds + | ^^^^^^ function or associated item cannot be called on `for<'a> fn(&'a ())` due to unsatisfied trait bounds | = note: the following trait bounds were not satisfied: - `for<'r> fn(&'r ()): X` + `for<'a> fn(&'a ()): X` = help: items from traits can only be used if the trait is implemented and in scope note: `X` defines an item `make_g`, perhaps you need to implement it --> $DIR/issue-57642-higher-ranked-subtype.rs:4:1 @@ -13,11 +13,11 @@ note: `X` defines an item `make_g`, perhaps you need to implement it LL | trait X { | ^^^^^^^ -error[E0599]: no function or associated item named `make_f` found for fn pointer `for<'r> fn(&'r ())` in the current scope +error[E0599]: no function or associated item named `make_f` found for fn pointer `for<'a> fn(&'a ())` in the current scope --> $DIR/issue-57642-higher-ranked-subtype.rs:35:25 | LL | let x = ::make_f(); - | ^^^^^^ function or associated item not found in `for<'r> fn(&'r ())` + | ^^^^^^ function or associated item not found in `for<'a> fn(&'a ())` | = help: items from traits can only be used if the trait is implemented and in scope note: `Y` defines an item `make_f`, perhaps you need to implement it diff --git a/src/test/ui/nll/issue-97997.stderr b/src/test/ui/nll/issue-97997.stderr index 78401bbf6540a..46440c021f543 100644 --- a/src/test/ui/nll/issue-97997.stderr +++ b/src/test/ui/nll/issue-97997.stderr @@ -4,7 +4,7 @@ error: implementation of `Foo` is not general enough LL | ::ASSOC; | ^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough | - = note: `Foo` would have to be implemented for the type `for<'r> fn(&'r u8)` + = note: `Foo` would have to be implemented for the type `for<'a> fn(&'a u8)` = note: ...but `Foo` is actually implemented for the type `fn(&'0 u8)`, for some specific lifetime `'0` error: implementation of `Foo` is not general enough @@ -13,7 +13,7 @@ error: implementation of `Foo` is not general enough LL | ::ASSOC; | ^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough | - = note: `Foo` would have to be implemented for the type `for<'r> fn(&'r u8)` + = note: `Foo` would have to be implemented for the type `for<'a> fn(&'a u8)` = note: ...but `Foo` is actually implemented for the type `fn(&'0 u8)`, for some specific lifetime `'0` error: aborting due to 2 previous errors diff --git a/src/test/ui/nll/relate_tys/impl-fn-ignore-binder-via-bottom.stderr b/src/test/ui/nll/relate_tys/impl-fn-ignore-binder-via-bottom.stderr index 8c47379886d2a..b945ffedda5ae 100644 --- a/src/test/ui/nll/relate_tys/impl-fn-ignore-binder-via-bottom.stderr +++ b/src/test/ui/nll/relate_tys/impl-fn-ignore-binder-via-bottom.stderr @@ -4,7 +4,7 @@ error: implementation of `Y` is not general enough LL | let _x = ::make_f(); | ^^^^^^^^^^^^^^^^^^^ implementation of `Y` is not general enough | - = note: `Y` would have to be implemented for the type `for<'r> fn(&'r ())` + = note: `Y` would have to be implemented for the type `for<'a> fn(&'a ())` = note: ...but `Y` is actually implemented for the type `fn(&'0 ())`, for some specific lifetime `'0` error: implementation of `Y` is not general enough @@ -13,7 +13,7 @@ error: implementation of `Y` is not general enough LL | let _x = ::make_f(); | ^^^^^^^^^^^^^^^^^^^ implementation of `Y` is not general enough | - = note: `Y` would have to be implemented for the type `for<'r> fn(&'r ())` + = note: `Y` would have to be implemented for the type `for<'a> fn(&'a ())` = note: ...but `Y` is actually implemented for the type `fn(&'0 ())`, for some specific lifetime `'0` error: implementation of `Y` is not general enough @@ -22,7 +22,7 @@ error: implementation of `Y` is not general enough LL | let _x = ::make_f(); | ^^^^^^^^^^^^^^^^^^^ implementation of `Y` is not general enough | - = note: `Y` would have to be implemented for the type `for<'r> fn(&'r ())` + = note: `Y` would have to be implemented for the type `for<'a> fn(&'a ())` = note: ...but `Y` is actually implemented for the type `fn(&'0 ())`, for some specific lifetime `'0` error: aborting due to 3 previous errors diff --git a/src/test/ui/nll/relate_tys/universe-violation.stderr b/src/test/ui/nll/relate_tys/universe-violation.stderr index 6f38154e37927..fe801b42c0a49 100644 --- a/src/test/ui/nll/relate_tys/universe-violation.stderr +++ b/src/test/ui/nll/relate_tys/universe-violation.stderr @@ -4,7 +4,7 @@ error[E0308]: mismatched types LL | let b: fn(&u32) -> &u32 = a; | ^ one type is more general than the other | - = note: expected fn pointer `for<'r> fn(&'r u32) -> &'r u32` + = note: expected fn pointer `for<'a> fn(&'a u32) -> &'a u32` found fn pointer `fn(&u32) -> &u32` error: aborting due to previous error diff --git a/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr b/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr index 5d9a044d107f9..61c7d2550caad 100644 --- a/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr +++ b/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr @@ -6,7 +6,7 @@ LL | twice(cell, value, |a, b| invoke(a, b)); | = note: defining type: generic::::{closure#0} with closure substs [ i16, - for<'r, 's> extern "rust-call" fn((std::option::Option>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) T)), + for<'a, 'b> extern "rust-call" fn((std::option::Option>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('b) }) T)), (), ] = note: number of external vids: 2 @@ -28,7 +28,7 @@ LL | twice(cell, value, |a, b| invoke(a, b)); | = note: defining type: generic_fail::::{closure#0} with closure substs [ i16, - for<'r, 's> extern "rust-call" fn((std::option::Option>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) T)), + for<'a, 'b> extern "rust-call" fn((std::option::Option>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('b) }) T)), (), ] = note: late-bound region is '_#2r diff --git a/src/test/ui/privacy/associated-item-privacy-inherent.rs b/src/test/ui/privacy/associated-item-privacy-inherent.rs index c3ae920238f18..7b7c734a99a1c 100644 --- a/src/test/ui/privacy/associated-item-privacy-inherent.rs +++ b/src/test/ui/privacy/associated-item-privacy-inherent.rs @@ -11,11 +11,11 @@ mod priv_nominal { pub macro mac() { let value = Pub::method; - //~^ ERROR type `for<'r> fn(&'r priv_nominal::Pub) {priv_nominal::Pub::method}` is private + //~^ ERROR type `for<'a> fn(&'a priv_nominal::Pub) {priv_nominal::Pub::method}` is private value; - //~^ ERROR type `for<'r> fn(&'r priv_nominal::Pub) {priv_nominal::Pub::method}` is private + //~^ ERROR type `for<'a> fn(&'a priv_nominal::Pub) {priv_nominal::Pub::method}` is private Pub.method(); - //~^ ERROR type `for<'r> fn(&'r priv_nominal::Pub) {priv_nominal::Pub::method}` is private + //~^ ERROR type `for<'a> fn(&'a priv_nominal::Pub) {priv_nominal::Pub::method}` is private Pub::CONST; //~^ ERROR associated constant `CONST` is private // let _: Pub::AssocTy; diff --git a/src/test/ui/privacy/associated-item-privacy-inherent.stderr b/src/test/ui/privacy/associated-item-privacy-inherent.stderr index 4478e5c2aba57..f4d4ee459204d 100644 --- a/src/test/ui/privacy/associated-item-privacy-inherent.stderr +++ b/src/test/ui/privacy/associated-item-privacy-inherent.stderr @@ -1,4 +1,4 @@ -error: type `for<'r> fn(&'r priv_nominal::Pub) {priv_nominal::Pub::method}` is private +error: type `for<'a> fn(&'a priv_nominal::Pub) {priv_nominal::Pub::method}` is private --> $DIR/associated-item-privacy-inherent.rs:13:21 | LL | let value = Pub::method; @@ -9,7 +9,7 @@ LL | priv_nominal::mac!(); | = note: this error originates in the macro `priv_nominal::mac` (in Nightly builds, run with -Z macro-backtrace for more info) -error: type `for<'r> fn(&'r priv_nominal::Pub) {priv_nominal::Pub::method}` is private +error: type `for<'a> fn(&'a priv_nominal::Pub) {priv_nominal::Pub::method}` is private --> $DIR/associated-item-privacy-inherent.rs:15:9 | LL | value; @@ -20,7 +20,7 @@ LL | priv_nominal::mac!(); | = note: this error originates in the macro `priv_nominal::mac` (in Nightly builds, run with -Z macro-backtrace for more info) -error: type `for<'r> fn(&'r priv_nominal::Pub) {priv_nominal::Pub::method}` is private +error: type `for<'a> fn(&'a priv_nominal::Pub) {priv_nominal::Pub::method}` is private --> $DIR/associated-item-privacy-inherent.rs:17:13 | LL | Pub.method(); diff --git a/src/test/ui/privacy/associated-item-privacy-trait.rs b/src/test/ui/privacy/associated-item-privacy-trait.rs index c07aeed99c74a..ad9a5e15c4e6e 100644 --- a/src/test/ui/privacy/associated-item-privacy-trait.rs +++ b/src/test/ui/privacy/associated-item-privacy-trait.rs @@ -13,11 +13,11 @@ mod priv_trait { pub macro mac() { let value = ::method; - //~^ ERROR type `for<'r> fn(&'r priv_trait::Pub) {::method}` is private + //~^ ERROR type `for<'a> fn(&'a priv_trait::Pub) {::method}` is private value; - //~^ ERROR type `for<'r> fn(&'r priv_trait::Pub) {::method}` is private + //~^ ERROR type `for<'a> fn(&'a priv_trait::Pub) {::method}` is private Pub.method(); - //~^ ERROR type `for<'r> fn(&'r Self) {::method}` is private + //~^ ERROR type `for<'a> fn(&'a Self) {::method}` is private ::CONST; //~^ ERROR associated constant `::CONST` is private let _: ::AssocTy; diff --git a/src/test/ui/privacy/associated-item-privacy-trait.stderr b/src/test/ui/privacy/associated-item-privacy-trait.stderr index 6095f5f42b86d..c4be1a9d9a202 100644 --- a/src/test/ui/privacy/associated-item-privacy-trait.stderr +++ b/src/test/ui/privacy/associated-item-privacy-trait.stderr @@ -1,4 +1,4 @@ -error: type `for<'r> fn(&'r priv_trait::Pub) {::method}` is private +error: type `for<'a> fn(&'a priv_trait::Pub) {::method}` is private --> $DIR/associated-item-privacy-trait.rs:15:21 | LL | let value = ::method; @@ -9,7 +9,7 @@ LL | priv_trait::mac!(); | = note: this error originates in the macro `priv_trait::mac` (in Nightly builds, run with -Z macro-backtrace for more info) -error: type `for<'r> fn(&'r priv_trait::Pub) {::method}` is private +error: type `for<'a> fn(&'a priv_trait::Pub) {::method}` is private --> $DIR/associated-item-privacy-trait.rs:17:9 | LL | value; @@ -20,7 +20,7 @@ LL | priv_trait::mac!(); | = note: this error originates in the macro `priv_trait::mac` (in Nightly builds, run with -Z macro-backtrace for more info) -error: type `for<'r> fn(&'r Self) {::method}` is private +error: type `for<'a> fn(&'a Self) {::method}` is private --> $DIR/associated-item-privacy-trait.rs:19:13 | LL | Pub.method(); diff --git a/src/test/ui/privacy/private-inferred-type-3.rs b/src/test/ui/privacy/private-inferred-type-3.rs index 00f0a715a836d..0337aedd00881 100644 --- a/src/test/ui/privacy/private-inferred-type-3.rs +++ b/src/test/ui/privacy/private-inferred-type-3.rs @@ -6,7 +6,7 @@ // error-pattern:type `fn() {::method}` is private // error-pattern:type `fn(u8) -> ext::PrivTupleStruct {ext::PrivTupleStruct}` is private // error-pattern:type `fn(u8) -> PubTupleStruct {PubTupleStruct}` is private -// error-pattern:type `for<'r> fn(&'r Pub) {Pub::::priv_method}` is private +// error-pattern:type `for<'a> fn(&'a Pub) {Pub::::priv_method}` is private #![feature(decl_macro)] diff --git a/src/test/ui/privacy/private-inferred-type-3.stderr b/src/test/ui/privacy/private-inferred-type-3.stderr index f9dd1c3d03509..00b61512de6b4 100644 --- a/src/test/ui/privacy/private-inferred-type-3.stderr +++ b/src/test/ui/privacy/private-inferred-type-3.stderr @@ -46,7 +46,7 @@ LL | ext::m!(); | = note: this error originates in the macro `ext::m` (in Nightly builds, run with -Z macro-backtrace for more info) -error: type `for<'r> fn(&'r Pub) {Pub::::priv_method}` is private +error: type `for<'a> fn(&'a Pub) {Pub::::priv_method}` is private --> $DIR/private-inferred-type-3.rs:16:5 | LL | ext::m!(); diff --git a/src/test/ui/privacy/private-inferred-type.rs b/src/test/ui/privacy/private-inferred-type.rs index b083a3970d6b9..e8743dd968feb 100644 --- a/src/test/ui/privacy/private-inferred-type.rs +++ b/src/test/ui/privacy/private-inferred-type.rs @@ -47,7 +47,7 @@ mod m { PubTupleStruct; //~^ ERROR type `fn(u8) -> PubTupleStruct {PubTupleStruct}` is private Pub(0u8).priv_method(); - //~^ ERROR type `for<'r> fn(&'r Pub) {Pub::::priv_method}` is private + //~^ ERROR type `for<'a> fn(&'a Pub) {Pub::::priv_method}` is private } trait Trait {} diff --git a/src/test/ui/privacy/private-inferred-type.stderr b/src/test/ui/privacy/private-inferred-type.stderr index aecd8b58c8311..fc3f9ab62bfa9 100644 --- a/src/test/ui/privacy/private-inferred-type.stderr +++ b/src/test/ui/privacy/private-inferred-type.stderr @@ -161,7 +161,7 @@ LL | m::m!(); | = note: this error originates in the macro `m::m` (in Nightly builds, run with -Z macro-backtrace for more info) -error: type `for<'r> fn(&'r Pub) {Pub::::priv_method}` is private +error: type `for<'a> fn(&'a Pub) {Pub::::priv_method}` is private --> $DIR/private-inferred-type.rs:49:18 | LL | Pub(0u8).priv_method(); diff --git a/src/test/ui/regions/issue-101280.stderr b/src/test/ui/regions/issue-101280.stderr index 3ce08966326d0..320d008aeff2f 100644 --- a/src/test/ui/regions/issue-101280.stderr +++ b/src/test/ui/regions/issue-101280.stderr @@ -7,7 +7,7 @@ LL | f | ^ one type is more general than the other | = note: expected fn pointer `for<'r> fn(Cell<(&'r i32, &'r i32)>)` - found fn pointer `for<'s> fn(Cell<(&'r i32, &'s i32)>)` + found fn pointer `for<'a> fn(Cell<(&'r i32, &'a i32)>)` error: aborting due to previous error diff --git a/src/test/ui/regions/region-lifetime-bounds-on-fns-where-clause.stderr b/src/test/ui/regions/region-lifetime-bounds-on-fns-where-clause.stderr index 20c0c9f4514d7..3b62c7b61c1b1 100644 --- a/src/test/ui/regions/region-lifetime-bounds-on-fns-where-clause.stderr +++ b/src/test/ui/regions/region-lifetime-bounds-on-fns-where-clause.stderr @@ -4,8 +4,8 @@ error[E0308]: mismatched types LL | let _: fn(&mut &isize, &mut &isize) = a; | ^ one type is more general than the other | - = note: expected fn pointer `for<'r, 's, 't, 't0> fn(&'r mut &'s isize, &'t mut &'t0 isize)` - found fn item `for<'r, 's> fn(&'r mut &isize, &'s mut &isize) {a::<'_, '_>}` + = note: expected fn pointer `for<'a, 'b, 'c, 'd> fn(&'a mut &'b isize, &'c mut &'d isize)` + found fn item `for<'a, 'b> fn(&'a mut &isize, &'b mut &isize) {a::<'_, '_>}` error: aborting due to previous error diff --git a/src/test/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.stderr b/src/test/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.stderr index 676b0904ebfa4..8a18a234b5c4e 100644 --- a/src/test/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.stderr +++ b/src/test/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.stderr @@ -4,8 +4,8 @@ error[E0308]: mismatched types LL | let _: fn(&mut &isize, &mut &isize, &mut &isize) = a; | ^ one type is more general than the other | - = note: expected fn pointer `for<'r, 's, 't, 't0, 't1, 't2> fn(&'r mut &'s isize, &'t mut &'t0 isize, &'t1 mut &'t2 isize)` - found fn item `for<'r, 's, 't> fn(&'r mut &isize, &'s mut &isize, &'t mut &isize) {a::<'_, '_, '_>}` + = note: expected fn pointer `for<'a, 'b, 'c, 'd, 'e, 'f> fn(&'a mut &'b isize, &'c mut &'d isize, &'e mut &'f isize)` + found fn item `for<'a, 'b, 'c> fn(&'a mut &isize, &'b mut &isize, &'c mut &isize) {a::<'_, '_, '_>}` error: aborting due to previous error diff --git a/src/test/ui/regions/regions-fn-subtyping-return-static-fail.stderr b/src/test/ui/regions/regions-fn-subtyping-return-static-fail.stderr index d87d0d2f6f991..8d82ff958ff3a 100644 --- a/src/test/ui/regions/regions-fn-subtyping-return-static-fail.stderr +++ b/src/test/ui/regions/regions-fn-subtyping-return-static-fail.stderr @@ -7,7 +7,7 @@ LL | want_G(baz); | arguments to this function are incorrect | = note: expected fn pointer `for<'cx> fn(&'cx S) -> &'static S` - found fn item `for<'r> fn(&'r S) -> &'r S {baz}` + found fn item `for<'a> fn(&'a S) -> &'a S {baz}` note: function defined here --> $DIR/regions-fn-subtyping-return-static-fail.rs:20:4 | diff --git a/src/test/ui/regions/regions-lifetime-bounds-on-fns.stderr b/src/test/ui/regions/regions-lifetime-bounds-on-fns.stderr index e02bed707dca4..17a9019436a1e 100644 --- a/src/test/ui/regions/regions-lifetime-bounds-on-fns.stderr +++ b/src/test/ui/regions/regions-lifetime-bounds-on-fns.stderr @@ -4,8 +4,8 @@ error[E0308]: mismatched types LL | let _: fn(&mut &isize, &mut &isize) = a; | ^ one type is more general than the other | - = note: expected fn pointer `for<'r, 's, 't, 't0> fn(&'r mut &'s isize, &'t mut &'t0 isize)` - found fn item `for<'r, 's> fn(&'r mut &isize, &'s mut &isize) {a::<'_, '_>}` + = note: expected fn pointer `for<'a, 'b, 'c, 'd> fn(&'a mut &'b isize, &'c mut &'d isize)` + found fn item `for<'a, 'b> fn(&'a mut &isize, &'b mut &isize) {a::<'_, '_>}` error: aborting due to previous error diff --git a/src/test/ui/rfc1623-2.stderr b/src/test/ui/rfc1623-2.stderr index 495d45e223416..945c6533c797b 100644 --- a/src/test/ui/rfc1623-2.stderr +++ b/src/test/ui/rfc1623-2.stderr @@ -23,7 +23,7 @@ help: consider making the type lifetime-generic with a new `'a` lifetime LL | &(non_elidable as for<'a> fn(&'a u8, &'a u8) -> &'a u8); | +++++++ ++ ++ ++ -error[E0605]: non-primitive cast: `for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8 {non_elidable}` as `for<'r, 's> fn(&'r u8, &'s u8) -> &u8` +error[E0605]: non-primitive cast: `for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8 {non_elidable}` as `for<'a, 'b> fn(&'a u8, &'b u8) -> &u8` --> $DIR/rfc1623-2.rs:10:6 | LL | &(non_elidable as fn(&u8, &u8) -> &u8); diff --git a/src/test/ui/suggestions/fn-or-tuple-struct-without-args.stderr b/src/test/ui/suggestions/fn-or-tuple-struct-without-args.stderr index 3c7b895e337e7..f05dba1d4ca7e 100644 --- a/src/test/ui/suggestions/fn-or-tuple-struct-without-args.stderr +++ b/src/test/ui/suggestions/fn-or-tuple-struct-without-args.stderr @@ -220,7 +220,7 @@ error[E0308]: mismatched types --> $DIR/fn-or-tuple-struct-without-args.rs:41:20 | LL | fn ban(&self) -> usize { 42 } - | ---------------------- for<'r> fn(&'r X) -> usize {::ban} defined here + | ---------------------- for<'a> fn(&'a X) -> usize {::ban} defined here ... LL | let _: usize = X::ban; | ----- ^^^^^^ expected `usize`, found fn item @@ -228,7 +228,7 @@ LL | let _: usize = X::ban; | expected due to this | = note: expected type `usize` - found fn item `for<'r> fn(&'r X) -> usize {::ban}` + found fn item `for<'a> fn(&'a X) -> usize {::ban}` help: use parentheses to call this associated function | LL | let _: usize = X::ban(/* &X */); @@ -238,7 +238,7 @@ error[E0308]: mismatched types --> $DIR/fn-or-tuple-struct-without-args.rs:42:20 | LL | fn bal(&self) -> usize; - | ----------------------- for<'r> fn(&'r X) -> usize {::bal} defined here + | ----------------------- for<'a> fn(&'a X) -> usize {::bal} defined here ... LL | let _: usize = X::bal; | ----- ^^^^^^ expected `usize`, found fn item @@ -246,7 +246,7 @@ LL | let _: usize = X::bal; | expected due to this | = note: expected type `usize` - found fn item `for<'r> fn(&'r X) -> usize {::bal}` + found fn item `for<'a> fn(&'a X) -> usize {::bal}` help: use parentheses to call this associated function | LL | let _: usize = X::bal(/* &X */); diff --git a/src/test/ui/suggestions/issue-101984.stderr b/src/test/ui/suggestions/issue-101984.stderr index c744c62d11f9b..81758a7007c21 100644 --- a/src/test/ui/suggestions/issue-101984.stderr +++ b/src/test/ui/suggestions/issue-101984.stderr @@ -2,11 +2,11 @@ error[E0308]: mismatched types --> $DIR/issue-101984.rs:21:13 | LL | let (cmp, router) = self.router.at()?; - | ^^^^^^^^^^^^^ ----------------- this expression has type `Match<&(for<'r> fn(&'r ()), Box)>` + | ^^^^^^^^^^^^^ ----------------- this expression has type `Match<&(for<'a> fn(&'a ()), Box)>` | | | expected struct `Match`, found tuple | - = note: expected struct `Match<&(for<'r> fn(&'r ()), Box)>` + = note: expected struct `Match<&(for<'a> fn(&'a ()), Box)>` found tuple `(_, _)` error: aborting due to previous error diff --git a/src/test/ui/suggestions/return-closures.stderr b/src/test/ui/suggestions/return-closures.stderr index e273793ea2c29..8b856d8de7033 100644 --- a/src/test/ui/suggestions/return-closures.stderr +++ b/src/test/ui/suggestions/return-closures.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/return-closures.rs:3:5 | LL | fn foo() { - | - help: try adding a return type: `-> impl for<'r> Fn(&'r i32) -> i32` + | - help: try adding a return type: `-> impl for<'a> Fn(&'a i32) -> i32` LL | LL | |x: &i32| 1i32 | ^^^^^^^^^^^^^^ expected `()`, found closure diff --git a/src/test/ui/symbol-names/impl1.legacy.stderr b/src/test/ui/symbol-names/impl1.legacy.stderr index b6012e41594b5..3d438df92b85d 100644 --- a/src/test/ui/symbol-names/impl1.legacy.stderr +++ b/src/test/ui/symbol-names/impl1.legacy.stderr @@ -64,7 +64,7 @@ error: demangling-alt(<[&dyn impl1::Foo+Assoc = extern "C" fn(&u8, ::.)+impl1::A LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ -error: def-path(<[&dyn Foo extern "C" fn(&'r u8, ...)> + AutoTrait; 3] as main::{closure#1}::Bar>::method) +error: def-path(<[&dyn Foo extern "C" fn(&'a u8, ...)> + AutoTrait; 3] as main::{closure#1}::Bar>::method) --> $DIR/impl1.rs:69:13 | LL | #[rustc_def_path] diff --git a/src/test/ui/symbol-names/impl1.rs b/src/test/ui/symbol-names/impl1.rs index 86f0a8b0bef4d..629c2f33ddcc6 100644 --- a/src/test/ui/symbol-names/impl1.rs +++ b/src/test/ui/symbol-names/impl1.rs @@ -67,8 +67,8 @@ fn main() { //[v0]~| ERROR demangling(<[&dyn //[v0]~| ERROR demangling-alt(<[&dyn impl1::Foo extern "C" fn(&'a u8, ...)> + impl1::AutoTrait; 3] as impl1::main::{closure#1}::Bar>::method) #[rustc_def_path] - //[legacy]~^ ERROR def-path(<[&dyn Foo extern "C" fn(&'r u8, ...)> + AutoTrait; 3] as main::{closure#1}::Bar>::method) - //[v0]~^^ ERROR def-path(<[&dyn Foo extern "C" fn(&'r u8, ...)> + AutoTrait; 3] as main::{closure#1}::Bar>::method) + //[legacy]~^ ERROR def-path(<[&dyn Foo extern "C" fn(&'a u8, ...)> + AutoTrait; 3] as main::{closure#1}::Bar>::method) + //[v0]~^^ ERROR def-path(<[&dyn Foo extern "C" fn(&'a u8, ...)> + AutoTrait; 3] as main::{closure#1}::Bar>::method) fn method(&self) {} } }; diff --git a/src/test/ui/symbol-names/impl1.v0.stderr b/src/test/ui/symbol-names/impl1.v0.stderr index 48f7473b6a0d1..33caad71f52fe 100644 --- a/src/test/ui/symbol-names/impl1.v0.stderr +++ b/src/test/ui/symbol-names/impl1.v0.stderr @@ -64,7 +64,7 @@ error: demangling-alt(<[&dyn impl1::Foo extern "C" fn(&'a u8, .. LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ -error: def-path(<[&dyn Foo extern "C" fn(&'r u8, ...)> + AutoTrait; 3] as main::{closure#1}::Bar>::method) +error: def-path(<[&dyn Foo extern "C" fn(&'a u8, ...)> + AutoTrait; 3] as main::{closure#1}::Bar>::method) --> $DIR/impl1.rs:69:13 | LL | #[rustc_def_path] diff --git a/src/test/ui/traits/associated_type_bound/check-trait-object-bounds-2.stderr b/src/test/ui/traits/associated_type_bound/check-trait-object-bounds-2.stderr index 4084f69a6f04b..10e82c54e0f2b 100644 --- a/src/test/ui/traits/associated_type_bound/check-trait-object-bounds-2.stderr +++ b/src/test/ui/traits/associated_type_bound/check-trait-object-bounds-2.stderr @@ -4,7 +4,7 @@ error[E0277]: expected a `FnOnce<(&i32,)>` closure, found `i32` LL | f:: X<'x, F = i32>>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ expected an `FnOnce<(&i32,)>` closure, found `i32` | - = help: the trait `for<'r> FnOnce<(&'r i32,)>` is not implemented for `i32` + = help: the trait `for<'a> FnOnce<(&'a i32,)>` is not implemented for `i32` note: required by a bound in `f` --> $DIR/check-trait-object-bounds-2.rs:8:9 | diff --git a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.stderr b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.stderr index f14bf6b0f7f5c..6344f114a9131 100644 --- a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.stderr @@ -4,7 +4,7 @@ error[E0308]: mismatched types LL | |x| x | ^^^^^ one type is more general than the other | - = note: expected trait `for<'r> Fn<(&'r X,)>` + = note: expected trait `for<'a> Fn<(&'a X,)>` found trait `Fn<(&X,)>` note: this closure does not fulfill the lifetime requirements --> $DIR/issue-57611-trait-alias.rs:21:9 diff --git a/src/test/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.stderr b/src/test/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.stderr index 9833304c636b1..802696e1b2f94 100644 --- a/src/test/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.stderr @@ -1,4 +1,4 @@ -error[E0277]: expected a `Fn<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}` +error[E0277]: expected a `Fn<(&isize,)>` closure, found `for<'a> unsafe fn(&'a isize) -> isize {square}` --> $DIR/unboxed-closures-unsafe-extern-fn.rs:20:21 | LL | let x = call_it(&square, 22); @@ -6,7 +6,7 @@ LL | let x = call_it(&square, 22); | | | required by a bound introduced by this call | - = help: the trait `for<'r> Fn<(&'r isize,)>` is not implemented for fn item `for<'r> unsafe fn(&'r isize) -> isize {square}` + = help: the trait `for<'a> Fn<(&'a isize,)>` is not implemented for fn item `for<'a> unsafe fn(&'a isize) -> isize {square}` = note: unsafe function cannot be called generically without an unsafe block note: required by a bound in `call_it` --> $DIR/unboxed-closures-unsafe-extern-fn.rs:9:15 @@ -14,7 +14,7 @@ note: required by a bound in `call_it` LL | fn call_it isize>(_: &F, _: isize) -> isize { | ^^^^^^^^^^^^^^^^^^^ required by this bound in `call_it` -error[E0277]: expected a `FnMut<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}` +error[E0277]: expected a `FnMut<(&isize,)>` closure, found `for<'a> unsafe fn(&'a isize) -> isize {square}` --> $DIR/unboxed-closures-unsafe-extern-fn.rs:25:25 | LL | let y = call_it_mut(&mut square, 22); @@ -22,7 +22,7 @@ LL | let y = call_it_mut(&mut square, 22); | | | required by a bound introduced by this call | - = help: the trait `for<'r> FnMut<(&'r isize,)>` is not implemented for fn item `for<'r> unsafe fn(&'r isize) -> isize {square}` + = help: the trait `for<'a> FnMut<(&'a isize,)>` is not implemented for fn item `for<'a> unsafe fn(&'a isize) -> isize {square}` = note: unsafe function cannot be called generically without an unsafe block note: required by a bound in `call_it_mut` --> $DIR/unboxed-closures-unsafe-extern-fn.rs:12:19 @@ -30,7 +30,7 @@ note: required by a bound in `call_it_mut` LL | fn call_it_mut isize>(_: &mut F, _: isize) -> isize { | ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `call_it_mut` -error[E0277]: expected a `FnOnce<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}` +error[E0277]: expected a `FnOnce<(&isize,)>` closure, found `for<'a> unsafe fn(&'a isize) -> isize {square}` --> $DIR/unboxed-closures-unsafe-extern-fn.rs:30:26 | LL | let z = call_it_once(square, 22); @@ -38,7 +38,7 @@ LL | let z = call_it_once(square, 22); | | | required by a bound introduced by this call | - = help: the trait `for<'r> FnOnce<(&'r isize,)>` is not implemented for fn item `for<'r> unsafe fn(&'r isize) -> isize {square}` + = help: the trait `for<'a> FnOnce<(&'a isize,)>` is not implemented for fn item `for<'a> unsafe fn(&'a isize) -> isize {square}` = note: unsafe function cannot be called generically without an unsafe block note: required by a bound in `call_it_once` --> $DIR/unboxed-closures-unsafe-extern-fn.rs:15:20 diff --git a/src/test/ui/unboxed-closures/unboxed-closures-wrong-abi.stderr b/src/test/ui/unboxed-closures/unboxed-closures-wrong-abi.stderr index 54c92e0cd040c..0bbb9836c5840 100644 --- a/src/test/ui/unboxed-closures/unboxed-closures-wrong-abi.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closures-wrong-abi.stderr @@ -1,42 +1,42 @@ -error[E0277]: expected a `Fn<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}` +error[E0277]: expected a `Fn<(&isize,)>` closure, found `for<'a> extern "C" fn(&'a isize) -> isize {square}` --> $DIR/unboxed-closures-wrong-abi.rs:20:21 | LL | let x = call_it(&square, 22); - | ------- ^^^^^^^ expected an `Fn<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}` + | ------- ^^^^^^^ expected an `Fn<(&isize,)>` closure, found `for<'a> extern "C" fn(&'a isize) -> isize {square}` | | | required by a bound introduced by this call | - = help: the trait `for<'r> Fn<(&'r isize,)>` is not implemented for fn item `for<'r> extern "C" fn(&'r isize) -> isize {square}` + = help: the trait `for<'a> Fn<(&'a isize,)>` is not implemented for fn item `for<'a> extern "C" fn(&'a isize) -> isize {square}` note: required by a bound in `call_it` --> $DIR/unboxed-closures-wrong-abi.rs:9:15 | LL | fn call_it isize>(_: &F, _: isize) -> isize { | ^^^^^^^^^^^^^^^^^^^ required by this bound in `call_it` -error[E0277]: expected a `FnMut<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}` +error[E0277]: expected a `FnMut<(&isize,)>` closure, found `for<'a> extern "C" fn(&'a isize) -> isize {square}` --> $DIR/unboxed-closures-wrong-abi.rs:25:25 | LL | let y = call_it_mut(&mut square, 22); - | ----------- ^^^^^^^^^^^ expected an `FnMut<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}` + | ----------- ^^^^^^^^^^^ expected an `FnMut<(&isize,)>` closure, found `for<'a> extern "C" fn(&'a isize) -> isize {square}` | | | required by a bound introduced by this call | - = help: the trait `for<'r> FnMut<(&'r isize,)>` is not implemented for fn item `for<'r> extern "C" fn(&'r isize) -> isize {square}` + = help: the trait `for<'a> FnMut<(&'a isize,)>` is not implemented for fn item `for<'a> extern "C" fn(&'a isize) -> isize {square}` note: required by a bound in `call_it_mut` --> $DIR/unboxed-closures-wrong-abi.rs:12:19 | LL | fn call_it_mut isize>(_: &mut F, _: isize) -> isize { | ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `call_it_mut` -error[E0277]: expected a `FnOnce<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}` +error[E0277]: expected a `FnOnce<(&isize,)>` closure, found `for<'a> extern "C" fn(&'a isize) -> isize {square}` --> $DIR/unboxed-closures-wrong-abi.rs:30:26 | LL | let z = call_it_once(square, 22); - | ------------ ^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}` + | ------------ ^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `for<'a> extern "C" fn(&'a isize) -> isize {square}` | | | required by a bound introduced by this call | - = help: the trait `for<'r> FnOnce<(&'r isize,)>` is not implemented for fn item `for<'r> extern "C" fn(&'r isize) -> isize {square}` + = help: the trait `for<'a> FnOnce<(&'a isize,)>` is not implemented for fn item `for<'a> extern "C" fn(&'a isize) -> isize {square}` note: required by a bound in `call_it_once` --> $DIR/unboxed-closures-wrong-abi.rs:15:20 | diff --git a/src/test/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.stderr b/src/test/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.stderr index 2fedb5b92c289..31a66790ce089 100644 --- a/src/test/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.stderr @@ -6,7 +6,7 @@ LL | let x = call_it(&square, 22); | | | required by a bound introduced by this call | - = help: the trait `for<'r> Fn<(&'r isize,)>` is not implemented for fn item `unsafe fn(isize) -> isize {square}` + = help: the trait `for<'a> Fn<(&'a isize,)>` is not implemented for fn item `unsafe fn(isize) -> isize {square}` = note: unsafe function cannot be called generically without an unsafe block note: required by a bound in `call_it` --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:10:15 @@ -22,7 +22,7 @@ LL | let y = call_it_mut(&mut square, 22); | | | required by a bound introduced by this call | - = help: the trait `for<'r> FnMut<(&'r isize,)>` is not implemented for fn item `unsafe fn(isize) -> isize {square}` + = help: the trait `for<'a> FnMut<(&'a isize,)>` is not implemented for fn item `unsafe fn(isize) -> isize {square}` = note: unsafe function cannot be called generically without an unsafe block note: required by a bound in `call_it_mut` --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:13:19 @@ -38,7 +38,7 @@ LL | let z = call_it_once(square, 22); | | | required by a bound introduced by this call | - = help: the trait `for<'r> FnOnce<(&'r isize,)>` is not implemented for fn item `unsafe fn(isize) -> isize {square}` + = help: the trait `for<'a> FnOnce<(&'a isize,)>` is not implemented for fn item `unsafe fn(isize) -> isize {square}` = note: unsafe function cannot be called generically without an unsafe block note: required by a bound in `call_it_once` --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:16:20 From 4c42e3831fd09fd1de401a7e60db0b21ec3b1ed6 Mon Sep 17 00:00:00 2001 From: Anirudh Date: Mon, 26 Sep 2022 19:28:51 +0530 Subject: [PATCH 271/586] Update docs so that deprecated method points to relevant method --- library/std/src/thread/mod.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs index ceea6986e3335..2de7da3793f09 100644 --- a/library/std/src/thread/mod.rs +++ b/library/std/src/thread/mod.rs @@ -779,6 +779,8 @@ pub fn panicking() -> bool { panicking::panicking() } +/// Use [`sleep`]. +/// /// Puts the current thread to sleep for at least the specified amount of time. /// /// The thread may sleep longer than the duration specified due to scheduling From 1fe3ce476c0c36485b90d0bd5dc8cb27f57be1c6 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Mon, 26 Sep 2022 09:20:20 -0700 Subject: [PATCH 272/586] rustdoc: remove unneeded CSS `td, th { padding 0 }` This was added in 510107815fe888319028c5e96001cdee70e7a931, to fix the display of the module items and search results tables (see the discussion in https://github.com/rust-lang/rust/pull/86725). Those aren't tables any more. The only remaining table is in docblock, which has its own padding declarations. --- src/librustdoc/html/static/css/rustdoc.css | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index 28dc4bf30108e..5257ab600c50a 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -299,11 +299,6 @@ summary { /* Fix some style changes due to normalize.css 8 */ -td, -th { - padding: 0; -} - table { border-collapse: collapse; } From 99904445b8d8e37f27ae7ababd5f3fb48b0d8813 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Mon, 26 Sep 2022 09:54:44 -0700 Subject: [PATCH 273/586] rustdoc: merge `table { border-collapse } into `.docblock table` This was added in 510107815fe888319028c5e96001cdee70e7a931, to fix the display of the module items and search results tables (see the discussion in https://github.com/rust-lang/rust/pull/86725). Those aren't tables any more. The only remaining table is in docblock, which needs this attribute to look right. --- src/librustdoc/html/static/css/rustdoc.css | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index 5257ab600c50a..679aea411d192 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -299,10 +299,6 @@ summary { /* Fix some style changes due to normalize.css 8 */ -table { - border-collapse: collapse; -} - button, input, optgroup, @@ -690,6 +686,7 @@ pre, .rustdoc.source .example-wrap { width: calc(100% - 2px); overflow-x: auto; display: block; + border-collapse: collapse; } .docblock table td { From 4fad063cbac1cbdbe831da23c0722487cebc81f3 Mon Sep 17 00:00:00 2001 From: Matthew Esposito Date: Mon, 26 Sep 2022 12:50:45 -0400 Subject: [PATCH 274/586] Document that Display entails ToString --- library/core/src/fmt/mod.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs index 905212eb372b1..372439f14ec83 100644 --- a/library/core/src/fmt/mod.rs +++ b/library/core/src/fmt/mod.rs @@ -709,12 +709,19 @@ pub use macros::Debug; /// Format trait for an empty format, `{}`. /// +/// Implementing this trait for a type will automatically implement the +/// [`ToString`][tostring] trait for the type, allowing the usage +/// of the [`.to_string()`][tostring_function] method. Prefer implementing +/// the `Display` trait for a type, rather than [`ToString`][tostring]. +/// /// `Display` is similar to [`Debug`], but `Display` is for user-facing /// output, and so cannot be derived. /// /// For more information on formatters, see [the module-level documentation][module]. /// /// [module]: ../../std/fmt/index.html +/// [tostring]: ../../std/string/trait.ToString.html +/// [tostring_function]: ../../std/string/trait.ToString.html#tymethod.to_string /// /// # Examples /// From aac7429c17aa558fbd9fb0be093e7bd9ccc73972 Mon Sep 17 00:00:00 2001 From: Nixon Enraght-Moony Date: Mon, 26 Sep 2022 18:06:48 +0100 Subject: [PATCH 275/586] Rustdoc-Json: List impls for primitives Closes #101695 --- src/librustdoc/json/conversions.rs | 7 +++- src/librustdoc/json/mod.rs | 7 ++-- src/rustdoc-json-types/lib.rs | 10 ++++-- .../primitives/primitive_impls.rs | 34 +++++++++++++++++++ .../{ => primitives}/primitive_overloading.rs | 0 .../primitive_type.rs} | 0 .../use_primitive.rs} | 2 +- src/tools/jsondoclint/src/item_kind.rs | 3 +- src/tools/jsondoclint/src/validator.rs | 10 +++--- 9 files changed, 60 insertions(+), 13 deletions(-) create mode 100644 src/test/rustdoc-json/primitives/primitive_impls.rs rename src/test/rustdoc-json/{ => primitives}/primitive_overloading.rs (100%) rename src/test/rustdoc-json/{primitives.rs => primitives/primitive_type.rs} (100%) rename src/test/rustdoc-json/{primitive.rs => primitives/use_primitive.rs} (88%) diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs index 49a31f5f1da1f..4170412caef87 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -272,7 +272,12 @@ fn from_clean_item(item: clean::Item, tcx: TyCtxt<'_>) -> ItemEnum { ConstantItem(c) => ItemEnum::Constant(c.into_tcx(tcx)), MacroItem(m) => ItemEnum::Macro(m.source), ProcMacroItem(m) => ItemEnum::ProcMacro(m.into_tcx(tcx)), - PrimitiveItem(p) => ItemEnum::PrimitiveType(p.as_sym().to_string()), + PrimitiveItem(p) => { + ItemEnum::Primitive(Primitive { + name: p.as_sym().to_string(), + impls: Vec::new(), // Added in JsonRenderer::item + }) + } TyAssocConstItem(ty) => ItemEnum::AssocConst { type_: ty.into_tcx(tcx), default: None }, AssocConstItem(ty, default) => { ItemEnum::AssocConst { type_: ty.into_tcx(tcx), default: Some(default.expr(tcx)) } diff --git a/src/librustdoc/json/mod.rs b/src/librustdoc/json/mod.rs index 5e8f5f6fe3eb9..8d6450838c1d0 100644 --- a/src/librustdoc/json/mod.rs +++ b/src/librustdoc/json/mod.rs @@ -219,12 +219,15 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> { u.impls = self.get_impls(item_id.expect_def_id()); false } + types::ItemEnum::Primitive(ref mut p) => { + p.impls = self.get_impls(item_id.expect_def_id()); + false + } types::ItemEnum::Method(_) | types::ItemEnum::Module(_) | types::ItemEnum::AssocConst { .. } - | types::ItemEnum::AssocType { .. } - | types::ItemEnum::PrimitiveType(_) => true, + | types::ItemEnum::AssocType { .. } => true, types::ItemEnum::ExternCrate { .. } | types::ItemEnum::Import(_) | types::ItemEnum::StructField(_) diff --git a/src/rustdoc-json-types/lib.rs b/src/rustdoc-json-types/lib.rs index fb183042670e8..7379b04ad1677 100644 --- a/src/rustdoc-json-types/lib.rs +++ b/src/rustdoc-json-types/lib.rs @@ -9,7 +9,7 @@ use std::path::PathBuf; use serde::{Deserialize, Serialize}; /// rustdoc format-version. -pub const FORMAT_VERSION: u32 = 21; +pub const FORMAT_VERSION: u32 = 22; /// A `Crate` is the root of the emitted JSON blob. It contains all type/documentation information /// about the language items in the local crate, as well as info about external items to allow @@ -254,7 +254,7 @@ pub enum ItemEnum { Macro(String), ProcMacro(ProcMacro), - PrimitiveType(String), + Primitive(Primitive), AssocConst { #[serde(rename = "type")] @@ -709,5 +709,11 @@ pub struct Static { pub expr: String, } +#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] +pub struct Primitive { + pub name: String, + pub impls: Vec, +} + #[cfg(test)] mod tests; diff --git a/src/test/rustdoc-json/primitives/primitive_impls.rs b/src/test/rustdoc-json/primitives/primitive_impls.rs new file mode 100644 index 0000000000000..1fc9374065f66 --- /dev/null +++ b/src/test/rustdoc-json/primitives/primitive_impls.rs @@ -0,0 +1,34 @@ +#![feature(no_core)] +#![feature(rustc_attrs)] +#![feature(rustdoc_internals)] +#![no_core] +#![rustc_coherence_is_core] + +// @set impl_i32 = "$.index[*][?(@.docs=='Only core can do this')].id" + +/// Only core can do this +impl i32 { + // @set identity = "$.index[*][?(@.docs=='Do Nothing')].id" + + /// Do Nothing + pub fn identity(self) -> Self { + self + } + + // @is "$.index[*][?(@.docs=='Only core can do this')].inner.items[*]" $identity +} + +// @set Trait = "$.index[*][?(@.name=='Trait')].id" +pub trait Trait {} +// @set impl_trait_for_i32 = "$.index[*][?(@.docs=='impl Trait for i32')].id" +/// impl Trait for i32 +impl Trait for i32 {} + +/// i32 +#[doc(primitive = "i32")] +mod prim_i32 {} + +// @set i32 = "$.index[*][?(@.docs=='i32')].id" +// @is "$.index[*][?(@.docs=='i32')].name" '"i32"' +// @is "$.index[*][?(@.docs=='i32')].inner.name" '"i32"' +// @ismany "$.index[*][?(@.docs=='i32')].inner.impls[*]" $impl_i32 $impl_trait_for_i32 diff --git a/src/test/rustdoc-json/primitive_overloading.rs b/src/test/rustdoc-json/primitives/primitive_overloading.rs similarity index 100% rename from src/test/rustdoc-json/primitive_overloading.rs rename to src/test/rustdoc-json/primitives/primitive_overloading.rs diff --git a/src/test/rustdoc-json/primitives.rs b/src/test/rustdoc-json/primitives/primitive_type.rs similarity index 100% rename from src/test/rustdoc-json/primitives.rs rename to src/test/rustdoc-json/primitives/primitive_type.rs diff --git a/src/test/rustdoc-json/primitive.rs b/src/test/rustdoc-json/primitives/use_primitive.rs similarity index 88% rename from src/test/rustdoc-json/primitive.rs rename to src/test/rustdoc-json/primitives/use_primitive.rs index 6454dd7f51fab..e22927374621f 100644 --- a/src/test/rustdoc-json/primitive.rs +++ b/src/test/rustdoc-json/primitives/use_primitive.rs @@ -5,7 +5,7 @@ #[doc(primitive = "usize")] mod usize {} -// @set local_crate_id = "$.index[*][?(@.name=='primitive')].crate_id" +// @set local_crate_id = "$.index[*][?(@.name=='use_primitive')].crate_id" // @has "$.index[*][?(@.name=='ilog10')]" // @!is "$.index[*][?(@.name=='ilog10')].crate_id" $local_crate_id diff --git a/src/tools/jsondoclint/src/item_kind.rs b/src/tools/jsondoclint/src/item_kind.rs index ad8e96a0bd81d..6d986e57501a3 100644 --- a/src/tools/jsondoclint/src/item_kind.rs +++ b/src/tools/jsondoclint/src/item_kind.rs @@ -142,8 +142,7 @@ impl Kind { ItemEnum::Static(_) => Static, ItemEnum::Macro(_) => Macro, ItemEnum::ProcMacro(_) => ProcMacro, - // https://github.com/rust-lang/rust/issues/100961 - ItemEnum::PrimitiveType(_) => Primitive, + ItemEnum::Primitive(_) => Primitive, ItemEnum::ForeignType => ForeignType, ItemEnum::ExternCrate { .. } => ExternCrate, ItemEnum::AssocConst { .. } => AssocConst, diff --git a/src/tools/jsondoclint/src/validator.rs b/src/tools/jsondoclint/src/validator.rs index a0e77127dc2ca..94af4c5e9e16d 100644 --- a/src/tools/jsondoclint/src/validator.rs +++ b/src/tools/jsondoclint/src/validator.rs @@ -4,8 +4,8 @@ use std::hash::Hash; use rustdoc_json_types::{ Constant, Crate, DynTrait, Enum, FnDecl, Function, FunctionPointer, GenericArg, GenericArgs, GenericBound, GenericParamDef, Generics, Id, Impl, Import, ItemEnum, Method, Module, OpaqueTy, - Path, ProcMacro, Static, Struct, StructKind, Term, Trait, TraitAlias, Type, TypeBinding, - TypeBindingKind, Typedef, Union, Variant, WherePredicate, + Path, Primitive, ProcMacro, Static, Struct, StructKind, Term, Trait, TraitAlias, Type, + TypeBinding, TypeBindingKind, Typedef, Union, Variant, WherePredicate, }; use crate::{item_kind::Kind, Error, ErrorKind}; @@ -76,7 +76,7 @@ impl<'a> Validator<'a> { ItemEnum::ForeignType => {} // nop ItemEnum::Macro(x) => self.check_macro(x), ItemEnum::ProcMacro(x) => self.check_proc_macro(x), - ItemEnum::PrimitiveType(x) => self.check_primitive_type(x), + ItemEnum::Primitive(x) => self.check_primitive_type(x), ItemEnum::Module(x) => self.check_module(x), // FIXME: Why don't these have their own structs? ItemEnum::ExternCrate { .. } => {} @@ -219,8 +219,8 @@ impl<'a> Validator<'a> { // nop } - fn check_primitive_type(&mut self, _: &'a str) { - // nop + fn check_primitive_type(&mut self, x: &'a Primitive) { + x.impls.iter().for_each(|i| self.add_impl_id(i)); } fn check_generics(&mut self, x: &'a Generics) { From 40f404468aa76f5d099d9617cecf91f72ac375b0 Mon Sep 17 00:00:00 2001 From: yancy Date: Mon, 26 Sep 2022 20:20:13 +0200 Subject: [PATCH 276/586] rustdoc: Update doc comment for splitn_mut to include mutable in the description --- library/core/src/slice/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index cd04fa0044241..aed8fbf092ed3 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -2076,7 +2076,7 @@ impl [T] { SplitN::new(self.split(pred), n) } - /// Returns an iterator over subslices separated by elements that match + /// Returns an iterator over mutable subslices separated by elements that match /// `pred`, limited to returning at most `n` items. The matched element is /// not contained in the subslices. /// From 0b97831af756b0b1dd7c75f1f5c35436b2424663 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Mon, 26 Sep 2022 10:50:51 -0700 Subject: [PATCH 277/586] rustdoc: give `.line-number` / `.line-numbers` meaningful names --- src/librustdoc/html/sources.rs | 2 +- src/librustdoc/html/static/css/rustdoc.css | 18 +++++++++--------- src/librustdoc/html/static/css/themes/ayu.css | 8 ++++---- src/librustdoc/html/static/css/themes/dark.css | 8 ++++---- .../html/static/css/themes/light.css | 8 ++++---- src/librustdoc/html/static/js/main.js | 6 +++--- .../html/static/js/scrape-examples.js | 2 +- src/librustdoc/html/static/js/source-script.js | 4 ++-- .../rustdoc-scrape-examples-macros/src/lib.rs | 8 ++++---- src/test/rustdoc-gui/basic-code.goml | 2 +- .../docblock-code-block-line-number.goml | 12 ++++++------ src/test/rustdoc-gui/source-code-page.goml | 16 ++++++++-------- 12 files changed, 47 insertions(+), 47 deletions(-) diff --git a/src/librustdoc/html/sources.rs b/src/librustdoc/html/sources.rs index 2e2bee78b95f9..7ab65bff3469f 100644 --- a/src/librustdoc/html/sources.rs +++ b/src/librustdoc/html/sources.rs @@ -274,7 +274,7 @@ pub(crate) fn print_src( ) { let lines = s.lines().count(); let mut line_numbers = Buffer::empty_from(buf); - line_numbers.write_str("

");
+    line_numbers.write_str("
");
     match source_context {
         SourceContext::Standalone => {
             for line in 1..=lines {
diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css
index 28dc4bf30108e..b4c7638b79841 100644
--- a/src/librustdoc/html/static/css/rustdoc.css
+++ b/src/librustdoc/html/static/css/rustdoc.css
@@ -578,7 +578,7 @@ h2.location a {
 	position: relative;
 }
 
-.example-wrap > pre.line-number {
+.example-wrap > pre.example-line-numbers {
 	overflow: initial;
 	border: 1px solid;
 	padding: 13px 8px;
@@ -591,15 +591,15 @@ h2.location a {
 	text-decoration: underline;
 }
 
-.line-numbers {
+.src-line-numbers {
 	text-align: right;
 }
-.rustdoc:not(.source) .example-wrap > pre:not(.line-number) {
+.rustdoc:not(.source) .example-wrap > pre:not(.example-line-numbers) {
 	width: 100%;
 	overflow-x: auto;
 }
 
-.rustdoc:not(.source) .example-wrap > pre.line-numbers {
+.rustdoc:not(.source) .example-wrap > pre.src-line-numbers {
 	width: auto;
 	overflow-x: visible;
 }
@@ -612,14 +612,14 @@ h2.location a {
 	text-align: center;
 }
 
-.content > .example-wrap pre.line-numbers {
+.content > .example-wrap pre.src-line-numbers {
 	position: relative;
 	-webkit-user-select: none;
 	-moz-user-select: none;
 	-ms-user-select: none;
 	user-select: none;
 }
-.line-numbers span {
+.src-line-numbers span {
 	cursor: pointer;
 }
 
@@ -2067,7 +2067,7 @@ in storage.js plus the media query with (min-width: 701px)
 	padding-bottom: 0;
 }
 
-.scraped-example:not(.expanded) .code-wrapper pre.line-numbers {
+.scraped-example:not(.expanded) .code-wrapper pre.src-line-numbers {
 	overflow-x: hidden;
 }
 
@@ -2113,12 +2113,12 @@ in storage.js plus the media query with (min-width: 701px)
 	bottom: 0;
 }
 
-.scraped-example .code-wrapper .line-numbers {
+.scraped-example .code-wrapper .src-line-numbers {
 	margin: 0;
 	padding: 14px 0;
 }
 
-.scraped-example .code-wrapper .line-numbers span {
+.scraped-example .code-wrapper .src-line-numbers span {
 	padding: 0 14px;
 }
 
diff --git a/src/librustdoc/html/static/css/themes/ayu.css b/src/librustdoc/html/static/css/themes/ayu.css
index e7a898e9fa62c..34411ace6fd37 100644
--- a/src/librustdoc/html/static/css/themes/ayu.css
+++ b/src/librustdoc/html/static/css/themes/ayu.css
@@ -93,8 +93,8 @@ pre, .rustdoc.source .example-wrap {
 	color: #ff7733;
 }
 
-.line-numbers span { color: #5c6773; }
-.line-numbers .line-highlighted {
+.src-line-numbers span { color: #5c6773; }
+.src-line-numbers .line-highlighted {
 	color: #708090;
 	background-color: rgba(255, 236, 164, 0.06);
 	padding-right: 4px;
@@ -171,7 +171,7 @@ details.rustdoc-toggle > summary::before {
 	color: #788797;
 }
 
-.line-numbers :target { background-color: transparent; }
+.src-line-numbers :target { background-color: transparent; }
 
 /* Code highlighting */
 pre.rust .number, pre.rust .string { color: #b8cc52; }
@@ -190,7 +190,7 @@ pre.rust .attribute {
 	color: #e6e1cf;
 }
 
-.example-wrap > pre.line-number {
+.example-wrap > pre.example-line-numbers {
 	color: #5c67736e;
 	border: none;
 }
diff --git a/src/librustdoc/html/static/css/themes/dark.css b/src/librustdoc/html/static/css/themes/dark.css
index 07a1ed8b7db74..9978f5f91874c 100644
--- a/src/librustdoc/html/static/css/themes/dark.css
+++ b/src/librustdoc/html/static/css/themes/dark.css
@@ -54,8 +54,8 @@ input:focus + .slider {
 	background: #444;
 }
 
-.line-numbers span { color: #3B91E2; }
-.line-numbers .line-highlighted {
+.src-line-numbers span { color: #3B91E2; }
+.src-line-numbers .line-highlighted {
 	background-color: #0a042f !important;
 }
 
@@ -141,7 +141,7 @@ details.rustdoc-toggle > summary::before {
 	background: none;
 }
 
-.line-numbers :target { background-color: transparent; }
+.src-line-numbers :target { background-color: transparent; }
 
 /* Code highlighting */
 pre.rust .kw { color: #ab8ac1; }
@@ -155,7 +155,7 @@ pre.rust .question-mark {
 	color: #ff9011;
 }
 
-.example-wrap > pre.line-number {
+.example-wrap > pre.example-line-numbers {
 	border-color: #4a4949;
 }
 
diff --git a/src/librustdoc/html/static/css/themes/light.css b/src/librustdoc/html/static/css/themes/light.css
index 64335f6292801..377aca7b3a79f 100644
--- a/src/librustdoc/html/static/css/themes/light.css
+++ b/src/librustdoc/html/static/css/themes/light.css
@@ -53,8 +53,8 @@ input:focus + .slider {
 	background-color: #fff;
 }
 
-.line-numbers span { color: #c67e2d; }
-.line-numbers .line-highlighted {
+.src-line-numbers span { color: #c67e2d; }
+.src-line-numbers .line-highlighted {
 	background-color: #FDFFD3 !important;
 }
 
@@ -125,7 +125,7 @@ body.source .example-wrap pre.rust a {
 .stab { background: #FFF5D6; border-color: #FFC600; }
 .stab.portability > code { background: none; }
 
-.line-numbers :target { background-color: transparent; }
+.src-line-numbers :target { background-color: transparent; }
 
 /* Code highlighting */
 pre.rust .kw { color: #8959A8; }
@@ -141,7 +141,7 @@ pre.rust .question-mark {
 	color: #ff9011;
 }
 
-.example-wrap > pre.line-number {
+.example-wrap > pre.example-line-numbers {
 	border-color: #c7c7c7;
 }
 
diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js
index c9674f11a5ecf..bbaf6d3b50797 100644
--- a/src/librustdoc/html/static/js/main.js
+++ b/src/librustdoc/html/static/js/main.js
@@ -699,7 +699,7 @@ function loadCss(cssFileName) {
     window.rustdoc_add_line_numbers_to_examples = () => {
         onEachLazy(document.getElementsByClassName("rust-example-rendered"), x => {
             const parent = x.parentNode;
-            const line_numbers = parent.querySelectorAll(".line-number");
+            const line_numbers = parent.querySelectorAll(".example-line-numbers");
             if (line_numbers.length > 0) {
                 return;
             }
@@ -709,7 +709,7 @@ function loadCss(cssFileName) {
                 elems.push(i + 1);
             }
             const node = document.createElement("pre");
-            addClass(node, "line-number");
+            addClass(node, "example-line-numbers");
             node.innerHTML = elems.join("\n");
             parent.insertBefore(node, x);
         });
@@ -718,7 +718,7 @@ function loadCss(cssFileName) {
     window.rustdoc_remove_line_numbers_from_examples = () => {
         onEachLazy(document.getElementsByClassName("rust-example-rendered"), x => {
             const parent = x.parentNode;
-            const line_numbers = parent.querySelectorAll(".line-number");
+            const line_numbers = parent.querySelectorAll(".example-line-numbers");
             for (const node of line_numbers) {
                 parent.removeChild(node);
             }
diff --git a/src/librustdoc/html/static/js/scrape-examples.js b/src/librustdoc/html/static/js/scrape-examples.js
index fd7a1449763eb..d0fd115fd15c6 100644
--- a/src/librustdoc/html/static/js/scrape-examples.js
+++ b/src/librustdoc/html/static/js/scrape-examples.js
@@ -8,7 +8,7 @@
 
     // Scroll code block to the given code location
     function scrollToLoc(elt, loc) {
-        const lines = elt.querySelector(".line-numbers");
+        const lines = elt.querySelector(".src-line-numbers");
         let scrollOffset;
 
         // If the block is greater than the size of the viewer,
diff --git a/src/librustdoc/html/static/js/source-script.js b/src/librustdoc/html/static/js/source-script.js
index 06d15d9e5ffea..8286e9201e649 100644
--- a/src/librustdoc/html/static/js/source-script.js
+++ b/src/librustdoc/html/static/js/source-script.js
@@ -183,7 +183,7 @@ function highlightSourceLines(match) {
     if (x) {
         x.scrollIntoView();
     }
-    onEachLazy(document.getElementsByClassName("line-numbers"), e => {
+    onEachLazy(document.getElementsByClassName("src-line-numbers"), e => {
         onEachLazy(e.getElementsByTagName("span"), i_e => {
             removeClass(i_e, "line-highlighted");
         });
@@ -245,7 +245,7 @@ window.addEventListener("hashchange", () => {
     }
 });
 
-onEachLazy(document.getElementsByClassName("line-numbers"), el => {
+onEachLazy(document.getElementsByClassName("src-line-numbers"), el => {
     el.addEventListener("click", handleSourceHighlight);
 });
 
diff --git a/src/test/run-make-fulldeps/rustdoc-scrape-examples-macros/src/lib.rs b/src/test/run-make-fulldeps/rustdoc-scrape-examples-macros/src/lib.rs
index bac3970a4d37f..d8658a0f25577 100644
--- a/src/test/run-make-fulldeps/rustdoc-scrape-examples-macros/src/lib.rs
+++ b/src/test/run-make-fulldeps/rustdoc-scrape-examples-macros/src/lib.rs
@@ -1,8 +1,8 @@
 // Scraped example should only include line numbers for items b and c in ex.rs
-// @!has foobar/fn.f.html '//*[@class="line-numbers"]' '14'
-// @has foobar/fn.f.html '//*[@class="line-numbers"]' '15'
-// @has foobar/fn.f.html '//*[@class="line-numbers"]' '21'
-// @!has foobar/fn.f.html '//*[@class="line-numbers"]' '22'
+// @!has foobar/fn.f.html '//*[@class="src-line-numbers"]' '14'
+// @has foobar/fn.f.html '//*[@class="src-line-numbers"]' '15'
+// @has foobar/fn.f.html '//*[@class="src-line-numbers"]' '21'
+// @!has foobar/fn.f.html '//*[@class="src-line-numbers"]' '22'
 
 pub fn f() {}
 
diff --git a/src/test/rustdoc-gui/basic-code.goml b/src/test/rustdoc-gui/basic-code.goml
index 27deb2c989c8b..79090b499c832 100644
--- a/src/test/rustdoc-gui/basic-code.goml
+++ b/src/test/rustdoc-gui/basic-code.goml
@@ -1,3 +1,3 @@
 goto: file://|DOC_PATH|/test_docs/index.html
 click: ".srclink"
-assert-count: (".line-numbers", 1)
+assert-count: (".src-line-numbers", 1)
diff --git a/src/test/rustdoc-gui/docblock-code-block-line-number.goml b/src/test/rustdoc-gui/docblock-code-block-line-number.goml
index ebfffbce71561..4e1e83c0fbd73 100644
--- a/src/test/rustdoc-gui/docblock-code-block-line-number.goml
+++ b/src/test/rustdoc-gui/docblock-code-block-line-number.goml
@@ -2,7 +2,7 @@
 goto: file://|DOC_PATH|/test_docs/fn.foo.html
 
 // We check that without this setting, there is no line number displayed.
-assert-false: "pre.line-number"
+assert-false: "pre.example-line-numbers"
 
 // We now set the setting to show the line numbers on code examples.
 local-storage: {"rustdoc-line-numbers": "true" }
@@ -10,16 +10,16 @@ local-storage: {"rustdoc-line-numbers": "true" }
 reload:
 
 // We wait for them to be added into the DOM by the JS...
-wait-for: "pre.line-number"
+wait-for: "pre.example-line-numbers"
 // If the test didn't fail, it means that it was found!
 // Let's now check some CSS properties...
-assert-css: ("pre.line-number", {
+assert-css: ("pre.example-line-numbers", {
     "margin": "0px",
     "padding": "13px 8px",
     "text-align": "right",
 })
 // The first code block has two lines so let's check its `
` elements lists both of them.
-assert-text: ("pre.line-number", "1\n2")
+assert-text: ("pre.example-line-numbers", "1\n2")
 
 // Now, try changing the setting dynamically. We'll turn it off, using the settings menu,
 // and make sure it goes away.
@@ -32,8 +32,8 @@ assert-css: ("#settings", {"display": "block"})
 // Then, click the toggle button.
 click: "input#line-numbers + .slider"
 wait-for: 100 // wait-for-false does not exist
-assert-false: "pre.line-number"
+assert-false: "pre.example-line-numbers"
 
 // Finally, turn it on again.
 click: "input#line-numbers + .slider"
-wait-for: "pre.line-number"
+wait-for: "pre.example-line-numbers"
diff --git a/src/test/rustdoc-gui/source-code-page.goml b/src/test/rustdoc-gui/source-code-page.goml
index 581f826a3d94d..5f0bb7f19c050 100644
--- a/src/test/rustdoc-gui/source-code-page.goml
+++ b/src/test/rustdoc-gui/source-code-page.goml
@@ -1,22 +1,22 @@
 // Checks that the interactions with the source code pages are working as expected.
 goto: file://|DOC_PATH|/src/test_docs/lib.rs.html
 // Check that we can click on the line number.
-click: ".line-numbers > span:nth-child(4)" // This is the span for line 4.
+click: ".src-line-numbers > span:nth-child(4)" // This is the span for line 4.
 // Ensure that the page URL was updated.
 assert-document-property: ({"URL": "lib.rs.html#4"}, ENDS_WITH)
 assert-attribute: ("//*[@id='4']", {"class": "line-highlighted"})
 // We now check that the good spans are highlighted
 goto: file://|DOC_PATH|/src/test_docs/lib.rs.html#4-6
-assert-attribute-false: (".line-numbers > span:nth-child(3)", {"class": "line-highlighted"})
-assert-attribute: (".line-numbers > span:nth-child(4)", {"class": "line-highlighted"})
-assert-attribute: (".line-numbers > span:nth-child(5)", {"class": "line-highlighted"})
-assert-attribute: (".line-numbers > span:nth-child(6)", {"class": "line-highlighted"})
-assert-attribute-false: (".line-numbers > span:nth-child(7)", {"class": "line-highlighted"})
+assert-attribute-false: (".src-line-numbers > span:nth-child(3)", {"class": "line-highlighted"})
+assert-attribute: (".src-line-numbers > span:nth-child(4)", {"class": "line-highlighted"})
+assert-attribute: (".src-line-numbers > span:nth-child(5)", {"class": "line-highlighted"})
+assert-attribute: (".src-line-numbers > span:nth-child(6)", {"class": "line-highlighted"})
+assert-attribute-false: (".src-line-numbers > span:nth-child(7)", {"class": "line-highlighted"})
 // This is to ensure that the content is correctly align with the line numbers.
 compare-elements-position: ("//*[@id='1']", ".rust > code > span", ("y"))
 
 // Assert that the line numbers text is aligned to the right.
-assert-css: (".line-numbers", {"text-align": "right"})
+assert-css: (".src-line-numbers", {"text-align": "right"})
 
 // Now let's check that clicking on something else than the line number doesn't
 // do anything (and certainly not add a `#NaN` to the URL!).
@@ -24,7 +24,7 @@ show-text: true
 goto: file://|DOC_PATH|/src/test_docs/lib.rs.html
 // We use this assert-position to know where we will click.
 assert-position: ("//*[@id='1']", {"x": 104, "y": 103})
-// We click on the left of the "1" span but still in the "line-number" `
`.
+// We click on the left of the "1" span but still in the "src-line-number" `
`.
 click: (103, 103)
 assert-document-property: ({"URL": "/lib.rs.html"}, ENDS_WITH)
 

From 9ca2ae3fa74c0598d0b0dfe6e84cae7b39913539 Mon Sep 17 00:00:00 2001
From: Michael Howell 
Date: Mon, 26 Sep 2022 12:21:27 -0700
Subject: [PATCH 278/586] rustdoc: simplify example-line-numbers CSS selector

---
 src/librustdoc/html/static/css/rustdoc.css      | 2 +-
 src/librustdoc/html/static/css/themes/ayu.css   | 2 +-
 src/librustdoc/html/static/css/themes/dark.css  | 2 +-
 src/librustdoc/html/static/css/themes/light.css | 2 +-
 4 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css
index b4c7638b79841..a8c044ab69bd9 100644
--- a/src/librustdoc/html/static/css/rustdoc.css
+++ b/src/librustdoc/html/static/css/rustdoc.css
@@ -578,7 +578,7 @@ h2.location a {
 	position: relative;
 }
 
-.example-wrap > pre.example-line-numbers {
+pre.example-line-numbers {
 	overflow: initial;
 	border: 1px solid;
 	padding: 13px 8px;
diff --git a/src/librustdoc/html/static/css/themes/ayu.css b/src/librustdoc/html/static/css/themes/ayu.css
index 34411ace6fd37..44238ca573dcd 100644
--- a/src/librustdoc/html/static/css/themes/ayu.css
+++ b/src/librustdoc/html/static/css/themes/ayu.css
@@ -190,7 +190,7 @@ pre.rust .attribute {
 	color: #e6e1cf;
 }
 
-.example-wrap > pre.example-line-numbers {
+pre.example-line-numbers {
 	color: #5c67736e;
 	border: none;
 }
diff --git a/src/librustdoc/html/static/css/themes/dark.css b/src/librustdoc/html/static/css/themes/dark.css
index 9978f5f91874c..858d836c03d5e 100644
--- a/src/librustdoc/html/static/css/themes/dark.css
+++ b/src/librustdoc/html/static/css/themes/dark.css
@@ -155,7 +155,7 @@ pre.rust .question-mark {
 	color: #ff9011;
 }
 
-.example-wrap > pre.example-line-numbers {
+pre.example-line-numbers {
 	border-color: #4a4949;
 }
 
diff --git a/src/librustdoc/html/static/css/themes/light.css b/src/librustdoc/html/static/css/themes/light.css
index 377aca7b3a79f..6fbea6f6c7a5d 100644
--- a/src/librustdoc/html/static/css/themes/light.css
+++ b/src/librustdoc/html/static/css/themes/light.css
@@ -141,7 +141,7 @@ pre.rust .question-mark {
 	color: #ff9011;
 }
 
-.example-wrap > pre.example-line-numbers {
+pre.example-line-numbers {
 	border-color: #c7c7c7;
 }
 

From ad8f519ed75ebaf12e2a2b56f2a580cfae87a75a Mon Sep 17 00:00:00 2001
From: Josh Stone 
Date: Mon, 26 Sep 2022 13:40:24 -0700
Subject: [PATCH 279/586] Enable inline stack probes on PowerPC and SystemZ

---
 .../src/spec/powerpc64_unknown_freebsd.rs     |  3 +-
 .../src/spec/powerpc64_unknown_linux_gnu.rs   |  3 +-
 .../src/spec/powerpc64_unknown_linux_musl.rs  |  3 +-
 .../src/spec/powerpc64_unknown_openbsd.rs     |  3 +-
 .../src/spec/powerpc64_wrs_vxworks.rs         |  3 +-
 .../src/spec/powerpc64le_unknown_freebsd.rs   |  3 +-
 .../src/spec/powerpc64le_unknown_linux_gnu.rs |  3 +-
 .../spec/powerpc64le_unknown_linux_musl.rs    |  3 +-
 .../src/spec/powerpc_unknown_freebsd.rs       |  3 +-
 .../src/spec/powerpc_unknown_linux_gnu.rs     |  3 +-
 .../src/spec/powerpc_unknown_linux_gnuspe.rs  |  3 +-
 .../src/spec/powerpc_unknown_linux_musl.rs    |  3 +-
 .../src/spec/powerpc_unknown_netbsd.rs        |  3 +-
 .../src/spec/powerpc_unknown_openbsd.rs       |  3 +-
 .../src/spec/powerpc_wrs_vxworks.rs           |  3 +-
 .../src/spec/powerpc_wrs_vxworks_spe.rs       |  3 +-
 .../src/spec/s390x_unknown_linux_gnu.rs       |  3 +-
 .../src/spec/s390x_unknown_linux_musl.rs      |  3 +-
 src/test/codegen/stack-probes-call.rs         | 22 ++++++++++++++
 src/test/codegen/stack-probes-inline.rs       | 26 +++++++++++++++++
 src/test/codegen/stack-probes.rs              | 22 --------------
 src/test/ui/abi/stack-probes-lto.rs           |  2 --
 src/test/ui/abi/stack-probes.rs               | 29 +++++++++++++++----
 23 files changed, 107 insertions(+), 48 deletions(-)
 create mode 100644 src/test/codegen/stack-probes-call.rs
 create mode 100644 src/test/codegen/stack-probes-inline.rs
 delete mode 100644 src/test/codegen/stack-probes.rs

diff --git a/compiler/rustc_target/src/spec/powerpc64_unknown_freebsd.rs b/compiler/rustc_target/src/spec/powerpc64_unknown_freebsd.rs
index 803453c4ac411..9f4cc3d80f1c9 100644
--- a/compiler/rustc_target/src/spec/powerpc64_unknown_freebsd.rs
+++ b/compiler/rustc_target/src/spec/powerpc64_unknown_freebsd.rs
@@ -1,11 +1,12 @@
 use crate::abi::Endian;
-use crate::spec::{LinkerFlavor, Target, TargetOptions};
+use crate::spec::{LinkerFlavor, StackProbeType, Target, TargetOptions};
 
 pub fn target() -> Target {
     let mut base = super::freebsd_base::opts();
     base.cpu = "ppc64".into();
     base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]);
     base.max_atomic_width = Some(64);
+    base.stack_probes = StackProbeType::Inline;
 
     Target {
         llvm_target: "powerpc64-unknown-freebsd".into(),
diff --git a/compiler/rustc_target/src/spec/powerpc64_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/powerpc64_unknown_linux_gnu.rs
index 1cb9ce40cb1e5..21955a616c2de 100644
--- a/compiler/rustc_target/src/spec/powerpc64_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/powerpc64_unknown_linux_gnu.rs
@@ -1,11 +1,12 @@
 use crate::abi::Endian;
-use crate::spec::{LinkerFlavor, Target, TargetOptions};
+use crate::spec::{LinkerFlavor, StackProbeType, Target, TargetOptions};
 
 pub fn target() -> Target {
     let mut base = super::linux_gnu_base::opts();
     base.cpu = "ppc64".into();
     base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]);
     base.max_atomic_width = Some(64);
+    base.stack_probes = StackProbeType::Inline;
 
     Target {
         llvm_target: "powerpc64-unknown-linux-gnu".into(),
diff --git a/compiler/rustc_target/src/spec/powerpc64_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/powerpc64_unknown_linux_musl.rs
index 159335eb60735..bbf86e4ff41ca 100644
--- a/compiler/rustc_target/src/spec/powerpc64_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/powerpc64_unknown_linux_musl.rs
@@ -1,11 +1,12 @@
 use crate::abi::Endian;
-use crate::spec::{LinkerFlavor, Target, TargetOptions};
+use crate::spec::{LinkerFlavor, StackProbeType, Target, TargetOptions};
 
 pub fn target() -> Target {
     let mut base = super::linux_musl_base::opts();
     base.cpu = "ppc64".into();
     base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]);
     base.max_atomic_width = Some(64);
+    base.stack_probes = StackProbeType::Inline;
 
     Target {
         llvm_target: "powerpc64-unknown-linux-musl".into(),
diff --git a/compiler/rustc_target/src/spec/powerpc64_unknown_openbsd.rs b/compiler/rustc_target/src/spec/powerpc64_unknown_openbsd.rs
index 9cb3a67dc58b3..bfa61a21fb3e6 100644
--- a/compiler/rustc_target/src/spec/powerpc64_unknown_openbsd.rs
+++ b/compiler/rustc_target/src/spec/powerpc64_unknown_openbsd.rs
@@ -1,11 +1,12 @@
 use crate::abi::Endian;
-use crate::spec::{LinkerFlavor, Target, TargetOptions};
+use crate::spec::{LinkerFlavor, StackProbeType, Target, TargetOptions};
 
 pub fn target() -> Target {
     let mut base = super::openbsd_base::opts();
     base.cpu = "ppc64".into();
     base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]);
     base.max_atomic_width = Some(64);
+    base.stack_probes = StackProbeType::Inline;
 
     Target {
         llvm_target: "powerpc64-unknown-openbsd".into(),
diff --git a/compiler/rustc_target/src/spec/powerpc64_wrs_vxworks.rs b/compiler/rustc_target/src/spec/powerpc64_wrs_vxworks.rs
index b7420d232ca80..4ebf342ad22e4 100644
--- a/compiler/rustc_target/src/spec/powerpc64_wrs_vxworks.rs
+++ b/compiler/rustc_target/src/spec/powerpc64_wrs_vxworks.rs
@@ -1,11 +1,12 @@
 use crate::abi::Endian;
-use crate::spec::{LinkerFlavor, Target, TargetOptions};
+use crate::spec::{LinkerFlavor, StackProbeType, Target, TargetOptions};
 
 pub fn target() -> Target {
     let mut base = super::vxworks_base::opts();
     base.cpu = "ppc64".into();
     base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]);
     base.max_atomic_width = Some(64);
+    base.stack_probes = StackProbeType::Inline;
 
     Target {
         llvm_target: "powerpc64-unknown-linux-gnu".into(),
diff --git a/compiler/rustc_target/src/spec/powerpc64le_unknown_freebsd.rs b/compiler/rustc_target/src/spec/powerpc64le_unknown_freebsd.rs
index a3d1800437139..a7ab907853143 100644
--- a/compiler/rustc_target/src/spec/powerpc64le_unknown_freebsd.rs
+++ b/compiler/rustc_target/src/spec/powerpc64le_unknown_freebsd.rs
@@ -1,10 +1,11 @@
-use crate::spec::{LinkerFlavor, Target, TargetOptions};
+use crate::spec::{LinkerFlavor, StackProbeType, Target, TargetOptions};
 
 pub fn target() -> Target {
     let mut base = super::freebsd_base::opts();
     base.cpu = "ppc64le".into();
     base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]);
     base.max_atomic_width = Some(64);
+    base.stack_probes = StackProbeType::Inline;
 
     Target {
         llvm_target: "powerpc64le-unknown-freebsd".into(),
diff --git a/compiler/rustc_target/src/spec/powerpc64le_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/powerpc64le_unknown_linux_gnu.rs
index e18ff3be4485a..69fd6be6dc0e0 100644
--- a/compiler/rustc_target/src/spec/powerpc64le_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/powerpc64le_unknown_linux_gnu.rs
@@ -1,10 +1,11 @@
-use crate::spec::{LinkerFlavor, Target, TargetOptions};
+use crate::spec::{LinkerFlavor, StackProbeType, Target, TargetOptions};
 
 pub fn target() -> Target {
     let mut base = super::linux_gnu_base::opts();
     base.cpu = "ppc64le".into();
     base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]);
     base.max_atomic_width = Some(64);
+    base.stack_probes = StackProbeType::Inline;
 
     Target {
         llvm_target: "powerpc64le-unknown-linux-gnu".into(),
diff --git a/compiler/rustc_target/src/spec/powerpc64le_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/powerpc64le_unknown_linux_musl.rs
index b84943d23a961..ae3a8b545191a 100644
--- a/compiler/rustc_target/src/spec/powerpc64le_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/powerpc64le_unknown_linux_musl.rs
@@ -1,10 +1,11 @@
-use crate::spec::{LinkerFlavor, Target, TargetOptions};
+use crate::spec::{LinkerFlavor, StackProbeType, Target, TargetOptions};
 
 pub fn target() -> Target {
     let mut base = super::linux_musl_base::opts();
     base.cpu = "ppc64le".into();
     base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]);
     base.max_atomic_width = Some(64);
+    base.stack_probes = StackProbeType::Inline;
 
     Target {
         llvm_target: "powerpc64le-unknown-linux-musl".into(),
diff --git a/compiler/rustc_target/src/spec/powerpc_unknown_freebsd.rs b/compiler/rustc_target/src/spec/powerpc_unknown_freebsd.rs
index 75ac66c276d57..b5d4e5de05e29 100644
--- a/compiler/rustc_target/src/spec/powerpc_unknown_freebsd.rs
+++ b/compiler/rustc_target/src/spec/powerpc_unknown_freebsd.rs
@@ -1,11 +1,12 @@
 use crate::abi::Endian;
-use crate::spec::{LinkerFlavor, Target, TargetOptions};
+use crate::spec::{LinkerFlavor, StackProbeType, Target, TargetOptions};
 
 pub fn target() -> Target {
     let mut base = super::freebsd_base::opts();
     // Extra hint to linker that we are generating secure-PLT code.
     base.add_pre_link_args(LinkerFlavor::Gcc, &["-m32", "--target=powerpc-unknown-freebsd13.0"]);
     base.max_atomic_width = Some(32);
+    base.stack_probes = StackProbeType::Inline;
 
     Target {
         llvm_target: "powerpc-unknown-freebsd13.0".into(),
diff --git a/compiler/rustc_target/src/spec/powerpc_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/powerpc_unknown_linux_gnu.rs
index 6686a0bbf04aa..0ceb66c327be5 100644
--- a/compiler/rustc_target/src/spec/powerpc_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/powerpc_unknown_linux_gnu.rs
@@ -1,10 +1,11 @@
 use crate::abi::Endian;
-use crate::spec::{LinkerFlavor, Target, TargetOptions};
+use crate::spec::{LinkerFlavor, StackProbeType, Target, TargetOptions};
 
 pub fn target() -> Target {
     let mut base = super::linux_gnu_base::opts();
     base.add_pre_link_args(LinkerFlavor::Gcc, &["-m32"]);
     base.max_atomic_width = Some(32);
+    base.stack_probes = StackProbeType::Inline;
 
     Target {
         llvm_target: "powerpc-unknown-linux-gnu".into(),
diff --git a/compiler/rustc_target/src/spec/powerpc_unknown_linux_gnuspe.rs b/compiler/rustc_target/src/spec/powerpc_unknown_linux_gnuspe.rs
index 6a250f4b51c90..716090f39cac2 100644
--- a/compiler/rustc_target/src/spec/powerpc_unknown_linux_gnuspe.rs
+++ b/compiler/rustc_target/src/spec/powerpc_unknown_linux_gnuspe.rs
@@ -1,10 +1,11 @@
 use crate::abi::Endian;
-use crate::spec::{LinkerFlavor, Target, TargetOptions};
+use crate::spec::{LinkerFlavor, StackProbeType, Target, TargetOptions};
 
 pub fn target() -> Target {
     let mut base = super::linux_gnu_base::opts();
     base.add_pre_link_args(LinkerFlavor::Gcc, &["-mspe"]);
     base.max_atomic_width = Some(32);
+    base.stack_probes = StackProbeType::Inline;
 
     Target {
         llvm_target: "powerpc-unknown-linux-gnuspe".into(),
diff --git a/compiler/rustc_target/src/spec/powerpc_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/powerpc_unknown_linux_musl.rs
index 34200c6790670..d8cd158584a3c 100644
--- a/compiler/rustc_target/src/spec/powerpc_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/powerpc_unknown_linux_musl.rs
@@ -1,10 +1,11 @@
 use crate::abi::Endian;
-use crate::spec::{LinkerFlavor, Target, TargetOptions};
+use crate::spec::{LinkerFlavor, StackProbeType, Target, TargetOptions};
 
 pub fn target() -> Target {
     let mut base = super::linux_musl_base::opts();
     base.add_pre_link_args(LinkerFlavor::Gcc, &["-m32"]);
     base.max_atomic_width = Some(32);
+    base.stack_probes = StackProbeType::Inline;
 
     Target {
         llvm_target: "powerpc-unknown-linux-musl".into(),
diff --git a/compiler/rustc_target/src/spec/powerpc_unknown_netbsd.rs b/compiler/rustc_target/src/spec/powerpc_unknown_netbsd.rs
index 60661ef9b5d4f..7053e4b9c26fe 100644
--- a/compiler/rustc_target/src/spec/powerpc_unknown_netbsd.rs
+++ b/compiler/rustc_target/src/spec/powerpc_unknown_netbsd.rs
@@ -1,10 +1,11 @@
 use crate::abi::Endian;
-use crate::spec::{LinkerFlavor, Target, TargetOptions};
+use crate::spec::{LinkerFlavor, StackProbeType, Target, TargetOptions};
 
 pub fn target() -> Target {
     let mut base = super::netbsd_base::opts();
     base.add_pre_link_args(LinkerFlavor::Gcc, &["-m32"]);
     base.max_atomic_width = Some(32);
+    base.stack_probes = StackProbeType::Inline;
 
     Target {
         llvm_target: "powerpc-unknown-netbsd".into(),
diff --git a/compiler/rustc_target/src/spec/powerpc_unknown_openbsd.rs b/compiler/rustc_target/src/spec/powerpc_unknown_openbsd.rs
index ad2c3d40f35ed..dec85f9961b82 100644
--- a/compiler/rustc_target/src/spec/powerpc_unknown_openbsd.rs
+++ b/compiler/rustc_target/src/spec/powerpc_unknown_openbsd.rs
@@ -1,10 +1,11 @@
 use crate::abi::Endian;
-use crate::spec::Target;
+use crate::spec::{StackProbeType, Target};
 
 pub fn target() -> Target {
     let mut base = super::openbsd_base::opts();
     base.endian = Endian::Big;
     base.max_atomic_width = Some(32);
+    base.stack_probes = StackProbeType::Inline;
 
     Target {
         llvm_target: "powerpc-unknown-openbsd".into(),
diff --git a/compiler/rustc_target/src/spec/powerpc_wrs_vxworks.rs b/compiler/rustc_target/src/spec/powerpc_wrs_vxworks.rs
index 3f24966e06ec7..e0c5db6eacfe6 100644
--- a/compiler/rustc_target/src/spec/powerpc_wrs_vxworks.rs
+++ b/compiler/rustc_target/src/spec/powerpc_wrs_vxworks.rs
@@ -1,10 +1,11 @@
 use crate::abi::Endian;
-use crate::spec::{LinkerFlavor, Target, TargetOptions};
+use crate::spec::{LinkerFlavor, StackProbeType, Target, TargetOptions};
 
 pub fn target() -> Target {
     let mut base = super::vxworks_base::opts();
     base.add_pre_link_args(LinkerFlavor::Gcc, &["-m32", "--secure-plt"]);
     base.max_atomic_width = Some(32);
+    base.stack_probes = StackProbeType::Inline;
 
     Target {
         llvm_target: "powerpc-unknown-linux-gnu".into(),
diff --git a/compiler/rustc_target/src/spec/powerpc_wrs_vxworks_spe.rs b/compiler/rustc_target/src/spec/powerpc_wrs_vxworks_spe.rs
index 0f04f41f9e592..c7f41b1da87f6 100644
--- a/compiler/rustc_target/src/spec/powerpc_wrs_vxworks_spe.rs
+++ b/compiler/rustc_target/src/spec/powerpc_wrs_vxworks_spe.rs
@@ -1,10 +1,11 @@
 use crate::abi::Endian;
-use crate::spec::{LinkerFlavor, Target, TargetOptions};
+use crate::spec::{LinkerFlavor, StackProbeType, Target, TargetOptions};
 
 pub fn target() -> Target {
     let mut base = super::vxworks_base::opts();
     base.add_pre_link_args(LinkerFlavor::Gcc, &["-mspe", "--secure-plt"]);
     base.max_atomic_width = Some(32);
+    base.stack_probes = StackProbeType::Inline;
 
     Target {
         llvm_target: "powerpc-unknown-linux-gnuspe".into(),
diff --git a/compiler/rustc_target/src/spec/s390x_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/s390x_unknown_linux_gnu.rs
index 8757bbed8ad86..9bb9c931f5c46 100644
--- a/compiler/rustc_target/src/spec/s390x_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/s390x_unknown_linux_gnu.rs
@@ -1,5 +1,5 @@
 use crate::abi::Endian;
-use crate::spec::Target;
+use crate::spec::{StackProbeType, Target};
 
 pub fn target() -> Target {
     let mut base = super::linux_gnu_base::opts();
@@ -12,6 +12,7 @@ pub fn target() -> Target {
     base.features = "-vector".into();
     base.max_atomic_width = Some(64);
     base.min_global_align = Some(16);
+    base.stack_probes = StackProbeType::Inline;
 
     Target {
         llvm_target: "s390x-unknown-linux-gnu".into(),
diff --git a/compiler/rustc_target/src/spec/s390x_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/s390x_unknown_linux_musl.rs
index 4c855271a2ab5..f877279781de0 100644
--- a/compiler/rustc_target/src/spec/s390x_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/s390x_unknown_linux_musl.rs
@@ -1,5 +1,5 @@
 use crate::abi::Endian;
-use crate::spec::Target;
+use crate::spec::{StackProbeType, Target};
 
 pub fn target() -> Target {
     let mut base = super::linux_musl_base::opts();
@@ -13,6 +13,7 @@ pub fn target() -> Target {
     base.max_atomic_width = Some(64);
     base.min_global_align = Some(16);
     base.static_position_independent_executables = true;
+    base.stack_probes = StackProbeType::Inline;
 
     Target {
         llvm_target: "s390x-unknown-linux-musl".into(),
diff --git a/src/test/codegen/stack-probes-call.rs b/src/test/codegen/stack-probes-call.rs
new file mode 100644
index 0000000000000..56b02fdecadcb
--- /dev/null
+++ b/src/test/codegen/stack-probes-call.rs
@@ -0,0 +1,22 @@
+// Check the "probe-stack" attribute for targets with `StackProbeType::Call`,
+// or `StackProbeType::InlineOrCall` when running on older LLVM.
+
+// compile-flags: -C no-prepopulate-passes
+// revisions: i686 x86_64
+//[i686] compile-flags: --target i686-unknown-linux-gnu
+//[i686] needs-llvm-components: x86
+//[x86_64] compile-flags: --target x86_64-unknown-linux-gnu
+//[x86_64] needs-llvm-components: x86
+
+#![crate_type = "rlib"]
+#![feature(no_core, lang_items)]
+#![no_core]
+
+#[lang = "sized"]
+trait Sized {}
+
+#[no_mangle]
+pub fn foo() {
+// CHECK: @foo() unnamed_addr #0
+// CHECK: attributes #0 = { {{.*}}"probe-stack"="__rust_probestack"{{.*}} }
+}
diff --git a/src/test/codegen/stack-probes-inline.rs b/src/test/codegen/stack-probes-inline.rs
new file mode 100644
index 0000000000000..837a161081069
--- /dev/null
+++ b/src/test/codegen/stack-probes-inline.rs
@@ -0,0 +1,26 @@
+// Check the "probe-stack" attribute for targets with `StackProbeType::Inline`,
+// or `StackProbeType::InlineOrCall` when running on newer LLVM.
+
+// compile-flags: -C no-prepopulate-passes
+// revisions: powerpc powerpc64 powerpc64le s390x
+//[powerpc] compile-flags: --target powerpc-unknown-linux-gnu
+//[powerpc] needs-llvm-components: powerpc
+//[powerpc64] compile-flags: --target powerpc64-unknown-linux-gnu
+//[powerpc64] needs-llvm-components: powerpc
+//[powerpc64le] compile-flags: --target powerpc64le-unknown-linux-gnu
+//[powerpc64le] needs-llvm-components: powerpc
+//[s390x] compile-flags: --target s390x-unknown-linux-gnu
+//[s390x] needs-llvm-components: systemz
+
+#![crate_type = "rlib"]
+#![feature(no_core, lang_items)]
+#![no_core]
+
+#[lang = "sized"]
+trait Sized {}
+
+#[no_mangle]
+pub fn foo() {
+// CHECK: @foo() unnamed_addr #0
+// CHECK: attributes #0 = { {{.*}}"probe-stack"="inline-asm"{{.*}} }
+}
diff --git a/src/test/codegen/stack-probes.rs b/src/test/codegen/stack-probes.rs
deleted file mode 100644
index 9bd351df3eaa0..0000000000000
--- a/src/test/codegen/stack-probes.rs
+++ /dev/null
@@ -1,22 +0,0 @@
-// ignore-arm
-// ignore-aarch64
-// ignore-mips
-// ignore-mips64
-// ignore-powerpc
-// ignore-powerpc64
-// ignore-powerpc64le
-// ignore-riscv64
-// ignore-s390x
-// ignore-sparc
-// ignore-sparc64
-// ignore-wasm
-// ignore-emscripten
-// ignore-windows
-// compile-flags: -C no-prepopulate-passes
-
-#![crate_type = "lib"]
-
-#[no_mangle]
-pub fn foo() {
-// CHECK: @foo() unnamed_addr #0
-}
diff --git a/src/test/ui/abi/stack-probes-lto.rs b/src/test/ui/abi/stack-probes-lto.rs
index 74b5e843f7742..6d934538f4c81 100644
--- a/src/test/ui/abi/stack-probes-lto.rs
+++ b/src/test/ui/abi/stack-probes-lto.rs
@@ -3,8 +3,6 @@
 // ignore-aarch64
 // ignore-mips
 // ignore-mips64
-// ignore-powerpc
-// ignore-s390x
 // ignore-sparc
 // ignore-sparc64
 // ignore-wasm
diff --git a/src/test/ui/abi/stack-probes.rs b/src/test/ui/abi/stack-probes.rs
index b497af7abad50..e7b91644b3b29 100644
--- a/src/test/ui/abi/stack-probes.rs
+++ b/src/test/ui/abi/stack-probes.rs
@@ -3,8 +3,6 @@
 // ignore-aarch64
 // ignore-mips
 // ignore-mips64
-// ignore-powerpc
-// ignore-s390x
 // ignore-sparc
 // ignore-sparc64
 // ignore-wasm
@@ -27,8 +25,9 @@ fn main() {
     let args = env::args().skip(1).collect::>();
     if args.len() > 0 {
         match &args[0][..] {
-            "main-thread" => recurse(&MaybeUninit::uninit()),
-            "child-thread" => thread::spawn(|| recurse(&MaybeUninit::uninit())).join().unwrap(),
+            "main-recurse" => overflow_recurse(),
+            "child-recurse" => thread::spawn(overflow_recurse).join().unwrap(),
+            "child-frame" => overflow_frame(),
             _ => panic!(),
         }
         return;
@@ -41,9 +40,10 @@ fn main() {
     // that we report stack overflow on the main thread, see #43052 for some
     // details
     if cfg!(not(target_os = "linux")) {
-        assert_overflow(Command::new(&me).arg("main-thread"));
+        assert_overflow(Command::new(&me).arg("main-recurse"));
     }
-    assert_overflow(Command::new(&me).arg("child-thread"));
+    assert_overflow(Command::new(&me).arg("child-recurse"));
+    assert_overflow(Command::new(&me).arg("child-frame"));
 }
 
 #[allow(unconditional_recursion)]
@@ -55,6 +55,23 @@ fn recurse(array: &MaybeUninit<[u64; 1024]>) {
     recurse(&local);
 }
 
+#[inline(never)]
+fn overflow_recurse() {
+    recurse(&MaybeUninit::uninit());
+}
+
+fn overflow_frame() {
+    // By using a 1MiB stack frame with only 512KiB stack, we'll jump over any
+    // guard page, even with 64K pages -- but stack probes should catch it.
+    const STACK_SIZE: usize = 512 * 1024;
+    thread::Builder::new().stack_size(STACK_SIZE).spawn(|| {
+        let local: MaybeUninit<[u8; 2 * STACK_SIZE]> = MaybeUninit::uninit();
+        unsafe {
+            black_box(local.as_ptr() as u64);
+        }
+    }).unwrap().join().unwrap();
+}
+
 fn assert_overflow(cmd: &mut Command) {
     let output = cmd.output().unwrap();
     assert!(!output.status.success());

From 3fac709eab78c77874f0455fc432f5d7a744623d Mon Sep 17 00:00:00 2001
From: Michael Howell 
Date: Mon, 26 Sep 2022 15:28:26 -0700
Subject: [PATCH 280/586] rustdoc: remove no-op CSS `.srclink { font-weight;
 font-size }`

When this CSS was added in 34bd2b845b3acd84c5a9bddae3ff8081c19ec5e9, source
links were nested below headers.

https://github.com/rust-lang/rust/blob/34bd2b845b3acd84c5a9bddae3ff8081c19ec5e9/src/librustdoc/html/render.rs#L4015-L4019

Now, thanks to 458e7219bc2a62f72368279945cfda632a016da1, they are now
siblings of headers, and thanks to
270d09dca9aae263671c4d32bbc7cb60dc378af8, they have the same font size that
they would've had anyway.
---
 src/librustdoc/html/static/css/rustdoc.css | 7 -------
 1 file changed, 7 deletions(-)

diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css
index 28dc4bf30108e..bbaccbf0d9355 100644
--- a/src/librustdoc/html/static/css/rustdoc.css
+++ b/src/librustdoc/html/static/css/rustdoc.css
@@ -1118,13 +1118,6 @@ so that we can apply CSS-filters to change the arrow color in themes */
 	color: var(--right-side-color);
 }
 
-
-.impl-items .srclink, .impl .srclink, .methods .srclink {
-	/* Override header settings otherwise it's too bold */
-	font-weight: normal;
-	font-size: 1rem;
-}
-
 pre.rust .question-mark {
 	font-weight: bold;
 }

From 35adb367798476eb49d3e77d44999b5f8ce8fa34 Mon Sep 17 00:00:00 2001
From: Josh Stone 
Date: Mon, 26 Sep 2022 16:51:18 -0700
Subject: [PATCH 281/586] Avoid LLVM-deprecated `Optional::hasValue`

LLVM 15 added `Optional::has_value`, and LLVM `main` (16) has deprecated
`hasValue`. However, its `explicit operator bool` does the same thing,
and was added long ago, so we can use that across our full LLVM range of
compatibility.
---
 compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
index 09f377d349f45..879a3b660b4be 100644
--- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
@@ -1044,7 +1044,7 @@ extern "C" void LLVMRustSetModulePIELevel(LLVMModuleRef M) {
 extern "C" void LLVMRustSetModuleCodeModel(LLVMModuleRef M,
                                            LLVMRustCodeModel Model) {
   auto CM = fromRust(Model);
-  if (!CM.hasValue())
+  if (!CM)
     return;
   unwrap(M)->setCodeModel(*CM);
 }

From 880ebb657a066ef039139592750f4f4ca45f8277 Mon Sep 17 00:00:00 2001
From: Nicholas Nethercote 
Date: Tue, 27 Sep 2022 09:53:04 +1000
Subject: [PATCH 282/586] Minor improvements.

Add some comments, and mark one path as unreachable.
---
 compiler/rustc_parse/src/lexer/tokentrees.rs | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/compiler/rustc_parse/src/lexer/tokentrees.rs b/compiler/rustc_parse/src/lexer/tokentrees.rs
index 749a640f92eab..3aaf3d4865fdc 100644
--- a/compiler/rustc_parse/src/lexer/tokentrees.rs
+++ b/compiler/rustc_parse/src/lexer/tokentrees.rs
@@ -8,6 +8,8 @@ use rustc_span::Span;
 
 pub(super) struct TokenTreesReader<'a> {
     string_reader: StringReader<'a>,
+    /// The "next" token, which has been obtained from the `StringReader` but
+    /// not yet handled by the `TokenTreesReader`.
     token: Token,
     /// Stack of open delimiters and their spans. Used for error message.
     open_braces: Vec<(Delimiter, Span)>,
@@ -112,7 +114,7 @@ impl<'a> TokenTreesReader<'a> {
         // The span for beginning of the delimited section
         let pre_span = self.token.span;
 
-        // Parse the open delimiter.
+        // Move past the open delimiter.
         self.open_braces.push((delim, self.token.span));
         self.token = self.string_reader.next_token().0;
 
@@ -152,7 +154,7 @@ impl<'a> TokenTreesReader<'a> {
                 } else {
                     self.matching_delim_spans.push((open_brace, open_brace_span, close_brace_span));
                 }
-                // Parse the closing delimiter.
+                // Move past the closing delimiter.
                 self.token = self.string_reader.next_token().0;
             }
             // Incorrect delimiter.
@@ -208,7 +210,7 @@ impl<'a> TokenTreesReader<'a> {
                 // and an error emitted then. Thus we don't pop from
                 // self.open_braces here.
             }
-            _ => {}
+            _ => unreachable!(),
         }
 
         TokenTree::Delimited(delim_span, delim, tts)

From 0d9c01480b9142e9c0aea24500a9461c2bee5a68 Mon Sep 17 00:00:00 2001
From: Matthew Kelly 
Date: Mon, 26 Sep 2022 20:50:33 -0400
Subject: [PATCH 283/586] remove implied link bound per review

also update .stderr outputs
---
 compiler/rustc_error_codes/src/error_codes/E0311.md           | 4 +---
 src/test/ui/error-codes/E0311.stderr                          | 4 ++--
 .../suggest-introducing-and-adding-missing-lifetime.stderr    | 1 +
 3 files changed, 4 insertions(+), 5 deletions(-)

diff --git a/compiler/rustc_error_codes/src/error_codes/E0311.md b/compiler/rustc_error_codes/src/error_codes/E0311.md
index 638c3e0a4373f..768b849817db5 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0311.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0311.md
@@ -26,9 +26,7 @@ type parameter `T` to outlive `'anon` because of the `T: 'a bound` in
 outlive `'anon` in `no_restriction()`.
 
 If `no_restriction()` were to use `&T` instead of `&()` as an argument, the
-compiler would have added an implied bound [implied
-bound](https://rust-lang.github.io/rfcs/2089-implied-bounds.html), causing this
-to compile.
+compiler would have added an implied bound, causing this to compile.
 
 This error can be resolved by explicitly naming the elided lifetime for `x` and
 then explicily requiring that the generic parameter `T` outlives that lifetime:
diff --git a/src/test/ui/error-codes/E0311.stderr b/src/test/ui/error-codes/E0311.stderr
index bc0182555af86..9873b5ae6ff13 100644
--- a/src/test/ui/error-codes/E0311.stderr
+++ b/src/test/ui/error-codes/E0311.stderr
@@ -16,8 +16,8 @@ LL |     with_restriction::(x)
    |     ^^^^^^^^^^^^^^^^^^^^^
 help: consider adding an explicit lifetime bound...
    |
-LL | fn no_restriction(x: &()) -> &() {
-   |                    ++++
+LL | fn no_restriction<'a, T: 'a>(x: &()) -> &() {
+   |                   +++  ++++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/lifetimes/suggest-introducing-and-adding-missing-lifetime.stderr b/src/test/ui/lifetimes/suggest-introducing-and-adding-missing-lifetime.stderr
index a8b0996d8b0c7..31fd8a4d633e9 100644
--- a/src/test/ui/lifetimes/suggest-introducing-and-adding-missing-lifetime.stderr
+++ b/src/test/ui/lifetimes/suggest-introducing-and-adding-missing-lifetime.stderr
@@ -21,3 +21,4 @@ LL | fn no_restriction<'a, T: 'a>(x: &()) -> &() {
 
 error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0311`.

From e123a612977145e6ea47bd85307d13cfa52455d5 Mon Sep 17 00:00:00 2001
From: Takayuki Maeda 
Date: Mon, 26 Sep 2022 23:13:09 +0900
Subject: [PATCH 284/586] create a new local var

---
 compiler/rustc_parse/src/parser/item.rs | 8 +++-----
 1 file changed, 3 insertions(+), 5 deletions(-)

diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs
index 34f25bd0716ab..297efd8dd465a 100644
--- a/compiler/rustc_parse/src/parser/item.rs
+++ b/compiler/rustc_parse/src/parser/item.rs
@@ -1291,12 +1291,10 @@ impl<'a> Parser<'a> {
     /// Parses an enum declaration.
     fn parse_item_enum(&mut self) -> PResult<'a, ItemInfo> {
         if self.token.is_keyword(kw::Struct) {
-            let mut err = self.struct_span_err(
-                self.prev_token.span.to(self.token.span),
-                "`enum` and `struct` are mutually exclusive",
-            );
+            let span = self.prev_token.span.to(self.token.span);
+            let mut err = self.struct_span_err(span, "`enum` and `struct` are mutually exclusive");
             err.span_suggestion(
-                self.prev_token.span.to(self.token.span),
+                span,
                 "replace `enum struct` with",
                 "enum",
                 Applicability::MachineApplicable,

From 4f44dee50129ebd5da77a14a786849973f47b38f Mon Sep 17 00:00:00 2001
From: Takayuki Maeda 
Date: Mon, 26 Sep 2022 23:13:38 +0900
Subject: [PATCH 285/586] add a label to struct/enum/union ident name

---
 compiler/rustc_parse/src/parser/item.rs       | 36 +++++++++++++------
 ...edition-error-in-non-macro-position.stderr |  4 ++-
 .../parser/doc-before-struct-rbrace-1.stderr  |  3 ++
 .../ui/parser/fn-field-parse-error-ice.stderr |  2 ++
 src/test/ui/parser/issues/issue-48636.stderr  |  2 ++
 ...0-unicode-ident-after-missing-comma.stderr |  2 ++
 src/test/ui/parser/macro/issue-37113.stderr   |  2 ++
 .../missing-close-brace-in-struct.stderr      |  3 ++
 ...osing-angle-bracket-struct-field-ty.stderr |  3 ++
 src/test/ui/parser/recover-enum2.stderr       |  2 ++
 src/test/ui/parser/recover-field-semi.stderr  |  8 ++++-
 src/test/ui/parser/recover-struct.stderr      |  2 ++
 .../ui/parser/recovered-struct-variant.stderr |  4 ++-
 .../parser/removed-syntax-enum-newtype.stderr |  4 ++-
 .../ui/parser/removed-syntax-field-let.stderr |  2 ++
 .../removed-syntax-field-semicolon.stderr     |  2 ++
 ...ue-66270-pat-struct-parser-recovery.stderr |  2 ++
 src/test/ui/proc-macro/derive-bad.stderr      |  5 ++-
 src/test/ui/pub/pub-restricted-error.stderr   |  2 ++
 .../ui/structs/struct-fn-in-definition.stderr |  9 +++++
 ...t-field-type-including-single-colon.stderr |  4 +++
 ...on-invalid-type-node-after-recovery.stderr |  4 ++-
 22 files changed, 91 insertions(+), 16 deletions(-)

diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs
index 297efd8dd465a..6c4cfcf6ddf4c 100644
--- a/compiler/rustc_parse/src/parser/item.rs
+++ b/compiler/rustc_parse/src/parser/item.rs
@@ -1318,7 +1318,8 @@ impl<'a> Parser<'a> {
             (vec![], false)
         } else {
             self.parse_delim_comma_seq(Delimiter::Brace, |p| p.parse_enum_variant()).map_err(
-                |e| {
+                |mut e| {
+                    e.span_label(id.span, "while parsing this enum");
                     self.recover_stmt();
                     e
                 },
@@ -1345,7 +1346,8 @@ impl<'a> Parser<'a> {
 
                 let struct_def = if this.check(&token::OpenDelim(Delimiter::Brace)) {
                     // Parse a struct variant.
-                    let (fields, recovered) = this.parse_record_struct_body("struct", false)?;
+                    let (fields, recovered) =
+                        this.parse_record_struct_body("struct", ident.span, false)?;
                     VariantData::Struct(fields, recovered)
                 } else if this.check(&token::OpenDelim(Delimiter::Parenthesis)) {
                     VariantData::Tuple(this.parse_tuple_struct_body()?, DUMMY_NODE_ID)
@@ -1399,8 +1401,11 @@ impl<'a> Parser<'a> {
                 VariantData::Unit(DUMMY_NODE_ID)
             } else {
                 // If we see: `struct Foo where T: Copy { ... }`
-                let (fields, recovered) =
-                    self.parse_record_struct_body("struct", generics.where_clause.has_where_token)?;
+                let (fields, recovered) = self.parse_record_struct_body(
+                    "struct",
+                    class_name.span,
+                    generics.where_clause.has_where_token,
+                )?;
                 VariantData::Struct(fields, recovered)
             }
         // No `where` so: `struct Foo;`
@@ -1408,8 +1413,11 @@ impl<'a> Parser<'a> {
             VariantData::Unit(DUMMY_NODE_ID)
         // Record-style struct definition
         } else if self.token == token::OpenDelim(Delimiter::Brace) {
-            let (fields, recovered) =
-                self.parse_record_struct_body("struct", generics.where_clause.has_where_token)?;
+            let (fields, recovered) = self.parse_record_struct_body(
+                "struct",
+                class_name.span,
+                generics.where_clause.has_where_token,
+            )?;
             VariantData::Struct(fields, recovered)
         // Tuple-style struct definition with optional where-clause.
         } else if self.token == token::OpenDelim(Delimiter::Parenthesis) {
@@ -1438,12 +1446,18 @@ impl<'a> Parser<'a> {
 
         let vdata = if self.token.is_keyword(kw::Where) {
             generics.where_clause = self.parse_where_clause()?;
-            let (fields, recovered) =
-                self.parse_record_struct_body("union", generics.where_clause.has_where_token)?;
+            let (fields, recovered) = self.parse_record_struct_body(
+                "union",
+                class_name.span,
+                generics.where_clause.has_where_token,
+            )?;
             VariantData::Struct(fields, recovered)
         } else if self.token == token::OpenDelim(Delimiter::Brace) {
-            let (fields, recovered) =
-                self.parse_record_struct_body("union", generics.where_clause.has_where_token)?;
+            let (fields, recovered) = self.parse_record_struct_body(
+                "union",
+                class_name.span,
+                generics.where_clause.has_where_token,
+            )?;
             VariantData::Struct(fields, recovered)
         } else {
             let token_str = super::token_descr(&self.token);
@@ -1459,6 +1473,7 @@ impl<'a> Parser<'a> {
     fn parse_record_struct_body(
         &mut self,
         adt_ty: &str,
+        ident_span: Span,
         parsed_where: bool,
     ) -> PResult<'a, (Vec, /* recovered */ bool)> {
         let mut fields = Vec::new();
@@ -1473,6 +1488,7 @@ impl<'a> Parser<'a> {
                 match field {
                     Ok(field) => fields.push(field),
                     Err(mut err) => {
+                        err.span_label(ident_span, format!("while parsing this {adt_ty}"));
                         err.emit();
                         break;
                     }
diff --git a/src/test/ui/async-await/await-keyword/2018-edition-error-in-non-macro-position.stderr b/src/test/ui/async-await/await-keyword/2018-edition-error-in-non-macro-position.stderr
index ccbaa1f2af0d8..6bd8f671d7393 100644
--- a/src/test/ui/async-await/await-keyword/2018-edition-error-in-non-macro-position.stderr
+++ b/src/test/ui/async-await/await-keyword/2018-edition-error-in-non-macro-position.stderr
@@ -46,7 +46,9 @@ error: expected identifier, found keyword `await`
   --> $DIR/2018-edition-error-in-non-macro-position.rs:13:14
    |
 LL | struct Foo { await: () }
-   |              ^^^^^ expected identifier, found keyword
+   |        ---   ^^^^^ expected identifier, found keyword
+   |        |
+   |        while parsing this struct
    |
 help: escape `await` to use it as an identifier
    |
diff --git a/src/test/ui/parser/doc-before-struct-rbrace-1.stderr b/src/test/ui/parser/doc-before-struct-rbrace-1.stderr
index 19f90677398ea..92b5133b74dd6 100644
--- a/src/test/ui/parser/doc-before-struct-rbrace-1.stderr
+++ b/src/test/ui/parser/doc-before-struct-rbrace-1.stderr
@@ -1,6 +1,9 @@
 error[E0585]: found a documentation comment that doesn't document anything
   --> $DIR/doc-before-struct-rbrace-1.rs:3:5
    |
+LL | struct X {
+   |        - while parsing this struct
+LL |     a: u8,
 LL |     /// document
    |     ^^^^^^^^^^^^
    |
diff --git a/src/test/ui/parser/fn-field-parse-error-ice.stderr b/src/test/ui/parser/fn-field-parse-error-ice.stderr
index d582f61cc97a9..e9583f55b8efb 100644
--- a/src/test/ui/parser/fn-field-parse-error-ice.stderr
+++ b/src/test/ui/parser/fn-field-parse-error-ice.stderr
@@ -7,6 +7,8 @@ LL |     inner : dyn fn ()
 error: functions are not allowed in struct definitions
   --> $DIR/fn-field-parse-error-ice.rs:4:17
    |
+LL | struct Baz {
+   |        --- while parsing this struct
 LL |     inner : dyn fn ()
    |                 ^^
    |
diff --git a/src/test/ui/parser/issues/issue-48636.stderr b/src/test/ui/parser/issues/issue-48636.stderr
index 462723d1d931e..1a6e4cfd2b203 100644
--- a/src/test/ui/parser/issues/issue-48636.stderr
+++ b/src/test/ui/parser/issues/issue-48636.stderr
@@ -1,6 +1,8 @@
 error[E0585]: found a documentation comment that doesn't document anything
   --> $DIR/issue-48636.rs:7:5
    |
+LL | struct S {
+   |        - while parsing this struct
 LL |     x: u8
    |          - help: missing comma here: `,`
 LL |     /// The ID of the parent core
diff --git a/src/test/ui/parser/issues/issue-68000-unicode-ident-after-missing-comma.stderr b/src/test/ui/parser/issues/issue-68000-unicode-ident-after-missing-comma.stderr
index ef365a616437b..adabb68593c09 100644
--- a/src/test/ui/parser/issues/issue-68000-unicode-ident-after-missing-comma.stderr
+++ b/src/test/ui/parser/issues/issue-68000-unicode-ident-after-missing-comma.stderr
@@ -7,6 +7,8 @@ LL |     pub bar: Vecö
 error: expected `:`, found `}`
   --> $DIR/issue-68000-unicode-ident-after-missing-comma.rs:4:1
    |
+LL | pub struct Foo {
+   |            --- while parsing this struct
 LL |     pub bar: Vecö
    |                       - expected `:`
 LL |
diff --git a/src/test/ui/parser/macro/issue-37113.stderr b/src/test/ui/parser/macro/issue-37113.stderr
index 0912858ddc4a6..b1f8674fbdf38 100644
--- a/src/test/ui/parser/macro/issue-37113.stderr
+++ b/src/test/ui/parser/macro/issue-37113.stderr
@@ -1,6 +1,8 @@
 error: expected identifier, found `String`
   --> $DIR/issue-37113.rs:4:16
    |
+LL |         enum SomeEnum {
+   |              -------- while parsing this enum
 LL |             $( $t, )*
    |                ^^ expected identifier
 ...
diff --git a/src/test/ui/parser/mismatched-braces/missing-close-brace-in-struct.stderr b/src/test/ui/parser/mismatched-braces/missing-close-brace-in-struct.stderr
index a47d5506ef0b8..ad1e90e43ec4e 100644
--- a/src/test/ui/parser/mismatched-braces/missing-close-brace-in-struct.stderr
+++ b/src/test/ui/parser/mismatched-braces/missing-close-brace-in-struct.stderr
@@ -10,6 +10,9 @@ LL | fn main() {}
 error: expected identifier, found keyword `trait`
   --> $DIR/missing-close-brace-in-struct.rs:4:1
    |
+LL | pub(crate) struct Bar {
+   |                   --- while parsing this struct
+...
 LL | trait T {
    | ^^^^^ expected identifier, found keyword
 
diff --git a/src/test/ui/parser/missing-closing-angle-bracket-struct-field-ty.stderr b/src/test/ui/parser/missing-closing-angle-bracket-struct-field-ty.stderr
index 46ca1f06be67b..6d8b0c3fccde3 100644
--- a/src/test/ui/parser/missing-closing-angle-bracket-struct-field-ty.stderr
+++ b/src/test/ui/parser/missing-closing-angle-bracket-struct-field-ty.stderr
@@ -1,6 +1,9 @@
 error: expected one of `>`, a const expression, lifetime, or type, found `}`
   --> $DIR/missing-closing-angle-bracket-struct-field-ty.rs:9:1
    |
+LL | pub struct Foo {
+   |            --- while parsing this struct
+...
 LL |     c: Arc>,
    |                          - expected one of `>`, a const expression, lifetime, or type
 LL | }
diff --git a/src/test/ui/parser/recover-enum2.stderr b/src/test/ui/parser/recover-enum2.stderr
index ee29f06638f11..7634bca921c86 100644
--- a/src/test/ui/parser/recover-enum2.stderr
+++ b/src/test/ui/parser/recover-enum2.stderr
@@ -1,6 +1,8 @@
 error: expected type, found `{`
   --> $DIR/recover-enum2.rs:6:18
    |
+LL |         Var3 {
+   |         ---- while parsing this struct
 LL |             abc: {},
    |                  ^ expected type
 
diff --git a/src/test/ui/parser/recover-field-semi.stderr b/src/test/ui/parser/recover-field-semi.stderr
index 657366db9b4b7..3cf4847488c05 100644
--- a/src/test/ui/parser/recover-field-semi.stderr
+++ b/src/test/ui/parser/recover-field-semi.stderr
@@ -1,12 +1,16 @@
 error: struct fields are separated by `,`
   --> $DIR/recover-field-semi.rs:2:13
    |
+LL | struct Foo {
+   |        --- while parsing this struct
 LL |     foo: i32;
    |             ^ help: replace `;` with `,`
 
 error: union fields are separated by `,`
   --> $DIR/recover-field-semi.rs:7:13
    |
+LL | union Bar {
+   |       --- while parsing this union
 LL |     foo: i32;
    |             ^ help: replace `;` with `,`
 
@@ -14,7 +18,9 @@ error: struct fields are separated by `,`
   --> $DIR/recover-field-semi.rs:12:19
    |
 LL |     Qux { foo: i32; }
-   |                   ^ help: replace `;` with `,`
+   |     ---           ^ help: replace `;` with `,`
+   |     |
+   |     while parsing this struct
 
 error: unions cannot have zero fields
   --> $DIR/recover-field-semi.rs:6:1
diff --git a/src/test/ui/parser/recover-struct.stderr b/src/test/ui/parser/recover-struct.stderr
index 1b72184b0c886..9f6fb06caa34d 100644
--- a/src/test/ui/parser/recover-struct.stderr
+++ b/src/test/ui/parser/recover-struct.stderr
@@ -1,6 +1,8 @@
 error: expected `:`, found `Bad`
   --> $DIR/recover-struct.rs:4:9
    |
+LL |     struct Test {
+   |            ---- while parsing this struct
 LL |         Very
    |             - expected `:`
 LL |         Bad
diff --git a/src/test/ui/parser/recovered-struct-variant.stderr b/src/test/ui/parser/recovered-struct-variant.stderr
index 51aaf8bb3cfbe..78c67866fb0f1 100644
--- a/src/test/ui/parser/recovered-struct-variant.stderr
+++ b/src/test/ui/parser/recovered-struct-variant.stderr
@@ -2,7 +2,9 @@ error: expected `:`, found `,`
   --> $DIR/recovered-struct-variant.rs:2:10
    |
 LL |     A { a, b: usize }
-   |          ^ expected `:`
+   |     -    ^ expected `:`
+   |     |
+   |     while parsing this struct
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/parser/removed-syntax-enum-newtype.stderr b/src/test/ui/parser/removed-syntax-enum-newtype.stderr
index 2daa6249b4ce0..8f7ca356798e2 100644
--- a/src/test/ui/parser/removed-syntax-enum-newtype.stderr
+++ b/src/test/ui/parser/removed-syntax-enum-newtype.stderr
@@ -2,7 +2,9 @@ error: expected one of `<`, `where`, or `{`, found `=`
   --> $DIR/removed-syntax-enum-newtype.rs:1:8
    |
 LL | enum e = isize;
-   |        ^ expected one of `<`, `where`, or `{`
+   |      - ^ expected one of `<`, `where`, or `{`
+   |      |
+   |      while parsing this enum
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/parser/removed-syntax-field-let.stderr b/src/test/ui/parser/removed-syntax-field-let.stderr
index 10be2e045b2b8..ab3d2056581b6 100644
--- a/src/test/ui/parser/removed-syntax-field-let.stderr
+++ b/src/test/ui/parser/removed-syntax-field-let.stderr
@@ -1,6 +1,8 @@
 error: expected identifier, found keyword `let`
   --> $DIR/removed-syntax-field-let.rs:2:5
    |
+LL | struct S {
+   |        - while parsing this struct
 LL |     let foo: (),
    |     ^^^ expected identifier, found keyword
 
diff --git a/src/test/ui/parser/removed-syntax-field-semicolon.stderr b/src/test/ui/parser/removed-syntax-field-semicolon.stderr
index e4f75f672063c..532d4fb2b61f0 100644
--- a/src/test/ui/parser/removed-syntax-field-semicolon.stderr
+++ b/src/test/ui/parser/removed-syntax-field-semicolon.stderr
@@ -1,6 +1,8 @@
 error: struct fields are separated by `,`
   --> $DIR/removed-syntax-field-semicolon.rs:2:12
    |
+LL | struct S {
+   |        - while parsing this struct
 LL |     bar: ();
    |            ^ help: replace `;` with `,`
 
diff --git a/src/test/ui/pattern/issue-66270-pat-struct-parser-recovery.stderr b/src/test/ui/pattern/issue-66270-pat-struct-parser-recovery.stderr
index fef0f3c0e06ef..f40642f300cdf 100644
--- a/src/test/ui/pattern/issue-66270-pat-struct-parser-recovery.stderr
+++ b/src/test/ui/pattern/issue-66270-pat-struct-parser-recovery.stderr
@@ -1,6 +1,8 @@
 error: expected type, found `0`
   --> $DIR/issue-66270-pat-struct-parser-recovery.rs:4:22
    |
+LL | struct Bug {
+   |        --- while parsing this struct
 LL |     incorrect_field: 0,
    |                      ^ expected type
 
diff --git a/src/test/ui/proc-macro/derive-bad.stderr b/src/test/ui/proc-macro/derive-bad.stderr
index ae48141fb3133..241f99b28c24b 100644
--- a/src/test/ui/proc-macro/derive-bad.stderr
+++ b/src/test/ui/proc-macro/derive-bad.stderr
@@ -2,7 +2,10 @@ error: expected `:`, found `}`
   --> $DIR/derive-bad.rs:6:10
    |
 LL | #[derive(A)]
-   |          ^ expected `:`
+   |          ^
+   |          |
+   |          expected `:`
+   |          while parsing this struct
    |
    = note: this error originates in the derive macro `A` (in Nightly builds, run with -Z macro-backtrace for more info)
 
diff --git a/src/test/ui/pub/pub-restricted-error.stderr b/src/test/ui/pub/pub-restricted-error.stderr
index 95bf498c7f746..b47328f34e6eb 100644
--- a/src/test/ui/pub/pub-restricted-error.stderr
+++ b/src/test/ui/pub/pub-restricted-error.stderr
@@ -1,6 +1,8 @@
 error: expected identifier, found `(`
   --> $DIR/pub-restricted-error.rs:4:16
    |
+LL | struct Foo {
+   |        --- while parsing this struct
 LL |     pub(crate) () foo: usize,
    |                ^ expected identifier
 
diff --git a/src/test/ui/structs/struct-fn-in-definition.stderr b/src/test/ui/structs/struct-fn-in-definition.stderr
index 1d7cd52729586..472365c6ed739 100644
--- a/src/test/ui/structs/struct-fn-in-definition.stderr
+++ b/src/test/ui/structs/struct-fn-in-definition.stderr
@@ -1,6 +1,9 @@
 error: functions are not allowed in struct definitions
   --> $DIR/struct-fn-in-definition.rs:9:5
    |
+LL | struct S {
+   |        - while parsing this struct
+...
 LL |     fn foo() {}
    |     ^^^^^^^^^^^
    |
@@ -10,6 +13,9 @@ LL |     fn foo() {}
 error: functions are not allowed in union definitions
   --> $DIR/struct-fn-in-definition.rs:18:5
    |
+LL | union U {
+   |       - while parsing this union
+...
 LL |     fn foo() {}
    |     ^^^^^^^^^^^
    |
@@ -19,6 +25,9 @@ LL |     fn foo() {}
 error: functions are not allowed in enum definitions
   --> $DIR/struct-fn-in-definition.rs:27:5
    |
+LL | enum E {
+   |      - while parsing this enum
+...
 LL |     fn foo() {}
    |     ^^^^^^^^^^^
    |
diff --git a/src/test/ui/suggestions/struct-field-type-including-single-colon.stderr b/src/test/ui/suggestions/struct-field-type-including-single-colon.stderr
index 189759d64fc4e..4dd514480da40 100644
--- a/src/test/ui/suggestions/struct-field-type-including-single-colon.stderr
+++ b/src/test/ui/suggestions/struct-field-type-including-single-colon.stderr
@@ -12,6 +12,8 @@ LL |     a: foo::A,
 error: expected `,`, or `}`, found `:`
   --> $DIR/struct-field-type-including-single-colon.rs:9:11
    |
+LL | struct Foo {
+   |        --- while parsing this struct
 LL |     a: foo:A,
    |           ^
 
@@ -29,6 +31,8 @@ LL |     b: foo::bar::B,
 error: expected `,`, or `}`, found `:`
   --> $DIR/struct-field-type-including-single-colon.rs:15:16
    |
+LL | struct Bar {
+   |        --- while parsing this struct
 LL |     b: foo::bar:B,
    |                ^
 
diff --git a/src/test/ui/typeck/issue-69378-ice-on-invalid-type-node-after-recovery.stderr b/src/test/ui/typeck/issue-69378-ice-on-invalid-type-node-after-recovery.stderr
index 6bc9c8498c9d1..fc7c23a225240 100644
--- a/src/test/ui/typeck/issue-69378-ice-on-invalid-type-node-after-recovery.stderr
+++ b/src/test/ui/typeck/issue-69378-ice-on-invalid-type-node-after-recovery.stderr
@@ -2,7 +2,9 @@ error: expected identifier, found `0`
   --> $DIR/issue-69378-ice-on-invalid-type-node-after-recovery.rs:3:14
    |
 LL | struct Foo { 0: u8 }
-   |              ^ expected identifier
+   |        ---   ^ expected identifier
+   |        |
+   |        while parsing this struct
 
 error: aborting due to previous error
 

From 5d05908c70dde1f39fa15f1b13fff67c13303c98 Mon Sep 17 00:00:00 2001
From: Takayuki Maeda 
Date: Mon, 26 Sep 2022 23:43:31 +0900
Subject: [PATCH 286/586] fix a ui test

---
 src/test/ui/parser/issues/issue-101540.stderr | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/src/test/ui/parser/issues/issue-101540.stderr b/src/test/ui/parser/issues/issue-101540.stderr
index 53c7c9590e6ca..8af887050023c 100644
--- a/src/test/ui/parser/issues/issue-101540.stderr
+++ b/src/test/ui/parser/issues/issue-101540.stderr
@@ -1,6 +1,8 @@
 error: structs are not allowed in struct definitions
   --> $DIR/issue-101540.rs:2:5
    |
+LL | struct S1 {
+   |        -- while parsing this struct
 LL |     struct S2 {
    |     ^^^^^^^^^
    |

From 7f7e2165b1f1a271c6708f2a54c940bdaa254eb2 Mon Sep 17 00:00:00 2001
From: Nicholas Nethercote 
Date: Tue, 27 Sep 2022 12:04:03 +1000
Subject: [PATCH 287/586] Rename some variables.

These make the delimiter processing clearer.
---
 compiler/rustc_parse/src/lexer/tokentrees.rs | 20 ++++++++++----------
 1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/compiler/rustc_parse/src/lexer/tokentrees.rs b/compiler/rustc_parse/src/lexer/tokentrees.rs
index 3aaf3d4865fdc..6f6ab16cb597b 100644
--- a/compiler/rustc_parse/src/lexer/tokentrees.rs
+++ b/compiler/rustc_parse/src/lexer/tokentrees.rs
@@ -110,12 +110,12 @@ impl<'a> TokenTreesReader<'a> {
         err
     }
 
-    fn parse_token_tree_open_delim(&mut self, delim: Delimiter) -> TokenTree {
+    fn parse_token_tree_open_delim(&mut self, open_delim: Delimiter) -> TokenTree {
         // The span for beginning of the delimited section
         let pre_span = self.token.span;
 
         // Move past the open delimiter.
-        self.open_braces.push((delim, self.token.span));
+        self.open_braces.push((open_delim, self.token.span));
         self.token = self.string_reader.next_token().0;
 
         // Parse the token trees within the delimiters.
@@ -128,7 +128,7 @@ impl<'a> TokenTreesReader<'a> {
 
         match self.token.kind {
             // Correct delimiter.
-            token::CloseDelim(d) if d == delim => {
+            token::CloseDelim(close_delim) if close_delim == open_delim => {
                 let (open_brace, open_brace_span) = self.open_braces.pop().unwrap();
                 let close_brace_span = self.token.span;
 
@@ -138,12 +138,12 @@ impl<'a> TokenTreesReader<'a> {
                     if !sm.is_multiline(empty_block_span) {
                         // Only track if the block is in the form of `{}`, otherwise it is
                         // likely that it was written on purpose.
-                        self.last_delim_empty_block_spans.insert(delim, empty_block_span);
+                        self.last_delim_empty_block_spans.insert(open_delim, empty_block_span);
                     }
                 }
 
                 //only add braces
-                if let (Delimiter::Brace, Delimiter::Brace) = (open_brace, delim) {
+                if let (Delimiter::Brace, Delimiter::Brace) = (open_brace, open_delim) {
                     self.matching_block_spans.push((open_brace_span, close_brace_span));
                 }
 
@@ -158,7 +158,7 @@ impl<'a> TokenTreesReader<'a> {
                 self.token = self.string_reader.next_token().0;
             }
             // Incorrect delimiter.
-            token::CloseDelim(other) => {
+            token::CloseDelim(close_delim) => {
                 let mut unclosed_delimiter = None;
                 let mut candidate = None;
 
@@ -176,7 +176,7 @@ impl<'a> TokenTreesReader<'a> {
                         for (brace, brace_span) in &self.open_braces {
                             if let Some(padding) = sm.span_to_margin(*brace_span) {
                                 // high likelihood of these two corresponding
-                                if current_padding == padding && brace == &other {
+                                if current_padding == padding && brace == &close_delim {
                                     candidate = Some(*brace_span);
                                 }
                             }
@@ -185,7 +185,7 @@ impl<'a> TokenTreesReader<'a> {
                     let (tok, _) = self.open_braces.pop().unwrap();
                     self.unmatched_braces.push(UnmatchedBrace {
                         expected_delim: tok,
-                        found_delim: Some(other),
+                        found_delim: Some(close_delim),
                         found_span: self.token.span,
                         unclosed_span: unclosed_delimiter,
                         candidate_span: candidate,
@@ -201,7 +201,7 @@ impl<'a> TokenTreesReader<'a> {
                 // fn foo() {
                 //     bar(baz(
                 // }  // Incorrect delimiter but matches the earlier `{`
-                if !self.open_braces.iter().any(|&(b, _)| b == other) {
+                if !self.open_braces.iter().any(|&(b, _)| b == close_delim) {
                     self.token = self.string_reader.next_token().0;
                 }
             }
@@ -213,7 +213,7 @@ impl<'a> TokenTreesReader<'a> {
             _ => unreachable!(),
         }
 
-        TokenTree::Delimited(delim_span, delim, tts)
+        TokenTree::Delimited(delim_span, open_delim, tts)
     }
 
     fn close_delim_err(&mut self, delim: Delimiter) -> PErr<'a> {

From 594134d873a1020947da9b73803dcce76b6f5cf1 Mon Sep 17 00:00:00 2001
From: Michael Goulet 
Date: Sun, 25 Sep 2022 22:03:39 +0000
Subject: [PATCH 288/586] Structured suggestion for missing mut/const in
 pointer

---
 compiler/rustc_parse/src/parser/ty.rs      | 11 +++++++----
 src/test/ui/parser/bad-pointer-type.rs     |  2 +-
 src/test/ui/parser/bad-pointer-type.stderr | 11 ++++++++---
 src/test/ui/parser/double-pointer.rs       |  7 +++++++
 src/test/ui/parser/double-pointer.stderr   | 15 +++++++++++++++
 5 files changed, 38 insertions(+), 8 deletions(-)
 create mode 100644 src/test/ui/parser/double-pointer.rs
 create mode 100644 src/test/ui/parser/double-pointer.stderr

diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs
index b47f0c0978381..2a8512acf8cfa 100644
--- a/compiler/rustc_parse/src/parser/ty.rs
+++ b/compiler/rustc_parse/src/parser/ty.rs
@@ -397,10 +397,13 @@ impl<'a> Parser<'a> {
     fn parse_ty_ptr(&mut self) -> PResult<'a, TyKind> {
         let mutbl = self.parse_const_or_mut().unwrap_or_else(|| {
             let span = self.prev_token.span;
-            let msg = "expected mut or const in raw pointer type";
-            self.struct_span_err(span, msg)
-                .span_label(span, msg)
-                .help("use `*mut T` or `*const T` as appropriate")
+            self.struct_span_err(span, "expected `mut` or `const` keyword in raw pointer type")
+                .span_suggestions(
+                    span.shrink_to_hi(),
+                    "add `mut` or `const` here",
+                    ["mut ".to_string(), "const ".to_string()].into_iter(),
+                    Applicability::HasPlaceholders,
+                )
                 .emit();
             Mutability::Not
         });
diff --git a/src/test/ui/parser/bad-pointer-type.rs b/src/test/ui/parser/bad-pointer-type.rs
index 59e5e0c5d31db..6a82acb4cd6b5 100644
--- a/src/test/ui/parser/bad-pointer-type.rs
+++ b/src/test/ui/parser/bad-pointer-type.rs
@@ -1,5 +1,5 @@
 fn foo(_: *()) {
-    //~^ ERROR expected mut or const in raw pointer type
+    //~^ ERROR expected `mut` or `const` keyword in raw pointer type
 }
 
 fn main() {}
diff --git a/src/test/ui/parser/bad-pointer-type.stderr b/src/test/ui/parser/bad-pointer-type.stderr
index e18c220affe6e..b7225ca887dd4 100644
--- a/src/test/ui/parser/bad-pointer-type.stderr
+++ b/src/test/ui/parser/bad-pointer-type.stderr
@@ -1,10 +1,15 @@
-error: expected mut or const in raw pointer type
+error: expected `mut` or `const` keyword in raw pointer type
   --> $DIR/bad-pointer-type.rs:1:11
    |
 LL | fn foo(_: *()) {
-   |           ^ expected mut or const in raw pointer type
+   |           ^
    |
-   = help: use `*mut T` or `*const T` as appropriate
+help: add `mut` or `const` here
+   |
+LL | fn foo(_: *const ()) {
+   |            +++++
+LL | fn foo(_: *mut ()) {
+   |            +++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/parser/double-pointer.rs b/src/test/ui/parser/double-pointer.rs
new file mode 100644
index 0000000000000..54d34db4a50f4
--- /dev/null
+++ b/src/test/ui/parser/double-pointer.rs
@@ -0,0 +1,7 @@
+fn main() {
+    let x: i32 = 5;
+    let ptr: *const i32 = &x;
+    let dptr: **const i32 = &ptr;
+    //~^ ERROR expected `mut` or `const` keyword in raw pointer type
+    //~| HELP add `mut` or `const` here
+}
diff --git a/src/test/ui/parser/double-pointer.stderr b/src/test/ui/parser/double-pointer.stderr
new file mode 100644
index 0000000000000..28037f9326552
--- /dev/null
+++ b/src/test/ui/parser/double-pointer.stderr
@@ -0,0 +1,15 @@
+error: expected `mut` or `const` keyword in raw pointer type
+  --> $DIR/double-pointer.rs:4:15
+   |
+LL |     let dptr: **const i32 = &ptr;
+   |               ^
+   |
+help: add `mut` or `const` here
+   |
+LL |     let dptr: *const *const i32 = &ptr;
+   |                +++++
+LL |     let dptr: *mut *const i32 = &ptr;
+   |                +++
+
+error: aborting due to previous error
+

From 6d01c6d9c8851ddfa8d520c03e9ac93ef7f82ce3 Mon Sep 17 00:00:00 2001
From: Ellis Hoag 
Date: Mon, 26 Sep 2022 19:57:40 -0700
Subject: [PATCH 289/586] lint and remove unused diagnostic

---
 compiler/rustc_codegen_gcc/src/errors.rs               | 10 ++++------
 .../rustc_error_messages/locales/en-US/codegen_gcc.ftl |  3 ---
 2 files changed, 4 insertions(+), 9 deletions(-)

diff --git a/compiler/rustc_codegen_gcc/src/errors.rs b/compiler/rustc_codegen_gcc/src/errors.rs
index eb8528104fac3..83f4af16612e7 100644
--- a/compiler/rustc_codegen_gcc/src/errors.rs
+++ b/compiler/rustc_codegen_gcc/src/errors.rs
@@ -4,13 +4,12 @@ use rustc_middle::ty::Ty;
 use rustc_span::{Span, Symbol};
 use std::borrow::Cow;
 
-struct ExitCode {
-    pub exit_code: Option,
-}
+struct ExitCode(Option);
 
 impl IntoDiagnosticArg for ExitCode {
     fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
-        match self.exit_code {
+        let ExitCode(exit_code) = self;
+        match exit_code {
             Some(t) => t.into_diagnostic_arg(),
             None => DiagnosticArgValue::Str(Cow::Borrowed("None")),
         }
@@ -25,8 +24,7 @@ pub(crate) struct RanlibFailure {
 
 impl RanlibFailure {
     pub fn new(exit_code: Option) -> Self {
-        let exit_code = ExitCode{ exit_code };
-        RanlibFailure { exit_code }
+        RanlibFailure { exit_code: ExitCode(exit_code) }
     }
 }
 
diff --git a/compiler/rustc_error_messages/locales/en-US/codegen_gcc.ftl b/compiler/rustc_error_messages/locales/en-US/codegen_gcc.ftl
index 2497d55032396..178e1a67ccecf 100644
--- a/compiler/rustc_error_messages/locales/en-US/codegen_gcc.ftl
+++ b/compiler/rustc_error_messages/locales/en-US/codegen_gcc.ftl
@@ -1,9 +1,6 @@
 codegen_gcc_ranlib_failure =
     Ranlib exited with code {$exit_code}
 
-codegen_gcc_layout_size_overflow =
-    {$error}
-
 codegen_gcc_linkage_const_or_mut_type =
     must have type `*const T` or `*mut T` due to `#[linkage]` attribute
 

From 259bbfbc3dd5854f8ee3b89f921ac0812e43bb79 Mon Sep 17 00:00:00 2001
From: John Millikin 
Date: Sun, 18 Sep 2022 10:51:36 +0900
Subject: [PATCH 290/586] Add negation methods for signed non-zero integers.

---
 library/core/src/num/nonzero.rs | 154 ++++++++++++++++++++++++++++++++
 1 file changed, 154 insertions(+)

diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs
index 532a09736a7ac..d8e3c95cc8702 100644
--- a/library/core/src/num/nonzero.rs
+++ b/library/core/src/num/nonzero.rs
@@ -721,6 +721,160 @@ macro_rules! nonzero_signed_operations {
                     // SAFETY: absolute value of nonzero cannot yield zero values.
                     unsafe { $Uty::new_unchecked(self.get().unsigned_abs()) }
                 }
+
+                /// Returns `true` if `self` is negative and `false` if the
+                /// number is positive.
+                ///
+                /// # Example
+                ///
+                /// ```
+                /// #![feature(nonzero_negation_ops)]
+                ///
+                #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
+                /// # fn main() { test().unwrap(); }
+                /// # fn test() -> Option<()> {
+                #[doc = concat!("let pos_five = ", stringify!($Ty), "::new(5)?;")]
+                #[doc = concat!("let neg_five = ", stringify!($Ty), "::new(-5)?;")]
+                ///
+                /// assert!(neg_five.is_negative());
+                /// assert!(!pos_five.is_negative());
+                /// # Some(())
+                /// # }
+                /// ```
+                #[must_use]
+                #[inline(always)]
+                #[unstable(feature = "nonzero_negation_ops", issue = "none")]
+                pub const fn is_negative(self) -> bool {
+                    self.get().is_negative()
+                }
+
+                /// Checked negation. Computes `-self`, returning `None` if `self == i32::MIN`.
+                ///
+                /// # Example
+                ///
+                /// ```
+                /// #![feature(nonzero_negation_ops)]
+                ///
+                #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
+                /// # fn main() { test().unwrap(); }
+                /// # fn test() -> Option<()> {
+                #[doc = concat!("let pos_five = ", stringify!($Ty), "::new(5)?;")]
+                #[doc = concat!("let neg_five = ", stringify!($Ty), "::new(-5)?;")]
+                #[doc = concat!("let min = ", stringify!($Ty), "::new(",
+                                stringify!($Int), "::MIN)?;")]
+                ///
+                /// assert_eq!(pos_five.checked_neg(), Some(neg_five));
+                /// assert_eq!(min.checked_neg(), None);
+                /// # Some(())
+                /// # }
+                /// ```
+                #[inline]
+                #[unstable(feature = "nonzero_negation_ops", issue = "none")]
+                pub const fn checked_neg(self) -> Option<$Ty> {
+                    if let Some(result) = self.get().checked_neg() {
+                        // SAFETY: negation of nonzero cannot yield zero values.
+                        return Some(unsafe { $Ty::new_unchecked(result) });
+                    }
+                    None
+                }
+
+                /// Negates self, overflowing if this is equal to the minimum value.
+                ///
+                #[doc = concat!("See [`", stringify!($Int), "::overflowing_neg`]")]
+                /// for documentation on overflow behaviour.
+                ///
+                /// # Example
+                ///
+                /// ```
+                /// #![feature(nonzero_negation_ops)]
+                ///
+                #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
+                /// # fn main() { test().unwrap(); }
+                /// # fn test() -> Option<()> {
+                #[doc = concat!("let pos_five = ", stringify!($Ty), "::new(5)?;")]
+                #[doc = concat!("let neg_five = ", stringify!($Ty), "::new(-5)?;")]
+                #[doc = concat!("let min = ", stringify!($Ty), "::new(",
+                                stringify!($Int), "::MIN)?;")]
+                ///
+                /// assert_eq!(pos_five.overflowing_neg(), (neg_five, false));
+                /// assert_eq!(min.overflowing_neg(), (min, true));
+                /// # Some(())
+                /// # }
+                /// ```
+                #[inline]
+                #[unstable(feature = "nonzero_negation_ops", issue = "none")]
+                pub const fn overflowing_neg(self) -> ($Ty, bool) {
+                    let (result, overflow) = self.get().overflowing_neg();
+                    // SAFETY: negation of nonzero cannot yield zero values.
+                    ((unsafe { $Ty::new_unchecked(result) }), overflow)
+                }
+
+                /// Saturating negation. Computes `-self`, returning `MAX` if
+                /// `self == i32::MIN` instead of overflowing.
+                ///
+                /// # Example
+                ///
+                /// ```
+                /// #![feature(nonzero_negation_ops)]
+                ///
+                #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
+                /// # fn main() { test().unwrap(); }
+                /// # fn test() -> Option<()> {
+                #[doc = concat!("let pos_five = ", stringify!($Ty), "::new(5)?;")]
+                #[doc = concat!("let neg_five = ", stringify!($Ty), "::new(-5)?;")]
+                #[doc = concat!("let min = ", stringify!($Ty), "::new(",
+                                stringify!($Int), "::MIN)?;")]
+                #[doc = concat!("let min_plus_one = ", stringify!($Ty), "::new(",
+                                stringify!($Int), "::MIN + 1)?;")]
+                #[doc = concat!("let max = ", stringify!($Ty), "::new(",
+                                stringify!($Int), "::MAX)?;")]
+                ///
+                /// assert_eq!(pos_five.saturating_neg(), neg_five);
+                /// assert_eq!(min.saturating_neg(), max);
+                /// assert_eq!(max.saturating_neg(), min_plus_one);
+                /// # Some(())
+                /// # }
+                /// ```
+                #[inline]
+                #[unstable(feature = "nonzero_negation_ops", issue = "none")]
+                pub const fn saturating_neg(self) -> $Ty {
+                    if let Some(result) = self.checked_neg() {
+                        return result;
+                    }
+                    $Ty::MAX
+                }
+
+                /// Wrapping (modular) negation. Computes `-self`, wrapping around at the boundary
+                /// of the type.
+                ///
+                #[doc = concat!("See [`", stringify!($Int), "::wrapping_neg`]")]
+                /// for documentation on overflow behaviour.
+                ///
+                /// # Example
+                ///
+                /// ```
+                /// #![feature(nonzero_negation_ops)]
+                ///
+                #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
+                /// # fn main() { test().unwrap(); }
+                /// # fn test() -> Option<()> {
+                #[doc = concat!("let pos_five = ", stringify!($Ty), "::new(5)?;")]
+                #[doc = concat!("let neg_five = ", stringify!($Ty), "::new(-5)?;")]
+                #[doc = concat!("let min = ", stringify!($Ty), "::new(",
+                                stringify!($Int), "::MIN)?;")]
+                ///
+                /// assert_eq!(pos_five.wrapping_neg(), neg_five);
+                /// assert_eq!(min.wrapping_neg(), min);
+                /// # Some(())
+                /// # }
+                /// ```
+                #[inline]
+                #[unstable(feature = "nonzero_negation_ops", issue = "none")]
+                pub const fn wrapping_neg(self) -> $Ty {
+                    let result = self.get().wrapping_neg();
+                    // SAFETY: negation of nonzero cannot yield zero values.
+                    unsafe { $Ty::new_unchecked(result) }
+                }
             }
         )+
     }

From c91c64708b1acf3c262a2a6d6551f4bc0acfa656 Mon Sep 17 00:00:00 2001
From: Nicholas Nethercote 
Date: Tue, 27 Sep 2022 15:25:34 +1000
Subject: [PATCH 291/586] Fix an incorrect comment.

If a `\x` escape occurs in a non-byte literals (e.g. char literal,
string literal), it must be <= 0xff.
---
 compiler/rustc_lexer/src/unescape.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/compiler/rustc_lexer/src/unescape.rs b/compiler/rustc_lexer/src/unescape.rs
index 3da6bc14622a0..25d5f2772de40 100644
--- a/compiler/rustc_lexer/src/unescape.rs
+++ b/compiler/rustc_lexer/src/unescape.rs
@@ -184,7 +184,7 @@ fn scan_escape(chars: &mut Chars<'_>, mode: Mode) -> Result {
 
             let value = hi * 16 + lo;
 
-            // For a byte literal verify that it is within ASCII range.
+            // For a non-byte literal verify that it is within ASCII range.
             if !mode.is_bytes() && !is_ascii(value) {
                 return Err(EscapeError::OutOfRangeHexEscape);
             }

From 591c1f25b297c446ac13211f955d06a859206f1a Mon Sep 17 00:00:00 2001
From: Akshay 
Date: Tue, 27 Sep 2022 11:55:13 +0530
Subject: [PATCH 292/586] introduce `{char, u8}::is_ascii_octdigit`

---
 library/core/src/char/methods.rs | 32 ++++++++++++++++++++++++++++++++
 library/core/src/lib.rs          |  1 +
 library/core/src/num/mod.rs      | 32 ++++++++++++++++++++++++++++++++
 library/core/tests/ascii.rs      | 18 ++++++++++++++++++
 library/core/tests/lib.rs        |  1 +
 5 files changed, 84 insertions(+)

diff --git a/library/core/src/char/methods.rs b/library/core/src/char/methods.rs
index b7a63b7c67566..224bc9effe61e 100644
--- a/library/core/src/char/methods.rs
+++ b/library/core/src/char/methods.rs
@@ -1444,6 +1444,38 @@ impl char {
         matches!(*self, '0'..='9')
     }
 
+    /// Checks if the value is an ASCII octal digit:
+    /// U+0030 '0' ..= U+0037 '7'.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(is_ascii_octdigit)]
+    ///
+    /// let uppercase_a = 'A';
+    /// let a = 'a';
+    /// let zero = '0';
+    /// let seven = '7';
+    /// let nine = '9';
+    /// let percent = '%';
+    /// let lf = '\n';
+    ///
+    /// assert!(!uppercase_a.is_ascii_octdigit());
+    /// assert!(!a.is_ascii_octdigit());
+    /// assert!(zero.is_ascii_octdigit());
+    /// assert!(seven.is_ascii_octdigit());
+    /// assert!(!nine.is_ascii_octdigit());
+    /// assert!(!percent.is_ascii_octdigit());
+    /// assert!(!lf.is_ascii_octdigit());
+    /// ```
+    #[must_use]
+    #[unstable(feature = "is_ascii_octdigit", issue = "101288")]
+    #[rustc_const_unstable(feature = "is_ascii_octdigit", issue = "101288")]
+    #[inline]
+    pub const fn is_ascii_octdigit(&self) -> bool {
+        matches!(*self, '0'..='7')
+    }
+
     /// Checks if the value is an ASCII hexadecimal digit:
     ///
     /// - U+0030 '0' ..= U+0039 '9', or
diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
index 5690b5256e88c..18ad0bdc8b20e 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -164,6 +164,7 @@
 #![feature(const_slice_index)]
 #![feature(const_is_char_boundary)]
 #![feature(const_cstr_methods)]
+#![feature(is_ascii_octdigit)]
 //
 // Language features:
 #![feature(abi_unadjusted)]
diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs
index c0be235c120bf..01642a8dd31a8 100644
--- a/library/core/src/num/mod.rs
+++ b/library/core/src/num/mod.rs
@@ -622,6 +622,38 @@ impl u8 {
         matches!(*self, b'0'..=b'9')
     }
 
+    /// Checks if the value is an ASCII octal digit:
+    /// U+0030 '0' ..= U+0037 '7'.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(is_ascii_octdigit)]
+    ///
+    /// let uppercase_a = b'A';
+    /// let a = b'a';
+    /// let zero = b'0';
+    /// let seven = b'7';
+    /// let nine = b'9';
+    /// let percent = b'%';
+    /// let lf = b'\n';
+    ///
+    /// assert!(!uppercase_a.is_ascii_octdigit());
+    /// assert!(!a.is_ascii_octdigit());
+    /// assert!(zero.is_ascii_octdigit());
+    /// assert!(seven.is_ascii_octdigit());
+    /// assert!(!nine.is_ascii_octdigit());
+    /// assert!(!percent.is_ascii_octdigit());
+    /// assert!(!lf.is_ascii_octdigit());
+    /// ```
+    #[must_use]
+    #[unstable(feature = "is_ascii_octdigit", issue = "101288")]
+    #[rustc_const_unstable(feature = "is_ascii_octdigit", issue = "101288")]
+    #[inline]
+    pub const fn is_ascii_octdigit(&self) -> bool {
+        matches!(*self, b'0'..=b'7')
+    }
+
     /// Checks if the value is an ASCII hexadecimal digit:
     ///
     /// - U+0030 '0' ..= U+0039 '9', or
diff --git a/library/core/tests/ascii.rs b/library/core/tests/ascii.rs
index 6d2cf3e83bce9..f5f2dd0477885 100644
--- a/library/core/tests/ascii.rs
+++ b/library/core/tests/ascii.rs
@@ -251,6 +251,23 @@ fn test_is_ascii_digit() {
     );
 }
 
+#[test]
+fn test_is_ascii_octdigit() {
+    assert_all!(is_ascii_octdigit, "", "01234567");
+    assert_none!(
+        is_ascii_octdigit,
+        "abcdefghijklmnopqrstuvwxyz",
+        "ABCDEFGHIJKLMNOQPRSTUVWXYZ",
+        "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~",
+        " \t\n\x0c\r",
+        "\x00\x01\x02\x03\x04\x05\x06\x07",
+        "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
+        "\x10\x11\x12\x13\x14\x15\x16\x17",
+        "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
+        "\x7f",
+    );
+}
+
 #[test]
 fn test_is_ascii_hexdigit() {
     assert_all!(is_ascii_hexdigit, "", "0123456789", "abcdefABCDEF",);
@@ -454,6 +471,7 @@ fn ascii_ctype_const() {
         is_ascii_lowercase    => [true,  false, false, false, false];
         is_ascii_alphanumeric => [true,  true,  true,  false, false];
         is_ascii_digit        => [false, false, true,  false, false];
+        is_ascii_octdigit     => [false, false, false, false, false];
         is_ascii_hexdigit     => [true,  true,  true,  false, false];
         is_ascii_punctuation  => [false, false, false, true,  false];
         is_ascii_graphic      => [true,  true,  true,  true,  false];
diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs
index 46f603eaebaca..46538ddb20179 100644
--- a/library/core/tests/lib.rs
+++ b/library/core/tests/lib.rs
@@ -101,6 +101,7 @@
 #![feature(slice_flatten)]
 #![feature(provide_any)]
 #![feature(utf8_chunks)]
+#![feature(is_ascii_octdigit)]
 #![deny(unsafe_op_in_unsafe_fn)]
 
 extern crate test;

From b69c335327de660e495e09bce324bf364c937f6f Mon Sep 17 00:00:00 2001
From: Nicholas Nethercote 
Date: Tue, 27 Sep 2022 13:24:49 +1000
Subject: [PATCH 293/586] Tweak `FulfillProcessor`.

Avoids some unnecessary references and lifetimes.
---
 .../src/traits/fulfill.rs                     | 24 +++++++++----------
 1 file changed, 12 insertions(+), 12 deletions(-)

diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs
index 6f3a9412dde7a..f13736a76b214 100644
--- a/compiler/rustc_trait_selection/src/traits/fulfill.rs
+++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs
@@ -102,7 +102,7 @@ impl<'a, 'tcx> FulfillmentContext<'tcx> {
     }
 
     /// Attempts to select obligations using `selcx`.
-    fn select(&mut self, selcx: &mut SelectionContext<'a, 'tcx>) -> Vec> {
+    fn select(&mut self, selcx: SelectionContext<'a, 'tcx>) -> Vec> {
         let span = debug_span!("select", obligation_forest_size = ?self.predicates.len());
         let _enter = span.enter();
 
@@ -197,8 +197,8 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> {
         &mut self,
         infcx: &InferCtxt<'_, 'tcx>,
     ) -> Vec> {
-        let mut selcx = SelectionContext::new(infcx);
-        self.select(&mut selcx)
+        let selcx = SelectionContext::new(infcx);
+        self.select(selcx)
     }
 
     fn pending_obligations(&self) -> Vec> {
@@ -210,8 +210,8 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> {
     }
 }
 
-struct FulfillProcessor<'a, 'b, 'tcx> {
-    selcx: &'a mut SelectionContext<'b, 'tcx>,
+struct FulfillProcessor<'a, 'tcx> {
+    selcx: SelectionContext<'a, 'tcx>,
 }
 
 fn mk_pending(os: Vec>) -> Vec> {
@@ -220,7 +220,7 @@ fn mk_pending(os: Vec>) -> Vec ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> {
+impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
     type Obligation = PendingPredicateObligation<'tcx>;
     type Error = FulfillmentErrorCode<'tcx>;
     type OUT = Outcome;
@@ -291,7 +291,7 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> {
         if obligation.predicate.has_projections() {
             let mut obligations = Vec::new();
             let predicate = crate::traits::project::try_normalize_with_depth_to(
-                self.selcx,
+                &mut self.selcx,
                 obligation.param_env,
                 obligation.cause.clone(),
                 obligation.recursion_depth + 1,
@@ -608,7 +608,7 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> {
     }
 }
 
-impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> {
+impl<'a, 'tcx> FulfillProcessor<'a, 'tcx> {
     #[instrument(level = "debug", skip(self, obligation, stalled_on))]
     fn process_trait_obligation(
         &mut self,
@@ -643,7 +643,7 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> {
                 // information about the types in the trait.
                 stalled_on.clear();
                 stalled_on.extend(substs_infer_vars(
-                    self.selcx,
+                    &self.selcx,
                     trait_obligation.predicate.map_bound(|pred| pred.trait_ref.substs),
                 ));
 
@@ -695,12 +695,12 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> {
             }
         }
 
-        match project::poly_project_and_unify_type(self.selcx, &project_obligation) {
+        match project::poly_project_and_unify_type(&mut self.selcx, &project_obligation) {
             ProjectAndUnifyResult::Holds(os) => ProcessResult::Changed(mk_pending(os)),
             ProjectAndUnifyResult::FailedNormalization => {
                 stalled_on.clear();
                 stalled_on.extend(substs_infer_vars(
-                    self.selcx,
+                    &self.selcx,
                     project_obligation.predicate.map_bound(|pred| pred.projection_ty.substs),
                 ));
                 ProcessResult::Unchanged
@@ -718,7 +718,7 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> {
 
 /// Returns the set of inference variables contained in `substs`.
 fn substs_infer_vars<'a, 'tcx>(
-    selcx: &mut SelectionContext<'a, 'tcx>,
+    selcx: &SelectionContext<'a, 'tcx>,
     substs: ty::Binder<'tcx, SubstsRef<'tcx>>,
 ) -> impl Iterator> {
     selcx

From 1fc86a63f451b81606e4787692517dc613f333db Mon Sep 17 00:00:00 2001
From: lcnr 
Date: Mon, 26 Sep 2022 13:00:29 +0200
Subject: [PATCH 294/586] rustc_typeck to rustc_hir_analysis

---
 Cargo.lock                                    | 64 +++++++++----------
 compiler/rustc_codegen_llvm/src/consts.rs     |  2 +-
 .../rustc_codegen_ssa/src/traits/intrinsic.rs |  2 +-
 compiler/rustc_driver/Cargo.toml              |  2 +-
 compiler/rustc_driver/src/pretty.rs           |  2 +-
 .../Cargo.toml                                |  2 +-
 .../README.md                                 |  0
 .../src/astconv/errors.rs                     |  0
 .../src/astconv/generics.rs                   |  0
 .../src/astconv/mod.rs                        |  0
 .../src/bounds.rs                             |  0
 .../src/check/_match.rs                       |  0
 .../src/check/autoderef.rs                    |  0
 .../src/check/callee.rs                       |  0
 .../src/check/cast.rs                         |  0
 .../src/check/check.rs                        |  0
 .../src/check/closure.rs                      |  0
 .../src/check/coercion.rs                     |  0
 .../src/check/compare_method.rs               |  0
 .../src/check/demand.rs                       |  0
 .../src/check/diverges.rs                     |  0
 .../src/check/dropck.rs                       |  2 +-
 .../src/check/expectation.rs                  |  0
 .../src/check/expr.rs                         |  0
 .../src/check/fallback.rs                     |  0
 .../src/check/fn_ctxt/_impl.rs                |  0
 .../src/check/fn_ctxt/arg_matrix.rs           |  0
 .../src/check/fn_ctxt/checks.rs               |  0
 .../src/check/fn_ctxt/mod.rs                  |  0
 .../src/check/fn_ctxt/suggestions.rs          |  0
 .../src/check/gather_locals.rs                |  0
 .../src/check/generator_interior.rs           |  0
 .../check/generator_interior/drop_ranges.rs   |  0
 .../drop_ranges/cfg_build.rs                  |  0
 .../drop_ranges/cfg_propagate.rs              |  0
 .../drop_ranges/cfg_visualize.rs              |  0
 .../drop_ranges/record_consumed_borrow.rs     |  0
 .../src/check/inherited.rs                    |  0
 .../src/check/intrinsic.rs                    |  0
 .../src/check/intrinsicck.rs                  |  0
 .../src/check/method/confirm.rs               |  0
 .../src/check/method/mod.rs                   |  0
 .../src/check/method/prelude2021.rs           |  0
 .../src/check/method/probe.rs                 |  0
 .../src/check/method/suggest.rs               |  0
 .../src/check/mod.rs                          |  0
 .../src/check/op.rs                           |  0
 .../src/check/pat.rs                          |  0
 .../src/check/place_op.rs                     |  0
 .../src/check/region.rs                       |  0
 .../src/check/rvalue_scopes.rs                |  0
 .../src/check/upvar.rs                        |  0
 .../src/check/wfcheck.rs                      |  0
 .../src/check/writeback.rs                    |  0
 .../src/check_unused.rs                       |  0
 .../src/coherence/builtin.rs                  |  0
 .../src/coherence/inherent_impls.rs           |  0
 .../src/coherence/inherent_impls_overlap.rs   |  0
 .../src/coherence/mod.rs                      |  0
 .../src/coherence/orphan.rs                   |  0
 .../src/coherence/unsafety.rs                 |  0
 .../src/collect.rs                            |  0
 .../src/collect/item_bounds.rs                |  0
 .../src/collect/type_of.rs                    |  0
 .../src/constrained_generic_params.rs         |  0
 .../src/errors.rs                             |  0
 .../src/expr_use_visitor.rs                   |  0
 .../src/hir_wf_check.rs                       |  0
 .../src/impl_wf_check.rs                      |  0
 .../src/impl_wf_check/min_specialization.rs   |  0
 .../src/lib.rs                                |  0
 .../src/mem_categorization.rs                 |  0
 .../src/outlives/explicit.rs                  |  0
 .../src/outlives/implicit_infer.rs            |  0
 .../src/outlives/mod.rs                       |  0
 .../src/outlives/test.rs                      |  0
 .../src/outlives/utils.rs                     |  0
 .../src/structured_errors.rs                  |  0
 .../missing_cast_for_variadic_arg.rs          |  0
 .../structured_errors/sized_unsized_cast.rs   |  0
 .../wrong_number_of_generic_args.rs           |  0
 .../src/variance/constraints.rs               |  0
 .../src/variance/mod.rs                       |  0
 .../src/variance/solve.rs                     |  0
 .../src/variance/terms.rs                     |  0
 .../src/variance/test.rs                      |  0
 .../src/variance/xform.rs                     |  0
 .../src/infer/error_reporting/mod.rs          |  2 +-
 compiler/rustc_infer/src/infer/mod.rs         |  2 +-
 compiler/rustc_infer/src/lib.rs               |  2 +-
 compiler/rustc_interface/Cargo.toml           |  2 +-
 compiler/rustc_interface/src/passes.rs        |  5 +-
 compiler/rustc_middle/src/ty/cast.rs          |  2 +-
 compiler/rustc_middle/src/ty/context.rs       |  2 +-
 compiler/rustc_middle/src/ty/rvalue_scopes.rs |  2 +-
 compiler/rustc_middle/src/ty/sty.rs           |  4 +-
 compiler/rustc_mir_build/src/thir/cx/expr.rs  |  2 +-
 .../rustc_mir_build/src/thir/pattern/mod.rs   |  2 +-
 .../src/thir/pattern/usefulness.rs            |  2 +-
 compiler/rustc_passes/src/check_attr.rs       |  2 +-
 compiler/rustc_privacy/Cargo.toml             |  2 +-
 compiler/rustc_privacy/src/lib.rs             |  4 +-
 compiler/rustc_resolve/src/check_unused.rs    |  2 +-
 compiler/rustc_resolve/src/lib.rs             |  2 +-
 compiler/rustc_ty_utils/src/instance.rs       |  2 +-
 src/librustdoc/clean/mod.rs                   |  4 +-
 src/librustdoc/clean/types.rs                 |  2 +-
 src/librustdoc/core.rs                        |  2 +-
 src/librustdoc/lib.rs                         |  2 +-
 .../trait-where-clause-const.rs               |  2 +-
 ...eld-present-in-subfield-recursion-limit.rs |  2 +-
 .../src/default_union_representation.rs       |  2 +-
 src/tools/clippy/clippy_lints/src/escape.rs   |  4 +-
 .../clippy_lints/src/implicit_hasher.rs       |  2 +-
 .../clippy_lints/src/large_const_arrays.rs    |  2 +-
 src/tools/clippy/clippy_lints/src/lib.rs      |  2 +-
 .../clippy_lints/src/loops/mut_range_bound.rs |  4 +-
 .../clippy/clippy_lints/src/loops/utils.rs    |  2 +-
 .../src/matches/needless_match.rs             |  2 +-
 .../clippy/clippy_lints/src/methods/mod.rs    |  2 +-
 .../src/methods/unnecessary_to_owned.rs       |  2 +-
 .../clippy_lints/src/missing_const_for_fn.rs  |  2 +-
 .../src/needless_pass_by_value.rs             |  4 +-
 .../clippy/clippy_lints/src/non_copy_const.rs |  2 +-
 .../src/operators/assign_op_pattern.rs        |  2 +-
 .../clippy_lints/src/transmute/utils.rs       |  2 +-
 .../src/types/redundant_allocation.rs         |  2 +-
 .../clippy/clippy_lints/src/types/vec_box.rs  |  2 +-
 src/tools/clippy/clippy_lints/src/use_self.rs |  2 +-
 .../clippy_lints/src/utils/internal_lints.rs  |  2 +-
 .../clippy_lints/src/zero_sized_map_values.rs |  2 +-
 src/tools/clippy/clippy_utils/src/lib.rs      |  4 +-
 src/tools/clippy/clippy_utils/src/sugg.rs     |  4 +-
 src/tools/clippy/clippy_utils/src/usage.rs    |  4 +-
 .../transmutes_expressible_as_ptr_casts.fixed |  2 +-
 .../ui/transmutes_expressible_as_ptr_casts.rs |  2 +-
 .../crates/hir-ty/src/autoderef.rs            |  2 +-
 .../rust-analyzer/crates/hir-ty/src/infer.rs  |  2 +-
 .../crates/hir-ty/src/infer/coerce.rs         |  2 +-
 .../crates/hir-ty/src/method_resolution.rs    |  2 +-
 140 files changed, 101 insertions(+), 102 deletions(-)
 rename compiler/{rustc_typeck => rustc_hir_analysis}/Cargo.toml (97%)
 rename compiler/{rustc_typeck => rustc_hir_analysis}/README.md (100%)
 rename compiler/{rustc_typeck => rustc_hir_analysis}/src/astconv/errors.rs (100%)
 rename compiler/{rustc_typeck => rustc_hir_analysis}/src/astconv/generics.rs (100%)
 rename compiler/{rustc_typeck => rustc_hir_analysis}/src/astconv/mod.rs (100%)
 rename compiler/{rustc_typeck => rustc_hir_analysis}/src/bounds.rs (100%)
 rename compiler/{rustc_typeck => rustc_hir_analysis}/src/check/_match.rs (100%)
 rename compiler/{rustc_typeck => rustc_hir_analysis}/src/check/autoderef.rs (100%)
 rename compiler/{rustc_typeck => rustc_hir_analysis}/src/check/callee.rs (100%)
 rename compiler/{rustc_typeck => rustc_hir_analysis}/src/check/cast.rs (100%)
 rename compiler/{rustc_typeck => rustc_hir_analysis}/src/check/check.rs (100%)
 rename compiler/{rustc_typeck => rustc_hir_analysis}/src/check/closure.rs (100%)
 rename compiler/{rustc_typeck => rustc_hir_analysis}/src/check/coercion.rs (100%)
 rename compiler/{rustc_typeck => rustc_hir_analysis}/src/check/compare_method.rs (100%)
 rename compiler/{rustc_typeck => rustc_hir_analysis}/src/check/demand.rs (100%)
 rename compiler/{rustc_typeck => rustc_hir_analysis}/src/check/diverges.rs (100%)
 rename compiler/{rustc_typeck => rustc_hir_analysis}/src/check/dropck.rs (99%)
 rename compiler/{rustc_typeck => rustc_hir_analysis}/src/check/expectation.rs (100%)
 rename compiler/{rustc_typeck => rustc_hir_analysis}/src/check/expr.rs (100%)
 rename compiler/{rustc_typeck => rustc_hir_analysis}/src/check/fallback.rs (100%)
 rename compiler/{rustc_typeck => rustc_hir_analysis}/src/check/fn_ctxt/_impl.rs (100%)
 rename compiler/{rustc_typeck => rustc_hir_analysis}/src/check/fn_ctxt/arg_matrix.rs (100%)
 rename compiler/{rustc_typeck => rustc_hir_analysis}/src/check/fn_ctxt/checks.rs (100%)
 rename compiler/{rustc_typeck => rustc_hir_analysis}/src/check/fn_ctxt/mod.rs (100%)
 rename compiler/{rustc_typeck => rustc_hir_analysis}/src/check/fn_ctxt/suggestions.rs (100%)
 rename compiler/{rustc_typeck => rustc_hir_analysis}/src/check/gather_locals.rs (100%)
 rename compiler/{rustc_typeck => rustc_hir_analysis}/src/check/generator_interior.rs (100%)
 rename compiler/{rustc_typeck => rustc_hir_analysis}/src/check/generator_interior/drop_ranges.rs (100%)
 rename compiler/{rustc_typeck => rustc_hir_analysis}/src/check/generator_interior/drop_ranges/cfg_build.rs (100%)
 rename compiler/{rustc_typeck => rustc_hir_analysis}/src/check/generator_interior/drop_ranges/cfg_propagate.rs (100%)
 rename compiler/{rustc_typeck => rustc_hir_analysis}/src/check/generator_interior/drop_ranges/cfg_visualize.rs (100%)
 rename compiler/{rustc_typeck => rustc_hir_analysis}/src/check/generator_interior/drop_ranges/record_consumed_borrow.rs (100%)
 rename compiler/{rustc_typeck => rustc_hir_analysis}/src/check/inherited.rs (100%)
 rename compiler/{rustc_typeck => rustc_hir_analysis}/src/check/intrinsic.rs (100%)
 rename compiler/{rustc_typeck => rustc_hir_analysis}/src/check/intrinsicck.rs (100%)
 rename compiler/{rustc_typeck => rustc_hir_analysis}/src/check/method/confirm.rs (100%)
 rename compiler/{rustc_typeck => rustc_hir_analysis}/src/check/method/mod.rs (100%)
 rename compiler/{rustc_typeck => rustc_hir_analysis}/src/check/method/prelude2021.rs (100%)
 rename compiler/{rustc_typeck => rustc_hir_analysis}/src/check/method/probe.rs (100%)
 rename compiler/{rustc_typeck => rustc_hir_analysis}/src/check/method/suggest.rs (100%)
 rename compiler/{rustc_typeck => rustc_hir_analysis}/src/check/mod.rs (100%)
 rename compiler/{rustc_typeck => rustc_hir_analysis}/src/check/op.rs (100%)
 rename compiler/{rustc_typeck => rustc_hir_analysis}/src/check/pat.rs (100%)
 rename compiler/{rustc_typeck => rustc_hir_analysis}/src/check/place_op.rs (100%)
 rename compiler/{rustc_typeck => rustc_hir_analysis}/src/check/region.rs (100%)
 rename compiler/{rustc_typeck => rustc_hir_analysis}/src/check/rvalue_scopes.rs (100%)
 rename compiler/{rustc_typeck => rustc_hir_analysis}/src/check/upvar.rs (100%)
 rename compiler/{rustc_typeck => rustc_hir_analysis}/src/check/wfcheck.rs (100%)
 rename compiler/{rustc_typeck => rustc_hir_analysis}/src/check/writeback.rs (100%)
 rename compiler/{rustc_typeck => rustc_hir_analysis}/src/check_unused.rs (100%)
 rename compiler/{rustc_typeck => rustc_hir_analysis}/src/coherence/builtin.rs (100%)
 rename compiler/{rustc_typeck => rustc_hir_analysis}/src/coherence/inherent_impls.rs (100%)
 rename compiler/{rustc_typeck => rustc_hir_analysis}/src/coherence/inherent_impls_overlap.rs (100%)
 rename compiler/{rustc_typeck => rustc_hir_analysis}/src/coherence/mod.rs (100%)
 rename compiler/{rustc_typeck => rustc_hir_analysis}/src/coherence/orphan.rs (100%)
 rename compiler/{rustc_typeck => rustc_hir_analysis}/src/coherence/unsafety.rs (100%)
 rename compiler/{rustc_typeck => rustc_hir_analysis}/src/collect.rs (100%)
 rename compiler/{rustc_typeck => rustc_hir_analysis}/src/collect/item_bounds.rs (100%)
 rename compiler/{rustc_typeck => rustc_hir_analysis}/src/collect/type_of.rs (100%)
 rename compiler/{rustc_typeck => rustc_hir_analysis}/src/constrained_generic_params.rs (100%)
 rename compiler/{rustc_typeck => rustc_hir_analysis}/src/errors.rs (100%)
 rename compiler/{rustc_typeck => rustc_hir_analysis}/src/expr_use_visitor.rs (100%)
 rename compiler/{rustc_typeck => rustc_hir_analysis}/src/hir_wf_check.rs (100%)
 rename compiler/{rustc_typeck => rustc_hir_analysis}/src/impl_wf_check.rs (100%)
 rename compiler/{rustc_typeck => rustc_hir_analysis}/src/impl_wf_check/min_specialization.rs (100%)
 rename compiler/{rustc_typeck => rustc_hir_analysis}/src/lib.rs (100%)
 rename compiler/{rustc_typeck => rustc_hir_analysis}/src/mem_categorization.rs (100%)
 rename compiler/{rustc_typeck => rustc_hir_analysis}/src/outlives/explicit.rs (100%)
 rename compiler/{rustc_typeck => rustc_hir_analysis}/src/outlives/implicit_infer.rs (100%)
 rename compiler/{rustc_typeck => rustc_hir_analysis}/src/outlives/mod.rs (100%)
 rename compiler/{rustc_typeck => rustc_hir_analysis}/src/outlives/test.rs (100%)
 rename compiler/{rustc_typeck => rustc_hir_analysis}/src/outlives/utils.rs (100%)
 rename compiler/{rustc_typeck => rustc_hir_analysis}/src/structured_errors.rs (100%)
 rename compiler/{rustc_typeck => rustc_hir_analysis}/src/structured_errors/missing_cast_for_variadic_arg.rs (100%)
 rename compiler/{rustc_typeck => rustc_hir_analysis}/src/structured_errors/sized_unsized_cast.rs (100%)
 rename compiler/{rustc_typeck => rustc_hir_analysis}/src/structured_errors/wrong_number_of_generic_args.rs (100%)
 rename compiler/{rustc_typeck => rustc_hir_analysis}/src/variance/constraints.rs (100%)
 rename compiler/{rustc_typeck => rustc_hir_analysis}/src/variance/mod.rs (100%)
 rename compiler/{rustc_typeck => rustc_hir_analysis}/src/variance/solve.rs (100%)
 rename compiler/{rustc_typeck => rustc_hir_analysis}/src/variance/terms.rs (100%)
 rename compiler/{rustc_typeck => rustc_hir_analysis}/src/variance/test.rs (100%)
 rename compiler/{rustc_typeck => rustc_hir_analysis}/src/variance/xform.rs (100%)

diff --git a/Cargo.lock b/Cargo.lock
index 16c0b644e4f70..c99a07f40b2e5 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -3394,6 +3394,7 @@ dependencies = [
  "rustc_errors",
  "rustc_feature",
  "rustc_hir",
+ "rustc_hir_analysis",
  "rustc_hir_pretty",
  "rustc_interface",
  "rustc_lint",
@@ -3407,7 +3408,6 @@ dependencies = [
  "rustc_session",
  "rustc_span",
  "rustc_target",
- "rustc_typeck",
  "serde_json",
  "tracing",
  "winapi",
@@ -3512,6 +3512,35 @@ dependencies = [
  "tracing",
 ]
 
+[[package]]
+name = "rustc_hir_analysis"
+version = "0.0.0"
+dependencies = [
+ "rustc_arena",
+ "rustc_ast",
+ "rustc_attr",
+ "rustc_data_structures",
+ "rustc_errors",
+ "rustc_feature",
+ "rustc_graphviz",
+ "rustc_hir",
+ "rustc_hir_pretty",
+ "rustc_index",
+ "rustc_infer",
+ "rustc_lint",
+ "rustc_macros",
+ "rustc_middle",
+ "rustc_serialize",
+ "rustc_session",
+ "rustc_span",
+ "rustc_target",
+ "rustc_trait_selection",
+ "rustc_ty_utils",
+ "rustc_type_ir",
+ "smallvec",
+ "tracing",
+]
+
 [[package]]
 name = "rustc_hir_pretty"
 version = "0.0.0"
@@ -3591,6 +3620,7 @@ dependencies = [
  "rustc_errors",
  "rustc_expand",
  "rustc_hir",
+ "rustc_hir_analysis",
  "rustc_incremental",
  "rustc_lint",
  "rustc_macros",
@@ -3613,7 +3643,6 @@ dependencies = [
  "rustc_trait_selection",
  "rustc_traits",
  "rustc_ty_utils",
- "rustc_typeck",
  "smallvec",
  "tracing",
  "winapi",
@@ -3923,12 +3952,12 @@ dependencies = [
  "rustc_data_structures",
  "rustc_errors",
  "rustc_hir",
+ "rustc_hir_analysis",
  "rustc_macros",
  "rustc_middle",
  "rustc_session",
  "rustc_span",
  "rustc_trait_selection",
- "rustc_typeck",
  "tracing",
 ]
 
@@ -4212,35 +4241,6 @@ dependencies = [
  "smallvec",
 ]
 
-[[package]]
-name = "rustc_typeck"
-version = "0.0.0"
-dependencies = [
- "rustc_arena",
- "rustc_ast",
- "rustc_attr",
- "rustc_data_structures",
- "rustc_errors",
- "rustc_feature",
- "rustc_graphviz",
- "rustc_hir",
- "rustc_hir_pretty",
- "rustc_index",
- "rustc_infer",
- "rustc_lint",
- "rustc_macros",
- "rustc_middle",
- "rustc_serialize",
- "rustc_session",
- "rustc_span",
- "rustc_target",
- "rustc_trait_selection",
- "rustc_ty_utils",
- "rustc_type_ir",
- "smallvec",
- "tracing",
-]
-
 [[package]]
 name = "rustc_version"
 version = "0.4.0"
diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs
index a559f7f3d5703..ee2fc65e37b83 100644
--- a/compiler/rustc_codegen_llvm/src/consts.rs
+++ b/compiler/rustc_codegen_llvm/src/consts.rs
@@ -552,7 +552,7 @@ impl<'ll> StaticMethods for CodegenCx<'ll, '_> {
                 // `#[used(compiler)]` is explicitly requested. This is to avoid similar breakage
                 // on other targets, in particular MachO targets have *their* static constructor
                 // lists broken if `llvm.compiler.used` is emitted rather than llvm.used. However,
-                // that check happens when assigning the `CodegenFnAttrFlags` in `rustc_typeck`,
+                // that check happens when assigning the `CodegenFnAttrFlags` in `rustc_hir_analysis`,
                 // so we don't need to take care of it here.
                 self.add_compiler_used_global(g);
             }
diff --git a/compiler/rustc_codegen_ssa/src/traits/intrinsic.rs b/compiler/rustc_codegen_ssa/src/traits/intrinsic.rs
index 7755e67938c32..450672fb94122 100644
--- a/compiler/rustc_codegen_ssa/src/traits/intrinsic.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/intrinsic.rs
@@ -5,7 +5,7 @@ use rustc_span::Span;
 use rustc_target::abi::call::FnAbi;
 
 pub trait IntrinsicCallMethods<'tcx>: BackendTypes {
-    /// Remember to add all intrinsics here, in `compiler/rustc_typeck/src/check/mod.rs`,
+    /// Remember to add all intrinsics here, in `compiler/rustc_hir_analysis/src/check/mod.rs`,
     /// and in `library/core/src/intrinsics.rs`; if you need access to any LLVM intrinsics,
     /// add them to `compiler/rustc_codegen_llvm/src/context.rs`.
     fn codegen_intrinsic_call(
diff --git a/compiler/rustc_driver/Cargo.toml b/compiler/rustc_driver/Cargo.toml
index d1d02ed73f959..59e937777483e 100644
--- a/compiler/rustc_driver/Cargo.toml
+++ b/compiler/rustc_driver/Cargo.toml
@@ -30,7 +30,7 @@ rustc_error_codes = { path = "../rustc_error_codes" }
 rustc_interface = { path = "../rustc_interface" }
 rustc_ast = { path = "../rustc_ast" }
 rustc_span = { path = "../rustc_span" }
-rustc_typeck = { path = "../rustc_typeck" }
+rustc_hir_analysis = { path = "../rustc_hir_analysis" }
 
 [target.'cfg(unix)'.dependencies]
 libc = "0.2"
diff --git a/compiler/rustc_driver/src/pretty.rs b/compiler/rustc_driver/src/pretty.rs
index e97da4322fa01..f9b1316d2eb5f 100644
--- a/compiler/rustc_driver/src/pretty.rs
+++ b/compiler/rustc_driver/src/pretty.rs
@@ -502,7 +502,7 @@ fn print_with_analysis(
 
         ThirTree => {
             let mut out = String::new();
-            abort_on_err(rustc_typeck::check_crate(tcx), tcx.sess);
+            abort_on_err(rustc_hir_analysis::check_crate(tcx), tcx.sess);
             debug!("pretty printing THIR tree");
             for did in tcx.hir().body_owners() {
                 let _ = writeln!(
diff --git a/compiler/rustc_typeck/Cargo.toml b/compiler/rustc_hir_analysis/Cargo.toml
similarity index 97%
rename from compiler/rustc_typeck/Cargo.toml
rename to compiler/rustc_hir_analysis/Cargo.toml
index cae29c1d3c5f9..dd26b3da7bcf6 100644
--- a/compiler/rustc_typeck/Cargo.toml
+++ b/compiler/rustc_hir_analysis/Cargo.toml
@@ -1,5 +1,5 @@
 [package]
-name = "rustc_typeck"
+name = "rustc_hir_analysis"
 version = "0.0.0"
 edition = "2021"
 
diff --git a/compiler/rustc_typeck/README.md b/compiler/rustc_hir_analysis/README.md
similarity index 100%
rename from compiler/rustc_typeck/README.md
rename to compiler/rustc_hir_analysis/README.md
diff --git a/compiler/rustc_typeck/src/astconv/errors.rs b/compiler/rustc_hir_analysis/src/astconv/errors.rs
similarity index 100%
rename from compiler/rustc_typeck/src/astconv/errors.rs
rename to compiler/rustc_hir_analysis/src/astconv/errors.rs
diff --git a/compiler/rustc_typeck/src/astconv/generics.rs b/compiler/rustc_hir_analysis/src/astconv/generics.rs
similarity index 100%
rename from compiler/rustc_typeck/src/astconv/generics.rs
rename to compiler/rustc_hir_analysis/src/astconv/generics.rs
diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs
similarity index 100%
rename from compiler/rustc_typeck/src/astconv/mod.rs
rename to compiler/rustc_hir_analysis/src/astconv/mod.rs
diff --git a/compiler/rustc_typeck/src/bounds.rs b/compiler/rustc_hir_analysis/src/bounds.rs
similarity index 100%
rename from compiler/rustc_typeck/src/bounds.rs
rename to compiler/rustc_hir_analysis/src/bounds.rs
diff --git a/compiler/rustc_typeck/src/check/_match.rs b/compiler/rustc_hir_analysis/src/check/_match.rs
similarity index 100%
rename from compiler/rustc_typeck/src/check/_match.rs
rename to compiler/rustc_hir_analysis/src/check/_match.rs
diff --git a/compiler/rustc_typeck/src/check/autoderef.rs b/compiler/rustc_hir_analysis/src/check/autoderef.rs
similarity index 100%
rename from compiler/rustc_typeck/src/check/autoderef.rs
rename to compiler/rustc_hir_analysis/src/check/autoderef.rs
diff --git a/compiler/rustc_typeck/src/check/callee.rs b/compiler/rustc_hir_analysis/src/check/callee.rs
similarity index 100%
rename from compiler/rustc_typeck/src/check/callee.rs
rename to compiler/rustc_hir_analysis/src/check/callee.rs
diff --git a/compiler/rustc_typeck/src/check/cast.rs b/compiler/rustc_hir_analysis/src/check/cast.rs
similarity index 100%
rename from compiler/rustc_typeck/src/check/cast.rs
rename to compiler/rustc_hir_analysis/src/check/cast.rs
diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
similarity index 100%
rename from compiler/rustc_typeck/src/check/check.rs
rename to compiler/rustc_hir_analysis/src/check/check.rs
diff --git a/compiler/rustc_typeck/src/check/closure.rs b/compiler/rustc_hir_analysis/src/check/closure.rs
similarity index 100%
rename from compiler/rustc_typeck/src/check/closure.rs
rename to compiler/rustc_hir_analysis/src/check/closure.rs
diff --git a/compiler/rustc_typeck/src/check/coercion.rs b/compiler/rustc_hir_analysis/src/check/coercion.rs
similarity index 100%
rename from compiler/rustc_typeck/src/check/coercion.rs
rename to compiler/rustc_hir_analysis/src/check/coercion.rs
diff --git a/compiler/rustc_typeck/src/check/compare_method.rs b/compiler/rustc_hir_analysis/src/check/compare_method.rs
similarity index 100%
rename from compiler/rustc_typeck/src/check/compare_method.rs
rename to compiler/rustc_hir_analysis/src/check/compare_method.rs
diff --git a/compiler/rustc_typeck/src/check/demand.rs b/compiler/rustc_hir_analysis/src/check/demand.rs
similarity index 100%
rename from compiler/rustc_typeck/src/check/demand.rs
rename to compiler/rustc_hir_analysis/src/check/demand.rs
diff --git a/compiler/rustc_typeck/src/check/diverges.rs b/compiler/rustc_hir_analysis/src/check/diverges.rs
similarity index 100%
rename from compiler/rustc_typeck/src/check/diverges.rs
rename to compiler/rustc_hir_analysis/src/check/diverges.rs
diff --git a/compiler/rustc_typeck/src/check/dropck.rs b/compiler/rustc_hir_analysis/src/check/dropck.rs
similarity index 99%
rename from compiler/rustc_typeck/src/check/dropck.rs
rename to compiler/rustc_hir_analysis/src/check/dropck.rs
index ab143c059820d..e5b212eb757b6 100644
--- a/compiler/rustc_typeck/src/check/dropck.rs
+++ b/compiler/rustc_hir_analysis/src/check/dropck.rs
@@ -1,4 +1,4 @@
-// FIXME(@lcnr): Move this module out of `rustc_typeck`.
+// FIXME(@lcnr): Move this module out of `rustc_hir_analysis`.
 //
 // We don't do any drop checking during hir typeck.
 use crate::hir::def_id::{DefId, LocalDefId};
diff --git a/compiler/rustc_typeck/src/check/expectation.rs b/compiler/rustc_hir_analysis/src/check/expectation.rs
similarity index 100%
rename from compiler/rustc_typeck/src/check/expectation.rs
rename to compiler/rustc_hir_analysis/src/check/expectation.rs
diff --git a/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_hir_analysis/src/check/expr.rs
similarity index 100%
rename from compiler/rustc_typeck/src/check/expr.rs
rename to compiler/rustc_hir_analysis/src/check/expr.rs
diff --git a/compiler/rustc_typeck/src/check/fallback.rs b/compiler/rustc_hir_analysis/src/check/fallback.rs
similarity index 100%
rename from compiler/rustc_typeck/src/check/fallback.rs
rename to compiler/rustc_hir_analysis/src/check/fallback.rs
diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs b/compiler/rustc_hir_analysis/src/check/fn_ctxt/_impl.rs
similarity index 100%
rename from compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs
rename to compiler/rustc_hir_analysis/src/check/fn_ctxt/_impl.rs
diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/arg_matrix.rs b/compiler/rustc_hir_analysis/src/check/fn_ctxt/arg_matrix.rs
similarity index 100%
rename from compiler/rustc_typeck/src/check/fn_ctxt/arg_matrix.rs
rename to compiler/rustc_hir_analysis/src/check/fn_ctxt/arg_matrix.rs
diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs b/compiler/rustc_hir_analysis/src/check/fn_ctxt/checks.rs
similarity index 100%
rename from compiler/rustc_typeck/src/check/fn_ctxt/checks.rs
rename to compiler/rustc_hir_analysis/src/check/fn_ctxt/checks.rs
diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/mod.rs b/compiler/rustc_hir_analysis/src/check/fn_ctxt/mod.rs
similarity index 100%
rename from compiler/rustc_typeck/src/check/fn_ctxt/mod.rs
rename to compiler/rustc_hir_analysis/src/check/fn_ctxt/mod.rs
diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs b/compiler/rustc_hir_analysis/src/check/fn_ctxt/suggestions.rs
similarity index 100%
rename from compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs
rename to compiler/rustc_hir_analysis/src/check/fn_ctxt/suggestions.rs
diff --git a/compiler/rustc_typeck/src/check/gather_locals.rs b/compiler/rustc_hir_analysis/src/check/gather_locals.rs
similarity index 100%
rename from compiler/rustc_typeck/src/check/gather_locals.rs
rename to compiler/rustc_hir_analysis/src/check/gather_locals.rs
diff --git a/compiler/rustc_typeck/src/check/generator_interior.rs b/compiler/rustc_hir_analysis/src/check/generator_interior.rs
similarity index 100%
rename from compiler/rustc_typeck/src/check/generator_interior.rs
rename to compiler/rustc_hir_analysis/src/check/generator_interior.rs
diff --git a/compiler/rustc_typeck/src/check/generator_interior/drop_ranges.rs b/compiler/rustc_hir_analysis/src/check/generator_interior/drop_ranges.rs
similarity index 100%
rename from compiler/rustc_typeck/src/check/generator_interior/drop_ranges.rs
rename to compiler/rustc_hir_analysis/src/check/generator_interior/drop_ranges.rs
diff --git a/compiler/rustc_typeck/src/check/generator_interior/drop_ranges/cfg_build.rs b/compiler/rustc_hir_analysis/src/check/generator_interior/drop_ranges/cfg_build.rs
similarity index 100%
rename from compiler/rustc_typeck/src/check/generator_interior/drop_ranges/cfg_build.rs
rename to compiler/rustc_hir_analysis/src/check/generator_interior/drop_ranges/cfg_build.rs
diff --git a/compiler/rustc_typeck/src/check/generator_interior/drop_ranges/cfg_propagate.rs b/compiler/rustc_hir_analysis/src/check/generator_interior/drop_ranges/cfg_propagate.rs
similarity index 100%
rename from compiler/rustc_typeck/src/check/generator_interior/drop_ranges/cfg_propagate.rs
rename to compiler/rustc_hir_analysis/src/check/generator_interior/drop_ranges/cfg_propagate.rs
diff --git a/compiler/rustc_typeck/src/check/generator_interior/drop_ranges/cfg_visualize.rs b/compiler/rustc_hir_analysis/src/check/generator_interior/drop_ranges/cfg_visualize.rs
similarity index 100%
rename from compiler/rustc_typeck/src/check/generator_interior/drop_ranges/cfg_visualize.rs
rename to compiler/rustc_hir_analysis/src/check/generator_interior/drop_ranges/cfg_visualize.rs
diff --git a/compiler/rustc_typeck/src/check/generator_interior/drop_ranges/record_consumed_borrow.rs b/compiler/rustc_hir_analysis/src/check/generator_interior/drop_ranges/record_consumed_borrow.rs
similarity index 100%
rename from compiler/rustc_typeck/src/check/generator_interior/drop_ranges/record_consumed_borrow.rs
rename to compiler/rustc_hir_analysis/src/check/generator_interior/drop_ranges/record_consumed_borrow.rs
diff --git a/compiler/rustc_typeck/src/check/inherited.rs b/compiler/rustc_hir_analysis/src/check/inherited.rs
similarity index 100%
rename from compiler/rustc_typeck/src/check/inherited.rs
rename to compiler/rustc_hir_analysis/src/check/inherited.rs
diff --git a/compiler/rustc_typeck/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
similarity index 100%
rename from compiler/rustc_typeck/src/check/intrinsic.rs
rename to compiler/rustc_hir_analysis/src/check/intrinsic.rs
diff --git a/compiler/rustc_typeck/src/check/intrinsicck.rs b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs
similarity index 100%
rename from compiler/rustc_typeck/src/check/intrinsicck.rs
rename to compiler/rustc_hir_analysis/src/check/intrinsicck.rs
diff --git a/compiler/rustc_typeck/src/check/method/confirm.rs b/compiler/rustc_hir_analysis/src/check/method/confirm.rs
similarity index 100%
rename from compiler/rustc_typeck/src/check/method/confirm.rs
rename to compiler/rustc_hir_analysis/src/check/method/confirm.rs
diff --git a/compiler/rustc_typeck/src/check/method/mod.rs b/compiler/rustc_hir_analysis/src/check/method/mod.rs
similarity index 100%
rename from compiler/rustc_typeck/src/check/method/mod.rs
rename to compiler/rustc_hir_analysis/src/check/method/mod.rs
diff --git a/compiler/rustc_typeck/src/check/method/prelude2021.rs b/compiler/rustc_hir_analysis/src/check/method/prelude2021.rs
similarity index 100%
rename from compiler/rustc_typeck/src/check/method/prelude2021.rs
rename to compiler/rustc_hir_analysis/src/check/method/prelude2021.rs
diff --git a/compiler/rustc_typeck/src/check/method/probe.rs b/compiler/rustc_hir_analysis/src/check/method/probe.rs
similarity index 100%
rename from compiler/rustc_typeck/src/check/method/probe.rs
rename to compiler/rustc_hir_analysis/src/check/method/probe.rs
diff --git a/compiler/rustc_typeck/src/check/method/suggest.rs b/compiler/rustc_hir_analysis/src/check/method/suggest.rs
similarity index 100%
rename from compiler/rustc_typeck/src/check/method/suggest.rs
rename to compiler/rustc_hir_analysis/src/check/method/suggest.rs
diff --git a/compiler/rustc_typeck/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs
similarity index 100%
rename from compiler/rustc_typeck/src/check/mod.rs
rename to compiler/rustc_hir_analysis/src/check/mod.rs
diff --git a/compiler/rustc_typeck/src/check/op.rs b/compiler/rustc_hir_analysis/src/check/op.rs
similarity index 100%
rename from compiler/rustc_typeck/src/check/op.rs
rename to compiler/rustc_hir_analysis/src/check/op.rs
diff --git a/compiler/rustc_typeck/src/check/pat.rs b/compiler/rustc_hir_analysis/src/check/pat.rs
similarity index 100%
rename from compiler/rustc_typeck/src/check/pat.rs
rename to compiler/rustc_hir_analysis/src/check/pat.rs
diff --git a/compiler/rustc_typeck/src/check/place_op.rs b/compiler/rustc_hir_analysis/src/check/place_op.rs
similarity index 100%
rename from compiler/rustc_typeck/src/check/place_op.rs
rename to compiler/rustc_hir_analysis/src/check/place_op.rs
diff --git a/compiler/rustc_typeck/src/check/region.rs b/compiler/rustc_hir_analysis/src/check/region.rs
similarity index 100%
rename from compiler/rustc_typeck/src/check/region.rs
rename to compiler/rustc_hir_analysis/src/check/region.rs
diff --git a/compiler/rustc_typeck/src/check/rvalue_scopes.rs b/compiler/rustc_hir_analysis/src/check/rvalue_scopes.rs
similarity index 100%
rename from compiler/rustc_typeck/src/check/rvalue_scopes.rs
rename to compiler/rustc_hir_analysis/src/check/rvalue_scopes.rs
diff --git a/compiler/rustc_typeck/src/check/upvar.rs b/compiler/rustc_hir_analysis/src/check/upvar.rs
similarity index 100%
rename from compiler/rustc_typeck/src/check/upvar.rs
rename to compiler/rustc_hir_analysis/src/check/upvar.rs
diff --git a/compiler/rustc_typeck/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
similarity index 100%
rename from compiler/rustc_typeck/src/check/wfcheck.rs
rename to compiler/rustc_hir_analysis/src/check/wfcheck.rs
diff --git a/compiler/rustc_typeck/src/check/writeback.rs b/compiler/rustc_hir_analysis/src/check/writeback.rs
similarity index 100%
rename from compiler/rustc_typeck/src/check/writeback.rs
rename to compiler/rustc_hir_analysis/src/check/writeback.rs
diff --git a/compiler/rustc_typeck/src/check_unused.rs b/compiler/rustc_hir_analysis/src/check_unused.rs
similarity index 100%
rename from compiler/rustc_typeck/src/check_unused.rs
rename to compiler/rustc_hir_analysis/src/check_unused.rs
diff --git a/compiler/rustc_typeck/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs
similarity index 100%
rename from compiler/rustc_typeck/src/coherence/builtin.rs
rename to compiler/rustc_hir_analysis/src/coherence/builtin.rs
diff --git a/compiler/rustc_typeck/src/coherence/inherent_impls.rs b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs
similarity index 100%
rename from compiler/rustc_typeck/src/coherence/inherent_impls.rs
rename to compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs
diff --git a/compiler/rustc_typeck/src/coherence/inherent_impls_overlap.rs b/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs
similarity index 100%
rename from compiler/rustc_typeck/src/coherence/inherent_impls_overlap.rs
rename to compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs
diff --git a/compiler/rustc_typeck/src/coherence/mod.rs b/compiler/rustc_hir_analysis/src/coherence/mod.rs
similarity index 100%
rename from compiler/rustc_typeck/src/coherence/mod.rs
rename to compiler/rustc_hir_analysis/src/coherence/mod.rs
diff --git a/compiler/rustc_typeck/src/coherence/orphan.rs b/compiler/rustc_hir_analysis/src/coherence/orphan.rs
similarity index 100%
rename from compiler/rustc_typeck/src/coherence/orphan.rs
rename to compiler/rustc_hir_analysis/src/coherence/orphan.rs
diff --git a/compiler/rustc_typeck/src/coherence/unsafety.rs b/compiler/rustc_hir_analysis/src/coherence/unsafety.rs
similarity index 100%
rename from compiler/rustc_typeck/src/coherence/unsafety.rs
rename to compiler/rustc_hir_analysis/src/coherence/unsafety.rs
diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs
similarity index 100%
rename from compiler/rustc_typeck/src/collect.rs
rename to compiler/rustc_hir_analysis/src/collect.rs
diff --git a/compiler/rustc_typeck/src/collect/item_bounds.rs b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
similarity index 100%
rename from compiler/rustc_typeck/src/collect/item_bounds.rs
rename to compiler/rustc_hir_analysis/src/collect/item_bounds.rs
diff --git a/compiler/rustc_typeck/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs
similarity index 100%
rename from compiler/rustc_typeck/src/collect/type_of.rs
rename to compiler/rustc_hir_analysis/src/collect/type_of.rs
diff --git a/compiler/rustc_typeck/src/constrained_generic_params.rs b/compiler/rustc_hir_analysis/src/constrained_generic_params.rs
similarity index 100%
rename from compiler/rustc_typeck/src/constrained_generic_params.rs
rename to compiler/rustc_hir_analysis/src/constrained_generic_params.rs
diff --git a/compiler/rustc_typeck/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs
similarity index 100%
rename from compiler/rustc_typeck/src/errors.rs
rename to compiler/rustc_hir_analysis/src/errors.rs
diff --git a/compiler/rustc_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_analysis/src/expr_use_visitor.rs
similarity index 100%
rename from compiler/rustc_typeck/src/expr_use_visitor.rs
rename to compiler/rustc_hir_analysis/src/expr_use_visitor.rs
diff --git a/compiler/rustc_typeck/src/hir_wf_check.rs b/compiler/rustc_hir_analysis/src/hir_wf_check.rs
similarity index 100%
rename from compiler/rustc_typeck/src/hir_wf_check.rs
rename to compiler/rustc_hir_analysis/src/hir_wf_check.rs
diff --git a/compiler/rustc_typeck/src/impl_wf_check.rs b/compiler/rustc_hir_analysis/src/impl_wf_check.rs
similarity index 100%
rename from compiler/rustc_typeck/src/impl_wf_check.rs
rename to compiler/rustc_hir_analysis/src/impl_wf_check.rs
diff --git a/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs
similarity index 100%
rename from compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs
rename to compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs
diff --git a/compiler/rustc_typeck/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs
similarity index 100%
rename from compiler/rustc_typeck/src/lib.rs
rename to compiler/rustc_hir_analysis/src/lib.rs
diff --git a/compiler/rustc_typeck/src/mem_categorization.rs b/compiler/rustc_hir_analysis/src/mem_categorization.rs
similarity index 100%
rename from compiler/rustc_typeck/src/mem_categorization.rs
rename to compiler/rustc_hir_analysis/src/mem_categorization.rs
diff --git a/compiler/rustc_typeck/src/outlives/explicit.rs b/compiler/rustc_hir_analysis/src/outlives/explicit.rs
similarity index 100%
rename from compiler/rustc_typeck/src/outlives/explicit.rs
rename to compiler/rustc_hir_analysis/src/outlives/explicit.rs
diff --git a/compiler/rustc_typeck/src/outlives/implicit_infer.rs b/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs
similarity index 100%
rename from compiler/rustc_typeck/src/outlives/implicit_infer.rs
rename to compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs
diff --git a/compiler/rustc_typeck/src/outlives/mod.rs b/compiler/rustc_hir_analysis/src/outlives/mod.rs
similarity index 100%
rename from compiler/rustc_typeck/src/outlives/mod.rs
rename to compiler/rustc_hir_analysis/src/outlives/mod.rs
diff --git a/compiler/rustc_typeck/src/outlives/test.rs b/compiler/rustc_hir_analysis/src/outlives/test.rs
similarity index 100%
rename from compiler/rustc_typeck/src/outlives/test.rs
rename to compiler/rustc_hir_analysis/src/outlives/test.rs
diff --git a/compiler/rustc_typeck/src/outlives/utils.rs b/compiler/rustc_hir_analysis/src/outlives/utils.rs
similarity index 100%
rename from compiler/rustc_typeck/src/outlives/utils.rs
rename to compiler/rustc_hir_analysis/src/outlives/utils.rs
diff --git a/compiler/rustc_typeck/src/structured_errors.rs b/compiler/rustc_hir_analysis/src/structured_errors.rs
similarity index 100%
rename from compiler/rustc_typeck/src/structured_errors.rs
rename to compiler/rustc_hir_analysis/src/structured_errors.rs
diff --git a/compiler/rustc_typeck/src/structured_errors/missing_cast_for_variadic_arg.rs b/compiler/rustc_hir_analysis/src/structured_errors/missing_cast_for_variadic_arg.rs
similarity index 100%
rename from compiler/rustc_typeck/src/structured_errors/missing_cast_for_variadic_arg.rs
rename to compiler/rustc_hir_analysis/src/structured_errors/missing_cast_for_variadic_arg.rs
diff --git a/compiler/rustc_typeck/src/structured_errors/sized_unsized_cast.rs b/compiler/rustc_hir_analysis/src/structured_errors/sized_unsized_cast.rs
similarity index 100%
rename from compiler/rustc_typeck/src/structured_errors/sized_unsized_cast.rs
rename to compiler/rustc_hir_analysis/src/structured_errors/sized_unsized_cast.rs
diff --git a/compiler/rustc_typeck/src/structured_errors/wrong_number_of_generic_args.rs b/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs
similarity index 100%
rename from compiler/rustc_typeck/src/structured_errors/wrong_number_of_generic_args.rs
rename to compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs
diff --git a/compiler/rustc_typeck/src/variance/constraints.rs b/compiler/rustc_hir_analysis/src/variance/constraints.rs
similarity index 100%
rename from compiler/rustc_typeck/src/variance/constraints.rs
rename to compiler/rustc_hir_analysis/src/variance/constraints.rs
diff --git a/compiler/rustc_typeck/src/variance/mod.rs b/compiler/rustc_hir_analysis/src/variance/mod.rs
similarity index 100%
rename from compiler/rustc_typeck/src/variance/mod.rs
rename to compiler/rustc_hir_analysis/src/variance/mod.rs
diff --git a/compiler/rustc_typeck/src/variance/solve.rs b/compiler/rustc_hir_analysis/src/variance/solve.rs
similarity index 100%
rename from compiler/rustc_typeck/src/variance/solve.rs
rename to compiler/rustc_hir_analysis/src/variance/solve.rs
diff --git a/compiler/rustc_typeck/src/variance/terms.rs b/compiler/rustc_hir_analysis/src/variance/terms.rs
similarity index 100%
rename from compiler/rustc_typeck/src/variance/terms.rs
rename to compiler/rustc_hir_analysis/src/variance/terms.rs
diff --git a/compiler/rustc_typeck/src/variance/test.rs b/compiler/rustc_hir_analysis/src/variance/test.rs
similarity index 100%
rename from compiler/rustc_typeck/src/variance/test.rs
rename to compiler/rustc_hir_analysis/src/variance/test.rs
diff --git a/compiler/rustc_typeck/src/variance/xform.rs b/compiler/rustc_hir_analysis/src/variance/xform.rs
similarity index 100%
rename from compiler/rustc_typeck/src/variance/xform.rs
rename to compiler/rustc_hir_analysis/src/variance/xform.rs
diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
index 99469d1e1e7db..99de5b6598126 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
@@ -1862,7 +1862,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
 
         // In some (most?) cases cause.body_id points to actual body, but in some cases
         // it's an actual definition. According to the comments (e.g. in
-        // librustc_typeck/check/compare_method.rs:compare_predicate_entailment) the latter
+        // rustc_hir_analysis/check/compare_method.rs:compare_predicate_entailment) the latter
         // is relied upon by some other code. This might (or might not) need cleanup.
         let body_owner_def_id =
             self.tcx.hir().opt_local_def_id(cause.body_id).unwrap_or_else(|| {
diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs
index efc9c1ca46fe4..b9fd79e0d2f3a 100644
--- a/compiler/rustc_infer/src/infer/mod.rs
+++ b/compiler/rustc_infer/src/infer/mod.rs
@@ -581,7 +581,7 @@ impl<'tcx> TyCtxtInferExt<'tcx> for TyCtxt<'tcx> {
 }
 
 impl<'tcx> InferCtxtBuilder<'tcx> {
-    /// Used only by `rustc_typeck` during body type-checking/inference,
+    /// Used only by `rustc_hir_analysis` during body type-checking/inference,
     /// will initialize `in_progress_typeck_results` with fresh `TypeckResults`.
     /// Will also change the scope for opaque type defining use checks to the given owner.
     pub fn with_fresh_in_progress_typeck_results(mut self, table_owner: OwnerId) -> Self {
diff --git a/compiler/rustc_infer/src/lib.rs b/compiler/rustc_infer/src/lib.rs
index b91c098ab03db..e040634edb088 100644
--- a/compiler/rustc_infer/src/lib.rs
+++ b/compiler/rustc_infer/src/lib.rs
@@ -2,7 +2,7 @@
 //!
 //! - **Type inference.** The type inference code can be found in the `infer` module;
 //!   this code handles low-level equality and subtyping operations. The
-//!   type check pass in the compiler is found in the `rustc_typeck` crate.
+//!   type check pass in the compiler is found in the `rustc_hir_analysis` crate.
 //!
 //! For more information about how rustc works, see the [rustc dev guide].
 //!
diff --git a/compiler/rustc_interface/Cargo.toml b/compiler/rustc_interface/Cargo.toml
index da4002d09ad02..f3c38875b37c6 100644
--- a/compiler/rustc_interface/Cargo.toml
+++ b/compiler/rustc_interface/Cargo.toml
@@ -38,7 +38,7 @@ rustc_mir_build = { path = "../rustc_mir_build" }
 rustc_mir_transform = { path = "../rustc_mir_transform" }
 rustc_monomorphize = { path = "../rustc_monomorphize" }
 rustc_passes = { path = "../rustc_passes" }
-rustc_typeck = { path = "../rustc_typeck" }
+rustc_hir_analysis = { path = "../rustc_hir_analysis" }
 rustc_lint = { path = "../rustc_lint" }
 rustc_errors = { path = "../rustc_errors" }
 rustc_plugin_impl = { path = "../rustc_plugin_impl" }
diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs
index c41b154c3e066..ad3e020b581bf 100644
--- a/compiler/rustc_interface/src/passes.rs
+++ b/compiler/rustc_interface/src/passes.rs
@@ -37,7 +37,6 @@ use rustc_session::{Limit, Session};
 use rustc_span::symbol::{sym, Symbol};
 use rustc_span::FileName;
 use rustc_trait_selection::traits;
-use rustc_typeck as typeck;
 
 use std::any::Any;
 use std::cell::RefCell;
@@ -736,7 +735,7 @@ pub static DEFAULT_QUERY_PROVIDERS: LazyLock = LazyLock::new(|| {
     rustc_mir_transform::provide(providers);
     rustc_monomorphize::provide(providers);
     rustc_privacy::provide(providers);
-    typeck::provide(providers);
+    rustc_hir_analysis::provide(providers);
     ty::provide(providers);
     traits::provide(providers);
     rustc_passes::provide(providers);
@@ -880,7 +879,7 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> {
     });
 
     // passes are timed inside typeck
-    typeck::check_crate(tcx)?;
+    rustc_hir_analysis::check_crate(tcx)?;
 
     sess.time("misc_checking_2", || {
         parallel!(
diff --git a/compiler/rustc_middle/src/ty/cast.rs b/compiler/rustc_middle/src/ty/cast.rs
index 981e2d3b6d2d3..2de27102bcc0b 100644
--- a/compiler/rustc_middle/src/ty/cast.rs
+++ b/compiler/rustc_middle/src/ty/cast.rs
@@ -38,7 +38,7 @@ pub enum CastTy<'tcx> {
 }
 
 /// Cast Kind. See [RFC 401](https://rust-lang.github.io/rfcs/0401-coercions.html)
-/// (or librustc_typeck/check/cast.rs).
+/// (or rustc_hir_analysis/check/cast.rs).
 #[derive(Copy, Clone, Debug, TyEncodable, TyDecodable, HashStable)]
 pub enum CastKind {
     CoercionCast,
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index e430c327efe7c..4781585b82c38 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -574,7 +574,7 @@ pub struct TypeckResults<'tcx> {
 
     /// Tracks the rvalue scoping rules which defines finer scoping for rvalue expressions
     /// by applying extended parameter rules.
-    /// Details may be find in `rustc_typeck::check::rvalue_scopes`.
+    /// Details may be find in `rustc_hir_analysis::check::rvalue_scopes`.
     pub rvalue_scopes: RvalueScopes,
 
     /// Stores the type, expression, span and optional scope span of all types
diff --git a/compiler/rustc_middle/src/ty/rvalue_scopes.rs b/compiler/rustc_middle/src/ty/rvalue_scopes.rs
index e86dafae338f2..e79b79a25aec9 100644
--- a/compiler/rustc_middle/src/ty/rvalue_scopes.rs
+++ b/compiler/rustc_middle/src/ty/rvalue_scopes.rs
@@ -3,7 +3,7 @@ use rustc_data_structures::fx::FxHashMap;
 use rustc_hir as hir;
 
 /// `RvalueScopes` is a mapping from sub-expressions to _extended_ lifetime as determined by
-/// rules laid out in `rustc_typeck::check::rvalue_scopes`.
+/// rules laid out in `rustc_hir_analysis::check::rvalue_scopes`.
 #[derive(TyEncodable, TyDecodable, Clone, Debug, Default, Eq, PartialEq, HashStable)]
 pub struct RvalueScopes {
     map: FxHashMap>,
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index f4f4bb37c1acc..2f6ec836c3c06 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -315,7 +315,7 @@ impl<'tcx> ClosureSubsts<'tcx> {
     /// closure.
     // FIXME(eddyb) this should be unnecessary, as the shallowly resolved
     // type is known at the time of the creation of `ClosureSubsts`,
-    // see `rustc_typeck::check::closure`.
+    // see `rustc_hir_analysis::check::closure`.
     pub fn sig_as_fn_ptr_ty(self) -> Ty<'tcx> {
         self.split().closure_sig_as_fn_ptr_ty.expect_ty()
     }
@@ -2121,7 +2121,7 @@ impl<'tcx> Ty<'tcx> {
     ///
     /// Note that during type checking, we use an inference variable
     /// to represent the closure kind, because it has not yet been
-    /// inferred. Once upvar inference (in `rustc_typeck/src/check/upvar.rs`)
+    /// inferred. Once upvar inference (in `rustc_hir_analysis/src/check/upvar.rs`)
     /// is complete, that type variable will be unified.
     pub fn to_opt_closure_kind(self) -> Option {
         match self.kind() {
diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs
index 3f8a9d21cd8d1..bcf2ed6817210 100644
--- a/compiler/rustc_mir_build/src/thir/cx/expr.rs
+++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs
@@ -998,7 +998,7 @@ impl<'tcx> Cx<'tcx> {
             .temporary_scope(self.region_scope_tree, closure_expr.hir_id.local_id);
         let var_ty = place.base_ty;
 
-        // The result of capture analysis in `rustc_typeck/check/upvar.rs`represents a captured path
+        // The result of capture analysis in `rustc_hir_analysis/check/upvar.rs`represents a captured path
         // as it's seen for use within the closure and not at the time of closure creation.
         //
         // That is we see expect to see it start from a captured upvar and not something that is local
diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
index 11645f840c135..cd186421bb13b 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
@@ -86,7 +86,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
         // ```
         //
         // the type assigned to `Some(n)` in `unadjusted_pat` would be `Option` (this is
-        // determined in rustc_typeck::check::match). The adjustments would be
+        // determined in rustc_hir_analysis::check::match). The adjustments would be
         //
         // `vec![&&Option, &Option]`.
         //
diff --git a/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs b/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs
index 02e047afaf31f..22b5883714898 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs
@@ -746,7 +746,7 @@ impl<'p, 'tcx> Witness<'p, 'tcx> {
 /// Report that a match of a `non_exhaustive` enum marked with `non_exhaustive_omitted_patterns`
 /// is not exhaustive enough.
 ///
-/// NB: The partner lint for structs lives in `compiler/rustc_typeck/src/check/pat.rs`.
+/// NB: The partner lint for structs lives in `compiler/rustc_hir_analysis/src/check/pat.rs`.
 fn lint_non_exhaustive_omitted_patterns<'p, 'tcx>(
     cx: &MatchCheckCtxt<'p, 'tcx>,
     scrut_ty: Ty<'tcx>,
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index a21521ff68b19..897a0db930c79 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -1744,7 +1744,7 @@ impl CheckAttrVisitor<'_> {
                     }
                 }
                 Some(_) => {
-                    // This error case is handled in rustc_typeck::collect.
+                    // This error case is handled in rustc_hir_analysis::collect.
                 }
                 None => {
                     // Default case (compiler) when arg isn't defined.
diff --git a/compiler/rustc_privacy/Cargo.toml b/compiler/rustc_privacy/Cargo.toml
index 5785921fb1eda..832fdc9f01668 100644
--- a/compiler/rustc_privacy/Cargo.toml
+++ b/compiler/rustc_privacy/Cargo.toml
@@ -14,5 +14,5 @@ rustc_middle = { path = "../rustc_middle" }
 rustc_session = { path = "../rustc_session" }
 rustc_span = { path = "../rustc_span" }
 rustc_trait_selection = { path = "../rustc_trait_selection" }
-rustc_typeck = { path = "../rustc_typeck" }
+rustc_hir_analysis = { path = "../rustc_hir_analysis" }
 tracing = "0.1"
diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs
index 41d5f54b3664f..7ab07a671c47b 100644
--- a/compiler/rustc_privacy/src/lib.rs
+++ b/compiler/rustc_privacy/src/lib.rs
@@ -1207,7 +1207,7 @@ impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> {
             // Types in signatures.
             // FIXME: This is very ineffective. Ideally each HIR type should be converted
             // into a semantic type only once and the result should be cached somehow.
-            if self.visit(rustc_typeck::hir_ty_to_ty(self.tcx, hir_ty)).is_break() {
+            if self.visit(rustc_hir_analysis::hir_ty_to_ty(self.tcx, hir_ty)).is_break() {
                 return;
             }
         }
@@ -1236,7 +1236,7 @@ impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> {
         if self.maybe_typeck_results.is_none() {
             // Avoid calling `hir_trait_to_predicates` in bodies, it will ICE.
             // The traits' privacy in bodies is already checked as a part of trait object types.
-            let bounds = rustc_typeck::hir_trait_to_predicates(
+            let bounds = rustc_hir_analysis::hir_trait_to_predicates(
                 self.tcx,
                 trait_ref,
                 // NOTE: This isn't really right, but the actual type doesn't matter here. It's
diff --git a/compiler/rustc_resolve/src/check_unused.rs b/compiler/rustc_resolve/src/check_unused.rs
index 8b58b32b65649..01c3801f22329 100644
--- a/compiler/rustc_resolve/src/check_unused.rs
+++ b/compiler/rustc_resolve/src/check_unused.rs
@@ -6,7 +6,7 @@
 // `use` items.
 //
 // Unused trait imports can't be checked until the method resolution. We save
-// candidates here, and do the actual check in librustc_typeck/check_unused.rs.
+// candidates here, and do the actual check in rustc_hir_analysis/check_unused.rs.
 //
 // Checking for unused imports is split into three steps:
 //
diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs
index 583030b0e5048..9b52decd9c770 100644
--- a/compiler/rustc_resolve/src/lib.rs
+++ b/compiler/rustc_resolve/src/lib.rs
@@ -4,7 +4,7 @@
 //! Paths in macros, imports, expressions, types, patterns are resolved here.
 //! Label and lifetime names are resolved here as well.
 //!
-//! Type-relative name resolution (methods, fields, associated items) happens in `rustc_typeck`.
+//! Type-relative name resolution (methods, fields, associated items) happens in `rustc_hir_analysis`.
 
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
 #![feature(box_patterns)]
diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs
index 05738b6c48ae2..fa1dc90e4a24b 100644
--- a/compiler/rustc_ty_utils/src/instance.rs
+++ b/compiler/rustc_ty_utils/src/instance.rs
@@ -187,7 +187,7 @@ fn resolve_associated_item<'tcx>(
             // we know the error would've been caught (e.g. in an upstream crate).
             //
             // A better approach might be to just introduce a query (returning
-            // `Result<(), ErrorGuaranteed>`) for the check that `rustc_typeck`
+            // `Result<(), ErrorGuaranteed>`) for the check that `rustc_hir_analysis`
             // performs (i.e. that the definition's type in the `impl` matches
             // the declaration in the `trait`), so that we can cheaply check
             // here if it failed, instead of approximating it.
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index bd68dffb823d1..704292c10486b 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -17,6 +17,7 @@ use rustc_hir as hir;
 use rustc_hir::def::{CtorKind, DefKind, Res};
 use rustc_hir::def_id::{DefId, LOCAL_CRATE};
 use rustc_hir::PredicateOrigin;
+use rustc_hir_analysis::hir_ty_to_ty;
 use rustc_infer::infer::region_constraints::{Constraint, RegionConstraintData};
 use rustc_middle::middle::resolve_lifetime as rl;
 use rustc_middle::ty::fold::TypeFolder;
@@ -26,7 +27,6 @@ use rustc_middle::{bug, span_bug};
 use rustc_span::hygiene::{AstPass, MacroKind};
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::{self, ExpnKind};
-use rustc_typeck::hir_ty_to_ty;
 
 use std::assert_matches::assert_matches;
 use std::collections::hash_map::Entry;
@@ -632,7 +632,7 @@ fn clean_ty_generics<'tcx>(
     let mut impl_trait = BTreeMap::>::default();
 
     // Bounds in the type_params and lifetimes fields are repeated in the
-    // predicates field (see rustc_typeck::collect::ty_generics), so remove
+    // predicates field (see rustc_hir_analysis::collect::ty_generics), so remove
     // them.
     let stripped_params = gens
         .params
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index f06d2cf108de3..e53e93c4defb1 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -21,6 +21,7 @@ use rustc_hir::def::{CtorKind, DefKind, Res};
 use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
 use rustc_hir::lang_items::LangItem;
 use rustc_hir::{BodyId, Mutability};
+use rustc_hir_analysis::check::intrinsic::intrinsic_operation_unsafety;
 use rustc_index::vec::IndexVec;
 use rustc_middle::ty::fast_reject::SimplifiedType;
 use rustc_middle::ty::{self, TyCtxt};
@@ -31,7 +32,6 @@ use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::{self, FileName, Loc};
 use rustc_target::abi::VariantIdx;
 use rustc_target::spec::abi::Abi;
-use rustc_typeck::check::intrinsic::intrinsic_operation_unsafety;
 
 use crate::clean::cfg::Cfg;
 use crate::clean::clean_visibility;
diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs
index 76562d26a5502..09a26cbac3e49 100644
--- a/src/librustdoc/core.rs
+++ b/src/librustdoc/core.rs
@@ -293,7 +293,7 @@ pub(crate) fn create_config(
         override_queries: Some(|_sess, providers, _external_providers| {
             // Most lints will require typechecking, so just don't run them.
             providers.lint_mod = |_, _| {};
-            // Prevent `rustc_typeck::check_crate` from calling `typeck` on all bodies.
+            // Prevent `rustc_hir_analysis::check_crate` from calling `typeck` on all bodies.
             providers.typeck_item_bodies = |_, _| {};
             // hack so that `used_trait_imports` won't try to call typeck
             providers.used_trait_imports = |_, _| {
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index 23e3de45fa510..ef01b854e5a69 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -41,6 +41,7 @@ extern crate rustc_errors;
 extern crate rustc_expand;
 extern crate rustc_feature;
 extern crate rustc_hir;
+extern crate rustc_hir_analysis;
 extern crate rustc_hir_pretty;
 extern crate rustc_index;
 extern crate rustc_infer;
@@ -59,7 +60,6 @@ extern crate rustc_session;
 extern crate rustc_span;
 extern crate rustc_target;
 extern crate rustc_trait_selection;
-extern crate rustc_typeck;
 extern crate test;
 
 // See docs in https://github.com/rust-lang/rust/blob/master/compiler/rustc/src/main.rs
diff --git a/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause-const.rs b/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause-const.rs
index 7a88ec35c8f2a..47c38c979c328 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause-const.rs
+++ b/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause-const.rs
@@ -1,6 +1,6 @@
 // Like trait-where-clause.rs, but we are calling from a const context.
 // Checking the validity of traits' where clauses happen at a later stage.
-// (`rustc_const_eval` instead of `rustc_typeck`) Therefore one file as a
+// (`rustc_const_eval` instead of `rustc_hir_analysis`) Therefore one file as a
 // test is not enough.
 #![feature(const_trait_impl)]
 
diff --git a/src/test/ui/suggestions/non-existent-field-present-in-subfield-recursion-limit.rs b/src/test/ui/suggestions/non-existent-field-present-in-subfield-recursion-limit.rs
index 98b408daa022d..a7a3f98180a3f 100644
--- a/src/test/ui/suggestions/non-existent-field-present-in-subfield-recursion-limit.rs
+++ b/src/test/ui/suggestions/non-existent-field-present-in-subfield-recursion-limit.rs
@@ -1,4 +1,4 @@
-// In rustc_typeck::check::expr::no_such_field_err we recursively
+// In rustc_hir_analysis::check::expr::no_such_field_err we recursively
 // look in subfields for the field. This recursive search is limited
 // in depth for compile-time reasons and to avoid infinite recursion
 // in case of cycles. This file tests that the limit in the recursion
diff --git a/src/tools/clippy/clippy_lints/src/default_union_representation.rs b/src/tools/clippy/clippy_lints/src/default_union_representation.rs
index d559ad423df5f..3905a6c2e2119 100644
--- a/src/tools/clippy/clippy_lints/src/default_union_representation.rs
+++ b/src/tools/clippy/clippy_lints/src/default_union_representation.rs
@@ -4,7 +4,7 @@ use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty::layout::LayoutOf;
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::sym;
-use rustc_typeck::hir_ty_to_ty;
+use rustc_hir_analysis::hir_ty_to_ty;
 
 declare_clippy_lint! {
     /// ### What it does
diff --git a/src/tools/clippy/clippy_lints/src/escape.rs b/src/tools/clippy/clippy_lints/src/escape.rs
index a6ddb26e2dee3..8ccc969646ec5 100644
--- a/src/tools/clippy/clippy_lints/src/escape.rs
+++ b/src/tools/clippy/clippy_lints/src/escape.rs
@@ -10,7 +10,7 @@ use rustc_session::{declare_tool_lint, impl_lint_pass};
 use rustc_span::source_map::Span;
 use rustc_span::symbol::kw;
 use rustc_target::spec::abi::Abi;
-use rustc_typeck::expr_use_visitor::{Delegate, ExprUseVisitor, PlaceBase, PlaceWithHirId};
+use rustc_hir_analysis::expr_use_visitor::{Delegate, ExprUseVisitor, PlaceBase, PlaceWithHirId};
 
 #[derive(Copy, Clone)]
 pub struct BoxedLocal {
@@ -177,7 +177,7 @@ impl<'a, 'tcx> Delegate<'tcx> for EscapeDelegate<'a, 'tcx> {
         }
     }
 
-    fn fake_read(&mut self, _: &rustc_typeck::expr_use_visitor::PlaceWithHirId<'tcx>, _: FakeReadCause, _: HirId) {}
+    fn fake_read(&mut self, _: &rustc_hir_analysis::expr_use_visitor::PlaceWithHirId<'tcx>, _: FakeReadCause, _: HirId) {}
 }
 
 impl<'a, 'tcx> EscapeDelegate<'a, 'tcx> {
diff --git a/src/tools/clippy/clippy_lints/src/implicit_hasher.rs b/src/tools/clippy/clippy_lints/src/implicit_hasher.rs
index 804fdc2da0889..a920c3bba2aed 100644
--- a/src/tools/clippy/clippy_lints/src/implicit_hasher.rs
+++ b/src/tools/clippy/clippy_lints/src/implicit_hasher.rs
@@ -12,7 +12,7 @@ use rustc_middle::ty::{Ty, TypeckResults};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::source_map::Span;
 use rustc_span::symbol::sym;
-use rustc_typeck::hir_ty_to_ty;
+use rustc_hir_analysis::hir_ty_to_ty;
 
 use if_chain::if_chain;
 
diff --git a/src/tools/clippy/clippy_lints/src/large_const_arrays.rs b/src/tools/clippy/clippy_lints/src/large_const_arrays.rs
index 984c5cd4e37c2..d6eb53ae29b5a 100644
--- a/src/tools/clippy/clippy_lints/src/large_const_arrays.rs
+++ b/src/tools/clippy/clippy_lints/src/large_const_arrays.rs
@@ -7,7 +7,7 @@ use rustc_middle::ty::layout::LayoutOf;
 use rustc_middle::ty::{self, ConstKind};
 use rustc_session::{declare_tool_lint, impl_lint_pass};
 use rustc_span::{BytePos, Pos, Span};
-use rustc_typeck::hir_ty_to_ty;
+use rustc_hir_analysis::hir_ty_to_ty;
 
 declare_clippy_lint! {
     /// ### What it does
diff --git a/src/tools/clippy/clippy_lints/src/lib.rs b/src/tools/clippy/clippy_lints/src/lib.rs
index 00bf6445c12d2..c3db194c4ad85 100644
--- a/src/tools/clippy/clippy_lints/src/lib.rs
+++ b/src/tools/clippy/clippy_lints/src/lib.rs
@@ -43,7 +43,7 @@ extern crate rustc_session;
 extern crate rustc_span;
 extern crate rustc_target;
 extern crate rustc_trait_selection;
-extern crate rustc_typeck;
+extern crate rustc_hir_analysis;
 
 #[macro_use]
 extern crate clippy_utils;
diff --git a/src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs b/src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs
index be7f96e9bb077..6d585c2e45de6 100644
--- a/src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs
@@ -8,7 +8,7 @@ use rustc_infer::infer::TyCtxtInferExt;
 use rustc_lint::LateContext;
 use rustc_middle::{mir::FakeReadCause, ty};
 use rustc_span::source_map::Span;
-use rustc_typeck::expr_use_visitor::{Delegate, ExprUseVisitor, PlaceBase, PlaceWithHirId};
+use rustc_hir_analysis::expr_use_visitor::{Delegate, ExprUseVisitor, PlaceBase, PlaceWithHirId};
 
 pub(super) fn check(cx: &LateContext<'_>, arg: &Expr<'_>, body: &Expr<'_>) {
     if_chain! {
@@ -114,7 +114,7 @@ impl<'tcx> Delegate<'tcx> for MutatePairDelegate<'_, 'tcx> {
         }
     }
 
-    fn fake_read(&mut self, _: &rustc_typeck::expr_use_visitor::PlaceWithHirId<'tcx>, _: FakeReadCause, _: HirId) {}
+    fn fake_read(&mut self, _: &rustc_hir_analysis::expr_use_visitor::PlaceWithHirId<'tcx>, _: FakeReadCause, _: HirId) {}
 }
 
 impl MutatePairDelegate<'_, '_> {
diff --git a/src/tools/clippy/clippy_lints/src/loops/utils.rs b/src/tools/clippy/clippy_lints/src/loops/utils.rs
index 4801a84eb92ce..f1f58db80b306 100644
--- a/src/tools/clippy/clippy_lints/src/loops/utils.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/utils.rs
@@ -10,7 +10,7 @@ use rustc_middle::hir::nested_filter;
 use rustc_middle::ty::{self, Ty};
 use rustc_span::source_map::Spanned;
 use rustc_span::symbol::{sym, Symbol};
-use rustc_typeck::hir_ty_to_ty;
+use rustc_hir_analysis::hir_ty_to_ty;
 use std::iter::Iterator;
 
 #[derive(Debug, PartialEq, Eq)]
diff --git a/src/tools/clippy/clippy_lints/src/matches/needless_match.rs b/src/tools/clippy/clippy_lints/src/matches/needless_match.rs
index 634eef82e532a..58ea43e69d9b1 100644
--- a/src/tools/clippy/clippy_lints/src/matches/needless_match.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/needless_match.rs
@@ -11,7 +11,7 @@ use rustc_hir::LangItem::OptionNone;
 use rustc_hir::{Arm, BindingAnnotation, ByRef, Expr, ExprKind, FnRetTy, Guard, Node, Pat, PatKind, Path, QPath};
 use rustc_lint::LateContext;
 use rustc_span::sym;
-use rustc_typeck::hir_ty_to_ty;
+use rustc_hir_analysis::hir_ty_to_ty;
 
 pub(crate) fn check_match(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>], expr: &Expr<'_>) {
     if arms.len() > 1 && expr_ty_matches_p_ty(cx, ex, expr) && check_all_arms(cx, ex, arms) {
diff --git a/src/tools/clippy/clippy_lints/src/methods/mod.rs b/src/tools/clippy/clippy_lints/src/methods/mod.rs
index ddb6d1ca26c91..428a354ec6b1e 100644
--- a/src/tools/clippy/clippy_lints/src/methods/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/mod.rs
@@ -115,7 +115,7 @@ use rustc_middle::ty::{self, TraitRef, Ty};
 use rustc_semver::RustcVersion;
 use rustc_session::{declare_tool_lint, impl_lint_pass};
 use rustc_span::{sym, Span};
-use rustc_typeck::hir_ty_to_ty;
+use rustc_hir_analysis::hir_ty_to_ty;
 
 declare_clippy_lint! {
     /// ### What it does
diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs
index 79d784c342cac..559f32a563ed9 100644
--- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs
@@ -18,7 +18,7 @@ use rustc_middle::ty::{self, ParamTy, PredicateKind, ProjectionPredicate, TraitP
 use rustc_semver::RustcVersion;
 use rustc_span::{sym, Symbol};
 use rustc_trait_selection::traits::{query::evaluate_obligation::InferCtxtExt as _, Obligation, ObligationCause};
-use rustc_typeck::check::{FnCtxt, Inherited};
+use rustc_hir_analysis::check::{FnCtxt, Inherited};
 use std::cmp::max;
 
 use super::UNNECESSARY_TO_OWNED;
diff --git a/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs b/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs
index f24b41411c816..00376f0d79022 100644
--- a/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs
+++ b/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs
@@ -13,7 +13,7 @@ use rustc_middle::lint::in_external_macro;
 use rustc_semver::RustcVersion;
 use rustc_session::{declare_tool_lint, impl_lint_pass};
 use rustc_span::Span;
-use rustc_typeck::hir_ty_to_ty;
+use rustc_hir_analysis::hir_ty_to_ty;
 
 declare_clippy_lint! {
     /// ### What it does
diff --git a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs
index 060037ed49691..4f46872439c3c 100644
--- a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs
+++ b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs
@@ -22,7 +22,7 @@ use rustc_span::{sym, Span};
 use rustc_target::spec::abi::Abi;
 use rustc_trait_selection::traits;
 use rustc_trait_selection::traits::misc::can_type_implement_copy;
-use rustc_typeck::expr_use_visitor as euv;
+use rustc_hir_analysis::expr_use_visitor as euv;
 use std::borrow::Cow;
 
 declare_clippy_lint! {
@@ -341,5 +341,5 @@ impl<'tcx> euv::Delegate<'tcx> for MovedVariablesCtxt {
 
     fn mutate(&mut self, _: &euv::PlaceWithHirId<'tcx>, _: HirId) {}
 
-    fn fake_read(&mut self, _: &rustc_typeck::expr_use_visitor::PlaceWithHirId<'tcx>, _: FakeReadCause, _: HirId) {}
+    fn fake_read(&mut self, _: &rustc_hir_analysis::expr_use_visitor::PlaceWithHirId<'tcx>, _: FakeReadCause, _: HirId) {}
 }
diff --git a/src/tools/clippy/clippy_lints/src/non_copy_const.rs b/src/tools/clippy/clippy_lints/src/non_copy_const.rs
index 616ef9e2f867f..48ff737dae7bc 100644
--- a/src/tools/clippy/clippy_lints/src/non_copy_const.rs
+++ b/src/tools/clippy/clippy_lints/src/non_copy_const.rs
@@ -20,7 +20,7 @@ use rustc_middle::ty::adjustment::Adjust;
 use rustc_middle::ty::{self, Ty};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::{sym, InnerSpan, Span, DUMMY_SP};
-use rustc_typeck::hir_ty_to_ty;
+use rustc_hir_analysis::hir_ty_to_ty;
 
 // FIXME: this is a correctness problem but there's no suitable
 // warn-by-default category.
diff --git a/src/tools/clippy/clippy_lints/src/operators/assign_op_pattern.rs b/src/tools/clippy/clippy_lints/src/operators/assign_op_pattern.rs
index 2c22c8b3d0819..f134c6c4cdba5 100644
--- a/src/tools/clippy/clippy_lints/src/operators/assign_op_pattern.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/assign_op_pattern.rs
@@ -11,7 +11,7 @@ use rustc_lint::LateContext;
 use rustc_middle::mir::FakeReadCause;
 use rustc_middle::ty::BorrowKind;
 use rustc_trait_selection::infer::TyCtxtInferExt;
-use rustc_typeck::expr_use_visitor::{Delegate, ExprUseVisitor, PlaceBase, PlaceWithHirId};
+use rustc_hir_analysis::expr_use_visitor::{Delegate, ExprUseVisitor, PlaceBase, PlaceWithHirId};
 
 use super::ASSIGN_OP_PATTERN;
 
diff --git a/src/tools/clippy/clippy_lints/src/transmute/utils.rs b/src/tools/clippy/clippy_lints/src/transmute/utils.rs
index 8e90d20265ce1..fdf847bf44593 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/utils.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/utils.rs
@@ -2,7 +2,7 @@ use rustc_hir::Expr;
 use rustc_lint::LateContext;
 use rustc_middle::ty::{cast::CastKind, Ty};
 use rustc_span::DUMMY_SP;
-use rustc_typeck::check::{cast::{self, CastCheckResult}, FnCtxt, Inherited};
+use rustc_hir_analysis::check::{cast::{self, CastCheckResult}, FnCtxt, Inherited};
 
 // check if the component types of the transmuted collection and the result have different ABI,
 // size or alignment
diff --git a/src/tools/clippy/clippy_lints/src/types/redundant_allocation.rs b/src/tools/clippy/clippy_lints/src/types/redundant_allocation.rs
index a1312fcda0b71..d81c5c83845d8 100644
--- a/src/tools/clippy/clippy_lints/src/types/redundant_allocation.rs
+++ b/src/tools/clippy/clippy_lints/src/types/redundant_allocation.rs
@@ -5,7 +5,7 @@ use rustc_errors::Applicability;
 use rustc_hir::{self as hir, def_id::DefId, QPath, TyKind};
 use rustc_lint::LateContext;
 use rustc_span::symbol::sym;
-use rustc_typeck::hir_ty_to_ty;
+use rustc_hir_analysis::hir_ty_to_ty;
 
 use super::{utils, REDUNDANT_ALLOCATION};
 
diff --git a/src/tools/clippy/clippy_lints/src/types/vec_box.rs b/src/tools/clippy/clippy_lints/src/types/vec_box.rs
index b2f536ca7815b..236f9955722d0 100644
--- a/src/tools/clippy/clippy_lints/src/types/vec_box.rs
+++ b/src/tools/clippy/clippy_lints/src/types/vec_box.rs
@@ -8,7 +8,7 @@ use rustc_lint::LateContext;
 use rustc_middle::ty::layout::LayoutOf;
 use rustc_middle::ty::TypeVisitable;
 use rustc_span::symbol::sym;
-use rustc_typeck::hir_ty_to_ty;
+use rustc_hir_analysis::hir_ty_to_ty;
 
 use super::VEC_BOX;
 
diff --git a/src/tools/clippy/clippy_lints/src/use_self.rs b/src/tools/clippy/clippy_lints/src/use_self.rs
index ce51cb693fc02..6a767967ef409 100644
--- a/src/tools/clippy/clippy_lints/src/use_self.rs
+++ b/src/tools/clippy/clippy_lints/src/use_self.rs
@@ -16,7 +16,7 @@ use rustc_lint::{LateContext, LateLintPass};
 use rustc_semver::RustcVersion;
 use rustc_session::{declare_tool_lint, impl_lint_pass};
 use rustc_span::Span;
-use rustc_typeck::hir_ty_to_ty;
+use rustc_hir_analysis::hir_ty_to_ty;
 
 declare_clippy_lint! {
     /// ### What it does
diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints.rs
index 17d9a04185767..78c036186f506 100644
--- a/src/tools/clippy/clippy_lints/src/utils/internal_lints.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints.rs
@@ -32,7 +32,7 @@ use rustc_session::{declare_lint_pass, declare_tool_lint, impl_lint_pass};
 use rustc_span::source_map::Spanned;
 use rustc_span::symbol::Symbol;
 use rustc_span::{sym, BytePos, Span};
-use rustc_typeck::hir_ty_to_ty;
+use rustc_hir_analysis::hir_ty_to_ty;
 
 use std::borrow::{Borrow, Cow};
 
diff --git a/src/tools/clippy/clippy_lints/src/zero_sized_map_values.rs b/src/tools/clippy/clippy_lints/src/zero_sized_map_values.rs
index 386f3c527f174..703ba2ef4b054 100644
--- a/src/tools/clippy/clippy_lints/src/zero_sized_map_values.rs
+++ b/src/tools/clippy/clippy_lints/src/zero_sized_map_values.rs
@@ -7,7 +7,7 @@ use rustc_middle::ty::layout::LayoutOf as _;
 use rustc_middle::ty::{Adt, Ty, TypeVisitable};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::sym;
-use rustc_typeck::hir_ty_to_ty;
+use rustc_hir_analysis::hir_ty_to_ty;
 
 declare_clippy_lint! {
     /// ### What it does
diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs
index b1abd3b04c929..627d6b51944a6 100644
--- a/src/tools/clippy/clippy_utils/src/lib.rs
+++ b/src/tools/clippy/clippy_utils/src/lib.rs
@@ -32,7 +32,7 @@ extern crate rustc_session;
 extern crate rustc_span;
 extern crate rustc_target;
 extern crate rustc_trait_selection;
-extern crate rustc_typeck;
+extern crate rustc_hir_analysis;
 
 #[macro_use]
 pub mod sym_helper;
@@ -1386,7 +1386,7 @@ pub fn is_integer_literal(expr: &Expr<'_>, value: u128) -> bool {
 /// Examples of coercions can be found in the Nomicon at
 /// .
 ///
-/// See `rustc_middle::ty::adjustment::Adjustment` and `rustc_typeck::check::coercion` for more
+/// See `rustc_middle::ty::adjustment::Adjustment` and `rustc_hir_analysis::check::coercion` for more
 /// information on adjustments and coercions.
 pub fn is_adjusted(cx: &LateContext<'_>, e: &Expr<'_>) -> bool {
     cx.typeck_results().adjustments().get(e.hir_id).is_some()
diff --git a/src/tools/clippy/clippy_utils/src/sugg.rs b/src/tools/clippy/clippy_utils/src/sugg.rs
index f08275a4ac76b..e53c40e95760b 100644
--- a/src/tools/clippy/clippy_utils/src/sugg.rs
+++ b/src/tools/clippy/clippy_utils/src/sugg.rs
@@ -16,7 +16,7 @@ use rustc_middle::hir::place::ProjectionKind;
 use rustc_middle::mir::{FakeReadCause, Mutability};
 use rustc_middle::ty;
 use rustc_span::source_map::{BytePos, CharPos, Pos, Span, SyntaxContext};
-use rustc_typeck::expr_use_visitor::{Delegate, ExprUseVisitor, PlaceBase, PlaceWithHirId};
+use rustc_hir_analysis::expr_use_visitor::{Delegate, ExprUseVisitor, PlaceBase, PlaceWithHirId};
 use std::borrow::Cow;
 use std::fmt::{Display, Write as _};
 use std::ops::{Add, Neg, Not, Sub};
@@ -1056,7 +1056,7 @@ impl<'tcx> Delegate<'tcx> for DerefDelegate<'_, 'tcx> {
 
     fn mutate(&mut self, _: &PlaceWithHirId<'tcx>, _: HirId) {}
 
-    fn fake_read(&mut self, _: &rustc_typeck::expr_use_visitor::PlaceWithHirId<'tcx>, _: FakeReadCause, _: HirId) {}
+    fn fake_read(&mut self, _: &rustc_hir_analysis::expr_use_visitor::PlaceWithHirId<'tcx>, _: FakeReadCause, _: HirId) {}
 }
 
 #[cfg(test)]
diff --git a/src/tools/clippy/clippy_utils/src/usage.rs b/src/tools/clippy/clippy_utils/src/usage.rs
index a7c08839f5241..76bfec75726df 100644
--- a/src/tools/clippy/clippy_utils/src/usage.rs
+++ b/src/tools/clippy/clippy_utils/src/usage.rs
@@ -9,7 +9,7 @@ use rustc_lint::LateContext;
 use rustc_middle::hir::nested_filter;
 use rustc_middle::mir::FakeReadCause;
 use rustc_middle::ty;
-use rustc_typeck::expr_use_visitor::{Delegate, ExprUseVisitor, PlaceBase, PlaceWithHirId};
+use rustc_hir_analysis::expr_use_visitor::{Delegate, ExprUseVisitor, PlaceBase, PlaceWithHirId};
 
 /// Returns a set of mutated local variable IDs, or `None` if mutations could not be determined.
 pub fn mutated_variables<'tcx>(expr: &'tcx Expr<'_>, cx: &LateContext<'tcx>) -> Option {
@@ -73,7 +73,7 @@ impl<'tcx> Delegate<'tcx> for MutVarsDelegate {
         self.update(cmt);
     }
 
-    fn fake_read(&mut self, _: &rustc_typeck::expr_use_visitor::PlaceWithHirId<'tcx>, _: FakeReadCause, _: HirId) {}
+    fn fake_read(&mut self, _: &rustc_hir_analysis::expr_use_visitor::PlaceWithHirId<'tcx>, _: FakeReadCause, _: HirId) {}
 }
 
 pub struct ParamBindingIdCollector {
diff --git a/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.fixed b/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.fixed
index 539239fc18f94..7263abac15dfb 100644
--- a/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.fixed
+++ b/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.fixed
@@ -8,7 +8,7 @@
 
 use std::mem::{size_of, transmute};
 
-// rustc_typeck::check::cast contains documentation about when a cast `e as U` is
+// rustc_hir_analysis::check::cast contains documentation about when a cast `e as U` is
 // valid, which we quote from below.
 fn main() {
     // We should see an error message for each transmute, and no error messages for
diff --git a/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.rs b/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.rs
index b9e446dc89a95..d8e4421d4c18e 100644
--- a/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.rs
+++ b/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.rs
@@ -8,7 +8,7 @@
 
 use std::mem::{size_of, transmute};
 
-// rustc_typeck::check::cast contains documentation about when a cast `e as U` is
+// rustc_hir_analysis::check::cast contains documentation about when a cast `e as U` is
 // valid, which we quote from below.
 fn main() {
     // We should see an error message for each transmute, and no error messages for
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/autoderef.rs b/src/tools/rust-analyzer/crates/hir-ty/src/autoderef.rs
index 344036dd8139d..e106c4c2cfd6a 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/autoderef.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/autoderef.rs
@@ -1,7 +1,7 @@
 //! In certain situations, rust automatically inserts derefs as necessary: for
 //! example, field accesses `foo.bar` still work when `foo` is actually a
 //! reference to a type with the field `bar`. This is an approximation of the
-//! logic in rustc (which lives in librustc_typeck/check/autoderef.rs).
+//! logic in rustc (which lives in rustc_hir_analysis/check/autoderef.rs).
 
 use std::sync::Arc;
 
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs
index e37763e8ea7f0..9dbeba4f9f48f 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs
@@ -2,7 +2,7 @@
 //! the type of each expression and pattern.
 //!
 //! For type inference, compare the implementations in rustc (the various
-//! check_* methods in librustc_typeck/check/mod.rs are a good entry point) and
+//! check_* methods in rustc_hir_analysis/check/mod.rs are a good entry point) and
 //! IntelliJ-Rust (org.rust.lang.core.types.infer). Our entry point for
 //! inference here is the `infer` function, which infers the types of all
 //! expressions in a given function.
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/coerce.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/coerce.rs
index f54440bf5b372..8df25c83c6eb7 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/coerce.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/coerce.rs
@@ -3,7 +3,7 @@
 //! like going from `&Vec` to `&[T]`.
 //!
 //! See  and
-//! `librustc_typeck/check/coercion.rs`.
+//! `rustc_hir_analysis/check/coercion.rs`.
 
 use std::{iter, sync::Arc};
 
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs b/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs
index 41fcef73d9be4..cc21990d55371 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs
@@ -1,7 +1,7 @@
 //! This module is concerned with finding methods that a given type provides.
 //! For details about how this works in rustc, see the method lookup page in the
 //! [rustc guide](https://rust-lang.github.io/rustc-guide/method-lookup.html)
-//! and the corresponding code mostly in librustc_typeck/check/method/probe.rs.
+//! and the corresponding code mostly in rustc_hir_analysis/check/method/probe.rs.
 use std::{iter, ops::ControlFlow, sync::Arc};
 
 use arrayvec::ArrayVec;

From d04ea0ff1921fcf4f4bf1dc6f088b29471c34f95 Mon Sep 17 00:00:00 2001
From: bjorn3 <17426603+bjorn3@users.noreply.github.com>
Date: Tue, 27 Sep 2022 11:16:09 +0200
Subject: [PATCH 295/586] Allow passing rustix_use_libc cfg using RUSTFLAGS

Before this would error with

```
error: unexpected `rustix_use_libc` as condition name
  |
  = note: `-D unexpected-cfgs` implied by `-D warnings`
  = help: was set with `--cfg` but isn't in the `--check-cfg` expected names
```

I'm setting rustix_use_libc when testing bootstrapping rustc with cg_clif as I'm disabling inline asm here.
---
 src/bootstrap/lib.rs | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs
index c83490316b657..b20d43a3332c6 100644
--- a/src/bootstrap/lib.rs
+++ b/src/bootstrap/lib.rs
@@ -229,6 +229,8 @@ const EXTRA_CHECK_CFGS: &[(Option, &'static str, Option<&[&'static str]>)]
     // FIXME: Used by proc-macro2, but we should not be triggering on external dependencies.
     (Some(Mode::Rustc), "span_locations", None),
     (Some(Mode::ToolRustc), "span_locations", None),
+    // Can be passed in RUSTFLAGS to prevent direct syscalls in rustix.
+    (None, "rustix_use_libc", None),
 ];
 
 /// A structure representing a Rust compiler.

From 2286888ef9441d1efe4d912f2d2d7e8ccc8abd11 Mon Sep 17 00:00:00 2001
From: David Wood 
Date: Tue, 27 Sep 2022 11:01:49 +0100
Subject: [PATCH 296/586] session: remove now-unnecessary lint `#[allow]`s

In #101230, the internal diagnostic migration lints -
`diagnostic_outside_of_impl` and `untranslatable_diagnostic` - were
modified so that they wouldn't trigger on functions annotated with
`#[rustc_lint_diagnostics]`. However, this change has to make it into
the bootstrap compiler before the `#[allow]` annotations that it aims to
remove can be removed, which is possible now that #102051 has landed.

Signed-off-by: David Wood 
---
 compiler/rustc_session/src/parse.rs   |  8 -----
 compiler/rustc_session/src/session.rs | 44 ---------------------------
 2 files changed, 52 deletions(-)

diff --git a/compiler/rustc_session/src/parse.rs b/compiler/rustc_session/src/parse.rs
index b9202af2a6765..aaf265ad7c336 100644
--- a/compiler/rustc_session/src/parse.rs
+++ b/compiler/rustc_session/src/parse.rs
@@ -376,8 +376,6 @@ impl ParseSess {
     }
 
     #[rustc_lint_diagnostics]
-    #[allow(rustc::diagnostic_outside_of_impl)]
-    #[allow(rustc::untranslatable_diagnostic)]
     pub fn struct_err(
         &self,
         msg: impl Into,
@@ -386,22 +384,16 @@ impl ParseSess {
     }
 
     #[rustc_lint_diagnostics]
-    #[allow(rustc::diagnostic_outside_of_impl)]
-    #[allow(rustc::untranslatable_diagnostic)]
     pub fn struct_warn(&self, msg: impl Into) -> DiagnosticBuilder<'_, ()> {
         self.span_diagnostic.struct_warn(msg)
     }
 
     #[rustc_lint_diagnostics]
-    #[allow(rustc::diagnostic_outside_of_impl)]
-    #[allow(rustc::untranslatable_diagnostic)]
     pub fn struct_fatal(&self, msg: impl Into) -> DiagnosticBuilder<'_, !> {
         self.span_diagnostic.struct_fatal(msg)
     }
 
     #[rustc_lint_diagnostics]
-    #[allow(rustc::diagnostic_outside_of_impl)]
-    #[allow(rustc::untranslatable_diagnostic)]
     pub fn struct_diagnostic(
         &self,
         msg: impl Into,
diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs
index 0142e98176633..59b544ce9eb83 100644
--- a/compiler/rustc_session/src/session.rs
+++ b/compiler/rustc_session/src/session.rs
@@ -288,8 +288,6 @@ impl Session {
     }
 
     #[rustc_lint_diagnostics]
-    #[allow(rustc::untranslatable_diagnostic)]
-    #[allow(rustc::diagnostic_outside_of_impl)]
     pub fn struct_span_warn>(
         &self,
         sp: S,
@@ -298,8 +296,6 @@ impl Session {
         self.diagnostic().struct_span_warn(sp, msg)
     }
     #[rustc_lint_diagnostics]
-    #[allow(rustc::untranslatable_diagnostic)]
-    #[allow(rustc::diagnostic_outside_of_impl)]
     pub fn struct_span_warn_with_expectation>(
         &self,
         sp: S,
@@ -309,8 +305,6 @@ impl Session {
         self.diagnostic().struct_span_warn_with_expectation(sp, msg, id)
     }
     #[rustc_lint_diagnostics]
-    #[allow(rustc::untranslatable_diagnostic)]
-    #[allow(rustc::diagnostic_outside_of_impl)]
     pub fn struct_span_warn_with_code>(
         &self,
         sp: S,
@@ -320,14 +314,10 @@ impl Session {
         self.diagnostic().struct_span_warn_with_code(sp, msg, code)
     }
     #[rustc_lint_diagnostics]
-    #[allow(rustc::untranslatable_diagnostic)]
-    #[allow(rustc::diagnostic_outside_of_impl)]
     pub fn struct_warn(&self, msg: impl Into) -> DiagnosticBuilder<'_, ()> {
         self.diagnostic().struct_warn(msg)
     }
     #[rustc_lint_diagnostics]
-    #[allow(rustc::untranslatable_diagnostic)]
-    #[allow(rustc::diagnostic_outside_of_impl)]
     pub fn struct_warn_with_expectation(
         &self,
         msg: impl Into,
@@ -336,8 +326,6 @@ impl Session {
         self.diagnostic().struct_warn_with_expectation(msg, id)
     }
     #[rustc_lint_diagnostics]
-    #[allow(rustc::untranslatable_diagnostic)]
-    #[allow(rustc::diagnostic_outside_of_impl)]
     pub fn struct_span_allow>(
         &self,
         sp: S,
@@ -346,14 +334,10 @@ impl Session {
         self.diagnostic().struct_span_allow(sp, msg)
     }
     #[rustc_lint_diagnostics]
-    #[allow(rustc::untranslatable_diagnostic)]
-    #[allow(rustc::diagnostic_outside_of_impl)]
     pub fn struct_allow(&self, msg: impl Into) -> DiagnosticBuilder<'_, ()> {
         self.diagnostic().struct_allow(msg)
     }
     #[rustc_lint_diagnostics]
-    #[allow(rustc::untranslatable_diagnostic)]
-    #[allow(rustc::diagnostic_outside_of_impl)]
     pub fn struct_expect(
         &self,
         msg: impl Into,
@@ -362,8 +346,6 @@ impl Session {
         self.diagnostic().struct_expect(msg, id)
     }
     #[rustc_lint_diagnostics]
-    #[allow(rustc::untranslatable_diagnostic)]
-    #[allow(rustc::diagnostic_outside_of_impl)]
     pub fn struct_span_err>(
         &self,
         sp: S,
@@ -372,8 +354,6 @@ impl Session {
         self.diagnostic().struct_span_err(sp, msg)
     }
     #[rustc_lint_diagnostics]
-    #[allow(rustc::untranslatable_diagnostic)]
-    #[allow(rustc::diagnostic_outside_of_impl)]
     pub fn struct_span_err_with_code>(
         &self,
         sp: S,
@@ -384,8 +364,6 @@ impl Session {
     }
     // FIXME: This method should be removed (every error should have an associated error code).
     #[rustc_lint_diagnostics]
-    #[allow(rustc::untranslatable_diagnostic)]
-    #[allow(rustc::diagnostic_outside_of_impl)]
     pub fn struct_err(
         &self,
         msg: impl Into,
@@ -393,8 +371,6 @@ impl Session {
         self.parse_sess.struct_err(msg)
     }
     #[rustc_lint_diagnostics]
-    #[allow(rustc::untranslatable_diagnostic)]
-    #[allow(rustc::diagnostic_outside_of_impl)]
     pub fn struct_err_with_code(
         &self,
         msg: impl Into,
@@ -403,8 +379,6 @@ impl Session {
         self.diagnostic().struct_err_with_code(msg, code)
     }
     #[rustc_lint_diagnostics]
-    #[allow(rustc::untranslatable_diagnostic)]
-    #[allow(rustc::diagnostic_outside_of_impl)]
     pub fn struct_warn_with_code(
         &self,
         msg: impl Into,
@@ -413,8 +387,6 @@ impl Session {
         self.diagnostic().struct_warn_with_code(msg, code)
     }
     #[rustc_lint_diagnostics]
-    #[allow(rustc::untranslatable_diagnostic)]
-    #[allow(rustc::diagnostic_outside_of_impl)]
     pub fn struct_span_fatal>(
         &self,
         sp: S,
@@ -423,8 +395,6 @@ impl Session {
         self.diagnostic().struct_span_fatal(sp, msg)
     }
     #[rustc_lint_diagnostics]
-    #[allow(rustc::untranslatable_diagnostic)]
-    #[allow(rustc::diagnostic_outside_of_impl)]
     pub fn struct_span_fatal_with_code>(
         &self,
         sp: S,
@@ -434,21 +404,15 @@ impl Session {
         self.diagnostic().struct_span_fatal_with_code(sp, msg, code)
     }
     #[rustc_lint_diagnostics]
-    #[allow(rustc::untranslatable_diagnostic)]
-    #[allow(rustc::diagnostic_outside_of_impl)]
     pub fn struct_fatal(&self, msg: impl Into) -> DiagnosticBuilder<'_, !> {
         self.diagnostic().struct_fatal(msg)
     }
 
     #[rustc_lint_diagnostics]
-    #[allow(rustc::untranslatable_diagnostic)]
-    #[allow(rustc::diagnostic_outside_of_impl)]
     pub fn span_fatal>(&self, sp: S, msg: impl Into) -> ! {
         self.diagnostic().span_fatal(sp, msg)
     }
     #[rustc_lint_diagnostics]
-    #[allow(rustc::untranslatable_diagnostic)]
-    #[allow(rustc::diagnostic_outside_of_impl)]
     pub fn span_fatal_with_code>(
         &self,
         sp: S,
@@ -458,14 +422,10 @@ impl Session {
         self.diagnostic().span_fatal_with_code(sp, msg, code)
     }
     #[rustc_lint_diagnostics]
-    #[allow(rustc::untranslatable_diagnostic)]
-    #[allow(rustc::diagnostic_outside_of_impl)]
     pub fn fatal(&self, msg: impl Into) -> ! {
         self.diagnostic().fatal(msg).raise()
     }
     #[rustc_lint_diagnostics]
-    #[allow(rustc::untranslatable_diagnostic)]
-    #[allow(rustc::diagnostic_outside_of_impl)]
     pub fn span_err_or_warn>(
         &self,
         is_warning: bool,
@@ -479,8 +439,6 @@ impl Session {
         }
     }
     #[rustc_lint_diagnostics]
-    #[allow(rustc::untranslatable_diagnostic)]
-    #[allow(rustc::diagnostic_outside_of_impl)]
     pub fn span_err>(
         &self,
         sp: S,
@@ -489,8 +447,6 @@ impl Session {
         self.diagnostic().span_err(sp, msg)
     }
     #[rustc_lint_diagnostics]
-    #[allow(rustc::untranslatable_diagnostic)]
-    #[allow(rustc::diagnostic_outside_of_impl)]
     pub fn span_err_with_code>(
         &self,
         sp: S,

From 9bec0de3977e589fb92fc85ce9bc8fa99c3691f6 Mon Sep 17 00:00:00 2001
From: Mara Bos 
Date: Mon, 8 Aug 2022 16:17:08 +0200
Subject: [PATCH 297/586] Rewrite and refactor format_args!() builtin macro.

---
 compiler/rustc_builtin_macros/src/format.rs   | 2079 +++++++----------
 .../rustc_builtin_macros/src/format/expand.rs |  352 +++
 compiler/rustc_builtin_macros/src/lib.rs      |    1 +
 compiler/rustc_expand/src/build.rs            |    4 +
 compiler/rustc_span/src/symbol.rs             |   11 +
 src/test/ui/fmt/ifmt-bad-arg.stderr           |   14 +-
 src/test/ui/macros/format-parse-errors.stderr |    2 +-
 7 files changed, 1168 insertions(+), 1295 deletions(-)
 create mode 100644 compiler/rustc_builtin_macros/src/format/expand.rs

diff --git a/compiler/rustc_builtin_macros/src/format.rs b/compiler/rustc_builtin_macros/src/format.rs
index 2100487107517..06a831e36692e 100644
--- a/compiler/rustc_builtin_macros/src/format.rs
+++ b/compiler/rustc_builtin_macros/src/format.rs
@@ -1,271 +1,192 @@
-use ArgumentType::*;
-use Position::*;
-
 use rustc_ast as ast;
 use rustc_ast::ptr::P;
+use rustc_ast::token;
 use rustc_ast::tokenstream::TokenStream;
-use rustc_ast::visit::{self, Visitor};
-use rustc_ast::{token, BlockCheckMode, UnsafeSource};
-use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::{pluralize, Applicability, MultiSpan, PResult};
 use rustc_expand::base::{self, *};
 use rustc_parse_format as parse;
-use rustc_span::symbol::{sym, Ident, Symbol};
+use rustc_span::symbol::{Ident, Symbol};
 use rustc_span::{BytePos, InnerSpan, Span};
-use smallvec::SmallVec;
 
 use rustc_lint_defs::builtin::NAMED_ARGUMENTS_USED_POSITIONALLY;
 use rustc_lint_defs::{BufferedEarlyLint, BuiltinLintDiagnostics, LintId};
-use rustc_parse_format::Count;
-use std::borrow::Cow;
-use std::collections::hash_map::Entry;
-
-#[derive(PartialEq)]
-enum ArgumentType {
-    Placeholder(&'static str),
-    Count,
-}
 
-enum Position {
-    Exact(usize),
-    Capture(usize),
-    Named(Symbol, InnerSpan),
+mod expand;
+use expand::expand_parsed_format_args;
+
+// The format_args!() macro is expanded in three steps:
+//  1. First, `parse_args` will parse the `(literal, arg, arg, name=arg, name=arg)` syntax,
+//     but doesn't parse the template (the literal) itself.
+//  2. Second, `make_format_args` will parse the template, the format options, resolve argument references,
+//     produce diagnostics, and turn the whole thing into a `FormatArgs` structure.
+//  3. Finally, `expand_parsed_format_args` will turn that `FormatArgs` structure
+//     into the expression that the macro expands to.
+
+// Definitions:
+//
+// format_args!("hello {abc:.xyz$}!!", abc="world");
+// └──────────────────────────────────────────────┘
+//                     FormatArgs
+//
+// format_args!("hello {abc:.xyz$}!!", abc="world");
+//                                     └─────────┘
+//                                      argument
+//
+// format_args!("hello {abc:.xyz$}!!", abc="world");
+//              └───────────────────┘
+//                     template
+//
+// format_args!("hello {abc:.xyz$}!!", abc="world");
+//               └────┘└─────────┘└┘
+//                      pieces
+//
+// format_args!("hello {abc:.xyz$}!!", abc="world");
+//               └────┘           └┘
+//                   literal pieces
+//
+// format_args!("hello {abc:.xyz$}!!", abc="world");
+//                     └─────────┘
+//                     placeholder
+//
+// format_args!("hello {abc:.xyz$}!!", abc="world");
+//                      └─┘  └─┘
+//                      positions (could be names, numbers, empty, or `*`)
+
+/// (Parsed) format args.
+///
+/// Basically the "AST" for a complete `format_args!()`.
+///
+/// E.g., `format_args!("hello {name}");`.
+#[derive(Clone, Debug)]
+pub struct FormatArgs {
+    pub span: Span,
+    pub template: Vec,
+    pub arguments: Vec<(P, FormatArgKind)>,
 }
 
-/// Indicates how positional named argument (i.e. an named argument which is used by position
-/// instead of by name) is used in format string
-/// * `Arg` is the actual argument to print
-/// * `Width` is width format argument
-/// * `Precision` is precion format argument
-/// Example: `{Arg:Width$.Precision$}
-#[derive(Debug, Eq, PartialEq)]
-enum PositionalNamedArgType {
-    Arg,
-    Width,
-    Precision,
+#[derive(Clone, Debug)]
+pub enum FormatArgsPiece {
+    Literal(Symbol),
+    Placeholder(FormatPlaceholder),
 }
 
-/// Contains information necessary to create a lint for a positional named argument
-#[derive(Debug)]
-struct PositionalNamedArg {
-    ty: PositionalNamedArgType,
-    /// The piece of the using this argument (multiple pieces can use the same argument)
-    cur_piece: usize,
-    /// The InnerSpan for in the string to be replaced with the named argument
-    /// This will be None when the position is implicit
-    inner_span_to_replace: Option,
-    /// The name to use instead of the position
-    replacement: Symbol,
-    /// The span for the positional named argument (so the lint can point a message to it)
-    positional_named_arg_span: Span,
-    has_formatting: bool,
+#[derive(Clone, Debug)]
+pub enum FormatArgKind {
+    /// `format_args(…, arg)`
+    Normal,
+    /// `format_args(…, arg = 1)`
+    Named(Ident),
+    /// `format_args("… {arg} …")`
+    Captured(Ident),
 }
 
-impl PositionalNamedArg {
-    /// Determines:
-    /// 1) span to be replaced with the name of the named argument and
-    /// 2) span to be underlined for error messages
-    fn get_positional_arg_spans(&self, cx: &Context<'_, '_>) -> (Option, Option) {
-        if let Some(inner_span) = &self.inner_span_to_replace {
-            let span =
-                cx.fmtsp.from_inner(InnerSpan { start: inner_span.start, end: inner_span.end });
-            (Some(span), Some(span))
-        } else if self.ty == PositionalNamedArgType::Arg {
-            // In the case of a named argument whose position is implicit, if the argument *has*
-            // formatting, there will not be a span to replace. Instead, we insert the name after
-            // the `{`, which will be the first character of arg_span. If the argument does *not*
-            // have formatting, there may or may not be a span to replace. This is because
-            // whitespace is allowed in arguments without formatting (such as `format!("{  }", 1);`)
-            // but is not allowed in arguments with formatting (an error will be generated in cases
-            // like `format!("{ :1.1}", 1.0f32);`.
-            // For the message span, if there is formatting, we want to use the opening `{` and the
-            // next character, which will the `:` indicating the start of formatting. If there is
-            // not any formatting, we want to underline the entire span.
-            cx.arg_spans.get(self.cur_piece).map_or((None, None), |arg_span| {
-                if self.has_formatting {
-                    (
-                        Some(arg_span.with_lo(arg_span.lo() + BytePos(1)).shrink_to_lo()),
-                        Some(arg_span.with_hi(arg_span.lo() + BytePos(2))),
-                    )
-                } else {
-                    let replace_start = arg_span.lo() + BytePos(1);
-                    let replace_end = arg_span.hi() - BytePos(1);
-                    let to_replace = arg_span.with_lo(replace_start).with_hi(replace_end);
-                    (Some(to_replace), Some(*arg_span))
-                }
-            })
-        } else {
-            (None, None)
+impl FormatArgKind {
+    pub fn ident(&self) -> Option {
+        match self {
+            &Self::Normal => None,
+            &Self::Named(id) => Some(id),
+            &Self::Captured(id) => Some(id),
         }
     }
 }
 
-/// Encapsulates all the named arguments that have been used positionally
-#[derive(Debug)]
-struct PositionalNamedArgsLint {
-    positional_named_args: Vec,
+#[derive(Clone, Debug, PartialEq, Eq)]
+pub struct FormatPlaceholder {
+    /// Index into [`FormatArgs::arguments`].
+    pub argument: FormatArgPosition,
+    /// The span inside the format string for the full `{…}` placeholder.
+    pub span: Option,
+    /// `{}`, `{:?}`, or `{:x}`, etc.
+    pub format_trait: FormatTrait,
+    /// `{}` or `{:.5}` or `{:-^20}`, etc.
+    pub format_options: FormatOptions,
 }
 
-impl PositionalNamedArgsLint {
-    /// For a given positional argument, check if the index is for a named argument.
-    ///
-    /// Since positional arguments are required to come before named arguments, if the positional
-    /// index is greater than or equal to the start of named arguments, we know it's a named
-    /// argument used positionally.
-    ///
-    /// Example:
-    /// println!("{} {} {2}", 0, a=1, b=2);
-    ///
-    /// In this case, the first piece (`{}`) would be ArgumentImplicitlyIs with an index of 0. The
-    /// total number of arguments is 3 and the number of named arguments is 2, so the start of named
-    /// arguments is index 1. Therefore, the index of 0 is okay.
-    ///
-    /// The second piece (`{}`) would be ArgumentImplicitlyIs with an index of 1, which is the start
-    /// of named arguments, and so we should add a lint to use the named argument `a`.
-    ///
-    /// The third piece (`{2}`) would be ArgumentIs with an index of 2, which is greater than the
-    /// start of named arguments, and so we should add a lint to use the named argument `b`.
-    ///
-    /// This same check also works for width and precision formatting when either or both are
-    /// CountIsParam, which contains an index into the arguments.
-    fn maybe_add_positional_named_arg(
-        &mut self,
-        arg: Option<&FormatArg>,
-        ty: PositionalNamedArgType,
-        cur_piece: usize,
-        inner_span_to_replace: Option,
-        has_formatting: bool,
-    ) {
-        if let Some(arg) = arg {
-            if let Some(name) = arg.name {
-                self.push(name, ty, cur_piece, inner_span_to_replace, has_formatting)
-            }
-        }
-    }
+#[derive(Clone, Debug, PartialEq, Eq)]
+pub struct FormatArgPosition {
+    /// Which argument this position refers to (Ok),
+    /// or would've referred to if it existed (Err).
+    pub index: Result,
+    /// What kind of position this is. See [`FormatArgsPositionKind`].
+    pub kind: FormatArgPositionKind,
+    /// The span of the name or number.
+    pub span: Option,
+}
 
-    /// Construct a PositionalNamedArg struct and push it into the vec of positional
-    /// named arguments.
-    fn push(
-        &mut self,
-        arg_name: Ident,
-        ty: PositionalNamedArgType,
-        cur_piece: usize,
-        inner_span_to_replace: Option,
-        has_formatting: bool,
-    ) {
-        // In FormatSpec, `precision_span` starts at the leading `.`, which we want to keep in
-        // the lint suggestion, so increment `start` by 1 when `PositionalArgumentType` is
-        // `Precision`.
-        let inner_span_to_replace = if ty == PositionalNamedArgType::Precision {
-            inner_span_to_replace
-                .map(|is| rustc_parse_format::InnerSpan { start: is.start + 1, end: is.end })
-        } else {
-            inner_span_to_replace
-        };
-        self.positional_named_args.push(PositionalNamedArg {
-            ty,
-            cur_piece,
-            inner_span_to_replace,
-            replacement: arg_name.name,
-            positional_named_arg_span: arg_name.span,
-            has_formatting,
-        });
-    }
+#[derive(Copy, Clone, Debug, PartialEq, Eq)]
+pub enum FormatArgPositionKind {
+    /// `{}` or `{.*}`
+    Implicit,
+    /// `{1}` or `{:1$}` or `{:.1$}`
+    Number,
+    /// `{a}` or `{:a$}` or `{:.a$}`
+    Named,
+}
+
+#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
+pub enum FormatTrait {
+    /// `{}`
+    Display,
+    /// `{:?}`
+    Debug,
+    /// `{:e}`
+    LowerExp,
+    /// `{:E}`
+    UpperExp,
+    /// `{:o}`
+    Octal,
+    /// `{:p}`
+    Pointer,
+    /// `{:b}`
+    Binary,
+    /// `{:x}`
+    LowerHex,
+    /// `{:X}`
+    UpperHex,
+}
+
+#[derive(Clone, Debug, Default, PartialEq, Eq)]
+pub struct FormatOptions {
+    /// The width. E.g. `{:5}` or `{:width$}`.
+    pub width: Option,
+    /// The precision. E.g. `{:.5}` or `{:.precision$}`.
+    pub precision: Option,
+    /// The alignment. E.g. `{:>}` or `{:<}` or `{:^}`.
+    pub alignment: Option,
+    /// The fill character. E.g. the `.` in `{:.>10}`.
+    pub fill: Option,
+    /// The `+`, `-`, `0`, `#`, `x?` and `X?` flags.
+    pub flags: u32,
 }
 
-struct Context<'a, 'b> {
-    ecx: &'a mut ExtCtxt<'b>,
-    /// The macro's call site. References to unstable formatting internals must
-    /// use this span to pass the stability checker.
-    macsp: Span,
-    /// The span of the format string literal.
-    fmtsp: Span,
-
-    /// List of parsed argument expressions.
-    /// Named expressions are resolved early, and are appended to the end of
-    /// argument expressions.
-    ///
-    /// Example showing the various data structures in motion:
-    ///
-    /// * Original: `"{foo:o} {:o} {foo:x} {0:x} {1:o} {:x} {1:x} {0:o}"`
-    /// * Implicit argument resolution: `"{foo:o} {0:o} {foo:x} {0:x} {1:o} {1:x} {1:x} {0:o}"`
-    /// * Name resolution: `"{2:o} {0:o} {2:x} {0:x} {1:o} {1:x} {1:x} {0:o}"`
-    /// * `arg_types` (in JSON): `[[0, 1, 0], [0, 1, 1], [0, 1]]`
-    /// * `arg_unique_types` (in simplified JSON): `[["o", "x"], ["o", "x"], ["o", "x"]]`
-    /// * `names` (in JSON): `{"foo": 2}`
-    args: Vec,
-    /// The number of arguments that were added by implicit capturing.
-    num_captured_args: usize,
-    /// Placeholder slot numbers indexed by argument.
-    arg_types: Vec>,
-    /// Unique format specs seen for each argument.
-    arg_unique_types: Vec>,
-    /// Map from named arguments to their resolved indices.
-    names: FxHashMap,
-
-    /// The latest consecutive literal strings, or empty if there weren't any.
-    literal: String,
-
-    /// Collection of the compiled `rt::Argument` structures
-    pieces: Vec>,
-    /// Collection of string literals
-    str_pieces: Vec>,
-    /// Stays `true` if all formatting parameters are default (as in "{}{}").
-    all_pieces_simple: bool,
-
-    /// Mapping between positional argument references and indices into the
-    /// final generated static argument array. We record the starting indices
-    /// corresponding to each positional argument, and number of references
-    /// consumed so far for each argument, to facilitate correct `Position`
-    /// mapping in `build_piece`. In effect this can be seen as a "flattened"
-    /// version of `arg_unique_types`.
-    ///
-    /// Again with the example described above in docstring for `args`:
-    ///
-    /// * `arg_index_map` (in JSON): `[[0, 1, 0], [2, 3, 3], [4, 5]]`
-    arg_index_map: Vec>,
-
-    /// Starting offset of count argument slots.
-    count_args_index_offset: usize,
-
-    /// Count argument slots and tracking data structures.
-    /// Count arguments are separately tracked for de-duplication in case
-    /// multiple references are made to one argument. For example, in this
-    /// format string:
-    ///
-    /// * Original: `"{:.*} {:.foo$} {1:.*} {:.0$}"`
-    /// * Implicit argument resolution: `"{1:.0$} {2:.foo$} {1:.3$} {4:.0$}"`
-    /// * Name resolution: `"{1:.0$} {2:.5$} {1:.3$} {4:.0$}"`
-    /// * `count_positions` (in JSON): `{0: 0, 5: 1, 3: 2}`
-    /// * `count_args`: `vec![0, 5, 3]`
-    count_args: Vec,
-    /// Relative slot numbers for count arguments.
-    count_positions: FxHashMap,
-    /// Number of count slots assigned.
-    count_positions_count: usize,
-
-    /// Current position of the implicit positional arg pointer, as if it
-    /// still existed in this phase of processing.
-    /// Used only for `all_pieces_simple` tracking in `build_piece`.
-    curarg: usize,
-    /// Current piece being evaluated, used for error reporting.
-    curpiece: usize,
-    /// Keep track of invalid references to positional arguments.
-    invalid_refs: Vec<(usize, usize)>,
-    /// Spans of all the formatting arguments, in order.
-    arg_spans: Vec,
-    /// All the formatting arguments that have formatting flags set, in order for diagnostics.
-    arg_with_formatting: Vec>,
-
-    /// Whether this format string came from a string literal, as opposed to a macro.
-    is_literal: bool,
-    unused_names_lint: PositionalNamedArgsLint,
+#[derive(Clone, Debug, PartialEq, Eq)]
+pub enum FormatAlignment {
+    /// `{:<}`
+    Left,
+    /// `{:>}`
+    Right,
+    /// `{:^}`
+    Center,
 }
 
-pub struct FormatArg {
-    expr: P,
-    name: Option,
+#[derive(Clone, Debug, PartialEq, Eq)]
+pub enum FormatCount {
+    /// `{:0}` or `{:.0}`
+    Literal(usize),
+    /// `{:.*}`, `{:.0$}`, or `{:a$}`, etc.
+    Argument(FormatArgPosition),
+}
+
+// Only used in parse_args and report_invalid_references,
+// to indicate how a referred argument was used.
+#[derive(Clone, Copy, Debug, PartialEq, Eq)]
+enum PositionUsedAs {
+    Placeholder(Option),
+    Precision,
+    Width,
 }
+use PositionUsedAs::*;
 
 /// Parses the arguments from the given list of tokens, returning the diagnostic
 /// if there's a parse error so we can continue parsing other format!
@@ -274,15 +195,14 @@ pub struct FormatArg {
 /// If parsing succeeds, the return value is:
 ///
 /// ```text
-/// Some((fmtstr, parsed arguments, index map for named arguments))
+/// Some((fmtstr, parsed arguments))
 /// ```
 fn parse_args<'a>(
     ecx: &mut ExtCtxt<'a>,
     sp: Span,
     tts: TokenStream,
-) -> PResult<'a, (P, Vec, FxHashMap)> {
-    let mut args = Vec::::new();
-    let mut names = FxHashMap::::default();
+) -> PResult<'a, (P, Vec<(P, FormatArgKind)>)> {
+    let mut args = Vec::<(P, FormatArgKind)>::new();
 
     let mut p = ecx.new_parser_from_tts(tts);
 
@@ -347,21 +267,19 @@ fn parse_args<'a>(
                 p.bump();
                 p.expect(&token::Eq)?;
                 let e = p.parse_expr()?;
-                if let Some(&prev) = names.get(&ident.name) {
-                    ecx.struct_span_err(e.span, &format!("duplicate argument named `{}`", ident))
-                        .span_label(args[prev].expr.span, "previously here")
-                        .span_label(e.span, "duplicate argument")
-                        .emit();
+                if let Some(prev) =
+                    args.iter().rev().map_while(|a| a.1.ident()).find(|n| n.name == ident.name)
+                {
+                    ecx.struct_span_err(
+                        ident.span,
+                        &format!("duplicate argument named `{}`", ident),
+                    )
+                    .span_label(prev.span, "previously here")
+                    .span_label(ident.span, "duplicate argument")
+                    .emit();
                     continue;
                 }
-
-                // Resolve names into slots early.
-                // Since all the positional args are already seen at this point
-                // if the input is valid, we can simply append to the positional
-                // args. And remember the names.
-                let slot = args.len();
-                names.insert(ident.name, slot);
-                args.push(FormatArg { expr: e, name: Some(ident) });
+                args.push((e, FormatArgKind::Named(ident)));
             }
             _ => {
                 let e = p.parse_expr()?;
@@ -371,851 +289,31 @@ fn parse_args<'a>(
                         "positional arguments cannot follow named arguments",
                     );
                     err.span_label(e.span, "positional arguments must be before named arguments");
-                    for &pos in names.values() {
-                        err.span_label(args[pos].expr.span, "named argument");
+                    for arg in &args {
+                        if let Some(name) = arg.1.ident() {
+                            err.span_label(name.span.to(arg.0.span), "named argument");
+                        }
                     }
                     err.emit();
                 }
-                args.push(FormatArg { expr: e, name: None });
+                args.push((e, FormatArgKind::Normal));
             }
         }
     }
-    Ok((fmtstr, args, names))
+    Ok((fmtstr, args))
 }
 
-impl<'a, 'b> Context<'a, 'b> {
-    /// The number of arguments that were explicitly given.
-    fn num_args(&self) -> usize {
-        self.args.len() - self.num_captured_args
-    }
-
-    fn resolve_name_inplace(&mut self, p: &mut parse::Piece<'_>) {
-        // NOTE: the `unwrap_or` branch is needed in case of invalid format
-        // arguments, e.g., `format_args!("{foo}")`.
-        let lookup = |s: &str| self.names.get(&Symbol::intern(s)).copied().unwrap_or(0);
-
-        match *p {
-            parse::String(_) => {}
-            parse::NextArgument(ref mut arg) => {
-                if let parse::ArgumentNamed(s) = arg.position {
-                    arg.position = parse::ArgumentIs(lookup(s));
-                }
-                if let parse::CountIsName(s, _) = arg.format.width {
-                    arg.format.width = parse::CountIsParam(lookup(s));
-                }
-                if let parse::CountIsName(s, _) = arg.format.precision {
-                    arg.format.precision = parse::CountIsParam(lookup(s));
-                }
-            }
-        }
-    }
-
-    /// Verifies one piece of a parse string, and remembers it if valid.
-    /// All errors are not emitted as fatal so we can continue giving errors
-    /// about this and possibly other format strings.
-    fn verify_piece(&mut self, p: &parse::Piece<'a>) {
-        match *p {
-            parse::String(..) => {}
-            parse::NextArgument(ref arg) => {
-                // width/precision first, if they have implicit positional
-                // parameters it makes more sense to consume them first.
-                self.verify_count(
-                    arg.format.width,
-                    &arg.format.width_span,
-                    PositionalNamedArgType::Width,
-                );
-                self.verify_count(
-                    arg.format.precision,
-                    &arg.format.precision_span,
-                    PositionalNamedArgType::Precision,
-                );
-
-                let has_precision = arg.format.precision != Count::CountImplied;
-                let has_width = arg.format.width != Count::CountImplied;
-
-                if has_precision || has_width {
-                    // push before named params are resolved to aid diagnostics
-                    self.arg_with_formatting.push(arg.format);
-                }
-
-                // argument second, if it's an implicit positional parameter
-                // it's written second, so it should come after width/precision.
-                let pos = match arg.position {
-                    parse::ArgumentIs(i) => {
-                        self.unused_names_lint.maybe_add_positional_named_arg(
-                            self.args.get(i),
-                            PositionalNamedArgType::Arg,
-                            self.curpiece,
-                            Some(arg.position_span),
-                            has_precision || has_width,
-                        );
-
-                        Exact(i)
-                    }
-                    parse::ArgumentImplicitlyIs(i) => {
-                        self.unused_names_lint.maybe_add_positional_named_arg(
-                            self.args.get(i),
-                            PositionalNamedArgType::Arg,
-                            self.curpiece,
-                            None,
-                            has_precision || has_width,
-                        );
-                        Exact(i)
-                    }
-                    parse::ArgumentNamed(s) => {
-                        let symbol = Symbol::intern(s);
-                        let span = arg.position_span;
-                        Named(symbol, InnerSpan::new(span.start, span.end))
-                    }
-                };
-
-                let ty = Placeholder(match arg.format.ty {
-                    "" => "Display",
-                    "?" => "Debug",
-                    "e" => "LowerExp",
-                    "E" => "UpperExp",
-                    "o" => "Octal",
-                    "p" => "Pointer",
-                    "b" => "Binary",
-                    "x" => "LowerHex",
-                    "X" => "UpperHex",
-                    _ => {
-                        let fmtsp = self.fmtsp;
-                        let sp = arg
-                            .format
-                            .ty_span
-                            .map(|sp| fmtsp.from_inner(InnerSpan::new(sp.start, sp.end)));
-                        let mut err = self.ecx.struct_span_err(
-                            sp.unwrap_or(fmtsp),
-                            &format!("unknown format trait `{}`", arg.format.ty),
-                        );
-                        err.note(
-                            "the only appropriate formatting traits are:\n\
-                                - ``, which uses the `Display` trait\n\
-                                - `?`, which uses the `Debug` trait\n\
-                                - `e`, which uses the `LowerExp` trait\n\
-                                - `E`, which uses the `UpperExp` trait\n\
-                                - `o`, which uses the `Octal` trait\n\
-                                - `p`, which uses the `Pointer` trait\n\
-                                - `b`, which uses the `Binary` trait\n\
-                                - `x`, which uses the `LowerHex` trait\n\
-                                - `X`, which uses the `UpperHex` trait",
-                        );
-                        if let Some(sp) = sp {
-                            for (fmt, name) in &[
-                                ("", "Display"),
-                                ("?", "Debug"),
-                                ("e", "LowerExp"),
-                                ("E", "UpperExp"),
-                                ("o", "Octal"),
-                                ("p", "Pointer"),
-                                ("b", "Binary"),
-                                ("x", "LowerHex"),
-                                ("X", "UpperHex"),
-                            ] {
-                                // FIXME: rustfix (`run-rustfix`) fails to apply suggestions.
-                                // > "Cannot replace slice of data that was already replaced"
-                                err.tool_only_span_suggestion(
-                                    sp,
-                                    &format!("use the `{}` trait", name),
-                                    *fmt,
-                                    Applicability::MaybeIncorrect,
-                                );
-                            }
-                        }
-                        err.emit();
-                        ""
-                    }
-                });
-                self.verify_arg_type(pos, ty);
-                self.curpiece += 1;
-            }
-        }
-    }
-
-    fn verify_count(
-        &mut self,
-        c: parse::Count<'_>,
-        inner_span: &Option,
-        named_arg_type: PositionalNamedArgType,
-    ) {
-        match c {
-            parse::CountImplied | parse::CountIs(..) => {}
-            parse::CountIsParam(i) | parse::CountIsStar(i) => {
-                self.unused_names_lint.maybe_add_positional_named_arg(
-                    self.args.get(i),
-                    named_arg_type,
-                    self.curpiece,
-                    *inner_span,
-                    true,
-                );
-                self.verify_arg_type(Exact(i), Count);
-            }
-            parse::CountIsName(s, span) => {
-                self.verify_arg_type(
-                    Named(Symbol::intern(s), InnerSpan::new(span.start, span.end)),
-                    Count,
-                );
-            }
-        }
-    }
-
-    fn describe_num_args(&self) -> Cow<'_, str> {
-        match self.num_args() {
-            0 => "no arguments were given".into(),
-            1 => "there is 1 argument".into(),
-            x => format!("there are {} arguments", x).into(),
-        }
-    }
-
-    /// Handle invalid references to positional arguments. Output different
-    /// errors for the case where all arguments are positional and for when
-    /// there are named arguments or numbered positional arguments in the
-    /// format string.
-    fn report_invalid_references(&self, numbered_position_args: bool) {
-        let mut e;
-        let sp = if !self.arg_spans.is_empty() {
-            // Point at the formatting arguments.
-            MultiSpan::from_spans(self.arg_spans.clone())
-        } else {
-            MultiSpan::from_span(self.fmtsp)
-        };
-        let refs =
-            self.invalid_refs.iter().map(|(r, pos)| (r.to_string(), self.arg_spans.get(*pos)));
-
-        let mut zero_based_note = false;
-
-        let count = self.pieces.len()
-            + self
-                .arg_with_formatting
-                .iter()
-                .filter(|fmt| matches!(fmt.precision, parse::CountIsStar(_)))
-                .count();
-        if self.names.is_empty() && !numbered_position_args && count != self.num_args() {
-            e = self.ecx.struct_span_err(
-                sp,
-                &format!(
-                    "{} positional argument{} in format string, but {}",
-                    count,
-                    pluralize!(count),
-                    self.describe_num_args(),
-                ),
-            );
-            for arg in &self.args {
-                // Point at the arguments that will be formatted.
-                e.span_label(arg.expr.span, "");
-            }
-        } else {
-            let (mut refs, spans): (Vec<_>, Vec<_>) = refs.unzip();
-            // Avoid `invalid reference to positional arguments 7 and 7 (there is 1 argument)`
-            // for `println!("{7:7$}", 1);`
-            refs.sort();
-            refs.dedup();
-            let spans: Vec<_> = spans.into_iter().filter_map(|sp| sp.copied()).collect();
-            let sp = if self.arg_spans.is_empty() || spans.is_empty() {
-                MultiSpan::from_span(self.fmtsp)
-            } else {
-                MultiSpan::from_spans(spans)
-            };
-            let arg_list = if refs.len() == 1 {
-                format!("argument {}", refs[0])
-            } else {
-                let reg = refs.pop().unwrap();
-                format!("arguments {head} and {tail}", head = refs.join(", "), tail = reg)
-            };
-
-            e = self.ecx.struct_span_err(
-                sp,
-                &format!(
-                    "invalid reference to positional {} ({})",
-                    arg_list,
-                    self.describe_num_args()
-                ),
-            );
-            zero_based_note = true;
-        };
-
-        for fmt in &self.arg_with_formatting {
-            if let Some(span) = fmt.precision_span {
-                let span = self.fmtsp.from_inner(InnerSpan::new(span.start, span.end));
-                match fmt.precision {
-                    parse::CountIsParam(pos) if pos >= self.num_args() => {
-                        e.span_label(
-                            span,
-                            &format!(
-                                "this precision flag expects an `usize` argument at position {}, \
-                             but {}",
-                                pos,
-                                self.describe_num_args(),
-                            ),
-                        );
-                        zero_based_note = true;
-                    }
-                    parse::CountIsStar(pos) => {
-                        let count = self.pieces.len()
-                            + self
-                                .arg_with_formatting
-                                .iter()
-                                .filter(|fmt| matches!(fmt.precision, parse::CountIsStar(_)))
-                                .count();
-                        e.span_label(
-                            span,
-                            &format!(
-                            "this precision flag adds an extra required argument at position {}, \
-                             which is why there {} expected",
-                            pos,
-                            if count == 1 {
-                                "is 1 argument".to_string()
-                            } else {
-                                format!("are {} arguments", count)
-                            },
-                        ),
-                        );
-                        if let Some(arg) = self.args.get(pos) {
-                            e.span_label(
-                                arg.expr.span,
-                                "this parameter corresponds to the precision flag",
-                            );
-                        }
-                        zero_based_note = true;
-                    }
-                    _ => {}
-                }
-            }
-            if let Some(span) = fmt.width_span {
-                let span = self.fmtsp.from_inner(InnerSpan::new(span.start, span.end));
-                match fmt.width {
-                    parse::CountIsParam(pos) if pos >= self.num_args() => {
-                        e.span_label(
-                            span,
-                            &format!(
-                                "this width flag expects an `usize` argument at position {}, \
-                             but {}",
-                                pos,
-                                self.describe_num_args(),
-                            ),
-                        );
-                        zero_based_note = true;
-                    }
-                    _ => {}
-                }
-            }
-        }
-        if zero_based_note {
-            e.note("positional arguments are zero-based");
-        }
-        if !self.arg_with_formatting.is_empty() {
-            e.note(
-                "for information about formatting flags, visit \
-                    https://doc.rust-lang.org/std/fmt/index.html",
-            );
-        }
-
-        e.emit();
-    }
-
-    /// Actually verifies and tracks a given format placeholder
-    /// (a.k.a. argument).
-    fn verify_arg_type(&mut self, arg: Position, ty: ArgumentType) {
-        if let Exact(arg) = arg {
-            if arg >= self.num_args() {
-                self.invalid_refs.push((arg, self.curpiece));
-                return;
-            }
-        }
-
-        match arg {
-            Exact(arg) | Capture(arg) => {
-                match ty {
-                    Placeholder(_) => {
-                        // record every (position, type) combination only once
-                        let seen_ty = &mut self.arg_unique_types[arg];
-                        let i = seen_ty.iter().position(|x| *x == ty).unwrap_or_else(|| {
-                            let i = seen_ty.len();
-                            seen_ty.push(ty);
-                            i
-                        });
-                        self.arg_types[arg].push(i);
-                    }
-                    Count => {
-                        if let Entry::Vacant(e) = self.count_positions.entry(arg) {
-                            let i = self.count_positions_count;
-                            e.insert(i);
-                            self.count_args.push(arg);
-                            self.count_positions_count += 1;
-                        }
-                    }
-                }
-            }
-
-            Named(name, span) => {
-                match self.names.get(&name) {
-                    Some(&idx) => {
-                        // Treat as positional arg.
-                        self.verify_arg_type(Capture(idx), ty)
-                    }
-                    None => {
-                        // For the moment capturing variables from format strings expanded from macros is
-                        // disabled (see RFC #2795)
-                        if self.is_literal {
-                            // Treat this name as a variable to capture from the surrounding scope
-                            let idx = self.args.len();
-                            self.arg_types.push(Vec::new());
-                            self.arg_unique_types.push(Vec::new());
-                            let span = if self.is_literal {
-                                self.fmtsp.from_inner(span)
-                            } else {
-                                self.fmtsp
-                            };
-                            self.num_captured_args += 1;
-                            self.args.push(FormatArg {
-                                expr: self.ecx.expr_ident(span, Ident::new(name, span)),
-                                name: Some(Ident::new(name, span)),
-                            });
-                            self.names.insert(name, idx);
-                            self.verify_arg_type(Capture(idx), ty)
-                        } else {
-                            let msg = format!("there is no argument named `{}`", name);
-                            let sp = if self.is_literal {
-                                self.fmtsp.from_inner(span)
-                            } else {
-                                self.fmtsp
-                            };
-                            let mut err = self.ecx.struct_span_err(sp, &msg);
-
-                            err.note(&format!(
-                                "did you intend to capture a variable `{}` from \
-                                 the surrounding scope?",
-                                name
-                            ));
-                            err.note(
-                                "to avoid ambiguity, `format_args!` cannot capture variables \
-                                 when the format string is expanded from a macro",
-                            );
-
-                            err.emit();
-                        }
-                    }
-                }
-            }
-        }
-    }
-
-    /// Builds the mapping between format placeholders and argument objects.
-    fn build_index_map(&mut self) {
-        // NOTE: Keep the ordering the same as `into_expr`'s expansion would do!
-        let args_len = self.args.len();
-        self.arg_index_map.reserve(args_len);
-
-        let mut sofar = 0usize;
-
-        // Map the arguments
-        for i in 0..args_len {
-            let arg_types = &self.arg_types[i];
-            let arg_offsets = arg_types.iter().map(|offset| sofar + *offset).collect::>();
-            self.arg_index_map.push(arg_offsets);
-            sofar += self.arg_unique_types[i].len();
-        }
-
-        // Record starting index for counts, which appear just after arguments
-        self.count_args_index_offset = sofar;
-    }
-
-    fn rtpath(ecx: &ExtCtxt<'_>, s: Symbol) -> Vec {
-        ecx.std_path(&[sym::fmt, sym::rt, sym::v1, s])
-    }
-
-    fn build_count(&self, c: parse::Count<'_>) -> P {
-        let sp = self.macsp;
-        let count = |c, arg| {
-            let mut path = Context::rtpath(self.ecx, sym::Count);
-            path.push(Ident::new(c, sp));
-            match arg {
-                Some(arg) => self.ecx.expr_call_global(sp, path, vec![arg]),
-                None => self.ecx.expr_path(self.ecx.path_global(sp, path)),
-            }
-        };
-        match c {
-            parse::CountIs(i) => count(sym::Is, Some(self.ecx.expr_usize(sp, i))),
-            parse::CountIsParam(i) | parse::CountIsStar(i) => {
-                // This needs mapping too, as `i` is referring to a macro
-                // argument. If `i` is not found in `count_positions` then
-                // the error had already been emitted elsewhere.
-                let i = self.count_positions.get(&i).cloned().unwrap_or(0)
-                    + self.count_args_index_offset;
-                count(sym::Param, Some(self.ecx.expr_usize(sp, i)))
-            }
-            parse::CountImplied => count(sym::Implied, None),
-            // should never be the case, names are already resolved
-            parse::CountIsName(..) => panic!("should never happen"),
-        }
-    }
-
-    /// Build a literal expression from the accumulated string literals
-    fn build_literal_string(&mut self) -> P {
-        let sp = self.fmtsp;
-        let s = Symbol::intern(&self.literal);
-        self.literal.clear();
-        self.ecx.expr_str(sp, s)
-    }
-
-    /// Builds a static `rt::Argument` from a `parse::Piece` or append
-    /// to the `literal` string.
-    fn build_piece(
-        &mut self,
-        piece: &parse::Piece<'a>,
-        arg_index_consumed: &mut Vec,
-    ) -> Option> {
-        let sp = self.macsp;
-        match *piece {
-            parse::String(s) => {
-                self.literal.push_str(s);
-                None
-            }
-            parse::NextArgument(ref arg) => {
-                // Build the position
-                let pos = {
-                    match arg.position {
-                        parse::ArgumentIs(i, ..) | parse::ArgumentImplicitlyIs(i) => {
-                            // Map to index in final generated argument array
-                            // in case of multiple types specified
-                            let arg_idx = match arg_index_consumed.get_mut(i) {
-                                None => 0, // error already emitted elsewhere
-                                Some(offset) => {
-                                    let idx_map = &self.arg_index_map[i];
-                                    // unwrap_or branch: error already emitted elsewhere
-                                    let arg_idx = *idx_map.get(*offset).unwrap_or(&0);
-                                    *offset += 1;
-                                    arg_idx
-                                }
-                            };
-                            self.ecx.expr_usize(sp, arg_idx)
-                        }
-
-                        // should never be the case, because names are already
-                        // resolved.
-                        parse::ArgumentNamed(..) => panic!("should never happen"),
-                    }
-                };
-
-                let simple_arg = parse::Argument {
-                    position: {
-                        // We don't have ArgumentNext any more, so we have to
-                        // track the current argument ourselves.
-                        let i = self.curarg;
-                        self.curarg += 1;
-                        parse::ArgumentIs(i)
-                    },
-                    position_span: arg.position_span,
-                    format: parse::FormatSpec {
-                        fill: None,
-                        align: parse::AlignUnknown,
-                        flags: 0,
-                        precision: parse::CountImplied,
-                        precision_span: arg.format.precision_span,
-                        width: parse::CountImplied,
-                        width_span: arg.format.width_span,
-                        ty: arg.format.ty,
-                        ty_span: arg.format.ty_span,
-                    },
-                };
-
-                let fill = arg.format.fill.unwrap_or(' ');
-                let pos_simple = arg.position.index() == simple_arg.position.index();
-
-                if !pos_simple || arg.format != simple_arg.format {
-                    self.all_pieces_simple = false;
-                }
-
-                // Build the format
-                let fill = self.ecx.expr_char(sp, fill);
-                let align = |name| {
-                    let mut p = Context::rtpath(self.ecx, sym::Alignment);
-                    p.push(Ident::new(name, sp));
-                    self.ecx.path_global(sp, p)
-                };
-                let align = match arg.format.align {
-                    parse::AlignLeft => align(sym::Left),
-                    parse::AlignRight => align(sym::Right),
-                    parse::AlignCenter => align(sym::Center),
-                    parse::AlignUnknown => align(sym::Unknown),
-                };
-                let align = self.ecx.expr_path(align);
-                let flags = self.ecx.expr_u32(sp, arg.format.flags);
-                let prec = self.build_count(arg.format.precision);
-                let width = self.build_count(arg.format.width);
-                let path = self.ecx.path_global(sp, Context::rtpath(self.ecx, sym::FormatSpec));
-                let fmt = self.ecx.expr_struct(
-                    sp,
-                    path,
-                    vec![
-                        self.ecx.field_imm(sp, Ident::new(sym::fill, sp), fill),
-                        self.ecx.field_imm(sp, Ident::new(sym::align, sp), align),
-                        self.ecx.field_imm(sp, Ident::new(sym::flags, sp), flags),
-                        self.ecx.field_imm(sp, Ident::new(sym::precision, sp), prec),
-                        self.ecx.field_imm(sp, Ident::new(sym::width, sp), width),
-                    ],
-                );
-
-                let path = self.ecx.path_global(sp, Context::rtpath(self.ecx, sym::Argument));
-                Some(self.ecx.expr_struct(
-                    sp,
-                    path,
-                    vec![
-                        self.ecx.field_imm(sp, Ident::new(sym::position, sp), pos),
-                        self.ecx.field_imm(sp, Ident::new(sym::format, sp), fmt),
-                    ],
-                ))
-            }
-        }
-    }
-
-    /// Actually builds the expression which the format_args! block will be
-    /// expanded to.
-    fn into_expr(self) -> P {
-        let mut original_args = self.args;
-        let mut fmt_args = Vec::with_capacity(
-            self.arg_unique_types.iter().map(|v| v.len()).sum::() + self.count_args.len(),
-        );
-
-        // First, build up the static array which will become our precompiled
-        // format "string"
-        let pieces = self.ecx.expr_array_ref(self.fmtsp, self.str_pieces);
-
-        // We need to construct a &[ArgumentV1] to pass into the fmt::Arguments
-        // constructor. In general the expressions in this slice might be
-        // permuted from their order in original_args (such as in the case of
-        // "{1} {0}"), or may have multiple entries referring to the same
-        // element of original_args ("{0} {0}").
-        //
-        // The following vector has one item per element of our output slice,
-        // identifying the index of which element of original_args it's passing,
-        // and that argument's type.
-        let mut fmt_arg_index_and_ty = SmallVec::<[(usize, &ArgumentType); 8]>::new();
-        for (i, unique_types) in self.arg_unique_types.iter().enumerate() {
-            fmt_arg_index_and_ty.extend(unique_types.iter().map(|ty| (i, ty)));
-        }
-        fmt_arg_index_and_ty.extend(self.count_args.iter().map(|&i| (i, &Count)));
-
-        // Figure out whether there are permuted or repeated elements. If not,
-        // we can generate simpler code.
-        //
-        // The sequence has no indices out of order or repeated if: for every
-        // adjacent pair of elements, the first one's index is less than the
-        // second one's index.
-        let nicely_ordered =
-            fmt_arg_index_and_ty.array_windows().all(|[(i, _i_ty), (j, _j_ty)]| i < j);
-
-        // We want to emit:
-        //
-        //     [ArgumentV1::new(&$arg0, …), ArgumentV1::new(&$arg1, …), …]
-        //
-        // However, it's only legal to do so if $arg0, $arg1, … were written in
-        // exactly that order by the programmer. When arguments are permuted, we
-        // want them evaluated in the order written by the programmer, not in
-        // the order provided to fmt::Arguments. When arguments are repeated, we
-        // want the expression evaluated only once.
-        //
-        // Further, if any arg _after the first one_ contains a yield point such
-        // as `await` or `yield`, the above short form is inconvenient for the
-        // caller because it would keep a temporary of type ArgumentV1 alive
-        // across the yield point. ArgumentV1 can't implement Send since it
-        // holds a type-erased arbitrary type.
-        //
-        // Thus in the not nicely ordered case, and in the yielding case, we
-        // emit the following instead:
-        //
-        //     match (&$arg0, &$arg1, …) {
-        //         args => [ArgumentV1::new(args.$i, …), ArgumentV1::new(args.$j, …), …]
-        //     }
-        //
-        // for the sequence of indices $i, $j, … governed by fmt_arg_index_and_ty.
-        // This more verbose representation ensures that all arguments are
-        // evaluated a single time each, in the order written by the programmer,
-        // and that the surrounding future/generator (if any) is Send whenever
-        // possible.
-        let no_need_for_match = nicely_ordered
-            && !original_args.iter().skip(1).any(|arg| may_contain_yield_point(&arg.expr));
-
-        for (arg_index, arg_ty) in fmt_arg_index_and_ty {
-            let e = &mut original_args[arg_index].expr;
-            let span = e.span;
-            let arg = if no_need_for_match {
-                let expansion_span = e.span.with_ctxt(self.macsp.ctxt());
-                // The indices are strictly ordered so e has not been taken yet.
-                self.ecx.expr_addr_of(expansion_span, P(e.take()))
-            } else {
-                let def_site = self.ecx.with_def_site_ctxt(span);
-                let args_tuple = self.ecx.expr_ident(def_site, Ident::new(sym::args, def_site));
-                let member = Ident::new(sym::integer(arg_index), def_site);
-                self.ecx.expr(def_site, ast::ExprKind::Field(args_tuple, member))
-            };
-            fmt_args.push(Context::format_arg(self.ecx, self.macsp, span, arg_ty, arg));
-        }
-
-        let args_array = self.ecx.expr_array(self.macsp, fmt_args);
-        let args_slice = self.ecx.expr_addr_of(
-            self.macsp,
-            if no_need_for_match {
-                args_array
-            } else {
-                // In the !no_need_for_match case, none of the exprs were moved
-                // away in the previous loop.
-                //
-                // This uses the arg span for `&arg` so that borrowck errors
-                // point to the specific expression passed to the macro (the
-                // span is otherwise unavailable in the MIR used by borrowck).
-                let heads = original_args
-                    .into_iter()
-                    .map(|arg| {
-                        self.ecx.expr_addr_of(arg.expr.span.with_ctxt(self.macsp.ctxt()), arg.expr)
-                    })
-                    .collect();
-
-                let pat = self.ecx.pat_ident(self.macsp, Ident::new(sym::args, self.macsp));
-                let arm = self.ecx.arm(self.macsp, pat, args_array);
-                let head = self.ecx.expr(self.macsp, ast::ExprKind::Tup(heads));
-                self.ecx.expr_match(self.macsp, head, vec![arm])
-            },
-        );
-
-        // Now create the fmt::Arguments struct with all our locals we created.
-        let (fn_name, fn_args) = if self.all_pieces_simple {
-            ("new_v1", vec![pieces, args_slice])
-        } else {
-            // Build up the static array which will store our precompiled
-            // nonstandard placeholders, if there are any.
-            let fmt = self.ecx.expr_array_ref(self.macsp, self.pieces);
-
-            let path = self.ecx.std_path(&[sym::fmt, sym::UnsafeArg, sym::new]);
-            let unsafe_arg = self.ecx.expr_call_global(self.macsp, path, Vec::new());
-            let unsafe_expr = self.ecx.expr_block(P(ast::Block {
-                stmts: vec![self.ecx.stmt_expr(unsafe_arg)],
-                id: ast::DUMMY_NODE_ID,
-                rules: BlockCheckMode::Unsafe(UnsafeSource::CompilerGenerated),
-                span: self.macsp,
-                tokens: None,
-                could_be_bare_literal: false,
-            }));
-
-            ("new_v1_formatted", vec![pieces, args_slice, fmt, unsafe_expr])
-        };
-
-        let path = self.ecx.std_path(&[sym::fmt, sym::Arguments, Symbol::intern(fn_name)]);
-        self.ecx.expr_call_global(self.macsp, path, fn_args)
-    }
-
-    fn format_arg(
-        ecx: &ExtCtxt<'_>,
-        macsp: Span,
-        mut sp: Span,
-        ty: &ArgumentType,
-        arg: P,
-    ) -> P {
-        sp = ecx.with_def_site_ctxt(sp);
-        let trait_ = match *ty {
-            Placeholder(trait_) if trait_ == "" => return DummyResult::raw_expr(sp, true),
-            Placeholder(trait_) => trait_,
-            Count => {
-                let path = ecx.std_path(&[sym::fmt, sym::ArgumentV1, sym::from_usize]);
-                return ecx.expr_call_global(macsp, path, vec![arg]);
-            }
-        };
-        let new_fn_name = match trait_ {
-            "Display" => "new_display",
-            "Debug" => "new_debug",
-            "LowerExp" => "new_lower_exp",
-            "UpperExp" => "new_upper_exp",
-            "Octal" => "new_octal",
-            "Pointer" => "new_pointer",
-            "Binary" => "new_binary",
-            "LowerHex" => "new_lower_hex",
-            "UpperHex" => "new_upper_hex",
-            _ => unreachable!(),
-        };
-
-        let path = ecx.std_path(&[sym::fmt, sym::ArgumentV1, Symbol::intern(new_fn_name)]);
-        ecx.expr_call_global(sp, path, vec![arg])
-    }
-}
-
-fn expand_format_args_impl<'cx>(
-    ecx: &'cx mut ExtCtxt<'_>,
-    mut sp: Span,
-    tts: TokenStream,
-    nl: bool,
-) -> Box {
-    sp = ecx.with_def_site_ctxt(sp);
-    match parse_args(ecx, sp, tts) {
-        Ok((efmt, args, names)) => {
-            MacEager::expr(expand_preparsed_format_args(ecx, sp, efmt, args, names, nl))
-        }
-        Err(mut err) => {
-            err.emit();
-            DummyResult::any(sp)
-        }
-    }
-}
-
-pub fn expand_format_args<'cx>(
-    ecx: &'cx mut ExtCtxt<'_>,
-    sp: Span,
-    tts: TokenStream,
-) -> Box {
-    expand_format_args_impl(ecx, sp, tts, false)
-}
-
-pub fn expand_format_args_nl<'cx>(
-    ecx: &'cx mut ExtCtxt<'_>,
-    sp: Span,
-    tts: TokenStream,
-) -> Box {
-    expand_format_args_impl(ecx, sp, tts, true)
-}
-
-fn create_lints_for_named_arguments_used_positionally(cx: &mut Context<'_, '_>) {
-    for named_arg in &cx.unused_names_lint.positional_named_args {
-        let (position_sp_to_replace, position_sp_for_msg) = named_arg.get_positional_arg_spans(cx);
-
-        let msg = format!("named argument `{}` is not used by name", named_arg.replacement);
-
-        cx.ecx.buffered_early_lint.push(BufferedEarlyLint {
-            span: MultiSpan::from_span(named_arg.positional_named_arg_span),
-            msg: msg.into(),
-            node_id: ast::CRATE_NODE_ID,
-            lint_id: LintId::of(&NAMED_ARGUMENTS_USED_POSITIONALLY),
-            diagnostic: BuiltinLintDiagnostics::NamedArgumentUsedPositionally {
-                position_sp_to_replace,
-                position_sp_for_msg,
-                named_arg_sp: named_arg.positional_named_arg_span,
-                named_arg_name: named_arg.replacement.to_string(),
-                is_formatting_arg: named_arg.ty != PositionalNamedArgType::Arg,
-            },
-        });
-    }
-}
-
-/// Take the various parts of `format_args!(efmt, args..., name=names...)`
-/// and construct the appropriate formatting expression.
-pub fn expand_preparsed_format_args(
+pub fn make_format_args(
     ecx: &mut ExtCtxt<'_>,
-    sp: Span,
     efmt: P,
-    args: Vec,
-    names: FxHashMap,
+    mut args: Vec<(P, FormatArgKind)>,
     append_newline: bool,
-) -> P {
-    // NOTE: this verbose way of initializing `Vec>` is because
-    // `ArgumentType` does not derive `Clone`.
-    let arg_types: Vec<_> = (0..args.len()).map(|_| Vec::new()).collect();
-    let arg_unique_types: Vec<_> = (0..args.len()).map(|_| Vec::new()).collect();
-
-    let mut macsp = ecx.call_site();
-    macsp = ecx.with_def_site_ctxt(macsp);
+) -> Result {
+    let start_of_named_args =
+        args.iter().position(|arg| arg.1.ident().is_some()).unwrap_or(args.len());
 
     let msg = "format argument must be a string literal";
-    let fmt_sp = efmt.span;
-    let efmt_kind_is_lit: bool = matches!(efmt.kind, ast::ExprKind::Lit(_));
+    let fmt_span = efmt.span;
     let (fmt_str, fmt_style, fmt_span) = match expr_to_spanned_string(ecx, efmt, msg) {
         Ok(mut fmt) if append_newline => {
             fmt.0 = Symbol::intern(&format!("{}\n", fmt.0));
@@ -1230,7 +328,7 @@ pub fn expand_preparsed_format_args(
                 };
                 if !suggested {
                     err.span_suggestion(
-                        fmt_sp.shrink_to_lo(),
+                        fmt_span.shrink_to_lo(),
                         "you might be missing a string literal to format with",
                         format!("\"{}\", ", sugg_fmt),
                         Applicability::MaybeIncorrect,
@@ -1238,7 +336,7 @@ pub fn expand_preparsed_format_args(
                 }
                 err.emit();
             }
-            return DummyResult::raw_expr(sp, true);
+            return Err(());
         }
     };
 
@@ -1248,7 +346,7 @@ pub fn expand_preparsed_format_args(
     };
 
     let fmt_str = fmt_str.as_str(); // for the suggestions below
-    let fmt_snippet = ecx.source_map().span_to_snippet(fmt_sp).ok();
+    let fmt_snippet = ecx.source_map().span_to_snippet(fmt_span).ok();
     let mut parser = parse::Parser::new(
         fmt_str,
         str_style,
@@ -1257,18 +355,20 @@ pub fn expand_preparsed_format_args(
         parse::ParseMode::Format,
     );
 
-    let mut unverified_pieces = Vec::new();
+    let mut pieces = Vec::new();
     while let Some(piece) = parser.next() {
         if !parser.errors.is_empty() {
             break;
         } else {
-            unverified_pieces.push(piece);
+            pieces.push(piece);
         }
     }
 
+    let is_literal = parser.is_literal;
+
     if !parser.errors.is_empty() {
         let err = parser.errors.remove(0);
-        let sp = if efmt_kind_is_lit {
+        let sp = if is_literal {
             fmt_span.from_inner(InnerSpan::new(err.span.start, err.span.end))
         } else {
             // The format string could be another macro invocation, e.g.:
@@ -1287,24 +387,22 @@ pub fn expand_preparsed_format_args(
             e.note(¬e);
         }
         if let Some((label, span)) = err.secondary_label {
-            if efmt_kind_is_lit {
+            if is_literal {
                 e.span_label(fmt_span.from_inner(InnerSpan::new(span.start, span.end)), label);
             }
         }
         if err.should_be_replaced_with_positional_argument {
             let captured_arg_span =
                 fmt_span.from_inner(InnerSpan::new(err.span.start, err.span.end));
-            let n_positional_args =
-                args.iter().rposition(|arg| arg.name.is_none()).map_or(0, |i| i + 1);
             if let Ok(arg) = ecx.source_map().span_to_snippet(captured_arg_span) {
-                let span = match args[..n_positional_args].last() {
-                    Some(arg) => arg.expr.span,
-                    None => fmt_sp,
+                let span = match args[..start_of_named_args].last() {
+                    Some(arg) => arg.0.span,
+                    None => fmt_span,
                 };
                 e.multipart_suggestion_verbose(
                     "consider using a positional formatting argument instead",
                     vec![
-                        (captured_arg_span, n_positional_args.to_string()),
+                        (captured_arg_span, start_of_named_args.to_string()),
                         (span.shrink_to_hi(), format!(", {}", arg)),
                     ],
                     Applicability::MachineApplicable,
@@ -1312,241 +410,648 @@ pub fn expand_preparsed_format_args(
             }
         }
         e.emit();
-        return DummyResult::raw_expr(sp, true);
+        return Err(());
     }
 
-    let arg_spans = parser
-        .arg_places
-        .iter()
-        .map(|span| fmt_span.from_inner(InnerSpan::new(span.start, span.end)))
-        .collect();
-
-    let mut cx = Context {
-        ecx,
-        args,
-        num_captured_args: 0,
-        arg_types,
-        arg_unique_types,
-        names,
-        curarg: 0,
-        curpiece: 0,
-        arg_index_map: Vec::new(),
-        count_args: Vec::new(),
-        count_positions: FxHashMap::default(),
-        count_positions_count: 0,
-        count_args_index_offset: 0,
-        literal: String::new(),
-        pieces: Vec::with_capacity(unverified_pieces.len()),
-        str_pieces: Vec::with_capacity(unverified_pieces.len()),
-        all_pieces_simple: true,
-        macsp,
-        fmtsp: fmt_span,
-        invalid_refs: Vec::new(),
-        arg_spans,
-        arg_with_formatting: Vec::new(),
-        is_literal: parser.is_literal,
-        unused_names_lint: PositionalNamedArgsLint { positional_named_args: vec![] },
+    let to_span = |inner_span: rustc_parse_format::InnerSpan| {
+        is_literal.then(|| {
+            fmt_span.from_inner(InnerSpan { start: inner_span.start, end: inner_span.end })
+        })
     };
 
-    // This needs to happen *after* the Parser has consumed all pieces to create all the spans
-    let pieces = unverified_pieces
-        .into_iter()
-        .map(|mut piece| {
-            cx.verify_piece(&piece);
-            cx.resolve_name_inplace(&mut piece);
-            piece
-        })
-        .collect::>();
+    enum ArgRef<'a> {
+        Index(usize),
+        Name(&'a str, Option),
+    }
+    use ArgRef::*;
+
+    let num_explicit_args = args.len();
+    let mut used = vec![false; num_explicit_args];
+    let mut invalid_refs = Vec::new();
+    let mut numeric_refences_to_named_arg = Vec::new();
+
+    let mut lookup_arg = |arg: ArgRef<'_>,
+                          span: Option,
+                          used_as: PositionUsedAs,
+                          kind: FormatArgPositionKind|
+     -> FormatArgPosition {
+        let index = match arg {
+            Index(index) => {
+                if let Some((_, arg_kind)) = args.get(index) {
+                    match arg_kind {
+                        FormatArgKind::Normal => {
+                            used[index] = true;
+                            Ok(index)
+                        }
+                        FormatArgKind::Named(_) => {
+                            used[index] = true;
+                            numeric_refences_to_named_arg.push((index, span, used_as));
+                            Ok(index)
+                        }
+                        FormatArgKind::Captured(_) => {
+                            // Doesn't exist as an explicit argument.
+                            invalid_refs.push((index, span, used_as, kind));
+                            Err(index)
+                        }
+                    }
+                } else {
+                    invalid_refs.push((index, span, used_as, kind));
+                    Err(index)
+                }
+            }
+            Name(name, span) => {
+                let name = Symbol::intern(name);
+                if let Some(i) = args[start_of_named_args..]
+                    .iter()
+                    .position(|arg| arg.1.ident().is_some_and(|id| id.name == name))
+                {
+                    let index = start_of_named_args + i;
+                    if !matches!(args[index].1, FormatArgKind::Captured(_)) {
+                        used[index] = true;
+                    }
+                    Ok(index)
+                } else {
+                    let span = span.unwrap_or(fmt_span);
+                    let ident = Ident::new(name, span);
+                    let arg = if is_literal {
+                        ecx.expr_ident(span, ident)
+                    } else {
+                        // For the moment capturing variables from format strings expanded from macros is
+                        // disabled (see RFC #2795)
+                        ecx.struct_span_err(span, &format!("there is no argument named `{name}`"))
+                            .note(format!("did you intend to capture a variable `{name}` from the surrounding scope?"))
+                            .note("to avoid ambiguity, `format_args!` cannot capture variables when the format string is expanded from a macro")
+                            .emit();
+                        DummyResult::raw_expr(span, true)
+                    };
+                    args.push((arg, FormatArgKind::Captured(ident)));
+                    Ok(args.len() - 1)
+                }
+            }
+        };
+        FormatArgPosition { index, kind, span }
+    };
+
+    let mut template = Vec::new();
+    let mut unfinished_literal = String::new();
+    let mut placeholder_index = 0;
 
-    let numbered_position_args = pieces.iter().any(|arg: &parse::Piece<'_>| match *arg {
-        parse::String(_) => false,
-        parse::NextArgument(arg) => matches!(arg.position, parse::Position::ArgumentIs(..)),
-    });
+    for piece in pieces {
+        match piece {
+            parse::Piece::String(s) => {
+                unfinished_literal.push_str(s);
+            }
+            parse::Piece::NextArgument(parse::Argument { position, position_span, format }) => {
+                if !unfinished_literal.is_empty() {
+                    template.push(FormatArgsPiece::Literal(Symbol::intern(&unfinished_literal)));
+                    unfinished_literal.clear();
+                }
 
-    cx.build_index_map();
+                let span = parser.arg_places.get(placeholder_index).and_then(|&s| to_span(s));
+                placeholder_index += 1;
+
+                let position_span = to_span(position_span);
+                let argument = match position {
+                    parse::ArgumentImplicitlyIs(i) => lookup_arg(
+                        Index(i),
+                        position_span,
+                        Placeholder(span),
+                        FormatArgPositionKind::Implicit,
+                    ),
+                    parse::ArgumentIs(i) => lookup_arg(
+                        Index(i),
+                        position_span,
+                        Placeholder(span),
+                        FormatArgPositionKind::Number,
+                    ),
+                    parse::ArgumentNamed(name) => lookup_arg(
+                        Name(name, position_span),
+                        position_span,
+                        Placeholder(span),
+                        FormatArgPositionKind::Named,
+                    ),
+                };
 
-    let mut arg_index_consumed = vec![0usize; cx.arg_index_map.len()];
+                let alignment = match format.align {
+                    parse::AlignUnknown => None,
+                    parse::AlignLeft => Some(FormatAlignment::Left),
+                    parse::AlignRight => Some(FormatAlignment::Right),
+                    parse::AlignCenter => Some(FormatAlignment::Center),
+                };
 
-    for piece in pieces {
-        if let Some(piece) = cx.build_piece(&piece, &mut arg_index_consumed) {
-            let s = cx.build_literal_string();
-            cx.str_pieces.push(s);
-            cx.pieces.push(piece);
+                let format_trait = match format.ty {
+                    "" => FormatTrait::Display,
+                    "?" => FormatTrait::Debug,
+                    "e" => FormatTrait::LowerExp,
+                    "E" => FormatTrait::UpperExp,
+                    "o" => FormatTrait::Octal,
+                    "p" => FormatTrait::Pointer,
+                    "b" => FormatTrait::Binary,
+                    "x" => FormatTrait::LowerHex,
+                    "X" => FormatTrait::UpperHex,
+                    _ => {
+                        invalid_placeholder_type_error(ecx, format.ty, format.ty_span, fmt_span);
+                        FormatTrait::Display
+                    }
+                };
+
+                let precision_span = format.precision_span.and_then(to_span);
+                let precision = match format.precision {
+                    parse::CountIs(n) => Some(FormatCount::Literal(n)),
+                    parse::CountIsName(name, name_span) => Some(FormatCount::Argument(lookup_arg(
+                        Name(name, to_span(name_span)),
+                        precision_span,
+                        Precision,
+                        FormatArgPositionKind::Named,
+                    ))),
+                    parse::CountIsParam(i) => Some(FormatCount::Argument(lookup_arg(
+                        Index(i),
+                        precision_span,
+                        Precision,
+                        FormatArgPositionKind::Number,
+                    ))),
+                    parse::CountIsStar(i) => Some(FormatCount::Argument(lookup_arg(
+                        Index(i),
+                        precision_span,
+                        Precision,
+                        FormatArgPositionKind::Implicit,
+                    ))),
+                    parse::CountImplied => None,
+                };
+
+                let width_span = format.width_span.and_then(to_span);
+                let width = match format.width {
+                    parse::CountIs(n) => Some(FormatCount::Literal(n)),
+                    parse::CountIsName(name, name_span) => Some(FormatCount::Argument(lookup_arg(
+                        Name(name, to_span(name_span)),
+                        width_span,
+                        Width,
+                        FormatArgPositionKind::Named,
+                    ))),
+                    parse::CountIsParam(i) => Some(FormatCount::Argument(lookup_arg(
+                        Index(i),
+                        width_span,
+                        Width,
+                        FormatArgPositionKind::Number,
+                    ))),
+                    parse::CountIsStar(_) => unreachable!(),
+                    parse::CountImplied => None,
+                };
+
+                template.push(FormatArgsPiece::Placeholder(FormatPlaceholder {
+                    argument,
+                    span,
+                    format_trait,
+                    format_options: FormatOptions {
+                        fill: format.fill,
+                        alignment,
+                        flags: format.flags,
+                        precision,
+                        width,
+                    },
+                }));
+            }
         }
     }
 
-    if !cx.literal.is_empty() {
-        let s = cx.build_literal_string();
-        cx.str_pieces.push(s);
+    if !unfinished_literal.is_empty() {
+        template.push(FormatArgsPiece::Literal(Symbol::intern(&unfinished_literal)));
+        drop(unfinished_literal);
     }
 
-    if !cx.invalid_refs.is_empty() {
-        cx.report_invalid_references(numbered_position_args);
+    if !invalid_refs.is_empty() {
+        report_invalid_references(
+            ecx,
+            &invalid_refs,
+            &template,
+            fmt_span,
+            num_explicit_args,
+            &args,
+            parser,
+        );
     }
 
-    // Make sure that all arguments were used and all arguments have types.
-    let errs = cx
-        .arg_types
+    let unused = used
         .iter()
         .enumerate()
-        .filter(|(i, ty)| ty.is_empty() && !cx.count_positions.contains_key(&i))
+        .filter(|&(_, used)| !used)
         .map(|(i, _)| {
-            let msg = if cx.args[i].name.is_some() {
+            let msg = if let FormatArgKind::Named(_) = args[i].1 {
                 "named argument never used"
             } else {
                 "argument never used"
             };
-            (cx.args[i].expr.span, msg)
+            (args[i].0.span, msg)
         })
         .collect::>();
 
-    let errs_len = errs.len();
-    if !errs.is_empty() {
-        let args_used = cx.arg_types.len() - errs_len;
-        let args_unused = errs_len;
+    if !unused.is_empty() {
+        // If there's a lot of unused arguments,
+        // let's check if this format arguments looks like another syntax (printf / shell).
+        let detect_foreign_fmt = unused.len() > num_explicit_args / 2;
+        report_missing_placeholders(ecx, unused, detect_foreign_fmt, str_style, fmt_str, fmt_span);
+    }
 
-        let mut diag = {
-            if let [(sp, msg)] = &errs[..] {
-                let mut diag = cx.ecx.struct_span_err(*sp, *msg);
-                diag.span_label(*sp, *msg);
-                diag
-            } else {
-                let mut diag = cx.ecx.struct_span_err(
-                    errs.iter().map(|&(sp, _)| sp).collect::>(),
-                    "multiple unused formatting arguments",
-                );
-                diag.span_label(cx.fmtsp, "multiple missing formatting specifiers");
-                for (sp, msg) in errs {
-                    diag.span_label(sp, msg);
+    // Only check for unused named argument names if there are no other errors to avoid causing
+    // too much noise in output errors, such as when a named argument is entirely unused.
+    if invalid_refs.is_empty() && ecx.sess.err_count() == 0 {
+        for &(index, span, used_as) in &numeric_refences_to_named_arg {
+            let (position_sp_to_replace, position_sp_for_msg) = match used_as {
+                Placeholder(pspan) => (span, pspan),
+                Precision => {
+                    // Strip the leading `.` for precision.
+                    let span = span.map(|span| span.with_lo(span.lo() + BytePos(1)));
+                    (span, span)
                 }
-                diag
-            }
-        };
+                Width => (span, span),
+            };
+            let arg_name = args[index].1.ident().unwrap();
+            ecx.buffered_early_lint.push(BufferedEarlyLint {
+                span: arg_name.span.into(),
+                msg: format!("named argument `{}` is not used by name", arg_name.name).into(),
+                node_id: ast::CRATE_NODE_ID,
+                lint_id: LintId::of(&NAMED_ARGUMENTS_USED_POSITIONALLY),
+                diagnostic: BuiltinLintDiagnostics::NamedArgumentUsedPositionally {
+                    position_sp_to_replace,
+                    position_sp_for_msg,
+                    named_arg_sp: arg_name.span,
+                    named_arg_name: arg_name.name.to_string(),
+                    is_formatting_arg: matches!(used_as, Width | Precision),
+                },
+            });
+        }
+    }
 
-        // Used to ensure we only report translations for *one* kind of foreign format.
-        let mut found_foreign = false;
-        // Decide if we want to look for foreign formatting directives.
-        if args_used < args_unused {
-            use super::format_foreign as foreign;
-
-            // The set of foreign substitutions we've explained.  This prevents spamming the user
-            // with `%d should be written as {}` over and over again.
-            let mut explained = FxHashSet::default();
-
-            macro_rules! check_foreign {
-                ($kind:ident) => {{
-                    let mut show_doc_note = false;
-
-                    let mut suggestions = vec![];
-                    // account for `"` and account for raw strings `r#`
-                    let padding = str_style.map(|i| i + 2).unwrap_or(1);
-                    for sub in foreign::$kind::iter_subs(fmt_str, padding) {
-                        let (trn, success) = match sub.translate() {
-                            Ok(trn) => (trn, true),
-                            Err(Some(msg)) => (msg, false),
-
-                            // If it has no translation, don't call it out specifically.
-                            _ => continue,
-                        };
-
-                        let pos = sub.position();
-                        let sub = String::from(sub.as_str());
-                        if explained.contains(&sub) {
-                            continue;
-                        }
-                        explained.insert(sub.clone());
+    Ok(FormatArgs { span: fmt_span, template, arguments: args })
+}
 
-                        if !found_foreign {
-                            found_foreign = true;
-                            show_doc_note = true;
-                        }
+fn invalid_placeholder_type_error(
+    ecx: &ExtCtxt<'_>,
+    ty: &str,
+    ty_span: Option,
+    fmt_span: Span,
+) {
+    let sp = ty_span.map(|sp| fmt_span.from_inner(InnerSpan::new(sp.start, sp.end)));
+    let mut err =
+        ecx.struct_span_err(sp.unwrap_or(fmt_span), &format!("unknown format trait `{}`", ty));
+    err.note(
+        "the only appropriate formatting traits are:\n\
+                                - ``, which uses the `Display` trait\n\
+                                - `?`, which uses the `Debug` trait\n\
+                                - `e`, which uses the `LowerExp` trait\n\
+                                - `E`, which uses the `UpperExp` trait\n\
+                                - `o`, which uses the `Octal` trait\n\
+                                - `p`, which uses the `Pointer` trait\n\
+                                - `b`, which uses the `Binary` trait\n\
+                                - `x`, which uses the `LowerHex` trait\n\
+                                - `X`, which uses the `UpperHex` trait",
+    );
+    if let Some(sp) = sp {
+        for (fmt, name) in &[
+            ("", "Display"),
+            ("?", "Debug"),
+            ("e", "LowerExp"),
+            ("E", "UpperExp"),
+            ("o", "Octal"),
+            ("p", "Pointer"),
+            ("b", "Binary"),
+            ("x", "LowerHex"),
+            ("X", "UpperHex"),
+        ] {
+            err.tool_only_span_suggestion(
+                sp,
+                &format!("use the `{}` trait", name),
+                *fmt,
+                Applicability::MaybeIncorrect,
+            );
+        }
+    }
+    err.emit();
+}
 
-                        if let Some(inner_sp) = pos {
-                            let sp = fmt_sp.from_inner(inner_sp);
-
-                            if success {
-                                suggestions.push((sp, trn));
-                            } else {
-                                diag.span_note(
-                                    sp,
-                                    &format!("format specifiers use curly braces, and {}", trn),
-                                );
-                            }
-                        } else {
-                            if success {
-                                diag.help(&format!("`{}` should be written as `{}`", sub, trn));
-                            } else {
-                                diag.note(&format!(
-                                    "`{}` should use curly braces, and {}",
-                                    sub, trn
-                                ));
-                            }
-                        }
+fn report_missing_placeholders(
+    ecx: &mut ExtCtxt<'_>,
+    unused: Vec<(Span, &str)>,
+    detect_foreign_fmt: bool,
+    str_style: Option,
+    fmt_str: &str,
+    fmt_span: Span,
+) {
+    let mut diag = if let &[(span, msg)] = &unused[..] {
+        let mut diag = ecx.struct_span_err(span, msg);
+        diag.span_label(span, msg);
+        diag
+    } else {
+        let mut diag = ecx.struct_span_err(
+            unused.iter().map(|&(sp, _)| sp).collect::>(),
+            "multiple unused formatting arguments",
+        );
+        diag.span_label(fmt_span, "multiple missing formatting specifiers");
+        for &(span, msg) in &unused {
+            diag.span_label(span, msg);
+        }
+        diag
+    };
+
+    // Used to ensure we only report translations for *one* kind of foreign format.
+    let mut found_foreign = false;
+
+    // Decide if we want to look for foreign formatting directives.
+    if detect_foreign_fmt {
+        use super::format_foreign as foreign;
+
+        // The set of foreign substitutions we've explained.  This prevents spamming the user
+        // with `%d should be written as {}` over and over again.
+        let mut explained = FxHashSet::default();
+
+        macro_rules! check_foreign {
+            ($kind:ident) => {{
+                let mut show_doc_note = false;
+
+                let mut suggestions = vec![];
+                // account for `"` and account for raw strings `r#`
+                let padding = str_style.map(|i| i + 2).unwrap_or(1);
+                for sub in foreign::$kind::iter_subs(fmt_str, padding) {
+                    let (trn, success) = match sub.translate() {
+                        Ok(trn) => (trn, true),
+                        Err(Some(msg)) => (msg, false),
+
+                        // If it has no translation, don't call it out specifically.
+                        _ => continue,
+                    };
+
+                    let pos = sub.position();
+                    let sub = String::from(sub.as_str());
+                    if explained.contains(&sub) {
+                        continue;
                     }
+                    explained.insert(sub.clone());
 
-                    if show_doc_note {
-                        diag.note(concat!(
-                            stringify!($kind),
-                            " formatting not supported; see the documentation for `std::fmt`",
-                        ));
+                    if !found_foreign {
+                        found_foreign = true;
+                        show_doc_note = true;
                     }
-                    if suggestions.len() > 0 {
-                        diag.multipart_suggestion(
-                            "format specifiers use curly braces",
-                            suggestions,
-                            Applicability::MachineApplicable,
-                        );
+
+                    if let Some(inner_sp) = pos {
+                        let sp = fmt_span.from_inner(inner_sp);
+
+                        if success {
+                            suggestions.push((sp, trn));
+                        } else {
+                            diag.span_note(
+                                sp,
+                                &format!("format specifiers use curly braces, and {}", trn),
+                            );
+                        }
+                    } else {
+                        if success {
+                            diag.help(&format!("`{}` should be written as `{}`", sub, trn));
+                        } else {
+                            diag.note(&format!("`{}` should use curly braces, and {}", sub, trn));
+                        }
                     }
-                }};
-            }
+                }
 
-            check_foreign!(printf);
-            if !found_foreign {
-                check_foreign!(shell);
-            }
-        }
-        if !found_foreign && errs_len == 1 {
-            diag.span_label(cx.fmtsp, "formatting specifier missing");
+                if show_doc_note {
+                    diag.note(concat!(
+                        stringify!($kind),
+                        " formatting not supported; see the documentation for `std::fmt`",
+                    ));
+                }
+                if suggestions.len() > 0 {
+                    diag.multipart_suggestion(
+                        "format specifiers use curly braces",
+                        suggestions,
+                        Applicability::MachineApplicable,
+                    );
+                }
+            }};
         }
 
-        diag.emit();
-    } else if cx.invalid_refs.is_empty() && cx.ecx.sess.err_count() == 0 {
-        // Only check for unused named argument names if there are no other errors to avoid causing
-        // too much noise in output errors, such as when a named argument is entirely unused.
-        create_lints_for_named_arguments_used_positionally(&mut cx);
+        check_foreign!(printf);
+        if !found_foreign {
+            check_foreign!(shell);
+        }
+    }
+    if !found_foreign && unused.len() == 1 {
+        diag.span_label(fmt_span, "formatting specifier missing");
     }
 
-    cx.into_expr()
+    diag.emit();
 }
 
-fn may_contain_yield_point(e: &ast::Expr) -> bool {
-    struct MayContainYieldPoint(bool);
+/// Handle invalid references to positional arguments. Output different
+/// errors for the case where all arguments are positional and for when
+/// there are named arguments or numbered positional arguments in the
+/// format string.
+fn report_invalid_references(
+    ecx: &mut ExtCtxt<'_>,
+    invalid_refs: &[(usize, Option, PositionUsedAs, FormatArgPositionKind)],
+    template: &[FormatArgsPiece],
+    fmt_span: Span,
+    num_explicit_args: usize,
+    args: &[(P, FormatArgKind)],
+    parser: parse::Parser<'_>,
+) {
+    let num_args_desc = match num_explicit_args {
+        0 => "no arguments were given".to_string(),
+        1 => "there is 1 argument".to_string(),
+        n => format!("there are {} arguments", n),
+    };
 
-    impl Visitor<'_> for MayContainYieldPoint {
-        fn visit_expr(&mut self, e: &ast::Expr) {
-            if let ast::ExprKind::Await(_) | ast::ExprKind::Yield(_) = e.kind {
-                self.0 = true;
-            } else {
-                visit::walk_expr(self, e);
+    let mut e;
+
+    if template.iter().all(|piece| match piece {
+        FormatArgsPiece::Placeholder(FormatPlaceholder {
+            argument: FormatArgPosition { kind: FormatArgPositionKind::Number, .. },
+            ..
+        }) => false,
+        FormatArgsPiece::Placeholder(FormatPlaceholder {
+            format_options:
+                FormatOptions {
+                    precision:
+                        Some(FormatCount::Argument(FormatArgPosition {
+                            kind: FormatArgPositionKind::Number,
+                            ..
+                        })),
+                    ..
+                }
+                | FormatOptions {
+                    width:
+                        Some(FormatCount::Argument(FormatArgPosition {
+                            kind: FormatArgPositionKind::Number,
+                            ..
+                        })),
+                    ..
+                },
+            ..
+        }) => false,
+        _ => true,
+    }) {
+        // There are no numeric positions.
+        // Collect all the implicit positions:
+        let mut spans = Vec::new();
+        let mut num_placeholders = 0;
+        for piece in template {
+            let mut placeholder = None;
+            // `{arg:.*}`
+            if let FormatArgsPiece::Placeholder(FormatPlaceholder {
+                format_options:
+                    FormatOptions {
+                        precision:
+                            Some(FormatCount::Argument(FormatArgPosition {
+                                span,
+                                kind: FormatArgPositionKind::Implicit,
+                                ..
+                            })),
+                        ..
+                    },
+                ..
+            }) = piece
+            {
+                placeholder = *span;
+                num_placeholders += 1;
+            }
+            // `{}`
+            if let FormatArgsPiece::Placeholder(FormatPlaceholder {
+                argument: FormatArgPosition { kind: FormatArgPositionKind::Implicit, .. },
+                span,
+                ..
+            }) = piece
+            {
+                placeholder = *span;
+                num_placeholders += 1;
             }
+            // For `{:.*}`, we only push one span.
+            spans.extend(placeholder);
         }
-
-        fn visit_mac_call(&mut self, _: &ast::MacCall) {
-            self.0 = true;
+        let span = if spans.is_empty() {
+            MultiSpan::from_span(fmt_span)
+        } else {
+            MultiSpan::from_spans(spans)
+        };
+        e = ecx.struct_span_err(
+            span,
+            &format!(
+                "{} positional argument{} in format string, but {}",
+                num_placeholders,
+                pluralize!(num_placeholders),
+                num_args_desc,
+            ),
+        );
+        for (arg, _) in &args[..num_explicit_args] {
+            e.span_label(arg.span, "");
+        }
+        // Point out `{:.*}` placeholders: those take an extra argument.
+        let mut has_precision_star = false;
+        for piece in template {
+            if let FormatArgsPiece::Placeholder(FormatPlaceholder {
+                format_options:
+                    FormatOptions {
+                        precision:
+                            Some(FormatCount::Argument(FormatArgPosition {
+                                index,
+                                span: Some(span),
+                                kind: FormatArgPositionKind::Implicit,
+                                ..
+                            })),
+                        ..
+                    },
+                ..
+            }) = piece
+            {
+                let (Ok(index) | Err(index)) = index;
+                has_precision_star = true;
+                e.span_label(
+                    *span,
+                    &format!(
+                        "this precision flag adds an extra required argument at position {}, which is why there {} expected",
+                        index,
+                        if num_placeholders == 1 {
+                            "is 1 argument".to_string()
+                        } else {
+                            format!("are {} arguments", num_placeholders)
+                        },
+                    ),
+                );
+            }
+        }
+        if has_precision_star {
+            e.note("positional arguments are zero-based");
         }
+    } else {
+        let mut indexes: Vec<_> = invalid_refs.iter().map(|&(index, _, _, _)| index).collect();
+        // Avoid `invalid reference to positional arguments 7 and 7 (there is 1 argument)`
+        // for `println!("{7:7$}", 1);`
+        indexes.sort();
+        indexes.dedup();
+        let span: MultiSpan = if !parser.is_literal || parser.arg_places.is_empty() {
+            MultiSpan::from_span(fmt_span)
+        } else {
+            MultiSpan::from_spans(invalid_refs.iter().filter_map(|&(_, span, _, _)| span).collect())
+        };
+        let arg_list = if let &[index] = &indexes[..] {
+            format!("argument {index}")
+        } else {
+            let tail = indexes.pop().unwrap();
+            format!(
+                "arguments {head} and {tail}",
+                head = indexes.into_iter().map(|i| i.to_string()).collect::>().join(", ")
+            )
+        };
+        e = ecx.struct_span_err(
+            span,
+            &format!("invalid reference to positional {} ({})", arg_list, num_args_desc),
+        );
+        e.note("positional arguments are zero-based");
+    }
 
-        fn visit_attribute(&mut self, _: &ast::Attribute) {
-            // Conservatively assume this may be a proc macro attribute in
-            // expression position.
-            self.0 = true;
+    if template.iter().any(|piece| match piece {
+        FormatArgsPiece::Placeholder(FormatPlaceholder { format_options: f, .. }) => {
+            *f != FormatOptions::default()
         }
+        _ => false,
+    }) {
+        e.note("for information about formatting flags, visit https://doc.rust-lang.org/std/fmt/index.html");
+    }
+
+    e.emit();
+}
 
-        fn visit_item(&mut self, _: &ast::Item) {
-            // Do not recurse into nested items.
+fn expand_format_args_impl<'cx>(
+    ecx: &'cx mut ExtCtxt<'_>,
+    mut sp: Span,
+    tts: TokenStream,
+    nl: bool,
+) -> Box {
+    sp = ecx.with_def_site_ctxt(sp);
+    match parse_args(ecx, sp, tts) {
+        Ok((efmt, args)) => {
+            if let Ok(format_args) = make_format_args(ecx, efmt, args, nl) {
+                MacEager::expr(expand_parsed_format_args(ecx, format_args))
+            } else {
+                MacEager::expr(DummyResult::raw_expr(sp, true))
+            }
+        }
+        Err(mut err) => {
+            err.emit();
+            DummyResult::any(sp)
         }
     }
+}
 
-    let mut visitor = MayContainYieldPoint(false);
-    visitor.visit_expr(e);
-    visitor.0
+pub fn expand_format_args<'cx>(
+    ecx: &'cx mut ExtCtxt<'_>,
+    sp: Span,
+    tts: TokenStream,
+) -> Box {
+    expand_format_args_impl(ecx, sp, tts, false)
+}
+
+pub fn expand_format_args_nl<'cx>(
+    ecx: &'cx mut ExtCtxt<'_>,
+    sp: Span,
+    tts: TokenStream,
+) -> Box {
+    expand_format_args_impl(ecx, sp, tts, true)
 }
diff --git a/compiler/rustc_builtin_macros/src/format/expand.rs b/compiler/rustc_builtin_macros/src/format/expand.rs
new file mode 100644
index 0000000000000..d1c114a67ac1e
--- /dev/null
+++ b/compiler/rustc_builtin_macros/src/format/expand.rs
@@ -0,0 +1,352 @@
+use super::*;
+use rustc_ast as ast;
+use rustc_ast::visit::{self, Visitor};
+use rustc_ast::{BlockCheckMode, UnsafeSource};
+use rustc_data_structures::fx::FxIndexSet;
+use rustc_span::{sym, symbol::kw};
+
+#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
+enum ArgumentType {
+    Format(FormatTrait),
+    Usize,
+}
+
+fn make_argument(ecx: &ExtCtxt<'_>, sp: Span, arg: P, ty: ArgumentType) -> P {
+    // Generate:
+    //     ::core::fmt::ArgumentV1::new_…(arg)
+    use ArgumentType::*;
+    use FormatTrait::*;
+    ecx.expr_call_global(
+        sp,
+        ecx.std_path(&[
+            sym::fmt,
+            sym::ArgumentV1,
+            match ty {
+                Format(Display) => sym::new_display,
+                Format(Debug) => sym::new_debug,
+                Format(LowerExp) => sym::new_lower_exp,
+                Format(UpperExp) => sym::new_upper_exp,
+                Format(Octal) => sym::new_octal,
+                Format(Pointer) => sym::new_pointer,
+                Format(Binary) => sym::new_binary,
+                Format(LowerHex) => sym::new_lower_hex,
+                Format(UpperHex) => sym::new_upper_hex,
+                Usize => sym::from_usize,
+            },
+        ]),
+        vec![arg],
+    )
+}
+
+fn make_count(
+    ecx: &ExtCtxt<'_>,
+    sp: Span,
+    count: &Option,
+    argmap: &mut FxIndexSet<(usize, ArgumentType)>,
+) -> P {
+    // Generate:
+    //     ::core::fmt::rt::v1::Count::…(…)
+    match count {
+        Some(FormatCount::Literal(n)) => ecx.expr_call_global(
+            sp,
+            ecx.std_path(&[sym::fmt, sym::rt, sym::v1, sym::Count, sym::Is]),
+            vec![ecx.expr_usize(sp, *n)],
+        ),
+        Some(FormatCount::Argument(arg)) => {
+            if let Ok(arg_index) = arg.index {
+                let (i, _) = argmap.insert_full((arg_index, ArgumentType::Usize));
+                ecx.expr_call_global(
+                    sp,
+                    ecx.std_path(&[sym::fmt, sym::rt, sym::v1, sym::Count, sym::Param]),
+                    vec![ecx.expr_usize(sp, i)],
+                )
+            } else {
+                DummyResult::raw_expr(sp, true)
+            }
+        }
+        None => ecx.expr_path(ecx.path_global(
+            sp,
+            ecx.std_path(&[sym::fmt, sym::rt, sym::v1, sym::Count, sym::Implied]),
+        )),
+    }
+}
+
+fn make_format_spec(
+    ecx: &ExtCtxt<'_>,
+    sp: Span,
+    placeholder: &FormatPlaceholder,
+    argmap: &mut FxIndexSet<(usize, ArgumentType)>,
+) -> P {
+    // Generate:
+    //     ::core::fmt::rt::v1::Argument {
+    //         position: 0usize,
+    //         format: ::core::fmt::rt::v1::FormatSpec {
+    //             fill: ' ',
+    //             align: ::core::fmt::rt::v1::Alignment::Unknown,
+    //             flags: 0u32,
+    //             precision: ::core::fmt::rt::v1::Count::Implied,
+    //             width: ::core::fmt::rt::v1::Count::Implied,
+    //         },
+    //     }
+    let position = match placeholder.argument.index {
+        Ok(arg_index) => {
+            let (i, _) =
+                argmap.insert_full((arg_index, ArgumentType::Format(placeholder.format_trait)));
+            ecx.expr_usize(sp, i)
+        }
+        Err(_) => DummyResult::raw_expr(sp, true),
+    };
+    let fill = ecx.expr_char(sp, placeholder.format_options.fill.unwrap_or(' '));
+    let align = ecx.expr_path(ecx.path_global(
+        sp,
+        ecx.std_path(&[
+            sym::fmt,
+            sym::rt,
+            sym::v1,
+            sym::Alignment,
+            match placeholder.format_options.alignment {
+                Some(FormatAlignment::Left) => sym::Left,
+                Some(FormatAlignment::Right) => sym::Right,
+                Some(FormatAlignment::Center) => sym::Center,
+                None => sym::Unknown,
+            },
+        ]),
+    ));
+    let flags = ecx.expr_u32(sp, placeholder.format_options.flags);
+    let prec = make_count(ecx, sp, &placeholder.format_options.precision, argmap);
+    let width = make_count(ecx, sp, &placeholder.format_options.width, argmap);
+    ecx.expr_struct(
+        sp,
+        ecx.path_global(sp, ecx.std_path(&[sym::fmt, sym::rt, sym::v1, sym::Argument])),
+        vec![
+            ecx.field_imm(sp, Ident::new(sym::position, sp), position),
+            ecx.field_imm(
+                sp,
+                Ident::new(sym::format, sp),
+                ecx.expr_struct(
+                    sp,
+                    ecx.path_global(
+                        sp,
+                        ecx.std_path(&[sym::fmt, sym::rt, sym::v1, sym::FormatSpec]),
+                    ),
+                    vec![
+                        ecx.field_imm(sp, Ident::new(sym::fill, sp), fill),
+                        ecx.field_imm(sp, Ident::new(sym::align, sp), align),
+                        ecx.field_imm(sp, Ident::new(sym::flags, sp), flags),
+                        ecx.field_imm(sp, Ident::new(sym::precision, sp), prec),
+                        ecx.field_imm(sp, Ident::new(sym::width, sp), width),
+                    ],
+                ),
+            ),
+        ],
+    )
+}
+
+pub fn expand_parsed_format_args(ecx: &mut ExtCtxt<'_>, fmt: FormatArgs) -> P {
+    let macsp = ecx.with_def_site_ctxt(ecx.call_site());
+
+    let lit_pieces = ecx.expr_array_ref(
+        fmt.span,
+        fmt.template
+            .iter()
+            .enumerate()
+            .filter_map(|(i, piece)| match piece {
+                &FormatArgsPiece::Literal(s) => Some(ecx.expr_str(fmt.span, s)),
+                &FormatArgsPiece::Placeholder(_) => {
+                    // Inject empty string before placeholders when not already preceded by a literal piece.
+                    if i == 0 || matches!(fmt.template[i - 1], FormatArgsPiece::Placeholder(_)) {
+                        Some(ecx.expr_str(fmt.span, kw::Empty))
+                    } else {
+                        None
+                    }
+                }
+            })
+            .collect(),
+    );
+
+    let has_any_format_options = fmt.template.iter().any(|piece| {
+        let FormatArgsPiece::Placeholder(placeholder) = piece else { return false };
+        placeholder.format_options != Default::default()
+    });
+
+    let (args, format_options) = if has_any_format_options {
+        // Create a list of all _unique_ (argument, format trait) combinations.
+        // E.g. "{0} {0:x} {0} {1}" -> [(0, Display), (0, LowerHex), (1, Display)]
+        let mut argmap = FxIndexSet::default();
+        // Generate:
+        //     &[format_spec_0, format_spec_1, format_spec_2]
+        let format_options = ecx.expr_array_ref(
+            macsp,
+            fmt.template
+                .iter()
+                .filter_map(|piece| {
+                    let FormatArgsPiece::Placeholder(placeholder) = piece else { return None };
+                    Some(make_format_spec(ecx, macsp, placeholder, &mut argmap))
+                })
+                .collect(),
+        );
+        (Vec::from_iter(argmap), Some(format_options))
+    } else {
+        // Create a list of all (argument, format trait) pairs, one for each placeholder.
+        // E.g. "{0} {0:x} {0} {1}" -> [(0, Display), (0, LowerHex), (0, Display), (1, Display)]
+        let args = fmt
+            .template
+            .iter()
+            .filter_map(|piece| {
+                let FormatArgsPiece::Placeholder(placeholder) = piece else { return None };
+                Some((
+                    placeholder.argument.index.ok()?,
+                    ArgumentType::Format(placeholder.format_trait),
+                ))
+            })
+            .collect();
+        (args, None)
+    };
+
+    // If the args array contains exactly all the original arguments once,
+    // in order, we can use a simple array instead of a `match` construction.
+    // However, if there's a yield point in any argument except the first one,
+    // we don't do this, because an ArgumentV1 cannot be kept across yield points.
+    let use_simple_array = args.len() == fmt.arguments.len()
+        && args.iter().enumerate().all(|(i, &(j, _))| i == j)
+        && fmt.arguments.iter().skip(1).all(|(arg, _)| !may_contain_yield_point(arg));
+
+    let args_expr = if use_simple_array {
+        // Generate:
+        //     &[
+        //         ::core::fmt::ArgumentV1::new_display(&arg0),
+        //         ::core::fmt::ArgumentV1::new_lower_hex(&arg1),
+        //         ::core::fmt::ArgumentV1::new_debug(&arg2),
+        //     ]
+        ecx.expr_array_ref(
+            macsp,
+            fmt.arguments
+                .into_iter()
+                .zip(args)
+                .map(|((arg, _), (_, ty))| {
+                    let sp = arg.span.with_ctxt(macsp.ctxt());
+                    make_argument(ecx, sp, ecx.expr_addr_of(sp, arg), ty)
+                })
+                .collect(),
+        )
+    } else {
+        // Generate:
+        //     match (&arg0, &arg1, &arg2) {
+        //         args => &[
+        //             ::core::fmt::ArgumentV1::new_display(args.0),
+        //             ::core::fmt::ArgumentV1::new_lower_hex(args.1),
+        //             ::core::fmt::ArgumentV1::new_debug(args.0),
+        //         ]
+        //     }
+        let args_ident = Ident::new(sym::args, macsp);
+        let args = args
+            .iter()
+            .map(|&(arg_index, ty)| {
+                if let Some((arg, _)) = fmt.arguments.get(arg_index) {
+                    let sp = arg.span.with_ctxt(macsp.ctxt());
+                    make_argument(
+                        ecx,
+                        sp,
+                        ecx.expr_field(
+                            sp,
+                            ecx.expr_ident(macsp, args_ident),
+                            Ident::new(sym::integer(arg_index), macsp),
+                        ),
+                        ty,
+                    )
+                } else {
+                    DummyResult::raw_expr(macsp, true)
+                }
+            })
+            .collect();
+        ecx.expr_addr_of(
+            macsp,
+            ecx.expr_match(
+                macsp,
+                ecx.expr_tuple(
+                    macsp,
+                    fmt.arguments
+                        .into_iter()
+                        .map(|(arg, _)| ecx.expr_addr_of(arg.span.with_ctxt(macsp.ctxt()), arg))
+                        .collect(),
+                ),
+                [ecx.arm(macsp, ecx.pat_ident(macsp, args_ident), ecx.expr_array(macsp, args))]
+                    .into(),
+            ),
+        )
+    };
+
+    if let Some(format_options) = format_options {
+        // Generate:
+        //     ::core::fmt::Arguments::new_v1_formatted(
+        //         lit_pieces,
+        //         args,
+        //         format_options,
+        //         unsafe { ::core::fmt::UnsafeArg::new() }
+        //     )
+        ecx.expr_call_global(
+            macsp,
+            ecx.std_path(&[sym::fmt, sym::Arguments, sym::new_v1_formatted]),
+            vec![
+                lit_pieces,
+                args_expr,
+                format_options,
+                ecx.expr_block(P(ast::Block {
+                    stmts: vec![ecx.stmt_expr(ecx.expr_call_global(
+                        macsp,
+                        ecx.std_path(&[sym::fmt, sym::UnsafeArg, sym::new]),
+                        Vec::new(),
+                    ))],
+                    id: ast::DUMMY_NODE_ID,
+                    rules: BlockCheckMode::Unsafe(UnsafeSource::CompilerGenerated),
+                    span: macsp,
+                    tokens: None,
+                    could_be_bare_literal: false,
+                })),
+            ],
+        )
+    } else {
+        // Generate:
+        //     ::core::fmt::Arguments::new_v1(
+        //         lit_pieces,
+        //         args,
+        //     )
+        ecx.expr_call_global(
+            macsp,
+            ecx.std_path(&[sym::fmt, sym::Arguments, sym::new_v1]),
+            vec![lit_pieces, args_expr],
+        )
+    }
+}
+
+fn may_contain_yield_point(e: &ast::Expr) -> bool {
+    struct MayContainYieldPoint(bool);
+
+    impl Visitor<'_> for MayContainYieldPoint {
+        fn visit_expr(&mut self, e: &ast::Expr) {
+            if let ast::ExprKind::Await(_) | ast::ExprKind::Yield(_) = e.kind {
+                self.0 = true;
+            } else {
+                visit::walk_expr(self, e);
+            }
+        }
+
+        fn visit_mac_call(&mut self, _: &ast::MacCall) {
+            self.0 = true;
+        }
+
+        fn visit_attribute(&mut self, _: &ast::Attribute) {
+            // Conservatively assume this may be a proc macro attribute in
+            // expression position.
+            self.0 = true;
+        }
+
+        fn visit_item(&mut self, _: &ast::Item) {
+            // Do not recurse into nested items.
+        }
+    }
+
+    let mut visitor = MayContainYieldPoint(false);
+    visitor.visit_expr(e);
+    visitor.0
+}
diff --git a/compiler/rustc_builtin_macros/src/lib.rs b/compiler/rustc_builtin_macros/src/lib.rs
index 0de27d3d4070e..f058503064bf1 100644
--- a/compiler/rustc_builtin_macros/src/lib.rs
+++ b/compiler/rustc_builtin_macros/src/lib.rs
@@ -7,6 +7,7 @@
 #![feature(box_patterns)]
 #![feature(decl_macro)]
 #![feature(if_let_guard)]
+#![feature(is_some_with)]
 #![feature(is_sorted)]
 #![feature(let_chains)]
 #![feature(proc_macro_internals)]
diff --git a/compiler/rustc_expand/src/build.rs b/compiler/rustc_expand/src/build.rs
index 50d2be3cee5e0..0952e65cfee3d 100644
--- a/compiler/rustc_expand/src/build.rs
+++ b/compiler/rustc_expand/src/build.rs
@@ -252,6 +252,10 @@ impl<'a> ExtCtxt<'a> {
         self.expr_ident(span, Ident::with_dummy_span(kw::SelfLower))
     }
 
+    pub fn expr_field(&self, span: Span, expr: P, field: Ident) -> P {
+        self.expr(span, ast::ExprKind::Field(expr, field))
+    }
+
     pub fn expr_binary(
         &self,
         sp: Span,
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 502ef67fc6767..7657f9486c227 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -991,7 +991,18 @@ symbols! {
         never_type,
         never_type_fallback,
         new,
+        new_binary,
+        new_debug,
+        new_display,
+        new_lower_exp,
+        new_lower_hex,
+        new_octal,
+        new_pointer,
         new_unchecked,
+        new_upper_exp,
+        new_upper_hex,
+        new_v1,
+        new_v1_formatted,
         next,
         nll,
         no,
diff --git a/src/test/ui/fmt/ifmt-bad-arg.stderr b/src/test/ui/fmt/ifmt-bad-arg.stderr
index dbb4bc6d9370e..af645c2ba3ad7 100644
--- a/src/test/ui/fmt/ifmt-bad-arg.stderr
+++ b/src/test/ui/fmt/ifmt-bad-arg.stderr
@@ -117,20 +117,20 @@ LL |     format!("{} {}", 1, 2, foo=1, bar=2);
    |             multiple missing formatting specifiers
 
 error: duplicate argument named `foo`
-  --> $DIR/ifmt-bad-arg.rs:40:33
+  --> $DIR/ifmt-bad-arg.rs:40:29
    |
 LL |     format!("{foo}", foo=1, foo=2);
-   |                          -      ^ duplicate argument
-   |                          |
-   |                          previously here
+   |                      ---    ^^^ duplicate argument
+   |                      |
+   |                      previously here
 
 error: positional arguments cannot follow named arguments
   --> $DIR/ifmt-bad-arg.rs:41:35
    |
 LL |     format!("{foo} {} {}", foo=1, 2);
-   |                                -  ^ positional arguments must be before named arguments
-   |                                |
-   |                                named argument
+   |                            -----  ^ positional arguments must be before named arguments
+   |                            |
+   |                            named argument
 
 error: named argument never used
   --> $DIR/ifmt-bad-arg.rs:45:51
diff --git a/src/test/ui/macros/format-parse-errors.stderr b/src/test/ui/macros/format-parse-errors.stderr
index 1a7578e6076eb..f9ea4c63377b0 100644
--- a/src/test/ui/macros/format-parse-errors.stderr
+++ b/src/test/ui/macros/format-parse-errors.stderr
@@ -22,7 +22,7 @@ error: positional arguments cannot follow named arguments
   --> $DIR/format-parse-errors.rs:10:9
    |
 LL |         foo = foo,
-   |               --- named argument
+   |         --------- named argument
 LL |         bar,
    |         ^^^ positional arguments must be before named arguments
 

From 3ffcb655184e9e069af76d8d648e59eb9ff2cf6c Mon Sep 17 00:00:00 2001
From: Mara Bos 
Date: Fri, 26 Aug 2022 18:52:08 +0200
Subject: [PATCH 298/586] Update tests.

---
 .../diagnostic-derive.stderr                  |  10 +-
 .../ui/fmt/format-args-capture-issue-93378.rs |   4 +-
 .../format-args-capture-issue-93378.stderr    |  17 +-
 src/test/ui/fmt/ifmt-bad-arg.rs               |   6 +-
 src/test/ui/fmt/ifmt-bad-arg.stderr           |  76 ++---
 src/test/ui/issues/issue-75307.rs             |   2 +-
 src/test/ui/issues/issue-75307.stderr         |   8 +-
 src/test/ui/macros/issue-99265.stderr         | 278 +++++++++---------
 src/test/ui/macros/issue-99907.stderr         |   4 +-
 9 files changed, 190 insertions(+), 215 deletions(-)

diff --git a/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr b/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr
index 68602640a24f2..21a402c7b9da8 100644
--- a/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr
+++ b/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr
@@ -237,21 +237,19 @@ LL |     #[suggestion(typeck::suggestion, code = "{name}")]
    |                                             ^^^^^^^^
 
 error: invalid format string: expected `'}'` but string was terminated
-  --> $DIR/diagnostic-derive.rs:175:16
+  --> $DIR/diagnostic-derive.rs:175:10
    |
 LL | #[derive(Diagnostic)]
-   |           -    ^ expected `'}'` in format string
-   |           |
-   |           because of this opening brace
+   |          ^^^^^^^^^^ expected `'}'` in format string
    |
    = note: if you intended to print `{`, you can escape it using `{{`
    = note: this error originates in the derive macro `Diagnostic` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: invalid format string: unmatched `}` found
-  --> $DIR/diagnostic-derive.rs:185:15
+  --> $DIR/diagnostic-derive.rs:185:10
    |
 LL | #[derive(Diagnostic)]
-   |               ^ unmatched `}` in format string
+   |          ^^^^^^^^^^ unmatched `}` in format string
    |
    = note: if you intended to print `}`, you can escape it using `}}`
    = note: this error originates in the derive macro `Diagnostic` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/src/test/ui/fmt/format-args-capture-issue-93378.rs b/src/test/ui/fmt/format-args-capture-issue-93378.rs
index 6744444426472..9d722a0287a5c 100644
--- a/src/test/ui/fmt/format-args-capture-issue-93378.rs
+++ b/src/test/ui/fmt/format-args-capture-issue-93378.rs
@@ -3,9 +3,9 @@ fn main() {
     let b = "b";
 
     println!("{a} {b} {} {} {c} {}", c = "c");
-    //~^ ERROR: invalid reference to positional arguments 1 and 2 (there is 1 argument)
+    //~^ ERROR: 3 positional arguments in format string, but there is 1 argument
 
     let n = 1;
     println!("{a:.n$} {b:.*}");
-    //~^ ERROR: invalid reference to positional argument 0 (no arguments were given)
+    //~^ ERROR: 1 positional argument in format string, but no arguments were given
 }
diff --git a/src/test/ui/fmt/format-args-capture-issue-93378.stderr b/src/test/ui/fmt/format-args-capture-issue-93378.stderr
index b8e2b2afb3867..6429b0d46f6af 100644
--- a/src/test/ui/fmt/format-args-capture-issue-93378.stderr
+++ b/src/test/ui/fmt/format-args-capture-issue-93378.stderr
@@ -1,19 +1,14 @@
-error: invalid reference to positional arguments 1 and 2 (there is 1 argument)
-  --> $DIR/format-args-capture-issue-93378.rs:5:26
+error: 3 positional arguments in format string, but there is 1 argument
+  --> $DIR/format-args-capture-issue-93378.rs:5:23
    |
 LL |     println!("{a} {b} {} {} {c} {}", c = "c");
-   |                          ^^     ^^
-   |
-   = note: positional arguments are zero-based
+   |                       ^^ ^^     ^^       ---
 
-error: invalid reference to positional argument 0 (no arguments were given)
-  --> $DIR/format-args-capture-issue-93378.rs:9:23
+error: 1 positional argument in format string, but no arguments were given
+  --> $DIR/format-args-capture-issue-93378.rs:9:26
    |
 LL |     println!("{a:.n$} {b:.*}");
-   |                   -   ^^^--^
-   |                   |      |
-   |                   |      this precision flag adds an extra required argument at position 0, which is why there are 3 arguments expected
-   |                   this parameter corresponds to the precision flag
+   |                          ^^ this precision flag adds an extra required argument at position 0, which is why there is 1 argument expected
    |
    = note: positional arguments are zero-based
    = note: for information about formatting flags, visit https://doc.rust-lang.org/std/fmt/index.html
diff --git a/src/test/ui/fmt/ifmt-bad-arg.rs b/src/test/ui/fmt/ifmt-bad-arg.rs
index f00cb05c9ebc3..1bd9668de314e 100644
--- a/src/test/ui/fmt/ifmt-bad-arg.rs
+++ b/src/test/ui/fmt/ifmt-bad-arg.rs
@@ -20,9 +20,9 @@ fn main() {
     //~^ ERROR: invalid reference to positional argument 2 (there are 2 arguments)
 
     format!("{} {value} {} {}", 1, value=2);
-    //~^ ERROR: invalid reference to positional argument 2 (there are 2 arguments)
+    //~^ ERROR: 3 positional arguments in format string, but there are 2 arguments
     format!("{name} {value} {} {} {} {} {} {}", 0, name=1, value=2);
-    //~^ ERROR: invalid reference to positional arguments 3, 4 and 5 (there are 3 arguments)
+    //~^ ERROR: 6 positional arguments in format string, but there are 3 arguments
 
     format!("{} {foo} {} {bar} {}", 1, 2, 3);
     //~^ ERROR: cannot find value `foo` in this scope
@@ -79,7 +79,7 @@ tenth number: {}",
     //~^ ERROR 4 positional arguments in format string, but there are 3 arguments
     //~| ERROR mismatched types
     println!("{} {:07$.*} {}", 1, 3.2, 4);
-    //~^ ERROR 4 positional arguments in format string, but there are 3 arguments
+    //~^ ERROR invalid reference to positional arguments 3 and 7 (there are 3 arguments)
     //~| ERROR mismatched types
     println!("{} {:07$} {}", 1, 3.2, 4);
     //~^ ERROR invalid reference to positional argument 7 (there are 3 arguments)
diff --git a/src/test/ui/fmt/ifmt-bad-arg.stderr b/src/test/ui/fmt/ifmt-bad-arg.stderr
index af645c2ba3ad7..a71792d1ec912 100644
--- a/src/test/ui/fmt/ifmt-bad-arg.stderr
+++ b/src/test/ui/fmt/ifmt-bad-arg.stderr
@@ -5,10 +5,10 @@ LL |     format!("{}");
    |              ^^
 
 error: invalid reference to positional argument 1 (there is 1 argument)
-  --> $DIR/ifmt-bad-arg.rs:9:14
+  --> $DIR/ifmt-bad-arg.rs:9:15
    |
 LL |     format!("{1}", 1);
-   |              ^^^
+   |               ^
    |
    = note: positional arguments are zero-based
 
@@ -27,36 +27,32 @@ LL |     format!("{} {}");
    |              ^^ ^^
 
 error: invalid reference to positional argument 1 (there is 1 argument)
-  --> $DIR/ifmt-bad-arg.rs:16:18
+  --> $DIR/ifmt-bad-arg.rs:16:19
    |
 LL |     format!("{0} {1}", 1);
-   |                  ^^^
+   |                   ^
    |
    = note: positional arguments are zero-based
 
 error: invalid reference to positional argument 2 (there are 2 arguments)
-  --> $DIR/ifmt-bad-arg.rs:19:22
+  --> $DIR/ifmt-bad-arg.rs:19:23
    |
 LL |     format!("{0} {1} {2}", 1, 2);
-   |                      ^^^
+   |                       ^
    |
    = note: positional arguments are zero-based
 
-error: invalid reference to positional argument 2 (there are 2 arguments)
-  --> $DIR/ifmt-bad-arg.rs:22:28
+error: 3 positional arguments in format string, but there are 2 arguments
+  --> $DIR/ifmt-bad-arg.rs:22:14
    |
 LL |     format!("{} {value} {} {}", 1, value=2);
-   |                            ^^
-   |
-   = note: positional arguments are zero-based
+   |              ^^         ^^ ^^   -        -
 
-error: invalid reference to positional arguments 3, 4 and 5 (there are 3 arguments)
-  --> $DIR/ifmt-bad-arg.rs:24:38
+error: 6 positional arguments in format string, but there are 3 arguments
+  --> $DIR/ifmt-bad-arg.rs:24:29
    |
 LL |     format!("{name} {value} {} {} {} {} {} {}", 0, name=1, value=2);
-   |                                      ^^ ^^ ^^
-   |
-   = note: positional arguments are zero-based
+   |                             ^^ ^^ ^^ ^^ ^^ ^^   -       -        -
 
 error: multiple unused formatting arguments
   --> $DIR/ifmt-bad-arg.rs:32:17
@@ -191,33 +187,26 @@ error: 4 positional arguments in format string, but there are 3 arguments
    |
 LL |     println!("{} {:.*} {}", 1, 3.2, 4);
    |               ^^ ^^--^ ^^   -  ---  -
-   |                    |           |
-   |                    |           this parameter corresponds to the precision flag
+   |                    |
    |                    this precision flag adds an extra required argument at position 1, which is why there are 4 arguments expected
    |
    = note: positional arguments are zero-based
    = note: for information about formatting flags, visit https://doc.rust-lang.org/std/fmt/index.html
 
-error: 4 positional arguments in format string, but there are 3 arguments
-  --> $DIR/ifmt-bad-arg.rs:81:15
+error: invalid reference to positional arguments 3 and 7 (there are 3 arguments)
+  --> $DIR/ifmt-bad-arg.rs:81:21
    |
 LL |     println!("{} {:07$.*} {}", 1, 3.2, 4);
-   |               ^^ ^^^----^ ^^   -  ---  -
-   |                     | |           |
-   |                     | |           this parameter corresponds to the precision flag
-   |                     | this precision flag adds an extra required argument at position 1, which is why there are 4 arguments expected
-   |                     this width flag expects an `usize` argument at position 7, but there are 3 arguments
+   |                     ^^     ^
    |
    = note: positional arguments are zero-based
    = note: for information about formatting flags, visit https://doc.rust-lang.org/std/fmt/index.html
 
 error: invalid reference to positional argument 7 (there are 3 arguments)
-  --> $DIR/ifmt-bad-arg.rs:84:18
+  --> $DIR/ifmt-bad-arg.rs:84:21
    |
 LL |     println!("{} {:07$} {}", 1, 3.2, 4);
-   |                  ^^^--^
-   |                     |
-   |                     this width flag expects an `usize` argument at position 7, but there are 3 arguments
+   |                     ^^
    |
    = note: positional arguments are zero-based
    = note: for information about formatting flags, visit https://doc.rust-lang.org/std/fmt/index.html
@@ -240,24 +229,19 @@ LL |     println!("{:foo}", 1);
            - `X`, which uses the `UpperHex` trait
 
 error: invalid reference to positional arguments 4, 5, 6 and 7 (there is 1 argument)
-  --> $DIR/ifmt-bad-arg.rs:87:15
+  --> $DIR/ifmt-bad-arg.rs:87:16
    |
 LL |     println!("{5} {:4$} {6:7$}", 1);
-   |               ^^^ ^^--^ ^^^--^
-   |                     |      |
-   |                     |      this width flag expects an `usize` argument at position 7, but there is 1 argument
-   |                     this width flag expects an `usize` argument at position 4, but there is 1 argument
+   |                ^    ^^   ^ ^^
    |
    = note: positional arguments are zero-based
    = note: for information about formatting flags, visit https://doc.rust-lang.org/std/fmt/index.html
 
 error: invalid reference to positional argument 0 (no arguments were given)
-  --> $DIR/ifmt-bad-arg.rs:90:15
+  --> $DIR/ifmt-bad-arg.rs:90:20
    |
 LL |     println!("{foo:0$}");
-   |               ^^^^^--^
-   |                    |
-   |                    this width flag expects an `usize` argument at position 0, but no arguments were given
+   |                    ^^
    |
    = note: positional arguments are zero-based
    = note: for information about formatting flags, visit https://doc.rust-lang.org/std/fmt/index.html
@@ -318,10 +302,10 @@ error[E0308]: mismatched types
   --> $DIR/ifmt-bad-arg.rs:78:32
    |
 LL |     println!("{} {:.*} {}", 1, 3.2, 4);
-   |     ---------------------------^^^----
-   |     |                          |
-   |     |                          expected `usize`, found floating-point number
-   |     arguments to this function are incorrect
+   |                                ^^^
+   |                                |
+   |                                expected `usize`, found floating-point number
+   |                                arguments to this function are incorrect
    |
    = note: expected reference `&usize`
               found reference `&{float}`
@@ -336,10 +320,10 @@ error[E0308]: mismatched types
   --> $DIR/ifmt-bad-arg.rs:81:35
    |
 LL |     println!("{} {:07$.*} {}", 1, 3.2, 4);
-   |     ------------------------------^^^----
-   |     |                             |
-   |     |                             expected `usize`, found floating-point number
-   |     arguments to this function are incorrect
+   |                                   ^^^
+   |                                   |
+   |                                   expected `usize`, found floating-point number
+   |                                   arguments to this function are incorrect
    |
    = note: expected reference `&usize`
               found reference `&{float}`
diff --git a/src/test/ui/issues/issue-75307.rs b/src/test/ui/issues/issue-75307.rs
index 2fe112a3b95d4..cffa6bea8ed38 100644
--- a/src/test/ui/issues/issue-75307.rs
+++ b/src/test/ui/issues/issue-75307.rs
@@ -1,3 +1,3 @@
 fn main() {
-    format!(r"{}{}{}", named_arg=1); //~ ERROR invalid reference to positional arguments 1 and 2
+    format!(r"{}{}{}", named_arg=1); //~ ERROR 3 positional arguments in format string, but there is 1 argument
 }
diff --git a/src/test/ui/issues/issue-75307.stderr b/src/test/ui/issues/issue-75307.stderr
index 10c952006c208..c5b0b11e7d099 100644
--- a/src/test/ui/issues/issue-75307.stderr
+++ b/src/test/ui/issues/issue-75307.stderr
@@ -1,10 +1,8 @@
-error: invalid reference to positional arguments 1 and 2 (there is 1 argument)
-  --> $DIR/issue-75307.rs:2:17
+error: 3 positional arguments in format string, but there is 1 argument
+  --> $DIR/issue-75307.rs:2:15
    |
 LL |     format!(r"{}{}{}", named_arg=1);
-   |                 ^^^^
-   |
-   = note: positional arguments are zero-based
+   |               ^^^^^^             -
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/macros/issue-99265.stderr b/src/test/ui/macros/issue-99265.stderr
index 2bfeedd7d0737..9185dbff61ee0 100644
--- a/src/test/ui/macros/issue-99265.stderr
+++ b/src/test/ui/macros/issue-99265.stderr
@@ -77,18 +77,18 @@ help: use the named argument by name to avoid ambiguity
 LL |     println!("Hello {:width$}!", "x", width = 5);
    |                       ~~~~~~
 
-warning: named argument `width` is not used by name
-  --> $DIR/issue-99265.rs:23:46
+warning: named argument `f` is not used by name
+  --> $DIR/issue-99265.rs:23:33
    |
 LL |     println!("Hello {:1$.2$}!", f = 0.02f32, width = 5, precision = 2);
-   |                       --                     ^^^^^ this named argument is referred to by position in formatting string
-   |                       |
-   |                       this formatting argument uses named argument `width` by position
+   |                     --------    ^ this named argument is referred to by position in formatting string
+   |                     |
+   |                     this formatting argument uses named argument `f` by position
    |
 help: use the named argument by name to avoid ambiguity
    |
-LL |     println!("Hello {:width$.2$}!", f = 0.02f32, width = 5, precision = 2);
-   |                       ~~~~~~
+LL |     println!("Hello {f:1$.2$}!", f = 0.02f32, width = 5, precision = 2);
+   |                      +
 
 warning: named argument `precision` is not used by name
   --> $DIR/issue-99265.rs:23:57
@@ -103,31 +103,31 @@ help: use the named argument by name to avoid ambiguity
 LL |     println!("Hello {:1$.precision$}!", f = 0.02f32, width = 5, precision = 2);
    |                          ~~~~~~~~~~
 
-warning: named argument `f` is not used by name
-  --> $DIR/issue-99265.rs:23:33
+warning: named argument `width` is not used by name
+  --> $DIR/issue-99265.rs:23:46
    |
 LL |     println!("Hello {:1$.2$}!", f = 0.02f32, width = 5, precision = 2);
-   |                     --          ^ this named argument is referred to by position in formatting string
-   |                     |
-   |                     this formatting argument uses named argument `f` by position
+   |                       --                     ^^^^^ this named argument is referred to by position in formatting string
+   |                       |
+   |                       this formatting argument uses named argument `width` by position
    |
 help: use the named argument by name to avoid ambiguity
    |
-LL |     println!("Hello {f:1$.2$}!", f = 0.02f32, width = 5, precision = 2);
-   |                      +
+LL |     println!("Hello {:width$.2$}!", f = 0.02f32, width = 5, precision = 2);
+   |                       ~~~~~~
 
-warning: named argument `width` is not used by name
-  --> $DIR/issue-99265.rs:31:47
+warning: named argument `f` is not used by name
+  --> $DIR/issue-99265.rs:31:34
    |
 LL |     println!("Hello {0:1$.2$}!", f = 0.02f32, width = 5, precision = 2);
-   |                        --                     ^^^^^ this named argument is referred to by position in formatting string
-   |                        |
-   |                        this formatting argument uses named argument `width` by position
+   |                     ---------    ^ this named argument is referred to by position in formatting string
+   |                     |
+   |                     this formatting argument uses named argument `f` by position
    |
 help: use the named argument by name to avoid ambiguity
    |
-LL |     println!("Hello {0:width$.2$}!", f = 0.02f32, width = 5, precision = 2);
-   |                        ~~~~~~
+LL |     println!("Hello {f:1$.2$}!", f = 0.02f32, width = 5, precision = 2);
+   |                      ~
 
 warning: named argument `precision` is not used by name
   --> $DIR/issue-99265.rs:31:58
@@ -142,32 +142,32 @@ help: use the named argument by name to avoid ambiguity
 LL |     println!("Hello {0:1$.precision$}!", f = 0.02f32, width = 5, precision = 2);
    |                           ~~~~~~~~~~
 
-warning: named argument `f` is not used by name
-  --> $DIR/issue-99265.rs:31:34
+warning: named argument `width` is not used by name
+  --> $DIR/issue-99265.rs:31:47
    |
 LL |     println!("Hello {0:1$.2$}!", f = 0.02f32, width = 5, precision = 2);
-   |                      -           ^ this named argument is referred to by position in formatting string
-   |                      |
-   |                      this formatting argument uses named argument `f` by position
+   |                        --                     ^^^^^ this named argument is referred to by position in formatting string
+   |                        |
+   |                        this formatting argument uses named argument `width` by position
    |
 help: use the named argument by name to avoid ambiguity
    |
-LL |     println!("Hello {f:1$.2$}!", f = 0.02f32, width = 5, precision = 2);
-   |                      ~
+LL |     println!("Hello {0:width$.2$}!", f = 0.02f32, width = 5, precision = 2);
+   |                        ~~~~~~
 
-warning: named argument `width` is not used by name
-  --> $DIR/issue-99265.rs:52:9
+warning: named argument `f` is not used by name
+  --> $DIR/issue-99265.rs:49:9
    |
 LL |         "{}, Hello {1:2$.3$} {4:5$.6$}! {1}",
-   |                       -- this formatting argument uses named argument `width` by position
+   |                    --------- this formatting argument uses named argument `f` by position
 ...
-LL |         width = 5,
-   |         ^^^^^ this named argument is referred to by position in formatting string
+LL |         f = 0.02f32,
+   |         ^ this named argument is referred to by position in formatting string
    |
 help: use the named argument by name to avoid ambiguity
    |
-LL |         "{}, Hello {1:width$.3$} {4:5$.6$}! {1}",
-   |                       ~~~~~~
+LL |         "{}, Hello {f:2$.3$} {4:5$.6$}! {1}",
+   |                     ~
 
 warning: named argument `precision` is not used by name
   --> $DIR/issue-99265.rs:54:9
@@ -183,33 +183,33 @@ help: use the named argument by name to avoid ambiguity
 LL |         "{}, Hello {1:2$.precision$} {4:5$.6$}! {1}",
    |                          ~~~~~~~~~~
 
-warning: named argument `f` is not used by name
-  --> $DIR/issue-99265.rs:49:9
+warning: named argument `width` is not used by name
+  --> $DIR/issue-99265.rs:52:9
    |
 LL |         "{}, Hello {1:2$.3$} {4:5$.6$}! {1}",
-   |                     - this formatting argument uses named argument `f` by position
+   |                       -- this formatting argument uses named argument `width` by position
 ...
-LL |         f = 0.02f32,
-   |         ^ this named argument is referred to by position in formatting string
+LL |         width = 5,
+   |         ^^^^^ this named argument is referred to by position in formatting string
    |
 help: use the named argument by name to avoid ambiguity
    |
-LL |         "{}, Hello {f:2$.3$} {4:5$.6$}! {1}",
-   |                     ~
+LL |         "{}, Hello {1:width$.3$} {4:5$.6$}! {1}",
+   |                       ~~~~~~
 
-warning: named argument `width2` is not used by name
-  --> $DIR/issue-99265.rs:58:9
+warning: named argument `g` is not used by name
+  --> $DIR/issue-99265.rs:56:9
    |
 LL |         "{}, Hello {1:2$.3$} {4:5$.6$}! {1}",
-   |                                 -- this formatting argument uses named argument `width2` by position
+   |                              --------- this formatting argument uses named argument `g` by position
 ...
-LL |         width2 = 5,
-   |         ^^^^^^ this named argument is referred to by position in formatting string
+LL |         g = 0.02f32,
+   |         ^ this named argument is referred to by position in formatting string
    |
 help: use the named argument by name to avoid ambiguity
    |
-LL |         "{}, Hello {1:2$.3$} {4:width2$.6$}! {1}",
-   |                                 ~~~~~~~
+LL |         "{}, Hello {1:2$.3$} {g:5$.6$}! {1}",
+   |                               ~
 
 warning: named argument `precision2` is not used by name
   --> $DIR/issue-99265.rs:60:9
@@ -225,25 +225,25 @@ help: use the named argument by name to avoid ambiguity
 LL |         "{}, Hello {1:2$.3$} {4:5$.precision2$}! {1}",
    |                                    ~~~~~~~~~~~
 
-warning: named argument `g` is not used by name
-  --> $DIR/issue-99265.rs:56:9
+warning: named argument `width2` is not used by name
+  --> $DIR/issue-99265.rs:58:9
    |
 LL |         "{}, Hello {1:2$.3$} {4:5$.6$}! {1}",
-   |                               - this formatting argument uses named argument `g` by position
+   |                                 -- this formatting argument uses named argument `width2` by position
 ...
-LL |         g = 0.02f32,
-   |         ^ this named argument is referred to by position in formatting string
+LL |         width2 = 5,
+   |         ^^^^^^ this named argument is referred to by position in formatting string
    |
 help: use the named argument by name to avoid ambiguity
    |
-LL |         "{}, Hello {1:2$.3$} {g:5$.6$}! {1}",
-   |                               ~
+LL |         "{}, Hello {1:2$.3$} {4:width2$.6$}! {1}",
+   |                                 ~~~~~~~
 
 warning: named argument `f` is not used by name
   --> $DIR/issue-99265.rs:49:9
    |
 LL |         "{}, Hello {1:2$.3$} {4:5$.6$}! {1}",
-   |                                          - this formatting argument uses named argument `f` by position
+   |                                         --- this formatting argument uses named argument `f` by position
 ...
 LL |         f = 0.02f32,
    |         ^ this named argument is referred to by position in formatting string
@@ -257,7 +257,7 @@ warning: named argument `f` is not used by name
   --> $DIR/issue-99265.rs:64:31
    |
 LL |     println!("Hello {:0.1}!", f = 0.02f32);
-   |                     --        ^ this named argument is referred to by position in formatting string
+   |                     ------    ^ this named argument is referred to by position in formatting string
    |                     |
    |                     this formatting argument uses named argument `f` by position
    |
@@ -270,15 +270,28 @@ warning: named argument `f` is not used by name
   --> $DIR/issue-99265.rs:68:32
    |
 LL |     println!("Hello {0:0.1}!", f = 0.02f32);
-   |                      -         ^ this named argument is referred to by position in formatting string
-   |                      |
-   |                      this formatting argument uses named argument `f` by position
+   |                     -------    ^ this named argument is referred to by position in formatting string
+   |                     |
+   |                     this formatting argument uses named argument `f` by position
    |
 help: use the named argument by name to avoid ambiguity
    |
 LL |     println!("Hello {f:0.1}!", f = 0.02f32);
    |                      ~
 
+warning: named argument `v` is not used by name
+  --> $DIR/issue-99265.rs:79:23
+   |
+LL |     println!("{:0$}", v = val);
+   |               -----   ^ this named argument is referred to by position in formatting string
+   |               |
+   |               this formatting argument uses named argument `v` by position
+   |
+help: use the named argument by name to avoid ambiguity
+   |
+LL |     println!("{v:0$}", v = val);
+   |                +
+
 warning: named argument `v` is not used by name
   --> $DIR/issue-99265.rs:79:23
    |
@@ -293,17 +306,17 @@ LL |     println!("{:v$}", v = val);
    |                 ~~
 
 warning: named argument `v` is not used by name
-  --> $DIR/issue-99265.rs:79:23
+  --> $DIR/issue-99265.rs:84:24
    |
-LL |     println!("{:0$}", v = val);
-   |               --      ^ this named argument is referred to by position in formatting string
+LL |     println!("{0:0$}", v = val);
+   |               ------   ^ this named argument is referred to by position in formatting string
    |               |
    |               this formatting argument uses named argument `v` by position
    |
 help: use the named argument by name to avoid ambiguity
    |
 LL |     println!("{v:0$}", v = val);
-   |                +
+   |                ~
 
 warning: named argument `v` is not used by name
   --> $DIR/issue-99265.rs:84:24
@@ -318,31 +331,18 @@ help: use the named argument by name to avoid ambiguity
 LL |     println!("{0:v$}", v = val);
    |                  ~~
 
-warning: named argument `v` is not used by name
-  --> $DIR/issue-99265.rs:84:24
-   |
-LL |     println!("{0:0$}", v = val);
-   |                -       ^ this named argument is referred to by position in formatting string
-   |                |
-   |                this formatting argument uses named argument `v` by position
-   |
-help: use the named argument by name to avoid ambiguity
-   |
-LL |     println!("{v:0$}", v = val);
-   |                ~
-
 warning: named argument `v` is not used by name
   --> $DIR/issue-99265.rs:89:26
    |
 LL |     println!("{:0$.0$}", v = val);
-   |                 --       ^ this named argument is referred to by position in formatting string
-   |                 |
-   |                 this formatting argument uses named argument `v` by position
+   |               --------   ^ this named argument is referred to by position in formatting string
+   |               |
+   |               this formatting argument uses named argument `v` by position
    |
 help: use the named argument by name to avoid ambiguity
    |
-LL |     println!("{:v$.0$}", v = val);
-   |                 ~~
+LL |     println!("{v:0$.0$}", v = val);
+   |                +
 
 warning: named argument `v` is not used by name
   --> $DIR/issue-99265.rs:89:26
@@ -361,27 +361,27 @@ warning: named argument `v` is not used by name
   --> $DIR/issue-99265.rs:89:26
    |
 LL |     println!("{:0$.0$}", v = val);
-   |               --         ^ this named argument is referred to by position in formatting string
-   |               |
-   |               this formatting argument uses named argument `v` by position
+   |                 --       ^ this named argument is referred to by position in formatting string
+   |                 |
+   |                 this formatting argument uses named argument `v` by position
    |
 help: use the named argument by name to avoid ambiguity
    |
-LL |     println!("{v:0$.0$}", v = val);
-   |                +
+LL |     println!("{:v$.0$}", v = val);
+   |                 ~~
 
 warning: named argument `v` is not used by name
   --> $DIR/issue-99265.rs:96:27
    |
 LL |     println!("{0:0$.0$}", v = val);
-   |                  --       ^ this named argument is referred to by position in formatting string
-   |                  |
-   |                  this formatting argument uses named argument `v` by position
+   |               ---------   ^ this named argument is referred to by position in formatting string
+   |               |
+   |               this formatting argument uses named argument `v` by position
    |
 help: use the named argument by name to avoid ambiguity
    |
-LL |     println!("{0:v$.0$}", v = val);
-   |                  ~~
+LL |     println!("{v:0$.0$}", v = val);
+   |                ~
 
 warning: named argument `v` is not used by name
   --> $DIR/issue-99265.rs:96:27
@@ -400,14 +400,14 @@ warning: named argument `v` is not used by name
   --> $DIR/issue-99265.rs:96:27
    |
 LL |     println!("{0:0$.0$}", v = val);
-   |                -          ^ this named argument is referred to by position in formatting string
-   |                |
-   |                this formatting argument uses named argument `v` by position
+   |                  --       ^ this named argument is referred to by position in formatting string
+   |                  |
+   |                  this formatting argument uses named argument `v` by position
    |
 help: use the named argument by name to avoid ambiguity
    |
-LL |     println!("{v:0$.0$}", v = val);
-   |                ~
+LL |     println!("{0:v$.0$}", v = val);
+   |                  ~~
 
 warning: named argument `a` is not used by name
   --> $DIR/issue-99265.rs:104:28
@@ -426,28 +426,28 @@ warning: named argument `a` is not used by name
   --> $DIR/issue-99265.rs:104:28
    |
 LL |     println!("{} {a} {0}", a = 1);
-   |                       -    ^ this named argument is referred to by position in formatting string
-   |                       |
-   |                       this formatting argument uses named argument `a` by position
+   |                      ---   ^ this named argument is referred to by position in formatting string
+   |                      |
+   |                      this formatting argument uses named argument `a` by position
    |
 help: use the named argument by name to avoid ambiguity
    |
 LL |     println!("{} {a} {a}", a = 1);
    |                       ~
 
-warning: named argument `b` is not used by name
-  --> $DIR/issue-99265.rs:115:23
+warning: named argument `a` is not used by name
+  --> $DIR/issue-99265.rs:115:14
    |
 LL |                 {:1$.2$}",
-   |                   -- this formatting argument uses named argument `b` by position
+   |                 -------- this formatting argument uses named argument `a` by position
 ...
 LL |              a = 1.0, b = 1, c = 2,
-   |                       ^ this named argument is referred to by position in formatting string
+   |              ^ this named argument is referred to by position in formatting string
    |
 help: use the named argument by name to avoid ambiguity
    |
-LL |                 {:b$.2$}",
-   |                   ~~
+LL |                 {a:1$.2$}",
+   |                  +
 
 warning: named argument `c` is not used by name
   --> $DIR/issue-99265.rs:115:30
@@ -463,33 +463,33 @@ help: use the named argument by name to avoid ambiguity
 LL |                 {:1$.c$}",
    |                      ~~
 
-warning: named argument `a` is not used by name
-  --> $DIR/issue-99265.rs:115:14
+warning: named argument `b` is not used by name
+  --> $DIR/issue-99265.rs:115:23
    |
 LL |                 {:1$.2$}",
-   |                 -- this formatting argument uses named argument `a` by position
+   |                   -- this formatting argument uses named argument `b` by position
 ...
 LL |              a = 1.0, b = 1, c = 2,
-   |              ^ this named argument is referred to by position in formatting string
+   |                       ^ this named argument is referred to by position in formatting string
    |
 help: use the named argument by name to avoid ambiguity
    |
-LL |                 {a:1$.2$}",
-   |                  +
+LL |                 {:b$.2$}",
+   |                   ~~
 
-warning: named argument `b` is not used by name
-  --> $DIR/issue-99265.rs:126:23
+warning: named argument `a` is not used by name
+  --> $DIR/issue-99265.rs:126:14
    |
 LL |                 {0:1$.2$}",
-   |                    -- this formatting argument uses named argument `b` by position
+   |                 --------- this formatting argument uses named argument `a` by position
 ...
 LL |              a = 1.0, b = 1, c = 2,
-   |                       ^ this named argument is referred to by position in formatting string
+   |              ^ this named argument is referred to by position in formatting string
    |
 help: use the named argument by name to avoid ambiguity
    |
-LL |                 {0:b$.2$}",
-   |                    ~~
+LL |                 {a:1$.2$}",
+   |                  ~
 
 warning: named argument `c` is not used by name
   --> $DIR/issue-99265.rs:126:30
@@ -505,32 +505,32 @@ help: use the named argument by name to avoid ambiguity
 LL |                 {0:1$.c$}",
    |                       ~~
 
-warning: named argument `a` is not used by name
-  --> $DIR/issue-99265.rs:126:14
+warning: named argument `b` is not used by name
+  --> $DIR/issue-99265.rs:126:23
    |
 LL |                 {0:1$.2$}",
-   |                  - this formatting argument uses named argument `a` by position
+   |                    -- this formatting argument uses named argument `b` by position
 ...
 LL |              a = 1.0, b = 1, c = 2,
-   |              ^ this named argument is referred to by position in formatting string
+   |                       ^ this named argument is referred to by position in formatting string
    |
 help: use the named argument by name to avoid ambiguity
    |
-LL |                 {a:1$.2$}",
-   |                  ~
+LL |                 {0:b$.2$}",
+   |                    ~~
 
-warning: named argument `width` is not used by name
-  --> $DIR/issue-99265.rs:132:39
+warning: named argument `x` is not used by name
+  --> $DIR/issue-99265.rs:132:30
    |
 LL |     println!("{{{:1$.2$}}}", x = 1.0, width = 3, precision = 2);
-   |                   --                  ^^^^^ this named argument is referred to by position in formatting string
-   |                   |
-   |                   this formatting argument uses named argument `width` by position
+   |                 --------     ^ this named argument is referred to by position in formatting string
+   |                 |
+   |                 this formatting argument uses named argument `x` by position
    |
 help: use the named argument by name to avoid ambiguity
    |
-LL |     println!("{{{:width$.2$}}}", x = 1.0, width = 3, precision = 2);
-   |                   ~~~~~~
+LL |     println!("{{{x:1$.2$}}}", x = 1.0, width = 3, precision = 2);
+   |                  +
 
 warning: named argument `precision` is not used by name
   --> $DIR/issue-99265.rs:132:50
@@ -545,18 +545,18 @@ help: use the named argument by name to avoid ambiguity
 LL |     println!("{{{:1$.precision$}}}", x = 1.0, width = 3, precision = 2);
    |                      ~~~~~~~~~~
 
-warning: named argument `x` is not used by name
-  --> $DIR/issue-99265.rs:132:30
+warning: named argument `width` is not used by name
+  --> $DIR/issue-99265.rs:132:39
    |
 LL |     println!("{{{:1$.2$}}}", x = 1.0, width = 3, precision = 2);
-   |                 --           ^ this named argument is referred to by position in formatting string
-   |                 |
-   |                 this formatting argument uses named argument `x` by position
+   |                   --                  ^^^^^ this named argument is referred to by position in formatting string
+   |                   |
+   |                   this formatting argument uses named argument `width` by position
    |
 help: use the named argument by name to avoid ambiguity
    |
-LL |     println!("{{{x:1$.2$}}}", x = 1.0, width = 3, precision = 2);
-   |                  +
+LL |     println!("{{{:width$.2$}}}", x = 1.0, width = 3, precision = 2);
+   |                   ~~~~~~
 
 warning: 42 warnings emitted
 
diff --git a/src/test/ui/macros/issue-99907.stderr b/src/test/ui/macros/issue-99907.stderr
index 4786ce003b4c2..eefb28dee35b8 100644
--- a/src/test/ui/macros/issue-99907.stderr
+++ b/src/test/ui/macros/issue-99907.stderr
@@ -2,7 +2,7 @@ warning: named argument `f` is not used by name
   --> $DIR/issue-99907.rs:5:30
    |
 LL |     println!("Hello {:.1}!", f = 0.02f32);
-   |                     --       ^ this named argument is referred to by position in formatting string
+   |                     -----    ^ this named argument is referred to by position in formatting string
    |                     |
    |                     this formatting argument uses named argument `f` by position
    |
@@ -16,7 +16,7 @@ warning: named argument `f` is not used by name
   --> $DIR/issue-99907.rs:9:31
    |
 LL |     println!("Hello {:1.1}!", f = 0.02f32);
-   |                     --        ^ this named argument is referred to by position in formatting string
+   |                     ------    ^ this named argument is referred to by position in formatting string
    |                     |
    |                     this formatting argument uses named argument `f` by position
    |

From 8efc383047460f20c6061d2e075f202dcfa92a79 Mon Sep 17 00:00:00 2001
From: Mara Bos 
Date: Fri, 26 Aug 2022 19:13:17 +0200
Subject: [PATCH 299/586] Move FormatArgs structure to its own module.

---
 compiler/rustc_builtin_macros/src/format.rs   | 176 ++----------------
 .../rustc_builtin_macros/src/format/ast.rs    | 159 ++++++++++++++++
 2 files changed, 172 insertions(+), 163 deletions(-)
 create mode 100644 compiler/rustc_builtin_macros/src/format/ast.rs

diff --git a/compiler/rustc_builtin_macros/src/format.rs b/compiler/rustc_builtin_macros/src/format.rs
index 06a831e36692e..42a413210c764 100644
--- a/compiler/rustc_builtin_macros/src/format.rs
+++ b/compiler/rustc_builtin_macros/src/format.rs
@@ -1,7 +1,7 @@
-use rustc_ast as ast;
 use rustc_ast::ptr::P;
 use rustc_ast::token;
 use rustc_ast::tokenstream::TokenStream;
+use rustc_ast::Expr;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::{pluralize, Applicability, MultiSpan, PResult};
 use rustc_expand::base::{self, *};
@@ -12,6 +12,9 @@ use rustc_span::{BytePos, InnerSpan, Span};
 use rustc_lint_defs::builtin::NAMED_ARGUMENTS_USED_POSITIONALLY;
 use rustc_lint_defs::{BufferedEarlyLint, BuiltinLintDiagnostics, LintId};
 
+mod ast;
+use ast::*;
+
 mod expand;
 use expand::expand_parsed_format_args;
 
@@ -23,160 +26,7 @@ use expand::expand_parsed_format_args;
 //  3. Finally, `expand_parsed_format_args` will turn that `FormatArgs` structure
 //     into the expression that the macro expands to.
 
-// Definitions:
-//
-// format_args!("hello {abc:.xyz$}!!", abc="world");
-// └──────────────────────────────────────────────┘
-//                     FormatArgs
-//
-// format_args!("hello {abc:.xyz$}!!", abc="world");
-//                                     └─────────┘
-//                                      argument
-//
-// format_args!("hello {abc:.xyz$}!!", abc="world");
-//              └───────────────────┘
-//                     template
-//
-// format_args!("hello {abc:.xyz$}!!", abc="world");
-//               └────┘└─────────┘└┘
-//                      pieces
-//
-// format_args!("hello {abc:.xyz$}!!", abc="world");
-//               └────┘           └┘
-//                   literal pieces
-//
-// format_args!("hello {abc:.xyz$}!!", abc="world");
-//                     └─────────┘
-//                     placeholder
-//
-// format_args!("hello {abc:.xyz$}!!", abc="world");
-//                      └─┘  └─┘
-//                      positions (could be names, numbers, empty, or `*`)
-
-/// (Parsed) format args.
-///
-/// Basically the "AST" for a complete `format_args!()`.
-///
-/// E.g., `format_args!("hello {name}");`.
-#[derive(Clone, Debug)]
-pub struct FormatArgs {
-    pub span: Span,
-    pub template: Vec,
-    pub arguments: Vec<(P, FormatArgKind)>,
-}
-
-#[derive(Clone, Debug)]
-pub enum FormatArgsPiece {
-    Literal(Symbol),
-    Placeholder(FormatPlaceholder),
-}
-
-#[derive(Clone, Debug)]
-pub enum FormatArgKind {
-    /// `format_args(…, arg)`
-    Normal,
-    /// `format_args(…, arg = 1)`
-    Named(Ident),
-    /// `format_args("… {arg} …")`
-    Captured(Ident),
-}
-
-impl FormatArgKind {
-    pub fn ident(&self) -> Option {
-        match self {
-            &Self::Normal => None,
-            &Self::Named(id) => Some(id),
-            &Self::Captured(id) => Some(id),
-        }
-    }
-}
-
-#[derive(Clone, Debug, PartialEq, Eq)]
-pub struct FormatPlaceholder {
-    /// Index into [`FormatArgs::arguments`].
-    pub argument: FormatArgPosition,
-    /// The span inside the format string for the full `{…}` placeholder.
-    pub span: Option,
-    /// `{}`, `{:?}`, or `{:x}`, etc.
-    pub format_trait: FormatTrait,
-    /// `{}` or `{:.5}` or `{:-^20}`, etc.
-    pub format_options: FormatOptions,
-}
-
-#[derive(Clone, Debug, PartialEq, Eq)]
-pub struct FormatArgPosition {
-    /// Which argument this position refers to (Ok),
-    /// or would've referred to if it existed (Err).
-    pub index: Result,
-    /// What kind of position this is. See [`FormatArgsPositionKind`].
-    pub kind: FormatArgPositionKind,
-    /// The span of the name or number.
-    pub span: Option,
-}
-
-#[derive(Copy, Clone, Debug, PartialEq, Eq)]
-pub enum FormatArgPositionKind {
-    /// `{}` or `{.*}`
-    Implicit,
-    /// `{1}` or `{:1$}` or `{:.1$}`
-    Number,
-    /// `{a}` or `{:a$}` or `{:.a$}`
-    Named,
-}
-
-#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
-pub enum FormatTrait {
-    /// `{}`
-    Display,
-    /// `{:?}`
-    Debug,
-    /// `{:e}`
-    LowerExp,
-    /// `{:E}`
-    UpperExp,
-    /// `{:o}`
-    Octal,
-    /// `{:p}`
-    Pointer,
-    /// `{:b}`
-    Binary,
-    /// `{:x}`
-    LowerHex,
-    /// `{:X}`
-    UpperHex,
-}
-
-#[derive(Clone, Debug, Default, PartialEq, Eq)]
-pub struct FormatOptions {
-    /// The width. E.g. `{:5}` or `{:width$}`.
-    pub width: Option,
-    /// The precision. E.g. `{:.5}` or `{:.precision$}`.
-    pub precision: Option,
-    /// The alignment. E.g. `{:>}` or `{:<}` or `{:^}`.
-    pub alignment: Option,
-    /// The fill character. E.g. the `.` in `{:.>10}`.
-    pub fill: Option,
-    /// The `+`, `-`, `0`, `#`, `x?` and `X?` flags.
-    pub flags: u32,
-}
-
-#[derive(Clone, Debug, PartialEq, Eq)]
-pub enum FormatAlignment {
-    /// `{:<}`
-    Left,
-    /// `{:>}`
-    Right,
-    /// `{:^}`
-    Center,
-}
-
-#[derive(Clone, Debug, PartialEq, Eq)]
-pub enum FormatCount {
-    /// `{:0}` or `{:.0}`
-    Literal(usize),
-    /// `{:.*}`, `{:.0$}`, or `{:a$}`, etc.
-    Argument(FormatArgPosition),
-}
+// See format/ast.rs forthe FormatArgs structure.
 
 // Only used in parse_args and report_invalid_references,
 // to indicate how a referred argument was used.
@@ -201,8 +51,8 @@ fn parse_args<'a>(
     ecx: &mut ExtCtxt<'a>,
     sp: Span,
     tts: TokenStream,
-) -> PResult<'a, (P, Vec<(P, FormatArgKind)>)> {
-    let mut args = Vec::<(P, FormatArgKind)>::new();
+) -> PResult<'a, (P, Vec<(P, FormatArgKind)>)> {
+    let mut args = Vec::<(P, FormatArgKind)>::new();
 
     let mut p = ecx.new_parser_from_tts(tts);
 
@@ -305,8 +155,8 @@ fn parse_args<'a>(
 
 pub fn make_format_args(
     ecx: &mut ExtCtxt<'_>,
-    efmt: P,
-    mut args: Vec<(P, FormatArgKind)>,
+    efmt: P,
+    mut args: Vec<(P, FormatArgKind)>,
     append_newline: bool,
 ) -> Result {
     let start_of_named_args =
@@ -341,8 +191,8 @@ pub fn make_format_args(
     };
 
     let str_style = match fmt_style {
-        ast::StrStyle::Cooked => None,
-        ast::StrStyle::Raw(raw) => Some(raw as usize),
+        rustc_ast::StrStyle::Cooked => None,
+        rustc_ast::StrStyle::Raw(raw) => Some(raw as usize),
     };
 
     let fmt_str = fmt_str.as_str(); // for the suggestions below
@@ -669,7 +519,7 @@ pub fn make_format_args(
             ecx.buffered_early_lint.push(BufferedEarlyLint {
                 span: arg_name.span.into(),
                 msg: format!("named argument `{}` is not used by name", arg_name.name).into(),
-                node_id: ast::CRATE_NODE_ID,
+                node_id: rustc_ast::CRATE_NODE_ID,
                 lint_id: LintId::of(&NAMED_ARGUMENTS_USED_POSITIONALLY),
                 diagnostic: BuiltinLintDiagnostics::NamedArgumentUsedPositionally {
                     position_sp_to_replace,
@@ -850,7 +700,7 @@ fn report_invalid_references(
     template: &[FormatArgsPiece],
     fmt_span: Span,
     num_explicit_args: usize,
-    args: &[(P, FormatArgKind)],
+    args: &[(P, FormatArgKind)],
     parser: parse::Parser<'_>,
 ) {
     let num_args_desc = match num_explicit_args {
diff --git a/compiler/rustc_builtin_macros/src/format/ast.rs b/compiler/rustc_builtin_macros/src/format/ast.rs
new file mode 100644
index 0000000000000..d6f72497acff8
--- /dev/null
+++ b/compiler/rustc_builtin_macros/src/format/ast.rs
@@ -0,0 +1,159 @@
+use rustc_ast::ptr::P;
+use rustc_ast::Expr;
+use rustc_span::symbol::{Ident, Symbol};
+use rustc_span::Span;
+
+// Definitions:
+//
+// format_args!("hello {abc:.xyz$}!!", abc="world");
+// └──────────────────────────────────────────────┘
+//                     FormatArgs
+//
+// format_args!("hello {abc:.xyz$}!!", abc="world");
+//                                     └─────────┘
+//                                      argument
+//
+// format_args!("hello {abc:.xyz$}!!", abc="world");
+//              └───────────────────┘
+//                     template
+//
+// format_args!("hello {abc:.xyz$}!!", abc="world");
+//               └────┘└─────────┘└┘
+//                      pieces
+//
+// format_args!("hello {abc:.xyz$}!!", abc="world");
+//               └────┘           └┘
+//                   literal pieces
+//
+// format_args!("hello {abc:.xyz$}!!", abc="world");
+//                     └─────────┘
+//                     placeholder
+//
+// format_args!("hello {abc:.xyz$}!!", abc="world");
+//                      └─┘  └─┘
+//                      positions (could be names, numbers, empty, or `*`)
+
+/// (Parsed) format args.
+///
+/// Basically the "AST" for a complete `format_args!()`.
+///
+/// E.g., `format_args!("hello {name}");`.
+#[derive(Clone, Debug)]
+pub struct FormatArgs {
+    pub span: Span,
+    pub template: Vec,
+    pub arguments: Vec<(P, FormatArgKind)>,
+}
+
+#[derive(Clone, Debug)]
+pub enum FormatArgsPiece {
+    Literal(Symbol),
+    Placeholder(FormatPlaceholder),
+}
+
+#[derive(Clone, Debug)]
+pub enum FormatArgKind {
+    /// `format_args(…, arg)`
+    Normal,
+    /// `format_args(…, arg = 1)`
+    Named(Ident),
+    /// `format_args("… {arg} …")`
+    Captured(Ident),
+}
+
+impl FormatArgKind {
+    pub fn ident(&self) -> Option {
+        match self {
+            &Self::Normal => None,
+            &Self::Named(id) => Some(id),
+            &Self::Captured(id) => Some(id),
+        }
+    }
+}
+
+#[derive(Clone, Debug, PartialEq, Eq)]
+pub struct FormatPlaceholder {
+    /// Index into [`FormatArgs::arguments`].
+    pub argument: FormatArgPosition,
+    /// The span inside the format string for the full `{…}` placeholder.
+    pub span: Option,
+    /// `{}`, `{:?}`, or `{:x}`, etc.
+    pub format_trait: FormatTrait,
+    /// `{}` or `{:.5}` or `{:-^20}`, etc.
+    pub format_options: FormatOptions,
+}
+
+#[derive(Clone, Debug, PartialEq, Eq)]
+pub struct FormatArgPosition {
+    /// Which argument this position refers to (Ok),
+    /// or would've referred to if it existed (Err).
+    pub index: Result,
+    /// What kind of position this is. See [`FormatArgsPositionKind`].
+    pub kind: FormatArgPositionKind,
+    /// The span of the name or number.
+    pub span: Option,
+}
+
+#[derive(Copy, Clone, Debug, PartialEq, Eq)]
+pub enum FormatArgPositionKind {
+    /// `{}` or `{.*}`
+    Implicit,
+    /// `{1}` or `{:1$}` or `{:.1$}`
+    Number,
+    /// `{a}` or `{:a$}` or `{:.a$}`
+    Named,
+}
+
+#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
+pub enum FormatTrait {
+    /// `{}`
+    Display,
+    /// `{:?}`
+    Debug,
+    /// `{:e}`
+    LowerExp,
+    /// `{:E}`
+    UpperExp,
+    /// `{:o}`
+    Octal,
+    /// `{:p}`
+    Pointer,
+    /// `{:b}`
+    Binary,
+    /// `{:x}`
+    LowerHex,
+    /// `{:X}`
+    UpperHex,
+}
+
+#[derive(Clone, Debug, Default, PartialEq, Eq)]
+pub struct FormatOptions {
+    /// The width. E.g. `{:5}` or `{:width$}`.
+    pub width: Option,
+    /// The precision. E.g. `{:.5}` or `{:.precision$}`.
+    pub precision: Option,
+    /// The alignment. E.g. `{:>}` or `{:<}` or `{:^}`.
+    pub alignment: Option,
+    /// The fill character. E.g. the `.` in `{:.>10}`.
+    pub fill: Option,
+    /// The `+`, `-`, `0`, `#`, `x?` and `X?` flags.
+    pub flags: u32,
+}
+
+#[derive(Clone, Debug, PartialEq, Eq)]
+pub enum FormatAlignment {
+    /// `{:<}`
+    Left,
+    /// `{:>}`
+    Right,
+    /// `{:^}`
+    Center,
+}
+
+#[derive(Clone, Debug, PartialEq, Eq)]
+pub enum FormatCount {
+    /// `{:0}` or `{:.0}`
+    Literal(usize),
+    /// `{:.*}`, `{:.0$}`, or `{:a$}`, etc.
+    Argument(FormatArgPosition),
+}

From 00074926bb3a6ed60b96b6b4c70e0d017ed33513 Mon Sep 17 00:00:00 2001
From: Mara Bos 
Date: Fri, 26 Aug 2022 22:56:21 +0200
Subject: [PATCH 300/586] Fix typo.

---
 compiler/rustc_builtin_macros/src/format/ast.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/compiler/rustc_builtin_macros/src/format/ast.rs b/compiler/rustc_builtin_macros/src/format/ast.rs
index d6f72497acff8..cc0a3b0b24447 100644
--- a/compiler/rustc_builtin_macros/src/format/ast.rs
+++ b/compiler/rustc_builtin_macros/src/format/ast.rs
@@ -88,7 +88,7 @@ pub struct FormatArgPosition {
     /// Which argument this position refers to (Ok),
     /// or would've referred to if it existed (Err).
     pub index: Result,
-    /// What kind of position this is. See [`FormatArgsPositionKind`].
+    /// What kind of position this is. See [`FormatArgPositionKind`].
     pub kind: FormatArgPositionKind,
     /// The span of the name or number.
     pub span: Option,

From ae238efe9184089d63fd68de4bb66a1d25eb5133 Mon Sep 17 00:00:00 2001
From: Mara Bos 
Date: Sat, 27 Aug 2022 17:51:28 +0200
Subject: [PATCH 301/586] Prefer new_v1_formatted instead of new_v1 with
 duplicates.

---
 .../rustc_builtin_macros/src/format/expand.rs | 69 +++++++++----------
 1 file changed, 33 insertions(+), 36 deletions(-)

diff --git a/compiler/rustc_builtin_macros/src/format/expand.rs b/compiler/rustc_builtin_macros/src/format/expand.rs
index d1c114a67ac1e..a2a8213dafc27 100644
--- a/compiler/rustc_builtin_macros/src/format/expand.rs
+++ b/compiler/rustc_builtin_macros/src/format/expand.rs
@@ -164,18 +164,32 @@ pub fn expand_parsed_format_args(ecx: &mut ExtCtxt<'_>, fmt: FormatArgs) -> P [(0, Display), (0, LowerHex), (1, Display)]
-        let mut argmap = FxIndexSet::default();
+    // Create a list of all _unique_ (argument, format trait) combinations.
+    // E.g. "{0} {0:x} {0} {1}" -> [(0, Display), (0, LowerHex), (1, Display)]
+    let mut argmap = FxIndexSet::default();
+    for piece in &fmt.template {
+        let FormatArgsPiece::Placeholder(placeholder) = piece else { continue };
+        if placeholder.format_options != Default::default() {
+            // Can't use basic form if there's any formatting options.
+            use_format_options = true;
+        }
+        if let Ok(index) = placeholder.argument.index {
+            if !argmap.insert((index, ArgumentType::Format(placeholder.format_trait))) {
+                // Duplicate (argument, format trait) combination,
+                // which we'll only put once in the args array.
+                use_format_options = true;
+            }
+        }
+    }
+
+    let format_options = use_format_options.then(|| {
         // Generate:
         //     &[format_spec_0, format_spec_1, format_spec_2]
-        let format_options = ecx.expr_array_ref(
+        ecx.expr_array_ref(
             macsp,
             fmt.template
                 .iter()
@@ -184,34 +198,18 @@ pub fn expand_parsed_format_args(ecx: &mut ExtCtxt<'_>, fmt: FormatArgs) -> P [(0, Display), (0, LowerHex), (0, Display), (1, Display)]
-        let args = fmt
-            .template
-            .iter()
-            .filter_map(|piece| {
-                let FormatArgsPiece::Placeholder(placeholder) = piece else { return None };
-                Some((
-                    placeholder.argument.index.ok()?,
-                    ArgumentType::Format(placeholder.format_trait),
-                ))
-            })
-            .collect();
-        (args, None)
-    };
+        )
+    });
 
     // If the args array contains exactly all the original arguments once,
     // in order, we can use a simple array instead of a `match` construction.
     // However, if there's a yield point in any argument except the first one,
     // we don't do this, because an ArgumentV1 cannot be kept across yield points.
-    let use_simple_array = args.len() == fmt.arguments.len()
-        && args.iter().enumerate().all(|(i, &(j, _))| i == j)
+    let use_simple_array = argmap.len() == fmt.arguments.len()
+        && argmap.iter().enumerate().all(|(i, &(j, _))| i == j)
         && fmt.arguments.iter().skip(1).all(|(arg, _)| !may_contain_yield_point(arg));
 
-    let args_expr = if use_simple_array {
+    let args = if use_simple_array {
         // Generate:
         //     &[
         //         ::core::fmt::ArgumentV1::new_display(&arg0),
@@ -222,7 +220,7 @@ pub fn expand_parsed_format_args(ecx: &mut ExtCtxt<'_>, fmt: FormatArgs) -> P, fmt: FormatArgs) -> P, fmt: FormatArgs) -> P, fmt: FormatArgs) -> P, fmt: FormatArgs) -> P
Date: Sat, 27 Aug 2022 18:32:20 +0200
Subject: [PATCH 302/586] Tweak comments.

---
 compiler/rustc_builtin_macros/src/format.rs     | 2 +-
 compiler/rustc_builtin_macros/src/format/ast.rs | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/compiler/rustc_builtin_macros/src/format.rs b/compiler/rustc_builtin_macros/src/format.rs
index 42a413210c764..7228b270698b2 100644
--- a/compiler/rustc_builtin_macros/src/format.rs
+++ b/compiler/rustc_builtin_macros/src/format.rs
@@ -26,7 +26,7 @@ use expand::expand_parsed_format_args;
 //  3. Finally, `expand_parsed_format_args` will turn that `FormatArgs` structure
 //     into the expression that the macro expands to.
 
-// See format/ast.rs forthe FormatArgs structure.
+// See format/ast.rs for the FormatArgs structure and glossary.
 
 // Only used in parse_args and report_invalid_references,
 // to indicate how a referred argument was used.
diff --git a/compiler/rustc_builtin_macros/src/format/ast.rs b/compiler/rustc_builtin_macros/src/format/ast.rs
index cc0a3b0b24447..cb76482fe5314 100644
--- a/compiler/rustc_builtin_macros/src/format/ast.rs
+++ b/compiler/rustc_builtin_macros/src/format/ast.rs
@@ -96,7 +96,7 @@ pub struct FormatArgPosition {
 
 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
 pub enum FormatArgPositionKind {
-    /// `{}` or `{.*}`
+    /// `{}` or `{:.*}`
     Implicit,
     /// `{1}` or `{:1$}` or `{:.1$}`
     Number,

From df7fd119d2ad54667cfe46a60db6f7fb799d4e90 Mon Sep 17 00:00:00 2001
From: Mara Bos 
Date: Tue, 30 Aug 2022 17:18:01 +0200
Subject: [PATCH 303/586] Use if let chain.

---
 compiler/rustc_builtin_macros/src/format.rs | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/compiler/rustc_builtin_macros/src/format.rs b/compiler/rustc_builtin_macros/src/format.rs
index 7228b270698b2..fe963a0ea3aa6 100644
--- a/compiler/rustc_builtin_macros/src/format.rs
+++ b/compiler/rustc_builtin_macros/src/format.rs
@@ -236,10 +236,8 @@ pub fn make_format_args(
         if let Some(note) = err.note {
             e.note(¬e);
         }
-        if let Some((label, span)) = err.secondary_label {
-            if is_literal {
-                e.span_label(fmt_span.from_inner(InnerSpan::new(span.start, span.end)), label);
-            }
+        if let Some((label, span)) = err.secondary_label && is_literal {
+            e.span_label(fmt_span.from_inner(InnerSpan::new(span.start, span.end)), label);
         }
         if err.should_be_replaced_with_positional_argument {
             let captured_arg_span =

From 15754f5ea155600c62b8f4893fae78c5af1b08b2 Mon Sep 17 00:00:00 2001
From: Mara Bos 
Date: Tue, 30 Aug 2022 17:18:09 +0200
Subject: [PATCH 304/586] Move enum definition closer to its usage.

---
 compiler/rustc_builtin_macros/src/format.rs | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/compiler/rustc_builtin_macros/src/format.rs b/compiler/rustc_builtin_macros/src/format.rs
index fe963a0ea3aa6..f7c7e00ab22bc 100644
--- a/compiler/rustc_builtin_macros/src/format.rs
+++ b/compiler/rustc_builtin_macros/src/format.rs
@@ -267,17 +267,17 @@ pub fn make_format_args(
         })
     };
 
+    let num_explicit_args = args.len();
+    let mut used = vec![false; num_explicit_args];
+    let mut invalid_refs = Vec::new();
+    let mut numeric_refences_to_named_arg = Vec::new();
+
     enum ArgRef<'a> {
         Index(usize),
         Name(&'a str, Option),
     }
     use ArgRef::*;
 
-    let num_explicit_args = args.len();
-    let mut used = vec![false; num_explicit_args];
-    let mut invalid_refs = Vec::new();
-    let mut numeric_refences_to_named_arg = Vec::new();
-
     let mut lookup_arg = |arg: ArgRef<'_>,
                           span: Option,
                           used_as: PositionUsedAs,

From 8d9a5881ea18568f014ea09ec9d2f1d0cdacff1b Mon Sep 17 00:00:00 2001
From: Mara Bos 
Date: Tue, 30 Aug 2022 17:21:41 +0200
Subject: [PATCH 305/586] Flatten if-let and match into one.

---
 compiler/rustc_builtin_macros/src/format.rs | 33 +++++++++------------
 1 file changed, 14 insertions(+), 19 deletions(-)

diff --git a/compiler/rustc_builtin_macros/src/format.rs b/compiler/rustc_builtin_macros/src/format.rs
index f7c7e00ab22bc..1dd913ac6d2f0 100644
--- a/compiler/rustc_builtin_macros/src/format.rs
+++ b/compiler/rustc_builtin_macros/src/format.rs
@@ -285,26 +285,21 @@ pub fn make_format_args(
      -> FormatArgPosition {
         let index = match arg {
             Index(index) => {
-                if let Some((_, arg_kind)) = args.get(index) {
-                    match arg_kind {
-                        FormatArgKind::Normal => {
-                            used[index] = true;
-                            Ok(index)
-                        }
-                        FormatArgKind::Named(_) => {
-                            used[index] = true;
-                            numeric_refences_to_named_arg.push((index, span, used_as));
-                            Ok(index)
-                        }
-                        FormatArgKind::Captured(_) => {
-                            // Doesn't exist as an explicit argument.
-                            invalid_refs.push((index, span, used_as, kind));
-                            Err(index)
-                        }
+                match args.get(index) {
+                    Some((_, FormatArgKind::Normal)) => {
+                        used[index] = true;
+                        Ok(index)
+                    }
+                    Some((_, FormatArgKind::Named(_))) => {
+                        used[index] = true;
+                        numeric_refences_to_named_arg.push((index, span, used_as));
+                        Ok(index)
+                    }
+                    Some((_, FormatArgKind::Captured(_))) | None => {
+                        // Doesn't exist as an explicit argument.
+                        invalid_refs.push((index, span, used_as, kind));
+                        Err(index)
                     }
-                } else {
-                    invalid_refs.push((index, span, used_as, kind));
-                    Err(index)
                 }
             }
             Name(name, span) => {

From c1c6e3ae7c6c1d268b1d0f608e58d74f863d572b Mon Sep 17 00:00:00 2001
From: Mara Bos 
Date: Tue, 30 Aug 2022 17:26:50 +0200
Subject: [PATCH 306/586] Add clarifying comments.

---
 compiler/rustc_builtin_macros/src/format.rs | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/compiler/rustc_builtin_macros/src/format.rs b/compiler/rustc_builtin_macros/src/format.rs
index 1dd913ac6d2f0..26a9169a30b13 100644
--- a/compiler/rustc_builtin_macros/src/format.rs
+++ b/compiler/rustc_builtin_macros/src/format.rs
@@ -308,12 +308,15 @@ pub fn make_format_args(
                     .iter()
                     .position(|arg| arg.1.ident().is_some_and(|id| id.name == name))
                 {
+                    // Name found in `args`, so we resolve it to its index in that Vec.
                     let index = start_of_named_args + i;
                     if !matches!(args[index].1, FormatArgKind::Captured(_)) {
+                        // Mark it as used, if it was an explicit argument.
                         used[index] = true;
                     }
                     Ok(index)
                 } else {
+                    // Name not found in `args`, so we add it as an implicitly captured argument.
                     let span = span.unwrap_or(fmt_span);
                     let ident = Ident::new(name, span);
                     let arg = if is_literal {

From 14065639ca9ebf29ae6563f81920d443c26fd1fb Mon Sep 17 00:00:00 2001
From: Mara Bos 
Date: Tue, 6 Sep 2022 23:08:27 +0200
Subject: [PATCH 307/586] Update test.

---
 src/test/ui/fmt/ifmt-bad-arg.rs     | 2 +-
 src/test/ui/fmt/ifmt-bad-arg.stderr | 8 +++-----
 2 files changed, 4 insertions(+), 6 deletions(-)

diff --git a/src/test/ui/fmt/ifmt-bad-arg.rs b/src/test/ui/fmt/ifmt-bad-arg.rs
index 1bd9668de314e..68861d7bf3faf 100644
--- a/src/test/ui/fmt/ifmt-bad-arg.rs
+++ b/src/test/ui/fmt/ifmt-bad-arg.rs
@@ -95,5 +95,5 @@ tenth number: {}",
     println!("{:.*}");
     //~^ ERROR 2 positional arguments in format string, but no arguments were given
     println!("{:.0$}");
-    //~^ ERROR 1 positional argument in format string, but no arguments were given
+    //~^ ERROR invalid reference to positional argument 0 (no arguments were given)
 }
diff --git a/src/test/ui/fmt/ifmt-bad-arg.stderr b/src/test/ui/fmt/ifmt-bad-arg.stderr
index a71792d1ec912..1b595a50e9984 100644
--- a/src/test/ui/fmt/ifmt-bad-arg.stderr
+++ b/src/test/ui/fmt/ifmt-bad-arg.stderr
@@ -257,13 +257,11 @@ LL |     println!("{:.*}");
    = note: positional arguments are zero-based
    = note: for information about formatting flags, visit https://doc.rust-lang.org/std/fmt/index.html
 
-error: 1 positional argument in format string, but no arguments were given
-  --> $DIR/ifmt-bad-arg.rs:97:15
+error: invalid reference to positional argument 0 (no arguments were given)
+  --> $DIR/ifmt-bad-arg.rs:97:16
    |
 LL |     println!("{:.0$}");
-   |               ^^---^
-   |                 |
-   |                 this precision flag expects an `usize` argument at position 0, but no arguments were given
+   |                ^^^^
    |
    = note: positional arguments are zero-based
    = note: for information about formatting flags, visit https://doc.rust-lang.org/std/fmt/index.html

From cf53fef0d6d4d5d8f6733a3d1e98e3b774342819 Mon Sep 17 00:00:00 2001
From: Mara Bos 
Date: Tue, 6 Sep 2022 23:15:13 +0200
Subject: [PATCH 308/586] Turn format arguments Vec into its own struct.

With efficient lookup through a hash map.
---
 compiler/rustc_builtin_macros/src/format.rs   | 119 +++++++-----------
 .../rustc_builtin_macros/src/format/ast.rs    |  87 ++++++++++++-
 .../rustc_builtin_macros/src/format/expand.rs |  24 ++--
 3 files changed, 146 insertions(+), 84 deletions(-)

diff --git a/compiler/rustc_builtin_macros/src/format.rs b/compiler/rustc_builtin_macros/src/format.rs
index 26a9169a30b13..d3e8d854c7d34 100644
--- a/compiler/rustc_builtin_macros/src/format.rs
+++ b/compiler/rustc_builtin_macros/src/format.rs
@@ -45,14 +45,14 @@ use PositionUsedAs::*;
 /// If parsing succeeds, the return value is:
 ///
 /// ```text
-/// Some((fmtstr, parsed arguments))
+/// Ok((fmtstr, parsed arguments))
 /// ```
 fn parse_args<'a>(
     ecx: &mut ExtCtxt<'a>,
     sp: Span,
     tts: TokenStream,
-) -> PResult<'a, (P, Vec<(P, FormatArgKind)>)> {
-    let mut args = Vec::<(P, FormatArgKind)>::new();
+) -> PResult<'a, (P, FormatArguments)> {
+    let mut args = FormatArguments::new();
 
     let mut p = ecx.new_parser_from_tts(tts);
 
@@ -81,7 +81,6 @@ fn parse_args<'a>(
     };
 
     let mut first = true;
-    let mut named = false;
 
     while p.token != token::Eof {
         if !p.eat(&token::Comma) {
@@ -113,40 +112,40 @@ fn parse_args<'a>(
         } // accept trailing commas
         match p.token.ident() {
             Some((ident, _)) if p.look_ahead(1, |t| *t == token::Eq) => {
-                named = true;
                 p.bump();
                 p.expect(&token::Eq)?;
-                let e = p.parse_expr()?;
-                if let Some(prev) =
-                    args.iter().rev().map_while(|a| a.1.ident()).find(|n| n.name == ident.name)
-                {
+                let expr = p.parse_expr()?;
+                if let Some((_, prev)) = args.by_name(ident.name) {
                     ecx.struct_span_err(
                         ident.span,
                         &format!("duplicate argument named `{}`", ident),
                     )
-                    .span_label(prev.span, "previously here")
+                    .span_label(prev.kind.ident().unwrap().span, "previously here")
                     .span_label(ident.span, "duplicate argument")
                     .emit();
                     continue;
                 }
-                args.push((e, FormatArgKind::Named(ident)));
+                args.add(FormatArgument { kind: FormatArgumentKind::Named(ident), expr });
             }
             _ => {
-                let e = p.parse_expr()?;
-                if named {
+                let expr = p.parse_expr()?;
+                if !args.named_args().is_empty() {
                     let mut err = ecx.struct_span_err(
-                        e.span,
+                        expr.span,
                         "positional arguments cannot follow named arguments",
                     );
-                    err.span_label(e.span, "positional arguments must be before named arguments");
-                    for arg in &args {
-                        if let Some(name) = arg.1.ident() {
-                            err.span_label(name.span.to(arg.0.span), "named argument");
+                    err.span_label(
+                        expr.span,
+                        "positional arguments must be before named arguments",
+                    );
+                    for arg in args.named_args() {
+                        if let Some(name) = arg.kind.ident() {
+                            err.span_label(name.span.to(arg.expr.span), "named argument");
                         }
                     }
                     err.emit();
                 }
-                args.push((e, FormatArgKind::Normal));
+                args.add(FormatArgument { kind: FormatArgumentKind::Normal, expr });
             }
         }
     }
@@ -156,12 +155,9 @@ fn parse_args<'a>(
 pub fn make_format_args(
     ecx: &mut ExtCtxt<'_>,
     efmt: P,
-    mut args: Vec<(P, FormatArgKind)>,
+    mut args: FormatArguments,
     append_newline: bool,
 ) -> Result {
-    let start_of_named_args =
-        args.iter().position(|arg| arg.1.ident().is_some()).unwrap_or(args.len());
-
     let msg = "format argument must be a string literal";
     let fmt_span = efmt.span;
     let (fmt_str, fmt_style, fmt_span) = match expr_to_spanned_string(ecx, efmt, msg) {
@@ -172,9 +168,9 @@ pub fn make_format_args(
         Ok(fmt) => fmt,
         Err(err) => {
             if let Some((mut err, suggested)) = err {
-                let sugg_fmt = match args.len() {
+                let sugg_fmt = match args.explicit_args().len() {
                     0 => "{}".to_string(),
-                    _ => format!("{}{{}}", "{} ".repeat(args.len())),
+                    _ => format!("{}{{}}", "{} ".repeat(args.explicit_args().len())),
                 };
                 if !suggested {
                     err.span_suggestion(
@@ -243,14 +239,14 @@ pub fn make_format_args(
             let captured_arg_span =
                 fmt_span.from_inner(InnerSpan::new(err.span.start, err.span.end));
             if let Ok(arg) = ecx.source_map().span_to_snippet(captured_arg_span) {
-                let span = match args[..start_of_named_args].last() {
-                    Some(arg) => arg.0.span,
+                let span = match args.unnamed_args().last() {
+                    Some(arg) => arg.expr.span,
                     None => fmt_span,
                 };
                 e.multipart_suggestion_verbose(
                     "consider using a positional formatting argument instead",
                     vec![
-                        (captured_arg_span, start_of_named_args.to_string()),
+                        (captured_arg_span, args.unnamed_args().len().to_string()),
                         (span.shrink_to_hi(), format!(", {}", arg)),
                     ],
                     Applicability::MachineApplicable,
@@ -267,8 +263,7 @@ pub fn make_format_args(
         })
     };
 
-    let num_explicit_args = args.len();
-    let mut used = vec![false; num_explicit_args];
+    let mut used = vec![false; args.explicit_args().len()];
     let mut invalid_refs = Vec::new();
     let mut numeric_refences_to_named_arg = Vec::new();
 
@@ -285,32 +280,24 @@ pub fn make_format_args(
      -> FormatArgPosition {
         let index = match arg {
             Index(index) => {
-                match args.get(index) {
-                    Some((_, FormatArgKind::Normal)) => {
-                        used[index] = true;
-                        Ok(index)
-                    }
-                    Some((_, FormatArgKind::Named(_))) => {
-                        used[index] = true;
+                if let Some(arg) = args.by_index(index) {
+                    used[index] = true;
+                    if arg.kind.ident().is_some() {
+                        // This was a named argument, but it was used as a positional argument.
                         numeric_refences_to_named_arg.push((index, span, used_as));
-                        Ok(index)
-                    }
-                    Some((_, FormatArgKind::Captured(_))) | None => {
-                        // Doesn't exist as an explicit argument.
-                        invalid_refs.push((index, span, used_as, kind));
-                        Err(index)
                     }
+                    Ok(index)
+                } else {
+                    // Doesn't exist as an explicit argument.
+                    invalid_refs.push((index, span, used_as, kind));
+                    Err(index)
                 }
             }
             Name(name, span) => {
                 let name = Symbol::intern(name);
-                if let Some(i) = args[start_of_named_args..]
-                    .iter()
-                    .position(|arg| arg.1.ident().is_some_and(|id| id.name == name))
-                {
-                    // Name found in `args`, so we resolve it to its index in that Vec.
-                    let index = start_of_named_args + i;
-                    if !matches!(args[index].1, FormatArgKind::Captured(_)) {
+                if let Some((index, _)) = args.by_name(name) {
+                    // Name found in `args`, so we resolve it to its index.
+                    if index < args.explicit_args().len() {
                         // Mark it as used, if it was an explicit argument.
                         used[index] = true;
                     }
@@ -319,7 +306,7 @@ pub fn make_format_args(
                     // Name not found in `args`, so we add it as an implicitly captured argument.
                     let span = span.unwrap_or(fmt_span);
                     let ident = Ident::new(name, span);
-                    let arg = if is_literal {
+                    let expr = if is_literal {
                         ecx.expr_ident(span, ident)
                     } else {
                         // For the moment capturing variables from format strings expanded from macros is
@@ -330,8 +317,7 @@ pub fn make_format_args(
                             .emit();
                         DummyResult::raw_expr(span, true)
                     };
-                    args.push((arg, FormatArgKind::Captured(ident)));
-                    Ok(args.len() - 1)
+                    Ok(args.add(FormatArgument { kind: FormatArgumentKind::Captured(ident), expr }))
                 }
             }
         };
@@ -466,15 +452,7 @@ pub fn make_format_args(
     }
 
     if !invalid_refs.is_empty() {
-        report_invalid_references(
-            ecx,
-            &invalid_refs,
-            &template,
-            fmt_span,
-            num_explicit_args,
-            &args,
-            parser,
-        );
+        report_invalid_references(ecx, &invalid_refs, &template, fmt_span, &args, parser);
     }
 
     let unused = used
@@ -482,19 +460,19 @@ pub fn make_format_args(
         .enumerate()
         .filter(|&(_, used)| !used)
         .map(|(i, _)| {
-            let msg = if let FormatArgKind::Named(_) = args[i].1 {
+            let msg = if let FormatArgumentKind::Named(_) = args.explicit_args()[i].kind {
                 "named argument never used"
             } else {
                 "argument never used"
             };
-            (args[i].0.span, msg)
+            (args.explicit_args()[i].expr.span, msg)
         })
         .collect::>();
 
     if !unused.is_empty() {
         // If there's a lot of unused arguments,
         // let's check if this format arguments looks like another syntax (printf / shell).
-        let detect_foreign_fmt = unused.len() > num_explicit_args / 2;
+        let detect_foreign_fmt = unused.len() > args.explicit_args().len() / 2;
         report_missing_placeholders(ecx, unused, detect_foreign_fmt, str_style, fmt_str, fmt_span);
     }
 
@@ -511,7 +489,7 @@ pub fn make_format_args(
                 }
                 Width => (span, span),
             };
-            let arg_name = args[index].1.ident().unwrap();
+            let arg_name = args.explicit_args()[index].kind.ident().unwrap();
             ecx.buffered_early_lint.push(BufferedEarlyLint {
                 span: arg_name.span.into(),
                 msg: format!("named argument `{}` is not used by name", arg_name.name).into(),
@@ -695,11 +673,10 @@ fn report_invalid_references(
     invalid_refs: &[(usize, Option, PositionUsedAs, FormatArgPositionKind)],
     template: &[FormatArgsPiece],
     fmt_span: Span,
-    num_explicit_args: usize,
-    args: &[(P, FormatArgKind)],
+    args: &FormatArguments,
     parser: parse::Parser<'_>,
 ) {
-    let num_args_desc = match num_explicit_args {
+    let num_args_desc = match args.explicit_args().len() {
         0 => "no arguments were given".to_string(),
         1 => "there is 1 argument".to_string(),
         n => format!("there are {} arguments", n),
@@ -785,8 +762,8 @@ fn report_invalid_references(
                 num_args_desc,
             ),
         );
-        for (arg, _) in &args[..num_explicit_args] {
-            e.span_label(arg.span, "");
+        for arg in args.explicit_args() {
+            e.span_label(arg.expr.span, "");
         }
         // Point out `{:.*}` placeholders: those take an extra argument.
         let mut has_precision_star = false;
diff --git a/compiler/rustc_builtin_macros/src/format/ast.rs b/compiler/rustc_builtin_macros/src/format/ast.rs
index cb76482fe5314..139645248a1df 100644
--- a/compiler/rustc_builtin_macros/src/format/ast.rs
+++ b/compiler/rustc_builtin_macros/src/format/ast.rs
@@ -1,5 +1,6 @@
 use rustc_ast::ptr::P;
 use rustc_ast::Expr;
+use rustc_data_structures::fx::FxHashMap;
 use rustc_span::symbol::{Ident, Symbol};
 use rustc_span::Span;
 
@@ -42,17 +43,97 @@ use rustc_span::Span;
 pub struct FormatArgs {
     pub span: Span,
     pub template: Vec,
-    pub arguments: Vec<(P, FormatArgKind)>,
+    pub arguments: FormatArguments,
 }
 
+/// A piece of a format template string.
+///
+/// E.g. "hello" or "{name}".
 #[derive(Clone, Debug)]
 pub enum FormatArgsPiece {
     Literal(Symbol),
     Placeholder(FormatPlaceholder),
 }
 
+/// The arguments to format_args!().
+///
+/// E.g. `1, 2, name="ferris", n=3`,
+/// but also implicit captured arguments like `x` in `format_args!("{x}")`.
+#[derive(Clone, Debug)]
+pub struct FormatArguments {
+    arguments: Vec,
+    num_unnamed_args: usize,
+    num_explicit_args: usize,
+    names: FxHashMap,
+}
+
+impl FormatArguments {
+    pub fn new() -> Self {
+        Self {
+            arguments: Vec::new(),
+            names: FxHashMap::default(),
+            num_unnamed_args: 0,
+            num_explicit_args: 0,
+        }
+    }
+
+    pub fn add(&mut self, arg: FormatArgument) -> usize {
+        let index = self.arguments.len();
+        if let Some(name) = arg.kind.ident() {
+            self.names.insert(name.name, index);
+        } else if self.names.is_empty() {
+            // Only count the unnamed args before the first named arg.
+            // (Any later ones are errors.)
+            self.num_unnamed_args += 1;
+        }
+        if !matches!(arg.kind, FormatArgumentKind::Captured(..)) {
+            // This is an explicit argument.
+            // Make sure that all arguments so far are explcit.
+            assert_eq!(
+                self.num_explicit_args,
+                self.arguments.len(),
+                "captured arguments must be added last"
+            );
+            self.num_explicit_args += 1;
+        }
+        self.arguments.push(arg);
+        index
+    }
+
+    pub fn by_name(&self, name: Symbol) -> Option<(usize, &FormatArgument)> {
+        let i = *self.names.get(&name)?;
+        Some((i, &self.arguments[i]))
+    }
+
+    pub fn by_index(&self, i: usize) -> Option<&FormatArgument> {
+        (i < self.num_explicit_args).then(|| &self.arguments[i])
+    }
+
+    pub fn unnamed_args(&self) -> &[FormatArgument] {
+        &self.arguments[..self.num_unnamed_args]
+    }
+
+    pub fn named_args(&self) -> &[FormatArgument] {
+        &self.arguments[self.num_unnamed_args..self.num_explicit_args]
+    }
+
+    pub fn explicit_args(&self) -> &[FormatArgument] {
+        &self.arguments[..self.num_explicit_args]
+    }
+
+    pub fn into_vec(self) -> Vec {
+        self.arguments
+    }
+}
+
+#[derive(Clone, Debug)]
+pub struct FormatArgument {
+    pub kind: FormatArgumentKind,
+    pub expr: P,
+}
+
 #[derive(Clone, Debug)]
-pub enum FormatArgKind {
+pub enum FormatArgumentKind {
     /// `format_args(…, arg)`
     Normal,
     /// `format_args(…, arg = 1)`
@@ -61,7 +142,7 @@ pub enum FormatArgKind {
     Captured(Ident),
 }
 
-impl FormatArgKind {
+impl FormatArgumentKind {
     pub fn ident(&self) -> Option {
         match self {
             &Self::Normal => None,
diff --git a/compiler/rustc_builtin_macros/src/format/expand.rs b/compiler/rustc_builtin_macros/src/format/expand.rs
index a2a8213dafc27..9dde5efcb28b7 100644
--- a/compiler/rustc_builtin_macros/src/format/expand.rs
+++ b/compiler/rustc_builtin_macros/src/format/expand.rs
@@ -201,13 +201,15 @@ pub fn expand_parsed_format_args(ecx: &mut ExtCtxt<'_>, fmt: FormatArgs) -> P, fmt: FormatArgs) -> P, fmt: FormatArgs) -> P, fmt: FormatArgs) -> P
Date: Tue, 6 Sep 2022 23:15:44 +0200
Subject: [PATCH 309/586] Update doc comments.

---
 compiler/rustc_builtin_macros/src/format/ast.rs | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/compiler/rustc_builtin_macros/src/format/ast.rs b/compiler/rustc_builtin_macros/src/format/ast.rs
index 139645248a1df..01dbffa21b8aa 100644
--- a/compiler/rustc_builtin_macros/src/format/ast.rs
+++ b/compiler/rustc_builtin_macros/src/format/ast.rs
@@ -233,8 +233,8 @@ pub enum FormatAlignment {
 
 #[derive(Clone, Debug, PartialEq, Eq)]
 pub enum FormatCount {
-    /// `{:0}` or `{:.0}`
+    /// `{:5}` or `{:.5}`
     Literal(usize),
-    /// `{:.*}`, `{:.0$}`, or `{:a$}`, etc.
+    /// `{:.*}`, `{:.5$}`, or `{:a$}`, etc.
     Argument(FormatArgPosition),
 }

From 20bb600849495f6b283b7f9266a02af178ee659b Mon Sep 17 00:00:00 2001
From: Mara Bos 
Date: Tue, 6 Sep 2022 23:19:20 +0200
Subject: [PATCH 310/586] Remove confusing drop.

---
 compiler/rustc_builtin_macros/src/format.rs | 1 -
 1 file changed, 1 deletion(-)

diff --git a/compiler/rustc_builtin_macros/src/format.rs b/compiler/rustc_builtin_macros/src/format.rs
index d3e8d854c7d34..b15e2d084ef7f 100644
--- a/compiler/rustc_builtin_macros/src/format.rs
+++ b/compiler/rustc_builtin_macros/src/format.rs
@@ -448,7 +448,6 @@ pub fn make_format_args(
 
     if !unfinished_literal.is_empty() {
         template.push(FormatArgsPiece::Literal(Symbol::intern(&unfinished_literal)));
-        drop(unfinished_literal);
     }
 
     if !invalid_refs.is_empty() {

From 27b280e1b5370640fc0f181a52eaae6dc379d353 Mon Sep 17 00:00:00 2001
From: Deadbeef 
Date: Tue, 27 Sep 2022 13:42:32 +0000
Subject: [PATCH 311/586] Fix ICE in const_trait check code

This fixes #102156.
---
 compiler/rustc_passes/src/check_const.rs      |  2 +-
 .../rfc-2632-const-trait-impl/issue-102156.rs | 15 +++++++++++++++
 .../issue-102156.stderr                       | 19 +++++++++++++++++++
 3 files changed, 35 insertions(+), 1 deletion(-)
 create mode 100644 src/test/ui/rfc-2632-const-trait-impl/issue-102156.rs
 create mode 100644 src/test/ui/rfc-2632-const-trait-impl/issue-102156.stderr

diff --git a/compiler/rustc_passes/src/check_const.rs b/compiler/rustc_passes/src/check_const.rs
index 4062862ad747c..0af538454f068 100644
--- a/compiler/rustc_passes/src/check_const.rs
+++ b/compiler/rustc_passes/src/check_const.rs
@@ -199,7 +199,7 @@ impl<'tcx> Visitor<'tcx> for CheckConstVisitor<'tcx> {
             ..
         }) = item.kind
         {
-            let def_id = trait_ref.trait_def_id().unwrap();
+            let Some(def_id) = trait_ref.trait_def_id() else { return; };
             let source_map = tcx.sess.source_map();
             if !tcx.has_attr(def_id, sym::const_trait) {
                 tcx.sess
diff --git a/src/test/ui/rfc-2632-const-trait-impl/issue-102156.rs b/src/test/ui/rfc-2632-const-trait-impl/issue-102156.rs
new file mode 100644
index 0000000000000..fe4e910813013
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/issue-102156.rs
@@ -0,0 +1,15 @@
+#![feature(allocator_api)]
+#![feature(const_trait_impl)]
+
+use core::convert::{From, TryFrom};
+//~^ ERROR
+//~| ERROR
+
+use std::pin::Pin;
+use std::alloc::Allocator;
+impl const From> for Pin>
+where
+    A: 'static,
+{}
+
+pub fn main() {}
diff --git a/src/test/ui/rfc-2632-const-trait-impl/issue-102156.stderr b/src/test/ui/rfc-2632-const-trait-impl/issue-102156.stderr
new file mode 100644
index 0000000000000..8bf00eaff1fb9
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/issue-102156.stderr
@@ -0,0 +1,19 @@
+error[E0433]: failed to resolve: maybe a missing crate `core`?
+  --> $DIR/issue-102156.rs:4:5
+   |
+LL | use core::convert::{From, TryFrom};
+   |     ^^^^ maybe a missing crate `core`?
+   |
+   = help: consider adding `extern crate core` to use the `core` crate
+
+error[E0433]: failed to resolve: maybe a missing crate `core`?
+  --> $DIR/issue-102156.rs:4:5
+   |
+LL | use core::convert::{From, TryFrom};
+   |     ^^^^ maybe a missing crate `core`?
+   |
+   = help: consider adding `extern crate core` to use the `core` crate
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0433`.

From 0ab2c91a2d8fe770d9fc47f06545367bab8ea302 Mon Sep 17 00:00:00 2001
From: Arthur Cohen 
Date: Wed, 17 Aug 2022 13:43:59 +0200
Subject: [PATCH 312/586] attributes: Add #[rustc_safe_intrinsic] builtin

---
 compiler/rustc_feature/src/builtin_attrs.rs   |  1 +
 .../rustc_hir_analysis/src/check/intrinsic.rs | 57 +++----------------
 compiler/rustc_hir_analysis/src/collect.rs    |  2 +-
 compiler/rustc_span/src/symbol.rs             |  1 +
 src/librustdoc/clean/types.rs                 |  2 +-
 src/test/rustdoc/safe-intrinsic.rs            |  2 +
 src/test/ui/error-codes/E0308.rs              |  2 +
 src/test/ui/error-codes/E0308.stderr          |  2 +-
 src/test/ui/intrinsics/intrinsics-integer.rs  |  6 ++
 9 files changed, 24 insertions(+), 51 deletions(-)

diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs
index 700d9dab64be7..5ee6c9f238770 100644
--- a/compiler/rustc_feature/src/builtin_attrs.rs
+++ b/compiler/rustc_feature/src/builtin_attrs.rs
@@ -499,6 +499,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
     ),
     ungated!(rustc_const_unstable, Normal, template!(List: r#"feature = "name""#), DuplicatesOk),
     ungated!(rustc_const_stable, Normal, template!(List: r#"feature = "name""#), DuplicatesOk),
+    ungated!(rustc_safe_intrinsic, Normal, template!(Word), DuplicatesOk),
     ungated!(
         rustc_default_body_unstable, Normal,
         template!(List: r#"feature = "name", reason = "...", issue = "N""#), DuplicatesOk
diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
index ae484b4fedaf9..b43d492eb7aad 100644
--- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs
+++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
@@ -7,6 +7,7 @@ use crate::errors::{
 };
 use crate::require_same_types;
 
+use hir::def_id::DefId;
 use rustc_errors::struct_span_err;
 use rustc_hir as hir;
 use rustc_middle::traits::{ObligationCause, ObligationCauseCode};
@@ -61,51 +62,10 @@ fn equate_intrinsic_type<'tcx>(
 }
 
 /// Returns the unsafety of the given intrinsic.
-pub fn intrinsic_operation_unsafety(intrinsic: Symbol) -> hir::Unsafety {
-    match intrinsic {
-        // When adding a new intrinsic to this list,
-        // it's usually worth updating that intrinsic's documentation
-        // to note that it's safe to call, since
-        // safe extern fns are otherwise unprecedented.
-        sym::abort
-        | sym::assert_inhabited
-        | sym::assert_zero_valid
-        | sym::assert_uninit_valid
-        | sym::size_of
-        | sym::min_align_of
-        | sym::needs_drop
-        | sym::caller_location
-        | sym::add_with_overflow
-        | sym::sub_with_overflow
-        | sym::mul_with_overflow
-        | sym::wrapping_add
-        | sym::wrapping_sub
-        | sym::wrapping_mul
-        | sym::saturating_add
-        | sym::saturating_sub
-        | sym::rotate_left
-        | sym::rotate_right
-        | sym::ctpop
-        | sym::ctlz
-        | sym::cttz
-        | sym::bswap
-        | sym::bitreverse
-        | sym::discriminant_value
-        | sym::type_id
-        | sym::likely
-        | sym::unlikely
-        | sym::ptr_guaranteed_cmp
-        | sym::minnumf32
-        | sym::minnumf64
-        | sym::maxnumf32
-        | sym::rustc_peek
-        | sym::maxnumf64
-        | sym::type_name
-        | sym::forget
-        | sym::black_box
-        | sym::variant_count
-        | sym::ptr_mask => hir::Unsafety::Normal,
-        _ => hir::Unsafety::Unsafe,
+pub fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: DefId) -> hir::Unsafety {
+    match tcx.has_attr(intrinsic_id, sym::rustc_safe_intrinsic) {
+        true => hir::Unsafety::Normal,
+        false => hir::Unsafety::Unsafe,
     }
 }
 
@@ -113,7 +73,8 @@ pub fn intrinsic_operation_unsafety(intrinsic: Symbol) -> hir::Unsafety {
 /// and in `library/core/src/intrinsics.rs`.
 pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
     let param = |n| tcx.mk_ty_param(n, Symbol::intern(&format!("P{}", n)));
-    let intrinsic_name = tcx.item_name(it.def_id.to_def_id());
+    let intrinsic_id = it.def_id.to_def_id();
+    let intrinsic_name = tcx.item_name(intrinsic_id);
     let name_str = intrinsic_name.as_str();
 
     let bound_vars = tcx.mk_bound_variable_kinds(
@@ -160,7 +121,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
         };
         (n_tps, 0, inputs, output, hir::Unsafety::Unsafe)
     } else {
-        let unsafety = intrinsic_operation_unsafety(intrinsic_name);
+        let unsafety = intrinsic_operation_unsafety(tcx, intrinsic_id);
         let (n_tps, inputs, output) = match intrinsic_name {
             sym::abort => (0, Vec::new(), tcx.types.never),
             sym::unreachable => (0, Vec::new(), tcx.types.never),
@@ -351,7 +312,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
                 (
                     1,
                     vec![
-                        tcx.mk_imm_ref(tcx.mk_region(ty::ReLateBound(ty::INNERMOST, br)), param(0)),
+                        tcx.mk_imm_ref(tcx.mk_region(ty::ReLateBound(ty::INNERMOST, br)), param(0))
                     ],
                     tcx.mk_projection(discriminant_def_id, tcx.mk_substs([param(0).into()].iter())),
                 )
diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs
index e7deae2b557cd..315a2763c760b 100644
--- a/compiler/rustc_hir_analysis/src/collect.rs
+++ b/compiler/rustc_hir_analysis/src/collect.rs
@@ -2544,7 +2544,7 @@ fn compute_sig_of_foreign_fn_decl<'tcx>(
     abi: abi::Abi,
 ) -> ty::PolyFnSig<'tcx> {
     let unsafety = if abi == abi::Abi::RustIntrinsic {
-        intrinsic_operation_unsafety(tcx.item_name(def_id))
+        intrinsic_operation_unsafety(tcx, def_id)
     } else {
         hir::Unsafety::Unsafe
     };
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 502ef67fc6767..c6eff27b9885e 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -1282,6 +1282,7 @@ symbols! {
         rustc_reallocator,
         rustc_regions,
         rustc_reservation_impl,
+        rustc_safe_intrinsic,
         rustc_serialize,
         rustc_skip_array_during_method_dispatch,
         rustc_specialization_trait,
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index e53e93c4defb1..80bf2f2fd9042 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -689,7 +689,7 @@ impl Item {
                 let abi = tcx.fn_sig(self.item_id.as_def_id().unwrap()).abi();
                 hir::FnHeader {
                     unsafety: if abi == Abi::RustIntrinsic {
-                        intrinsic_operation_unsafety(self.name.unwrap())
+                        intrinsic_operation_unsafety(tcx, self.item_id.as_def_id().unwrap())
                     } else {
                         hir::Unsafety::Unsafe
                     },
diff --git a/src/test/rustdoc/safe-intrinsic.rs b/src/test/rustdoc/safe-intrinsic.rs
index d3bb8514b7e43..d08abdaeb1411 100644
--- a/src/test/rustdoc/safe-intrinsic.rs
+++ b/src/test/rustdoc/safe-intrinsic.rs
@@ -1,5 +1,6 @@
 #![feature(intrinsics)]
 #![feature(no_core)]
+#![feature(rustc_attrs)]
 
 #![no_core]
 #![crate_name = "foo"]
@@ -7,6 +8,7 @@
 extern "rust-intrinsic" {
     // @has 'foo/fn.abort.html'
     // @has - '//pre[@class="rust fn"]' 'pub extern "rust-intrinsic" fn abort() -> !'
+    #[rustc_safe_intrinsic]
     pub fn abort() -> !;
     // @has 'foo/fn.unreachable.html'
     // @has - '//pre[@class="rust fn"]' 'pub unsafe extern "rust-intrinsic" fn unreachable() -> !'
diff --git a/src/test/ui/error-codes/E0308.rs b/src/test/ui/error-codes/E0308.rs
index fa79bee570e18..dd9e0b284eaa2 100644
--- a/src/test/ui/error-codes/E0308.rs
+++ b/src/test/ui/error-codes/E0308.rs
@@ -1,6 +1,8 @@
 #![feature(intrinsics)]
+#![feature(rustc_attrs)]
 
 extern "rust-intrinsic" {
+    #[rustc_safe_intrinsic]
     fn size_of(); //~ ERROR E0308
 }
 
diff --git a/src/test/ui/error-codes/E0308.stderr b/src/test/ui/error-codes/E0308.stderr
index b71fb95e706aa..187b775f92dc0 100644
--- a/src/test/ui/error-codes/E0308.stderr
+++ b/src/test/ui/error-codes/E0308.stderr
@@ -1,5 +1,5 @@
 error[E0308]: intrinsic has wrong type
-  --> $DIR/E0308.rs:4:5
+  --> $DIR/E0308.rs:6:5
    |
 LL |     fn size_of();
    |     ^^^^^^^^^^^^^^^^ expected `()`, found `usize`
diff --git a/src/test/ui/intrinsics/intrinsics-integer.rs b/src/test/ui/intrinsics/intrinsics-integer.rs
index bac6c8d872b40..88bf42b685f4d 100644
--- a/src/test/ui/intrinsics/intrinsics-integer.rs
+++ b/src/test/ui/intrinsics/intrinsics-integer.rs
@@ -1,15 +1,21 @@
 // run-pass
 
 #![feature(intrinsics)]
+#![feature(rustc_attrs)]
 
 mod rusti {
     extern "rust-intrinsic" {
+        #[rustc_safe_intrinsic]
         pub fn ctpop(x: T) -> T;
+        #[rustc_safe_intrinsic]
         pub fn ctlz(x: T) -> T;
         pub fn ctlz_nonzero(x: T) -> T;
+        #[rustc_safe_intrinsic]
         pub fn cttz(x: T) -> T;
         pub fn cttz_nonzero(x: T) -> T;
+        #[rustc_safe_intrinsic]
         pub fn bswap(x: T) -> T;
+        #[rustc_safe_intrinsic]
         pub fn bitreverse(x: T) -> T;
     }
 }

From 99d57ee23d61293bc14f6a8f0eb9ad4fe10acc94 Mon Sep 17 00:00:00 2001
From: Arthur Cohen 
Date: Thu, 18 Aug 2022 11:15:26 +0200
Subject: [PATCH 313/586] core: Mark all safe intrinsics with
 #[rustc_safe_intrinsic]

---
 .../src/error_codes/E0094.md                  |  2 +
 .../src/error_codes/E0211.md                  |  2 +
 library/core/src/intrinsics.rs                | 38 +++++++++++++++++++
 src/test/ui/error-codes/E0094.rs              |  2 +
 src/test/ui/error-codes/E0094.stderr          |  2 +-
 src/test/ui/extern/extern-with-type-bounds.rs |  2 +
 .../ui/extern/extern-with-type-bounds.stderr  |  2 +-
 src/test/ui/intrinsics/intrinsic-alignment.rs |  1 +
 src/test/ui/structs-enums/rec-align-u32.rs    |  1 +
 src/test/ui/structs-enums/rec-align-u64.rs    |  1 +
 10 files changed, 51 insertions(+), 2 deletions(-)

diff --git a/compiler/rustc_error_codes/src/error_codes/E0094.md b/compiler/rustc_error_codes/src/error_codes/E0094.md
index ec86ec44ece8e..cc546bdbb3b35 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0094.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0094.md
@@ -6,6 +6,7 @@ Erroneous code example:
 #![feature(intrinsics)]
 
 extern "rust-intrinsic" {
+    #[rustc_safe_intrinsic]
     fn size_of() -> usize; // error: intrinsic has wrong number
                                  //        of type parameters
 }
@@ -19,6 +20,7 @@ Example:
 #![feature(intrinsics)]
 
 extern "rust-intrinsic" {
+    #[rustc_safe_intrinsic]
     fn size_of() -> usize; // ok!
 }
 ```
diff --git a/compiler/rustc_error_codes/src/error_codes/E0211.md b/compiler/rustc_error_codes/src/error_codes/E0211.md
index 77289f019005e..8c2462ebd9b86 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0211.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0211.md
@@ -7,6 +7,7 @@ used. Erroneous code examples:
 #![feature(intrinsics)]
 
 extern "rust-intrinsic" {
+    #[rustc_safe_intrinsic]
     fn size_of(); // error: intrinsic has wrong type
 }
 
@@ -42,6 +43,7 @@ For the first code example, please check the function definition. Example:
 #![feature(intrinsics)]
 
 extern "rust-intrinsic" {
+    #[rustc_safe_intrinsic]
     fn size_of() -> usize; // ok!
 }
 ```
diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs
index 12b43da5a4280..15ee14398b676 100644
--- a/library/core/src/intrinsics.rs
+++ b/library/core/src/intrinsics.rs
@@ -788,6 +788,7 @@ extern "rust-intrinsic" {
     /// uninitialized at that point in the control flow.
     ///
     /// This intrinsic should not be used outside of the compiler.
+    #[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
     pub fn rustc_peek(_: T) -> T;
 
     /// Aborts the execution of the process.
@@ -805,6 +806,7 @@ extern "rust-intrinsic" {
     /// On Unix, the
     /// process will probably terminate with a signal like `SIGABRT`, `SIGILL`, `SIGTRAP`, `SIGSEGV` or
     /// `SIGBUS`.  The precise behaviour is not guaranteed and not stable.
+    #[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
     pub fn abort() -> !;
 
     /// Informs the optimizer that this point in the code is not reachable,
@@ -843,6 +845,7 @@ extern "rust-intrinsic" {
     ///
     /// This intrinsic does not have a stable counterpart.
     #[rustc_const_unstable(feature = "const_likely", issue = "none")]
+    #[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
     pub fn likely(b: bool) -> bool;
 
     /// Hints to the compiler that branch condition is likely to be false.
@@ -857,6 +860,7 @@ extern "rust-intrinsic" {
     ///
     /// This intrinsic does not have a stable counterpart.
     #[rustc_const_unstable(feature = "const_likely", issue = "none")]
+    #[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
     pub fn unlikely(b: bool) -> bool;
 
     /// Executes a breakpoint trap, for inspection by a debugger.
@@ -876,6 +880,7 @@ extern "rust-intrinsic" {
     ///
     /// The stabilized version of this intrinsic is [`core::mem::size_of`].
     #[rustc_const_stable(feature = "const_size_of", since = "1.40.0")]
+    #[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
     pub fn size_of() -> usize;
 
     /// The minimum alignment of a type.
@@ -887,6 +892,7 @@ extern "rust-intrinsic" {
     ///
     /// The stabilized version of this intrinsic is [`core::mem::align_of`].
     #[rustc_const_stable(feature = "const_min_align_of", since = "1.40.0")]
+    #[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
     pub fn min_align_of() -> usize;
     /// The preferred alignment of a type.
     ///
@@ -915,6 +921,7 @@ extern "rust-intrinsic" {
     ///
     /// The stabilized version of this intrinsic is [`core::any::type_name`].
     #[rustc_const_unstable(feature = "const_type_name", issue = "63084")]
+    #[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
     pub fn type_name() -> &'static str;
 
     /// Gets an identifier which is globally unique to the specified type. This
@@ -928,6 +935,7 @@ extern "rust-intrinsic" {
     ///
     /// The stabilized version of this intrinsic is [`core::any::TypeId::of`].
     #[rustc_const_unstable(feature = "const_type_id", issue = "77125")]
+    #[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
     pub fn type_id() -> u64;
 
     /// A guard for unsafe functions that cannot ever be executed if `T` is uninhabited:
@@ -935,6 +943,7 @@ extern "rust-intrinsic" {
     ///
     /// This intrinsic does not have a stable counterpart.
     #[rustc_const_stable(feature = "const_assert_type", since = "1.59.0")]
+    #[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
     pub fn assert_inhabited();
 
     /// A guard for unsafe functions that cannot ever be executed if `T` does not permit
@@ -942,6 +951,7 @@ extern "rust-intrinsic" {
     ///
     /// This intrinsic does not have a stable counterpart.
     #[rustc_const_unstable(feature = "const_assert_type2", issue = "none")]
+    #[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
     pub fn assert_zero_valid();
 
     /// A guard for unsafe functions that cannot ever be executed if `T` has invalid
@@ -949,6 +959,7 @@ extern "rust-intrinsic" {
     ///
     /// This intrinsic does not have a stable counterpart.
     #[rustc_const_unstable(feature = "const_assert_type2", issue = "none")]
+    #[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
     pub fn assert_uninit_valid();
 
     /// Gets a reference to a static `Location` indicating where it was called.
@@ -960,6 +971,7 @@ extern "rust-intrinsic" {
     ///
     /// Consider using [`core::panic::Location::caller`] instead.
     #[rustc_const_unstable(feature = "const_caller_location", issue = "76156")]
+    #[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
     pub fn caller_location() -> &'static crate::panic::Location<'static>;
 
     /// Moves a value out of scope without running drop glue.
@@ -972,6 +984,7 @@ extern "rust-intrinsic" {
     /// Therefore, implementations must not require the user to uphold
     /// any safety invariants.
     #[rustc_const_unstable(feature = "const_intrinsic_forget", issue = "none")]
+    #[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
     pub fn forget(_: T);
 
     /// Reinterprets the bits of a value of one type as another type.
@@ -1251,6 +1264,7 @@ extern "rust-intrinsic" {
     ///
     /// The stabilized version of this intrinsic is [`mem::needs_drop`](crate::mem::needs_drop).
     #[rustc_const_stable(feature = "const_needs_drop", since = "1.40.0")]
+    #[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
     pub fn needs_drop() -> bool;
 
     /// Calculates the offset from a pointer.
@@ -1295,6 +1309,7 @@ extern "rust-intrinsic" {
     /// any safety invariants.
     ///
     /// Consider using [`pointer::mask`] instead.
+    #[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
     pub fn ptr_mask(ptr: *const T, mask: usize) -> *const T;
 
     /// Equivalent to the appropriate `llvm.memcpy.p0i8.0i8.*` intrinsic, with
@@ -1486,6 +1501,7 @@ extern "rust-intrinsic" {
     ///
     /// The stabilized version of this intrinsic is
     /// [`f32::min`]
+    #[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
     pub fn minnumf32(x: f32, y: f32) -> f32;
     /// Returns the minimum of two `f64` values.
     ///
@@ -1496,6 +1512,7 @@ extern "rust-intrinsic" {
     ///
     /// The stabilized version of this intrinsic is
     /// [`f64::min`]
+    #[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
     pub fn minnumf64(x: f64, y: f64) -> f64;
     /// Returns the maximum of two `f32` values.
     ///
@@ -1506,6 +1523,7 @@ extern "rust-intrinsic" {
     ///
     /// The stabilized version of this intrinsic is
     /// [`f32::max`]
+    #[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
     pub fn maxnumf32(x: f32, y: f32) -> f32;
     /// Returns the maximum of two `f64` values.
     ///
@@ -1516,6 +1534,7 @@ extern "rust-intrinsic" {
     ///
     /// The stabilized version of this intrinsic is
     /// [`f64::max`]
+    #[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
     pub fn maxnumf64(x: f64, y: f64) -> f64;
 
     /// Copies the sign from `y` to `x` for `f32` values.
@@ -1636,6 +1655,7 @@ extern "rust-intrinsic" {
     /// primitives via the `count_ones` method. For example,
     /// [`u32::count_ones`]
     #[rustc_const_stable(feature = "const_ctpop", since = "1.40.0")]
+    #[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
     pub fn ctpop(x: T) -> T;
 
     /// Returns the number of leading unset bits (zeroes) in an integer type `T`.
@@ -1673,6 +1693,7 @@ extern "rust-intrinsic" {
     /// assert_eq!(num_leading, 16);
     /// ```
     #[rustc_const_stable(feature = "const_ctlz", since = "1.40.0")]
+    #[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
     pub fn ctlz(x: T) -> T;
 
     /// Like `ctlz`, but extra-unsafe as it returns `undef` when
@@ -1729,6 +1750,7 @@ extern "rust-intrinsic" {
     /// assert_eq!(num_trailing, 16);
     /// ```
     #[rustc_const_stable(feature = "const_cttz", since = "1.40.0")]
+    #[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
     pub fn cttz(x: T) -> T;
 
     /// Like `cttz`, but extra-unsafe as it returns `undef` when
@@ -1761,6 +1783,7 @@ extern "rust-intrinsic" {
     /// primitives via the `swap_bytes` method. For example,
     /// [`u32::swap_bytes`]
     #[rustc_const_stable(feature = "const_bswap", since = "1.40.0")]
+    #[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
     pub fn bswap(x: T) -> T;
 
     /// Reverses the bits in an integer type `T`.
@@ -1774,6 +1797,7 @@ extern "rust-intrinsic" {
     /// primitives via the `reverse_bits` method. For example,
     /// [`u32::reverse_bits`]
     #[rustc_const_stable(feature = "const_bitreverse", since = "1.40.0")]
+    #[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
     pub fn bitreverse(x: T) -> T;
 
     /// Performs checked integer addition.
@@ -1787,6 +1811,7 @@ extern "rust-intrinsic" {
     /// primitives via the `overflowing_add` method. For example,
     /// [`u32::overflowing_add`]
     #[rustc_const_stable(feature = "const_int_overflow", since = "1.40.0")]
+    #[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
     pub fn add_with_overflow(x: T, y: T) -> (T, bool);
 
     /// Performs checked integer subtraction
@@ -1800,6 +1825,7 @@ extern "rust-intrinsic" {
     /// primitives via the `overflowing_sub` method. For example,
     /// [`u32::overflowing_sub`]
     #[rustc_const_stable(feature = "const_int_overflow", since = "1.40.0")]
+    #[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
     pub fn sub_with_overflow(x: T, y: T) -> (T, bool);
 
     /// Performs checked integer multiplication
@@ -1813,6 +1839,7 @@ extern "rust-intrinsic" {
     /// primitives via the `overflowing_mul` method. For example,
     /// [`u32::overflowing_mul`]
     #[rustc_const_stable(feature = "const_int_overflow", since = "1.40.0")]
+    #[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
     pub fn mul_with_overflow(x: T, y: T) -> (T, bool);
 
     /// Performs an exact division, resulting in undefined behavior where
@@ -1887,6 +1914,7 @@ extern "rust-intrinsic" {
     /// primitives via the `rotate_left` method. For example,
     /// [`u32::rotate_left`]
     #[rustc_const_stable(feature = "const_int_rotate", since = "1.40.0")]
+    #[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
     pub fn rotate_left(x: T, y: T) -> T;
 
     /// Performs rotate right.
@@ -1900,6 +1928,7 @@ extern "rust-intrinsic" {
     /// primitives via the `rotate_right` method. For example,
     /// [`u32::rotate_right`]
     #[rustc_const_stable(feature = "const_int_rotate", since = "1.40.0")]
+    #[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
     pub fn rotate_right(x: T, y: T) -> T;
 
     /// Returns (a + b) mod 2N, where N is the width of T in bits.
@@ -1913,6 +1942,7 @@ extern "rust-intrinsic" {
     /// primitives via the `wrapping_add` method. For example,
     /// [`u32::wrapping_add`]
     #[rustc_const_stable(feature = "const_int_wrapping", since = "1.40.0")]
+    #[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
     pub fn wrapping_add(a: T, b: T) -> T;
     /// Returns (a - b) mod 2N, where N is the width of T in bits.
     ///
@@ -1925,6 +1955,7 @@ extern "rust-intrinsic" {
     /// primitives via the `wrapping_sub` method. For example,
     /// [`u32::wrapping_sub`]
     #[rustc_const_stable(feature = "const_int_wrapping", since = "1.40.0")]
+    #[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
     pub fn wrapping_sub(a: T, b: T) -> T;
     /// Returns (a * b) mod 2N, where N is the width of T in bits.
     ///
@@ -1937,6 +1968,7 @@ extern "rust-intrinsic" {
     /// primitives via the `wrapping_mul` method. For example,
     /// [`u32::wrapping_mul`]
     #[rustc_const_stable(feature = "const_int_wrapping", since = "1.40.0")]
+    #[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
     pub fn wrapping_mul(a: T, b: T) -> T;
 
     /// Computes `a + b`, saturating at numeric bounds.
@@ -1950,6 +1982,7 @@ extern "rust-intrinsic" {
     /// primitives via the `saturating_add` method. For example,
     /// [`u32::saturating_add`]
     #[rustc_const_stable(feature = "const_int_saturating", since = "1.40.0")]
+    #[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
     pub fn saturating_add(a: T, b: T) -> T;
     /// Computes `a - b`, saturating at numeric bounds.
     ///
@@ -1962,6 +1995,7 @@ extern "rust-intrinsic" {
     /// primitives via the `saturating_sub` method. For example,
     /// [`u32::saturating_sub`]
     #[rustc_const_stable(feature = "const_int_saturating", since = "1.40.0")]
+    #[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
     pub fn saturating_sub(a: T, b: T) -> T;
 
     /// Returns the value of the discriminant for the variant in 'v';
@@ -1974,6 +2008,7 @@ extern "rust-intrinsic" {
     ///
     /// The stabilized version of this intrinsic is [`core::mem::discriminant`].
     #[rustc_const_unstable(feature = "const_discriminant", issue = "69821")]
+    #[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
     pub fn discriminant_value(v: &T) -> ::Discriminant;
 
     /// Returns the number of variants of the type `T` cast to a `usize`;
@@ -1986,6 +2021,7 @@ extern "rust-intrinsic" {
     ///
     /// The to-be-stabilized version of this intrinsic is [`mem::variant_count`].
     #[rustc_const_unstable(feature = "variant_count", issue = "73662")]
+    #[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
     pub fn variant_count() -> usize;
 
     /// Rust's "try catch" construct which invokes the function pointer `try_fn`
@@ -2019,6 +2055,7 @@ extern "rust-intrinsic" {
     /// Therefore, implementations must not require the user to uphold
     /// any safety invariants.
     #[rustc_const_unstable(feature = "const_raw_ptr_comparison", issue = "53020")]
+    #[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
     pub fn ptr_guaranteed_cmp(ptr: *const T, other: *const T) -> u8;
 
     /// Allocates a block of memory at compile time.
@@ -2069,6 +2106,7 @@ extern "rust-intrinsic" {
     ///
     /// [`std::hint::black_box`]: crate::hint::black_box
     #[rustc_const_unstable(feature = "const_black_box", issue = "none")]
+    #[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
     pub fn black_box(dummy: T) -> T;
 
     /// `ptr` must point to a vtable.
diff --git a/src/test/ui/error-codes/E0094.rs b/src/test/ui/error-codes/E0094.rs
index 0d58e5a2862c4..a2ec932c12455 100644
--- a/src/test/ui/error-codes/E0094.rs
+++ b/src/test/ui/error-codes/E0094.rs
@@ -1,5 +1,7 @@
 #![feature(intrinsics)]
+
 extern "rust-intrinsic" {
+    #[rustc_safe_intrinsic]
     fn size_of() -> usize; //~ ERROR E0094
 }
 
diff --git a/src/test/ui/error-codes/E0094.stderr b/src/test/ui/error-codes/E0094.stderr
index da97f3a014b06..531cd4c784d33 100644
--- a/src/test/ui/error-codes/E0094.stderr
+++ b/src/test/ui/error-codes/E0094.stderr
@@ -1,5 +1,5 @@
 error[E0094]: intrinsic has wrong number of type parameters: found 2, expected 1
-  --> $DIR/E0094.rs:3:15
+  --> $DIR/E0094.rs:5:15
    |
 LL |     fn size_of() -> usize;
    |               ^^^^^^ expected 1 type parameter
diff --git a/src/test/ui/extern/extern-with-type-bounds.rs b/src/test/ui/extern/extern-with-type-bounds.rs
index 8f9683e4a7485..a72aa4171a103 100644
--- a/src/test/ui/extern/extern-with-type-bounds.rs
+++ b/src/test/ui/extern/extern-with-type-bounds.rs
@@ -2,6 +2,7 @@
 
 extern "rust-intrinsic" {
     // Real example from libcore
+    #[rustc_safe_intrinsic]
     fn type_id() -> u64;
 
     // Silent bounds made explicit to make sure they are actually
@@ -10,6 +11,7 @@ extern "rust-intrinsic" {
 
     // Bounds aren't checked right now, so this should work
     // even though it's incorrect.
+    #[rustc_safe_intrinsic]
     fn size_of() -> usize;
 
     // Unresolved bounds should still error.
diff --git a/src/test/ui/extern/extern-with-type-bounds.stderr b/src/test/ui/extern/extern-with-type-bounds.stderr
index acd0596422f8a..88be1e5dd3da0 100644
--- a/src/test/ui/extern/extern-with-type-bounds.stderr
+++ b/src/test/ui/extern/extern-with-type-bounds.stderr
@@ -1,5 +1,5 @@
 error[E0405]: cannot find trait `NoSuchTrait` in this scope
-  --> $DIR/extern-with-type-bounds.rs:16:20
+  --> $DIR/extern-with-type-bounds.rs:18:20
    |
 LL |     fn align_of() -> usize;
    |                    ^^^^^^^^^^^ not found in this scope
diff --git a/src/test/ui/intrinsics/intrinsic-alignment.rs b/src/test/ui/intrinsics/intrinsic-alignment.rs
index 6007eba8c0906..c8b1ff1dbce3b 100644
--- a/src/test/ui/intrinsics/intrinsic-alignment.rs
+++ b/src/test/ui/intrinsics/intrinsic-alignment.rs
@@ -6,6 +6,7 @@
 mod rusti {
     extern "rust-intrinsic" {
         pub fn pref_align_of() -> usize;
+        #[rustc_safe_intrinsic]
         pub fn min_align_of() -> usize;
     }
 }
diff --git a/src/test/ui/structs-enums/rec-align-u32.rs b/src/test/ui/structs-enums/rec-align-u32.rs
index 889294daa340c..ee704198d193b 100644
--- a/src/test/ui/structs-enums/rec-align-u32.rs
+++ b/src/test/ui/structs-enums/rec-align-u32.rs
@@ -10,6 +10,7 @@ use std::mem;
 mod rusti {
     extern "rust-intrinsic" {
         pub fn pref_align_of() -> usize;
+        #[rustc_safe_intrinsic]
         pub fn min_align_of() -> usize;
     }
 }
diff --git a/src/test/ui/structs-enums/rec-align-u64.rs b/src/test/ui/structs-enums/rec-align-u64.rs
index 3bc2d16cf9df2..40ede9705f115 100644
--- a/src/test/ui/structs-enums/rec-align-u64.rs
+++ b/src/test/ui/structs-enums/rec-align-u64.rs
@@ -12,6 +12,7 @@ use std::mem;
 mod rusti {
     extern "rust-intrinsic" {
         pub fn pref_align_of() -> usize;
+        #[rustc_safe_intrinsic]
         pub fn min_align_of() -> usize;
     }
 }

From 67fd09d3b833d2ede9aeef10c1f05cff68aac225 Mon Sep 17 00:00:00 2001
From: Ralf Jung 
Date: Tue, 27 Sep 2022 15:59:10 +0200
Subject: [PATCH 314/586] also query type_uninhabited_from

---
 compiler/rustc_lint/src/builtin.rs            | 14 ++++++--
 .../ui/consts/const-eval/ub-enum.32bit.stderr | 36 +++++++++----------
 .../ui/consts/const-eval/ub-enum.64bit.stderr | 36 +++++++++----------
 src/test/ui/consts/const-eval/ub-enum.rs      |  1 +
 src/test/ui/lint/invalid_value.rs             |  2 +-
 5 files changed, 49 insertions(+), 40 deletions(-)

diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs
index 529e709c5db30..146c4971348ea 100644
--- a/compiler/rustc_lint/src/builtin.rs
+++ b/compiler/rustc_lint/src/builtin.rs
@@ -2425,8 +2425,12 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue {
         }
 
         /// Determines whether the given type is inhabited. `None` means that we don't know.
-        fn ty_inhabited(ty: Ty<'_>) -> Option {
+        fn ty_inhabited<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option {
             use rustc_type_ir::sty::TyKind::*;
+            if !cx.tcx.type_uninhabited_from(cx.param_env.and(ty)).is_empty() {
+                // This is definitely uninhabited from some module.
+                return Some(false);
+            }
             match ty.kind() {
                 Never => Some(false),
                 Int(_) | Uint(_) | Float(_) | Bool | Char | RawPtr(_) => Some(true),
@@ -2436,10 +2440,13 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue {
             }
         }
         /// Determines whether a product type formed from a list of types is inhabited.
-        fn tys_inhabited<'tcx>(tys: impl Iterator>) -> Option {
+        fn tys_inhabited<'tcx>(
+            cx: &LateContext<'tcx>,
+            tys: impl Iterator>,
+        ) -> Option {
             let mut definitely_inhabited = true; // with no fields, we are definitely inhabited.
             for ty in tys {
-                match ty_inhabited(ty) {
+                match ty_inhabited(cx, ty) {
                     // If any type is uninhabited, the product is uninhabited.
                     Some(false) => return Some(false),
                     // Otherwise go searching for a `None`.
@@ -2550,6 +2557,7 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue {
                     let span = cx.tcx.def_span(adt_def.did());
                     let mut potential_variants = adt_def.variants().iter().filter_map(|variant| {
                         let inhabited = tys_inhabited(
+                            cx,
                             variant.fields.iter().map(|field| field.ty(cx.tcx, substs)),
                         );
                         let definitely_inhabited = match inhabited {
diff --git a/src/test/ui/consts/const-eval/ub-enum.32bit.stderr b/src/test/ui/consts/const-eval/ub-enum.32bit.stderr
index 752fd01f33805..80395e32db0ca 100644
--- a/src/test/ui/consts/const-eval/ub-enum.32bit.stderr
+++ b/src/test/ui/consts/const-eval/ub-enum.32bit.stderr
@@ -1,5 +1,5 @@
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-enum.rs:23:1
+  --> $DIR/ub-enum.rs:24:1
    |
 LL | const BAD_ENUM: Enum = unsafe { mem::transmute(1usize) };
    | ^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .: encountered 0x00000001, but expected a valid enum tag
@@ -10,7 +10,7 @@ LL | const BAD_ENUM: Enum = unsafe { mem::transmute(1usize) };
            }
 
 error: any use of this value will cause an error
-  --> $DIR/ub-enum.rs:26:1
+  --> $DIR/ub-enum.rs:27:1
    |
 LL | const BAD_ENUM_PTR: Enum = unsafe { mem::transmute(&1) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
@@ -22,7 +22,7 @@ LL | const BAD_ENUM_PTR: Enum = unsafe { mem::transmute(&1) };
    = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
 
 error: any use of this value will cause an error
-  --> $DIR/ub-enum.rs:30:1
+  --> $DIR/ub-enum.rs:31:1
    |
 LL | const BAD_ENUM_WRAPPED: Wrap = unsafe { mem::transmute(&1) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
@@ -33,7 +33,7 @@ LL | const BAD_ENUM_WRAPPED: Wrap = unsafe { mem::transmute(&1) };
    = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-enum.rs:43:1
+  --> $DIR/ub-enum.rs:44:1
    |
 LL | const BAD_ENUM2: Enum2 = unsafe { mem::transmute(0usize) };
    | ^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .: encountered 0x00000000, but expected a valid enum tag
@@ -44,7 +44,7 @@ LL | const BAD_ENUM2: Enum2 = unsafe { mem::transmute(0usize) };
            }
 
 error: any use of this value will cause an error
-  --> $DIR/ub-enum.rs:45:1
+  --> $DIR/ub-enum.rs:46:1
    |
 LL | const BAD_ENUM2_PTR: Enum2 = unsafe { mem::transmute(&0) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
@@ -55,7 +55,7 @@ LL | const BAD_ENUM2_PTR: Enum2 = unsafe { mem::transmute(&0) };
    = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
 
 error: any use of this value will cause an error
-  --> $DIR/ub-enum.rs:49:1
+  --> $DIR/ub-enum.rs:50:1
    |
 LL | const BAD_ENUM2_WRAPPED: Wrap = unsafe { mem::transmute(&0) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
@@ -66,13 +66,13 @@ LL | const BAD_ENUM2_WRAPPED: Wrap = unsafe { mem::transmute(&0) };
    = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/ub-enum.rs:59:42
+  --> $DIR/ub-enum.rs:60:42
    |
 LL | const BAD_ENUM2_UNDEF : Enum2 = unsafe { MaybeUninit { uninit: () }.init };
    |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory
 
 error: any use of this value will cause an error
-  --> $DIR/ub-enum.rs:64:1
+  --> $DIR/ub-enum.rs:65:1
    |
 LL | const BAD_ENUM2_OPTION_PTR: Option = unsafe { mem::transmute(&0) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
@@ -83,7 +83,7 @@ LL | const BAD_ENUM2_OPTION_PTR: Option = unsafe { mem::transmute(&0) };
    = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-enum.rs:82:1
+  --> $DIR/ub-enum.rs:83:1
    |
 LL | const BAD_UNINHABITED_VARIANT1: UninhDiscriminant = unsafe { mem::transmute(1u8) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at ..0: encountered a value of the never type `!`
@@ -94,7 +94,7 @@ LL | const BAD_UNINHABITED_VARIANT1: UninhDiscriminant = unsafe { mem::transmute
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-enum.rs:84:1
+  --> $DIR/ub-enum.rs:85:1
    |
 LL | const BAD_UNINHABITED_VARIANT2: UninhDiscriminant = unsafe { mem::transmute(3u8) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at ..0: encountered a value of uninhabited type Never
@@ -105,7 +105,7 @@ LL | const BAD_UNINHABITED_VARIANT2: UninhDiscriminant = unsafe { mem::transmute
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-enum.rs:92:1
+  --> $DIR/ub-enum.rs:93:1
    |
 LL | const BAD_OPTION_CHAR: Option<(char, char)> = Some(('x', unsafe { mem::transmute(!0u32) }));
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at ..0.1: encountered 0xffffffff, but expected a valid unicode scalar value (in `0..=0x10FFFF` but not in `0xD800..=0xDFFF`)
@@ -116,13 +116,13 @@ LL | const BAD_OPTION_CHAR: Option<(char, char)> = Some(('x', unsafe { mem::tran
            }
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/ub-enum.rs:97:77
+  --> $DIR/ub-enum.rs:98:77
    |
 LL | const BAD_UNINHABITED_WITH_DATA1: Result<(i32, Never), (i32, !)> = unsafe { mem::transmute(0u64) };
    |                                                                             ^^^^^^^^^^^^^^^^^^^^ transmuting to uninhabited type
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/ub-enum.rs:99:77
+  --> $DIR/ub-enum.rs:100:77
    |
 LL | const BAD_UNINHABITED_WITH_DATA2: Result<(i32, !), (i32, Never)> = unsafe { mem::transmute(0u64) };
    |                                                                             ^^^^^^^^^^^^^^^^^^^^ transmuting to uninhabited type
@@ -132,7 +132,7 @@ error: aborting due to 13 previous errors
 For more information about this error, try `rustc --explain E0080`.
 Future incompatibility report: Future breakage diagnostic:
 error: any use of this value will cause an error
-  --> $DIR/ub-enum.rs:26:1
+  --> $DIR/ub-enum.rs:27:1
    |
 LL | const BAD_ENUM_PTR: Enum = unsafe { mem::transmute(&1) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
@@ -145,7 +145,7 @@ LL | const BAD_ENUM_PTR: Enum = unsafe { mem::transmute(&1) };
 
 Future breakage diagnostic:
 error: any use of this value will cause an error
-  --> $DIR/ub-enum.rs:30:1
+  --> $DIR/ub-enum.rs:31:1
    |
 LL | const BAD_ENUM_WRAPPED: Wrap = unsafe { mem::transmute(&1) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
@@ -158,7 +158,7 @@ LL | const BAD_ENUM_WRAPPED: Wrap = unsafe { mem::transmute(&1) };
 
 Future breakage diagnostic:
 error: any use of this value will cause an error
-  --> $DIR/ub-enum.rs:45:1
+  --> $DIR/ub-enum.rs:46:1
    |
 LL | const BAD_ENUM2_PTR: Enum2 = unsafe { mem::transmute(&0) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
@@ -171,7 +171,7 @@ LL | const BAD_ENUM2_PTR: Enum2 = unsafe { mem::transmute(&0) };
 
 Future breakage diagnostic:
 error: any use of this value will cause an error
-  --> $DIR/ub-enum.rs:49:1
+  --> $DIR/ub-enum.rs:50:1
    |
 LL | const BAD_ENUM2_WRAPPED: Wrap = unsafe { mem::transmute(&0) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
@@ -184,7 +184,7 @@ LL | const BAD_ENUM2_WRAPPED: Wrap = unsafe { mem::transmute(&0) };
 
 Future breakage diagnostic:
 error: any use of this value will cause an error
-  --> $DIR/ub-enum.rs:64:1
+  --> $DIR/ub-enum.rs:65:1
    |
 LL | const BAD_ENUM2_OPTION_PTR: Option = unsafe { mem::transmute(&0) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
diff --git a/src/test/ui/consts/const-eval/ub-enum.64bit.stderr b/src/test/ui/consts/const-eval/ub-enum.64bit.stderr
index 3f1546a2786ca..d20f63a728994 100644
--- a/src/test/ui/consts/const-eval/ub-enum.64bit.stderr
+++ b/src/test/ui/consts/const-eval/ub-enum.64bit.stderr
@@ -1,5 +1,5 @@
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-enum.rs:23:1
+  --> $DIR/ub-enum.rs:24:1
    |
 LL | const BAD_ENUM: Enum = unsafe { mem::transmute(1usize) };
    | ^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .: encountered 0x0000000000000001, but expected a valid enum tag
@@ -10,7 +10,7 @@ LL | const BAD_ENUM: Enum = unsafe { mem::transmute(1usize) };
            }
 
 error: any use of this value will cause an error
-  --> $DIR/ub-enum.rs:26:1
+  --> $DIR/ub-enum.rs:27:1
    |
 LL | const BAD_ENUM_PTR: Enum = unsafe { mem::transmute(&1) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
@@ -22,7 +22,7 @@ LL | const BAD_ENUM_PTR: Enum = unsafe { mem::transmute(&1) };
    = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
 
 error: any use of this value will cause an error
-  --> $DIR/ub-enum.rs:30:1
+  --> $DIR/ub-enum.rs:31:1
    |
 LL | const BAD_ENUM_WRAPPED: Wrap = unsafe { mem::transmute(&1) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
@@ -33,7 +33,7 @@ LL | const BAD_ENUM_WRAPPED: Wrap = unsafe { mem::transmute(&1) };
    = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-enum.rs:43:1
+  --> $DIR/ub-enum.rs:44:1
    |
 LL | const BAD_ENUM2: Enum2 = unsafe { mem::transmute(0usize) };
    | ^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .: encountered 0x0000000000000000, but expected a valid enum tag
@@ -44,7 +44,7 @@ LL | const BAD_ENUM2: Enum2 = unsafe { mem::transmute(0usize) };
            }
 
 error: any use of this value will cause an error
-  --> $DIR/ub-enum.rs:45:1
+  --> $DIR/ub-enum.rs:46:1
    |
 LL | const BAD_ENUM2_PTR: Enum2 = unsafe { mem::transmute(&0) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
@@ -55,7 +55,7 @@ LL | const BAD_ENUM2_PTR: Enum2 = unsafe { mem::transmute(&0) };
    = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
 
 error: any use of this value will cause an error
-  --> $DIR/ub-enum.rs:49:1
+  --> $DIR/ub-enum.rs:50:1
    |
 LL | const BAD_ENUM2_WRAPPED: Wrap = unsafe { mem::transmute(&0) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
@@ -66,13 +66,13 @@ LL | const BAD_ENUM2_WRAPPED: Wrap = unsafe { mem::transmute(&0) };
    = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/ub-enum.rs:59:42
+  --> $DIR/ub-enum.rs:60:42
    |
 LL | const BAD_ENUM2_UNDEF : Enum2 = unsafe { MaybeUninit { uninit: () }.init };
    |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory
 
 error: any use of this value will cause an error
-  --> $DIR/ub-enum.rs:64:1
+  --> $DIR/ub-enum.rs:65:1
    |
 LL | const BAD_ENUM2_OPTION_PTR: Option = unsafe { mem::transmute(&0) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
@@ -83,7 +83,7 @@ LL | const BAD_ENUM2_OPTION_PTR: Option = unsafe { mem::transmute(&0) };
    = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-enum.rs:82:1
+  --> $DIR/ub-enum.rs:83:1
    |
 LL | const BAD_UNINHABITED_VARIANT1: UninhDiscriminant = unsafe { mem::transmute(1u8) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at ..0: encountered a value of the never type `!`
@@ -94,7 +94,7 @@ LL | const BAD_UNINHABITED_VARIANT1: UninhDiscriminant = unsafe { mem::transmute
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-enum.rs:84:1
+  --> $DIR/ub-enum.rs:85:1
    |
 LL | const BAD_UNINHABITED_VARIANT2: UninhDiscriminant = unsafe { mem::transmute(3u8) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at ..0: encountered a value of uninhabited type Never
@@ -105,7 +105,7 @@ LL | const BAD_UNINHABITED_VARIANT2: UninhDiscriminant = unsafe { mem::transmute
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-enum.rs:92:1
+  --> $DIR/ub-enum.rs:93:1
    |
 LL | const BAD_OPTION_CHAR: Option<(char, char)> = Some(('x', unsafe { mem::transmute(!0u32) }));
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at ..0.1: encountered 0xffffffff, but expected a valid unicode scalar value (in `0..=0x10FFFF` but not in `0xD800..=0xDFFF`)
@@ -116,13 +116,13 @@ LL | const BAD_OPTION_CHAR: Option<(char, char)> = Some(('x', unsafe { mem::tran
            }
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/ub-enum.rs:97:77
+  --> $DIR/ub-enum.rs:98:77
    |
 LL | const BAD_UNINHABITED_WITH_DATA1: Result<(i32, Never), (i32, !)> = unsafe { mem::transmute(0u64) };
    |                                                                             ^^^^^^^^^^^^^^^^^^^^ transmuting to uninhabited type
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/ub-enum.rs:99:77
+  --> $DIR/ub-enum.rs:100:77
    |
 LL | const BAD_UNINHABITED_WITH_DATA2: Result<(i32, !), (i32, Never)> = unsafe { mem::transmute(0u64) };
    |                                                                             ^^^^^^^^^^^^^^^^^^^^ transmuting to uninhabited type
@@ -132,7 +132,7 @@ error: aborting due to 13 previous errors
 For more information about this error, try `rustc --explain E0080`.
 Future incompatibility report: Future breakage diagnostic:
 error: any use of this value will cause an error
-  --> $DIR/ub-enum.rs:26:1
+  --> $DIR/ub-enum.rs:27:1
    |
 LL | const BAD_ENUM_PTR: Enum = unsafe { mem::transmute(&1) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
@@ -145,7 +145,7 @@ LL | const BAD_ENUM_PTR: Enum = unsafe { mem::transmute(&1) };
 
 Future breakage diagnostic:
 error: any use of this value will cause an error
-  --> $DIR/ub-enum.rs:30:1
+  --> $DIR/ub-enum.rs:31:1
    |
 LL | const BAD_ENUM_WRAPPED: Wrap = unsafe { mem::transmute(&1) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
@@ -158,7 +158,7 @@ LL | const BAD_ENUM_WRAPPED: Wrap = unsafe { mem::transmute(&1) };
 
 Future breakage diagnostic:
 error: any use of this value will cause an error
-  --> $DIR/ub-enum.rs:45:1
+  --> $DIR/ub-enum.rs:46:1
    |
 LL | const BAD_ENUM2_PTR: Enum2 = unsafe { mem::transmute(&0) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
@@ -171,7 +171,7 @@ LL | const BAD_ENUM2_PTR: Enum2 = unsafe { mem::transmute(&0) };
 
 Future breakage diagnostic:
 error: any use of this value will cause an error
-  --> $DIR/ub-enum.rs:49:1
+  --> $DIR/ub-enum.rs:50:1
    |
 LL | const BAD_ENUM2_WRAPPED: Wrap = unsafe { mem::transmute(&0) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
@@ -184,7 +184,7 @@ LL | const BAD_ENUM2_WRAPPED: Wrap = unsafe { mem::transmute(&0) };
 
 Future breakage diagnostic:
 error: any use of this value will cause an error
-  --> $DIR/ub-enum.rs:64:1
+  --> $DIR/ub-enum.rs:65:1
    |
 LL | const BAD_ENUM2_OPTION_PTR: Option = unsafe { mem::transmute(&0) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
diff --git a/src/test/ui/consts/const-eval/ub-enum.rs b/src/test/ui/consts/const-eval/ub-enum.rs
index d8dc6d057a73d..9e1c28e2351a8 100644
--- a/src/test/ui/consts/const-eval/ub-enum.rs
+++ b/src/test/ui/consts/const-eval/ub-enum.rs
@@ -1,5 +1,6 @@
 // stderr-per-bitwidth
 #![feature(never_type)]
+#![allow(invalid_value)]
 
 use std::mem;
 
diff --git a/src/test/ui/lint/invalid_value.rs b/src/test/ui/lint/invalid_value.rs
index c37a472ffe10f..51edb2b7baf59 100644
--- a/src/test/ui/lint/invalid_value.rs
+++ b/src/test/ui/lint/invalid_value.rs
@@ -41,7 +41,7 @@ enum OneFruitNonZero {
 
 enum TwoUninhabited {
     A(!),
-    B(!),
+    B(Void),
 }
 
 #[allow(unused)]

From 9ad2f00f6a9ba359f35b270162a7ca6c412876eb Mon Sep 17 00:00:00 2001
From: Urgau 
Date: Sat, 24 Sep 2022 12:34:56 +0200
Subject: [PATCH 315/586] Stabilize bench_black_box

---
 compiler/rustc_codegen_cranelift/example/std_example.rs | 2 +-
 compiler/rustc_codegen_gcc/tests/run/int.rs             | 2 +-
 compiler/rustc_index/src/lib.rs                         | 1 -
 library/alloc/tests/lib.rs                              | 1 -
 library/core/src/hint.rs                                | 2 +-
 library/core/tests/lib.rs                               | 1 -
 library/std/src/lib.rs                                  | 1 -
 library/test/src/lib.rs                                 | 1 -
 src/test/incremental/spans_significant_w_panic.rs       | 1 -
 src/test/ui/box/issue-95036.rs                          | 2 +-
 src/test/ui/consts/cast-discriminant-zst-enum.rs        | 1 -
 src/test/ui/consts/const_discriminant.rs                | 1 -
 src/test/ui/issues/issue-99838.rs                       | 2 +-
 src/test/ui/oom_unwind.rs                               | 2 --
 src/test/ui/process/process-panic-after-fork.rs         | 1 -
 src/test/ui/sanitize/address.rs                         | 4 +---
 src/test/ui/sanitize/hwaddress.rs                       | 2 --
 src/test/ui/sanitize/leak.rs                            | 2 --
 src/test/ui/sanitize/memory-eager.rs                    | 1 -
 src/test/ui/sanitize/memory.rs                          | 1 -
 src/tools/miri/tests/fail/invalid_bool.rs               | 2 +-
 src/tools/miri/tests/pass/float.rs                      | 2 +-
 src/tools/miri/tests/pass/u128.rs                       | 1 -
 23 files changed, 8 insertions(+), 28 deletions(-)

diff --git a/compiler/rustc_codegen_cranelift/example/std_example.rs b/compiler/rustc_codegen_cranelift/example/std_example.rs
index 0b5b6cd55d720..ad108c34992e3 100644
--- a/compiler/rustc_codegen_cranelift/example/std_example.rs
+++ b/compiler/rustc_codegen_cranelift/example/std_example.rs
@@ -1,4 +1,4 @@
-#![feature(core_intrinsics, generators, generator_trait, is_sorted, bench_black_box)]
+#![feature(core_intrinsics, generators, generator_trait, is_sorted)]
 
 #[cfg(target_arch = "x86_64")]
 use std::arch::x86_64::*;
diff --git a/compiler/rustc_codegen_gcc/tests/run/int.rs b/compiler/rustc_codegen_gcc/tests/run/int.rs
index 2b90e4ae8d82b..75779622b54cd 100644
--- a/compiler/rustc_codegen_gcc/tests/run/int.rs
+++ b/compiler/rustc_codegen_gcc/tests/run/int.rs
@@ -3,7 +3,7 @@
 // Run-time:
 //   status: 0
 
-#![feature(bench_black_box, const_black_box, core_intrinsics, start)]
+#![feature(const_black_box, core_intrinsics, start)]
 
 #![no_std]
 
diff --git a/compiler/rustc_index/src/lib.rs b/compiler/rustc_index/src/lib.rs
index a00d7bd680147..51d30f2868990 100644
--- a/compiler/rustc_index/src/lib.rs
+++ b/compiler/rustc_index/src/lib.rs
@@ -1,7 +1,6 @@
 #![deny(rustc::untranslatable_diagnostic)]
 #![deny(rustc::diagnostic_outside_of_impl)]
 #![feature(allow_internal_unstable)]
-#![feature(bench_black_box)]
 #![feature(extend_one)]
 #![cfg_attr(bootstrap, feature(let_else))]
 #![feature(min_specialization)]
diff --git a/library/alloc/tests/lib.rs b/library/alloc/tests/lib.rs
index 490c0d8f76cda..f83d58bd1b5e0 100644
--- a/library/alloc/tests/lib.rs
+++ b/library/alloc/tests/lib.rs
@@ -41,7 +41,6 @@
 #![feature(pointer_is_aligned)]
 #![feature(slice_flatten)]
 #![feature(thin_box)]
-#![feature(bench_black_box)]
 #![feature(strict_provenance)]
 #![feature(once_cell)]
 #![feature(drain_keep_rest)]
diff --git a/library/core/src/hint.rs b/library/core/src/hint.rs
index 764e2796202c9..f9267371aa745 100644
--- a/library/core/src/hint.rs
+++ b/library/core/src/hint.rs
@@ -217,7 +217,7 @@ pub fn spin_loop() {
 ///
 /// [`std::convert::identity`]: crate::convert::identity
 #[inline]
-#[unstable(feature = "bench_black_box", issue = "64102")]
+#[stable(feature = "bench_black_box", since = "CURRENT_RUSTC_VERSION")]
 #[rustc_const_unstable(feature = "const_black_box", issue = "none")]
 pub const fn black_box(dummy: T) -> T {
     crate::intrinsics::black_box(dummy)
diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs
index 46f603eaebaca..6d58ed9743d6a 100644
--- a/library/core/tests/lib.rs
+++ b/library/core/tests/lib.rs
@@ -2,7 +2,6 @@
 #![feature(array_chunks)]
 #![feature(array_methods)]
 #![feature(array_windows)]
-#![feature(bench_black_box)]
 #![feature(bigint_helper_methods)]
 #![feature(cell_update)]
 #![feature(const_assume)]
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs
index 3131dd4726984..8e924608d436e 100644
--- a/library/std/src/lib.rs
+++ b/library/std/src/lib.rs
@@ -351,7 +351,6 @@
 #![feature(trace_macros)]
 //
 // Only used in tests/benchmarks:
-#![feature(bench_black_box)]
 //
 // Only for const-ness:
 #![feature(const_io_structs)]
diff --git a/library/test/src/lib.rs b/library/test/src/lib.rs
index 3b7193adcc758..33c6ea5853227 100644
--- a/library/test/src/lib.rs
+++ b/library/test/src/lib.rs
@@ -15,7 +15,6 @@
 
 #![unstable(feature = "test", issue = "50297")]
 #![doc(test(attr(deny(warnings))))]
-#![feature(bench_black_box)]
 #![feature(internal_output_capture)]
 #![feature(staged_api)]
 #![feature(process_exitcode_internals)]
diff --git a/src/test/incremental/spans_significant_w_panic.rs b/src/test/incremental/spans_significant_w_panic.rs
index e9e35791aa158..6f51c9729e370 100644
--- a/src/test/incremental/spans_significant_w_panic.rs
+++ b/src/test/incremental/spans_significant_w_panic.rs
@@ -8,7 +8,6 @@
 // compile-flags: -C overflow-checks=on -Z query-dep-graph
 
 #![feature(rustc_attrs)]
-#![feature(bench_black_box)]
 #![rustc_partition_codegened(module = "spans_significant_w_panic", cfg = "rpass2")]
 #![rustc_partition_codegened(module = "spans_significant_w_panic", cfg = "rpass4")]
 
diff --git a/src/test/ui/box/issue-95036.rs b/src/test/ui/box/issue-95036.rs
index c2d4275aa49d3..0611fabc15c08 100644
--- a/src/test/ui/box/issue-95036.rs
+++ b/src/test/ui/box/issue-95036.rs
@@ -1,7 +1,7 @@
 // compile-flags: -O
 // build-pass
 
-#![feature(allocator_api, bench_black_box)]
+#![feature(allocator_api)]
 
 #[inline(never)]
 pub fn by_ref(node: &mut Box<[u8; 1], &std::alloc::Global>) {
diff --git a/src/test/ui/consts/cast-discriminant-zst-enum.rs b/src/test/ui/consts/cast-discriminant-zst-enum.rs
index e59ae297da1a7..2767f178fb664 100644
--- a/src/test/ui/consts/cast-discriminant-zst-enum.rs
+++ b/src/test/ui/consts/cast-discriminant-zst-enum.rs
@@ -1,6 +1,5 @@
 // run-pass
 // Test a ZST enum whose dicriminant is ~0i128. This caused an ICE when casting to an i32.
-#![feature(bench_black_box)]
 use std::hint::black_box;
 
 #[derive(Copy, Clone)]
diff --git a/src/test/ui/consts/const_discriminant.rs b/src/test/ui/consts/const_discriminant.rs
index f623c5101f4cd..79e68590e85d4 100644
--- a/src/test/ui/consts/const_discriminant.rs
+++ b/src/test/ui/consts/const_discriminant.rs
@@ -1,6 +1,5 @@
 // run-pass
 #![feature(const_discriminant)]
-#![feature(bench_black_box)]
 #![allow(dead_code)]
 
 use std::mem::{discriminant, Discriminant};
diff --git a/src/test/ui/issues/issue-99838.rs b/src/test/ui/issues/issue-99838.rs
index eaeeac72b25e1..2e81d5e8221c4 100644
--- a/src/test/ui/issues/issue-99838.rs
+++ b/src/test/ui/issues/issue-99838.rs
@@ -1,5 +1,5 @@
 // run-pass
-#![feature(bench_black_box)]
+
 use std::hint;
 
 struct U16(u16);
diff --git a/src/test/ui/oom_unwind.rs b/src/test/ui/oom_unwind.rs
index d036c817a0e83..21a8fb2b22bee 100644
--- a/src/test/ui/oom_unwind.rs
+++ b/src/test/ui/oom_unwind.rs
@@ -4,8 +4,6 @@
 // needs-unwind
 // only-linux
 
-#![feature(bench_black_box)]
-
 use std::hint::black_box;
 use std::mem::forget;
 use std::panic::catch_unwind;
diff --git a/src/test/ui/process/process-panic-after-fork.rs b/src/test/ui/process/process-panic-after-fork.rs
index 1ccf6bb051c20..08b30b600e737 100644
--- a/src/test/ui/process/process-panic-after-fork.rs
+++ b/src/test/ui/process/process-panic-after-fork.rs
@@ -7,7 +7,6 @@
 // ignore-sgx no processes
 // ignore-android: FIXME(#85261)
 
-#![feature(bench_black_box)]
 #![feature(rustc_private)]
 #![feature(never_type)]
 #![feature(panic_always_abort)]
diff --git a/src/test/ui/sanitize/address.rs b/src/test/ui/sanitize/address.rs
index 9a26a351d992c..5b2cea87560fd 100644
--- a/src/test/ui/sanitize/address.rs
+++ b/src/test/ui/sanitize/address.rs
@@ -5,9 +5,7 @@
 //
 // run-fail
 // error-pattern: AddressSanitizer: stack-buffer-overflow
-// error-pattern: 'xs' (line 15) <== Memory access at offset
-
-#![feature(bench_black_box)]
+// error-pattern: 'xs' (line 13) <== Memory access at offset
 
 use std::hint::black_box;
 
diff --git a/src/test/ui/sanitize/hwaddress.rs b/src/test/ui/sanitize/hwaddress.rs
index b988035f75e4c..f9b37a155aad7 100644
--- a/src/test/ui/sanitize/hwaddress.rs
+++ b/src/test/ui/sanitize/hwaddress.rs
@@ -10,8 +10,6 @@
 // run-fail
 // error-pattern: HWAddressSanitizer: tag-mismatch
 
-#![feature(bench_black_box)]
-
 use std::hint::black_box;
 
 fn main() {
diff --git a/src/test/ui/sanitize/leak.rs b/src/test/ui/sanitize/leak.rs
index f63f81352dada..cbb44ae8acd60 100644
--- a/src/test/ui/sanitize/leak.rs
+++ b/src/test/ui/sanitize/leak.rs
@@ -6,8 +6,6 @@
 // run-fail
 // error-pattern: LeakSanitizer: detected memory leaks
 
-#![feature(bench_black_box)]
-
 use std::hint::black_box;
 use std::mem;
 
diff --git a/src/test/ui/sanitize/memory-eager.rs b/src/test/ui/sanitize/memory-eager.rs
index cc0593ec07dcd..0018c2f758182 100644
--- a/src/test/ui/sanitize/memory-eager.rs
+++ b/src/test/ui/sanitize/memory-eager.rs
@@ -17,7 +17,6 @@
 
 #![feature(core_intrinsics)]
 #![feature(start)]
-#![feature(bench_black_box)]
 
 use std::hint::black_box;
 use std::mem::MaybeUninit;
diff --git a/src/test/ui/sanitize/memory.rs b/src/test/ui/sanitize/memory.rs
index 14d4de65dd378..1a9ac3a4f3c32 100644
--- a/src/test/ui/sanitize/memory.rs
+++ b/src/test/ui/sanitize/memory.rs
@@ -16,7 +16,6 @@
 
 #![feature(core_intrinsics)]
 #![feature(start)]
-#![feature(bench_black_box)]
 #![allow(invalid_value)]
 
 use std::hint::black_box;
diff --git a/src/tools/miri/tests/fail/invalid_bool.rs b/src/tools/miri/tests/fail/invalid_bool.rs
index 525f8831c1c00..dde414f417740 100644
--- a/src/tools/miri/tests/fail/invalid_bool.rs
+++ b/src/tools/miri/tests/fail/invalid_bool.rs
@@ -1,7 +1,7 @@
 // Validation makes this fail in the wrong place
 // Make sure we find these even with many checks disabled.
 //@compile-flags: -Zmiri-disable-alignment-check -Zmiri-disable-stacked-borrows -Zmiri-disable-validation
-#![feature(bench_black_box)]
+
 
 fn main() {
     let b = unsafe { std::mem::transmute::(2) };
diff --git a/src/tools/miri/tests/pass/float.rs b/src/tools/miri/tests/pass/float.rs
index 48dd99441ebff..ce62fb0de04f8 100644
--- a/src/tools/miri/tests/pass/float.rs
+++ b/src/tools/miri/tests/pass/float.rs
@@ -1,4 +1,4 @@
-#![feature(stmt_expr_attributes, bench_black_box)]
+#![feature(stmt_expr_attributes)]
 #![allow(arithmetic_overflow)]
 use std::fmt::Debug;
 use std::hint::black_box;
diff --git a/src/tools/miri/tests/pass/u128.rs b/src/tools/miri/tests/pass/u128.rs
index 0ef7a514cb653..6def529dbe7c3 100644
--- a/src/tools/miri/tests/pass/u128.rs
+++ b/src/tools/miri/tests/pass/u128.rs
@@ -1,4 +1,3 @@
-#![feature(bench_black_box)]
 use std::hint::black_box as b;
 
 fn main() {

From d7b6bd8f131a269102662ff249e916d6f7069f97 Mon Sep 17 00:00:00 2001
From: Takayuki Maeda 
Date: Tue, 27 Sep 2022 17:20:55 +0900
Subject: [PATCH 316/586] improve errors for incomplete functions in struct
 definitions

---
 compiler/rustc_parse/src/parser/item.rs       | 28 +++++++++++--------
 .../ui/parser/fn-field-parse-error-ice.rs     |  2 +-
 .../ui/parser/fn-field-parse-error-ice.stderr | 10 ++++---
 .../incomplete-fn-in-struct-definition.rs     |  5 ++++
 .../incomplete-fn-in-struct-definition.stderr | 13 +++++++++
 5 files changed, 42 insertions(+), 16 deletions(-)
 create mode 100644 src/test/ui/structs/incomplete-fn-in-struct-definition.rs
 create mode 100644 src/test/ui/structs/incomplete-fn-in-struct-definition.stderr

diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs
index 6c4cfcf6ddf4c..746ddfdf4b97e 100644
--- a/compiler/rustc_parse/src/parser/item.rs
+++ b/compiler/rustc_parse/src/parser/item.rs
@@ -1753,18 +1753,24 @@ impl<'a> Parser<'a> {
                 };
                 // We use `parse_fn` to get a span for the function
                 let fn_parse_mode = FnParseMode { req_name: |_| true, req_body: true };
-                if let Err(mut db) =
-                    self.parse_fn(&mut AttrVec::new(), fn_parse_mode, lo, &inherited_vis)
-                {
-                    db.delay_as_bug();
+                match self.parse_fn(&mut AttrVec::new(), fn_parse_mode, lo, &inherited_vis) {
+                    Ok(_) => {
+                        let mut err = self.struct_span_err(
+                            lo.to(self.prev_token.span),
+                            &format!("functions are not allowed in {adt_ty} definitions"),
+                        );
+                        err.help(
+                            "unlike in C++, Java, and C#, functions are declared in `impl` blocks",
+                        );
+                        err.help("see https://doc.rust-lang.org/book/ch05-03-method-syntax.html for more information");
+                        err
+                    }
+                    Err(err) => {
+                        err.cancel();
+                        self.restore_snapshot(snapshot);
+                        self.expected_ident_found()
+                    }
                 }
-                let mut err = self.struct_span_err(
-                    lo.to(self.prev_token.span),
-                    &format!("functions are not allowed in {adt_ty} definitions"),
-                );
-                err.help("unlike in C++, Java, and C#, functions are declared in `impl` blocks");
-                err.help("see https://doc.rust-lang.org/book/ch05-03-method-syntax.html for more information");
-                err
             } else if self.eat_keyword(kw::Struct) {
                 match self.parse_item_struct() {
                     Ok((ident, _)) => {
diff --git a/src/test/ui/parser/fn-field-parse-error-ice.rs b/src/test/ui/parser/fn-field-parse-error-ice.rs
index 4ea55062fc4be..188257ea53a31 100644
--- a/src/test/ui/parser/fn-field-parse-error-ice.rs
+++ b/src/test/ui/parser/fn-field-parse-error-ice.rs
@@ -3,7 +3,7 @@
 struct Baz {
     inner : dyn fn ()
     //~^ ERROR expected `,`, or `}`, found keyword `fn`
-    //~| ERROR functions are not allowed in struct definitions
+    //~| ERROR expected identifier, found keyword `fn`
     //~| ERROR cannot find type `dyn` in this scope
 }
 
diff --git a/src/test/ui/parser/fn-field-parse-error-ice.stderr b/src/test/ui/parser/fn-field-parse-error-ice.stderr
index e9583f55b8efb..3bf68e8cc04fe 100644
--- a/src/test/ui/parser/fn-field-parse-error-ice.stderr
+++ b/src/test/ui/parser/fn-field-parse-error-ice.stderr
@@ -4,16 +4,18 @@ error: expected `,`, or `}`, found keyword `fn`
 LL |     inner : dyn fn ()
    |                ^ help: try adding a comma: `,`
 
-error: functions are not allowed in struct definitions
+error: expected identifier, found keyword `fn`
   --> $DIR/fn-field-parse-error-ice.rs:4:17
    |
 LL | struct Baz {
    |        --- while parsing this struct
 LL |     inner : dyn fn ()
-   |                 ^^
+   |                 ^^ expected identifier, found keyword
    |
-   = help: unlike in C++, Java, and C#, functions are declared in `impl` blocks
-   = help: see https://doc.rust-lang.org/book/ch05-03-method-syntax.html for more information
+help: escape `fn` to use it as an identifier
+   |
+LL |     inner : dyn r#fn ()
+   |                 ++
 
 error[E0412]: cannot find type `dyn` in this scope
   --> $DIR/fn-field-parse-error-ice.rs:4:13
diff --git a/src/test/ui/structs/incomplete-fn-in-struct-definition.rs b/src/test/ui/structs/incomplete-fn-in-struct-definition.rs
new file mode 100644
index 0000000000000..b43d1d4395a58
--- /dev/null
+++ b/src/test/ui/structs/incomplete-fn-in-struct-definition.rs
@@ -0,0 +1,5 @@
+fn main() {}
+
+struct S {
+    fn //~ ERROR expected identifier, found keyword `fn`
+}
diff --git a/src/test/ui/structs/incomplete-fn-in-struct-definition.stderr b/src/test/ui/structs/incomplete-fn-in-struct-definition.stderr
new file mode 100644
index 0000000000000..2c86060671021
--- /dev/null
+++ b/src/test/ui/structs/incomplete-fn-in-struct-definition.stderr
@@ -0,0 +1,13 @@
+error: expected identifier, found keyword `fn`
+  --> $DIR/incomplete-fn-in-struct-definition.rs:4:5
+   |
+LL |     fn
+   |     ^^ expected identifier, found keyword
+   |
+help: escape `fn` to use it as an identifier
+   |
+LL |     r#fn
+   |     ++
+
+error: aborting due to previous error
+

From 8846c0853d8687fda0e5f23f6687b03b243980ee Mon Sep 17 00:00:00 2001
From: Jacob Hoffman-Andrews 
Date: Tue, 27 Sep 2022 09:21:24 -0700
Subject: [PATCH 317/586] rustdoc: use CSS containment to speed up render

https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Containment

This affected layout a little and required adjustments to the CSS to
keep spacing the same. In particular, the margins of adjacent items
usually overlap with each other. However, when an item has contain:
layout, any margins of child nodes push out the size of the item itself.
This was making spacing between items a little too big. To solve that, I
removed margins in some places: in particular for certain classes that
often occur at the end of a `details.rustdoc-toggle` block, I removed
their bottom margin. Generally, the margins provided by the next item
down are sufficient.

Also remove an unnecessary margin-top on .code-header.
---
 src/librustdoc/html/static/css/rustdoc.css    | 42 +++++++++++++------
 .../rustdoc-gui/sidebar-mobile-scroll.goml    |  6 +--
 2 files changed, 32 insertions(+), 16 deletions(-)

diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css
index e7a05b80c127f..a3712a73b5195 100644
--- a/src/librustdoc/html/static/css/rustdoc.css
+++ b/src/librustdoc/html/static/css/rustdoc.css
@@ -132,7 +132,7 @@ h1, h2, h3, h4, h5, h6 {
 	font-weight: 500;
 }
 h1, h2, h3, h4 {
-	margin: 20px 0 15px 0;
+	margin: 25px 0 15px 0;
 	padding-bottom: 6px;
 }
 .docblock h3, .docblock h4, h5, h6 {
@@ -176,8 +176,6 @@ h4.code-header {
 	border-bottom-style: none;
 	margin: 0;
 	padding: 0;
-	margin-top: 0.6rem;
-	margin-bottom: 0.4rem;
 }
 .impl,
 .impl-items .method,
@@ -292,6 +290,11 @@ p {
 	   https://www.w3.org/WAI/WCAG21/Understanding/visual-presentation.html */
 	margin: 0 0 .75em 0;
 }
+/* For the last child of a div, the margin will be taken care of
+	by the margin-top of the next item. */
+p:last-child {
+	margin: 0;
+}
 
 summary {
 	outline: none;
@@ -565,9 +568,16 @@ h2.location a {
 
 .rustdoc .example-wrap {
 	display: flex;
-	margin-bottom: 10px;
 	position: relative;
 }
+.rustdoc .example-wrap {
+	margin-bottom: 10px;
+}
+/* For the last child of a div, the margin will be taken care of
+	by the margin-top of the next item. */
+.rustdoc .example-wrap:last-child {
+	margin-bottom: 0px;
+}
 
 pre.example-line-numbers {
 	overflow: initial;
@@ -726,10 +736,6 @@ pre, .rustdoc.source .example-wrap {
 	margin-left: 24px;
 }
 
-.content .impl-items .docblock, .content .impl-items .item-info {
-	margin-bottom: .6em;
-}
-
 #main-content > .item-info {
 	margin-top: 0;
 	margin-left: 0;
@@ -1532,6 +1538,16 @@ details.dir-entry a {
 	display: block;
 }
 
+/* We use CSS containment on the details elements because most sizeable elements
+	of the page are contained in one of these. This also makes re-rendering
+	faster on document changes (like closing and opening toggles).
+	Unfortunately we can't yet specify contain: content or contain: strict
+	because the [-]/[+] toggles extend past the boundaries of the 
+ https://developer.mozilla.org/en-US/docs/Web/CSS/contain */ +details.rustdoc-toggle { + contain: layout; +} + /* The hideme class is used on summary tags that contain a span with placeholder text shown only when the toggle is closed. For instance, "Expand description" or "Show methods". */ @@ -2012,17 +2028,17 @@ in storage.js plus the media query with (min-width: 701px) margin-bottom: 0.75em; } -.method-toggle[open] { +.method-toggle[open]:not(:last-child) { margin-bottom: 2em; } -.implementors-toggle[open] { +.implementors-toggle[open]:not(:last-child) { margin-bottom: 2em; } -#trait-implementations-list .method-toggle, -#synthetic-implementations-list .method-toggle, -#blanket-implementations-list .method-toggle { +#trait-implementations-list .method-toggle:not(:last-child), +#synthetic-implementations-list .method-toggle:not(:last-child), +#blanket-implementations-list .method-toggle:not(:last-child) { margin-bottom: 1em; } diff --git a/src/test/rustdoc-gui/sidebar-mobile-scroll.goml b/src/test/rustdoc-gui/sidebar-mobile-scroll.goml index dc50185f01b25..3259c02fa4920 100644 --- a/src/test/rustdoc-gui/sidebar-mobile-scroll.goml +++ b/src/test/rustdoc-gui/sidebar-mobile-scroll.goml @@ -6,7 +6,7 @@ assert-css: (".sidebar", {"display": "block", "left": "-1000px"}) // Scroll down. scroll-to: "//h2[@id='blanket-implementations']" -assert-window-property: {"pageYOffset": "643"} +assert-window-property: {"pageYOffset": "645"} // Open the sidebar menu. click: ".sidebar-menu-toggle" @@ -21,11 +21,11 @@ assert-window-property: {"pageYOffset": "0"} // Close the sidebar menu. Make sure the scroll position gets restored. click: ".sidebar-menu-toggle" wait-for-css: (".sidebar", {"left": "-1000px"}) -assert-window-property: {"pageYOffset": "643"} +assert-window-property: {"pageYOffset": "645"} // Now test that scrollability returns when the browser window is just resized. click: ".sidebar-menu-toggle" wait-for-css: (".sidebar", {"left": "0px"}) assert-window-property: {"pageYOffset": "0"} size: (900, 600) -assert-window-property: {"pageYOffset": "643"} +assert-window-property: {"pageYOffset": "645"} From 5095f54219d16cc67b087763044acfce09c3fc9d Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Tue, 27 Sep 2022 17:46:34 +0100 Subject: [PATCH 318/586] Update cargo 22 commits in 73ba3f35e0205844418260722c11602113179c4a..f5fed93ba24607980647962c59863bbabb03ce14 2022-09-18 06:38:16 +0000 to 2022-09-27 12:03:57 +0000 - build-scripts.md: Use em dash consistently. (rust-lang/cargo#11150) - Indicate how Cargo locates the manifest (rust-lang/cargo#10770) - Reduce references to `[project]` within cargo (rust-lang/cargo#11135) - Iteratively construct target cfg (rust-lang/cargo#11114) - update comment about `CARGO_BIN_EXE_` (rust-lang/cargo#11146) - Call out that not all config values can be set via env vars (rust-lang/cargo#11139) - Bump to 0.67.0, update changelog (rust-lang/cargo#11137) - ci: update toolchain for building api doc (rust-lang/cargo#11134) - Http publish not noop (rust-lang/cargo#11111) - Improve errors for TOML fields that support workspace inheritance (rust-lang/cargo#11113) - switch to `std::task::ready!()` where possible (rust-lang/cargo#11130) - Report cmd aliasing failure with more contexts (rust-lang/cargo#11087) - minor: remove unused mut (rust-lang/cargo#11127) - fix(cli): Forward non-UTF8 arguments to external subcommands (rust-lang/cargo#11118) - This change adds an example to the authors attribute in the manifest. (rust-lang/cargo#10938) - Add support for relative git submodule paths (rust-lang/cargo#11106) - make unknown features on `cargo add` more discoverable (rust-lang/cargo#11098) - Unlink old final artifacts before compilation (rust-lang/cargo#11122) - refactor(cli): Prepare for clap v4 (rust-lang/cargo#11116) - fix(cli): Error trailing args rather than ignore (rust-lang/cargo#11119) - Add a minor clarification (rust-lang/cargo#11093) - doc(changelog): mention CVE fixes (rust-lang/cargo#11104) --- Cargo.lock | 24 +++++++++++++++++++++++- src/tools/cargo | 2 +- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c99a07f40b2e5..180f70474ba67 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -288,7 +288,7 @@ dependencies = [ [[package]] name = "cargo" -version = "0.66.0" +version = "0.67.0" dependencies = [ "anyhow", "atty", @@ -330,8 +330,10 @@ dependencies = [ "pretty_env_logger", "rustc-workspace-hack", "rustfix", + "same-file", "semver", "serde", + "serde-value", "serde_ignored", "serde_json", "shell-escape", @@ -417,6 +419,7 @@ dependencies = [ "anyhow", "cargo-test-macro", "cargo-util", + "crates-io", "filetime", "flate2", "git2", @@ -2418,6 +2421,15 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "ordered-float" +version = "2.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7940cf2ca942593318d07fcf2596cdca60a85c9e7fab408a5e21a4f9dcd40d87" +dependencies = [ + "num-traits", +] + [[package]] name = "os_info" version = "3.5.0" @@ -4437,6 +4449,16 @@ dependencies = [ "serde_derive", ] +[[package]] +name = "serde-value" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3a1a3341211875ef120e117ea7fd5228530ae7e7036a779fdc9117be6b3282c" +dependencies = [ + "ordered-float", + "serde", +] + [[package]] name = "serde_derive" version = "1.0.143" diff --git a/src/tools/cargo b/src/tools/cargo index 73ba3f35e0205..f5fed93ba2460 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit 73ba3f35e0205844418260722c11602113179c4a +Subproject commit f5fed93ba24607980647962c59863bbabb03ce14 From 337a73da6e819a9c6374e9c4ce07565cde8f91e2 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Mon, 5 Sep 2022 17:21:19 +0200 Subject: [PATCH 319/586] Do not overwrite binders for another HirId. --- compiler/rustc_ast_lowering/src/item.rs | 2 + compiler/rustc_hir/src/hir.rs | 1 + compiler/rustc_hir/src/intravisit.rs | 14 ++++- compiler/rustc_hir_analysis/src/collect.rs | 4 +- compiler/rustc_resolve/src/late/lifetimes.rs | 55 ++++++++++++------- .../higher-ranked-fn-type.quiet.stderr | 18 ++++++ .../ui/where-clauses/higher-ranked-fn-type.rs | 25 +++++++++ .../higher-ranked-fn-type.verbose.stderr | 18 ++++++ 8 files changed, 112 insertions(+), 25 deletions(-) create mode 100644 src/test/ui/where-clauses/higher-ranked-fn-type.quiet.stderr create mode 100644 src/test/ui/where-clauses/higher-ranked-fn-type.rs create mode 100644 src/test/ui/where-clauses/higher-ranked-fn-type.verbose.stderr diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index d9b18d68e537f..9a46444d82398 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -1478,6 +1478,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let bounded_ty = self.ty_path(ty_id, param_span, hir::QPath::Resolved(None, ty_path)); Some(hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate { + hir_id: self.next_id(), bounded_ty: self.arena.alloc(bounded_ty), bounds, span, @@ -1508,6 +1509,7 @@ impl<'hir> LoweringContext<'_, 'hir> { ref bounds, span, }) => hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate { + hir_id: self.next_id(), bound_generic_params: self.lower_generic_params(bound_generic_params), bounded_ty: self .lower_ty(bounded_ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Type)), diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index c1948052e3c51..cde8ec7370124 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -731,6 +731,7 @@ pub enum PredicateOrigin { /// A type bound (e.g., `for<'c> Foo: Send + Clone + 'c`). #[derive(Debug, HashStable_Generic)] pub struct WhereBoundPredicate<'hir> { + pub hir_id: HirId, pub span: Span, /// Origin of the predicate. pub origin: PredicateOrigin, diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index 8f5f314ecae1d..8777a54ba09b4 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -847,20 +847,28 @@ pub fn walk_where_predicate<'v, V: Visitor<'v>>( ) { match *predicate { WherePredicate::BoundPredicate(WhereBoundPredicate { + hir_id, ref bounded_ty, bounds, bound_generic_params, - .. + origin: _, + span: _, }) => { + visitor.visit_id(hir_id); visitor.visit_ty(bounded_ty); walk_list!(visitor, visit_param_bound, bounds); walk_list!(visitor, visit_generic_param, bound_generic_params); } - WherePredicate::RegionPredicate(WhereRegionPredicate { ref lifetime, bounds, .. }) => { + WherePredicate::RegionPredicate(WhereRegionPredicate { + ref lifetime, + bounds, + span: _, + in_where_clause: _, + }) => { visitor.visit_lifetime(lifetime); walk_list!(visitor, visit_param_bound, bounds); } - WherePredicate::EqPredicate(WhereEqPredicate { ref lhs_ty, ref rhs_ty, .. }) => { + WherePredicate::EqPredicate(WhereEqPredicate { ref lhs_ty, ref rhs_ty, span: _ }) => { visitor.visit_ty(lhs_ty); visitor.visit_ty(rhs_ty); } diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index e7deae2b557cd..97cdfff74d7eb 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -697,7 +697,7 @@ impl<'tcx> ItemCtxt<'tcx> { } else { None }; - let bvars = self.tcx.late_bound_vars(bp.bounded_ty.hir_id); + let bvars = self.tcx.late_bound_vars(bp.hir_id); bp.bounds.iter().filter_map(move |b| bt.map(|bt| (bt, b, bvars))).filter( |(_, b, _)| match assoc_name { @@ -2295,7 +2295,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP match predicate { hir::WherePredicate::BoundPredicate(bound_pred) => { let ty = icx.to_ty(bound_pred.bounded_ty); - let bound_vars = icx.tcx.late_bound_vars(bound_pred.bounded_ty.hir_id); + let bound_vars = icx.tcx.late_bound_vars(bound_pred.hir_id); // Keep the type around in a dummy predicate, in case of no bounds. // That way, `where Ty:` is not a complete noop (see #53696) and `Ty` diff --git a/compiler/rustc_resolve/src/late/lifetimes.rs b/compiler/rustc_resolve/src/late/lifetimes.rs index 9fb1af20ac976..0c29ff364dcdf 100644 --- a/compiler/rustc_resolve/src/late/lifetimes.rs +++ b/compiler/rustc_resolve/src/late/lifetimes.rs @@ -326,6 +326,7 @@ fn convert_named_region_map(named_region_map: NamedRegionMap) -> ResolveLifetime } debug!(?rl.defs); + debug!(?rl.late_bound_vars); rl } @@ -507,7 +508,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { }) .unzip(); - self.map.late_bound_vars.insert(e.hir_id, binders); + self.record_late_bound_vars(e.hir_id, binders); let scope = Scope::Binder { hir_id: e.hir_id, lifetimes, @@ -531,7 +532,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { match &item.kind { hir::ItemKind::Impl(hir::Impl { of_trait, .. }) => { if let Some(of_trait) = of_trait { - self.map.late_bound_vars.insert(of_trait.hir_ref_id, Vec::default()); + self.record_late_bound_vars(of_trait.hir_ref_id, Vec::default()); } } _ => {} @@ -583,7 +584,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { resolved_lifetimes.late_bound_vars.iter() { late_bound_vars.iter().for_each(|(&local_id, late_bound_vars)| { - self.map.late_bound_vars.insert( + self.record_late_bound_vars( hir::HirId { owner, local_id }, late_bound_vars.clone(), ); @@ -614,7 +615,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => None, }) .collect(); - self.map.late_bound_vars.insert(item.hir_id(), vec![]); + self.record_late_bound_vars(item.hir_id(), vec![]); let scope = Scope::Binder { hir_id: item.hir_id(), lifetimes, @@ -663,7 +664,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { (pair, r) }) .unzip(); - self.map.late_bound_vars.insert(ty.hir_id, binders); + self.record_late_bound_vars(ty.hir_id, binders); let scope = Scope::Binder { hir_id: ty.hir_id, lifetimes, @@ -817,7 +818,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => {} } } - self.map.late_bound_vars.insert(ty.hir_id, vec![]); + self.record_late_bound_vars(ty.hir_id, vec![]); let scope = Scope::Binder { hir_id: ty.hir_id, @@ -861,7 +862,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => None, }) .collect(); - self.map.late_bound_vars.insert(trait_item.hir_id(), vec![]); + self.record_late_bound_vars(trait_item.hir_id(), vec![]); let scope = Scope::Binder { hir_id: trait_item.hir_id(), lifetimes, @@ -909,9 +910,9 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { GenericParamKind::Const { .. } | GenericParamKind::Type { .. } => None, }) .collect(); - self.map.late_bound_vars.insert(ty.hir_id, vec![]); + self.record_late_bound_vars(impl_item.hir_id(), vec![]); let scope = Scope::Binder { - hir_id: ty.hir_id, + hir_id: impl_item.hir_id(), lifetimes, s: self.scope, scope_type: BinderScopeType::Normal, @@ -995,13 +996,14 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { for predicate in generics.predicates { match predicate { &hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate { + hir_id, ref bounded_ty, bounds, ref bound_generic_params, origin, .. }) => { - let (lifetimes, binders): (FxIndexMap, Vec<_>) = + let lifetimes: FxIndexMap = bound_generic_params .iter() .filter(|param| { @@ -1009,19 +1011,23 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { }) .enumerate() .map(|(late_bound_idx, param)| { - let pair = - Region::late(late_bound_idx as u32, this.tcx.hir(), param); - let r = late_region_as_bound_region(this.tcx, &pair.1); - (pair, r) + Region::late(late_bound_idx as u32, this.tcx.hir(), param) + }) + .collect(); + let binders: Vec<_> = + lifetimes + .iter() + .map(|(_, region)| { + late_region_as_bound_region(this.tcx, region) }) - .unzip(); - this.map.late_bound_vars.insert(bounded_ty.hir_id, binders.clone()); + .collect(); + this.record_late_bound_vars(hir_id, binders.clone()); // Even if there are no lifetimes defined here, we still wrap it in a binder // scope. If there happens to be a nested poly trait ref (an error), that // will be `Concatenating` anyways, so we don't have to worry about the depth // being wrong. let scope = Scope::Binder { - hir_id: bounded_ty.hir_id, + hir_id, lifetimes, s: this.scope, scope_type: BinderScopeType::Normal, @@ -1089,7 +1095,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { // imagine there's a better way to go about this. let (binders, scope_type) = self.poly_trait_ref_binder_info(); - self.map.late_bound_vars.insert(*hir_id, binders); + self.record_late_bound_vars(*hir_id, binders); let scope = Scope::Binder { hir_id: *hir_id, lifetimes: FxIndexMap::default(), @@ -1127,7 +1133,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { binders.extend(binders_iter); debug!(?binders); - self.map.late_bound_vars.insert(trait_ref.trait_ref.hir_ref_id, binders); + self.record_late_bound_vars(trait_ref.trait_ref.hir_ref_id, binders); // Always introduce a scope here, even if this is in a where clause and // we introduced the binders around the bounded Ty. In that case, we @@ -1211,6 +1217,15 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { } } + fn record_late_bound_vars(&mut self, hir_id: hir::HirId, binder: Vec) { + if let Some(old) = self.map.late_bound_vars.insert(hir_id, binder) { + bug!( + "overwrote bound vars for {hir_id:?}:\nold={old:?}\nnew={:?}", + self.map.late_bound_vars[&hir_id] + ) + } + } + /// Visits self by adding a scope and handling recursive walk over the contents with `walk`. /// /// Handles visiting fns and methods. These are a bit complicated because we must distinguish @@ -1268,7 +1283,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { late_region_as_bound_region(self.tcx, &pair.1) }) .collect(); - self.map.late_bound_vars.insert(hir_id, binders); + self.record_late_bound_vars(hir_id, binders); let scope = Scope::Binder { hir_id, lifetimes, diff --git a/src/test/ui/where-clauses/higher-ranked-fn-type.quiet.stderr b/src/test/ui/where-clauses/higher-ranked-fn-type.quiet.stderr new file mode 100644 index 0000000000000..d9950a3d9b7cd --- /dev/null +++ b/src/test/ui/where-clauses/higher-ranked-fn-type.quiet.stderr @@ -0,0 +1,18 @@ +error[E0277]: the trait bound `for<'b> for<'b> fn(&'b ()): Foo` is not satisfied + --> $DIR/higher-ranked-fn-type.rs:20:5 + | +LL | called() + | ^^^^^^ the trait `for<'b> Foo` is not implemented for `for<'b> fn(&'b ())` + | +note: required by a bound in `called` + --> $DIR/higher-ranked-fn-type.rs:12:25 + | +LL | fn called() + | ------ required by a bound in this +LL | where +LL | for<'b> fn(&'b ()): Foo, + | ^^^ required by this bound in `called` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/where-clauses/higher-ranked-fn-type.rs b/src/test/ui/where-clauses/higher-ranked-fn-type.rs new file mode 100644 index 0000000000000..0d8893e08d319 --- /dev/null +++ b/src/test/ui/where-clauses/higher-ranked-fn-type.rs @@ -0,0 +1,25 @@ +// revisions: quiet verbose +// [verbose]compile-flags: -Zverbose + +#![allow(unused_parens)] + +trait Foo { + type Assoc; +} + +fn called() +where + for<'b> fn(&'b ()): Foo, +{ +} + +fn caller() +where + (for<'a> fn(&'a ())): Foo, +{ + called() + //[quiet]~^ ERROR the trait bound `for<'b> for<'b> fn(&'b ()): Foo` is not satisfied + //[verbose]~^^ ERROR the trait bound `for<'b> fn(&ReLateBound( +} + +fn main() {} diff --git a/src/test/ui/where-clauses/higher-ranked-fn-type.verbose.stderr b/src/test/ui/where-clauses/higher-ranked-fn-type.verbose.stderr new file mode 100644 index 0000000000000..24660ec3539e6 --- /dev/null +++ b/src/test/ui/where-clauses/higher-ranked-fn-type.verbose.stderr @@ -0,0 +1,18 @@ +error[E0277]: the trait bound `for<'b> fn(&ReLateBound(DebruijnIndex(1), BoundRegion { var: 0, kind: BrNamed(DefId(0:6 ~ higher_ranked_fn_type[1209]::called::'b), 'b) }) ()): Foo` is not satisfied + --> $DIR/higher-ranked-fn-type.rs:20:5 + | +LL | called() + | ^^^^^^ the trait `for<'b> Foo` is not implemented for `fn(&ReLateBound(DebruijnIndex(1), BoundRegion { var: 0, kind: BrNamed(DefId(0:6 ~ higher_ranked_fn_type[1209]::called::'b), 'b) }) ())` + | +note: required by a bound in `called` + --> $DIR/higher-ranked-fn-type.rs:12:25 + | +LL | fn called() + | ------ required by a bound in this +LL | where +LL | for<'b> fn(&'b ()): Foo, + | ^^^ required by this bound in `called` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. From ca2e0bb51ad1a00190430134c67da5cda356745e Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 27 Sep 2022 00:45:50 +0000 Subject: [PATCH 320/586] Deny associated type bindings within associated type bindings --- compiler/rustc_hir_analysis/src/astconv/mod.rs | 12 +++++++++--- src/test/ui/associated-consts/issue-102335-const.rs | 12 ++++++++++++ .../ui/associated-consts/issue-102335-const.stderr | 9 +++++++++ .../ui/associated-type-bounds/issue-102335-ty.rs | 12 ++++++++++++ .../ui/associated-type-bounds/issue-102335-ty.stderr | 9 +++++++++ .../ui/generic-associated-types/issue-102335-gat.rs | 12 ++++++++++++ .../generic-associated-types/issue-102335-gat.stderr | 9 +++++++++ src/test/ui/suggestions/issue-85347.rs | 1 + src/test/ui/suggestions/issue-85347.stderr | 11 +++++++++-- 9 files changed, 82 insertions(+), 5 deletions(-) create mode 100644 src/test/ui/associated-consts/issue-102335-const.rs create mode 100644 src/test/ui/associated-consts/issue-102335-const.stderr create mode 100644 src/test/ui/associated-type-bounds/issue-102335-ty.rs create mode 100644 src/test/ui/associated-type-bounds/issue-102335-ty.stderr create mode 100644 src/test/ui/generic-associated-types/issue-102335-gat.rs create mode 100644 src/test/ui/generic-associated-types/issue-102335-gat.stderr diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index b3cbb606c728d..244018ebbeb74 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -595,7 +595,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { "create_substs_for_associated_item(span: {:?}, item_def_id: {:?}, item_segment: {:?}", span, item_def_id, item_segment ); - self.create_substs_for_ast_path( + let (args, _) = self.create_substs_for_ast_path( span, item_def_id, parent_substs, @@ -603,8 +603,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { item_segment.args(), item_segment.infer_args, None, - ) - .0 + ); + + let assoc_bindings = self.create_assoc_bindings_for_generic_args(item_segment.args()); + if let Some(b) = assoc_bindings.first() { + Self::prohibit_assoc_ty_binding(self.tcx(), b.span); + } + + args } /// Instantiates the path for the given trait reference, assuming that it's diff --git a/src/test/ui/associated-consts/issue-102335-const.rs b/src/test/ui/associated-consts/issue-102335-const.rs new file mode 100644 index 0000000000000..f60cb92da7f6b --- /dev/null +++ b/src/test/ui/associated-consts/issue-102335-const.rs @@ -0,0 +1,12 @@ +#![feature(associated_const_equality)] + +trait T { + type A: S = 34>; + //~^ ERROR associated type bindings are not allowed here +} + +trait S { + const C: i32; +} + +fn main() {} diff --git a/src/test/ui/associated-consts/issue-102335-const.stderr b/src/test/ui/associated-consts/issue-102335-const.stderr new file mode 100644 index 0000000000000..531d15c5900c5 --- /dev/null +++ b/src/test/ui/associated-consts/issue-102335-const.stderr @@ -0,0 +1,9 @@ +error[E0229]: associated type bindings are not allowed here + --> $DIR/issue-102335-const.rs:4:17 + | +LL | type A: S = 34>; + | ^^^^^^^^ associated type not allowed here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0229`. diff --git a/src/test/ui/associated-type-bounds/issue-102335-ty.rs b/src/test/ui/associated-type-bounds/issue-102335-ty.rs new file mode 100644 index 0000000000000..363df73c1ffd7 --- /dev/null +++ b/src/test/ui/associated-type-bounds/issue-102335-ty.rs @@ -0,0 +1,12 @@ +trait T { + type A: S = ()>; + //~^ ERROR associated type bindings are not allowed here +} + +trait Q {} + +trait S { + type C: Q; +} + +fn main() {} diff --git a/src/test/ui/associated-type-bounds/issue-102335-ty.stderr b/src/test/ui/associated-type-bounds/issue-102335-ty.stderr new file mode 100644 index 0000000000000..8777b2965153a --- /dev/null +++ b/src/test/ui/associated-type-bounds/issue-102335-ty.stderr @@ -0,0 +1,9 @@ +error[E0229]: associated type bindings are not allowed here + --> $DIR/issue-102335-ty.rs:2:17 + | +LL | type A: S = ()>; + | ^^^^^^^^^ associated type not allowed here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0229`. diff --git a/src/test/ui/generic-associated-types/issue-102335-gat.rs b/src/test/ui/generic-associated-types/issue-102335-gat.rs new file mode 100644 index 0000000000000..a7255fdcbf5e1 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-102335-gat.rs @@ -0,0 +1,12 @@ +trait T { + type A: S = ()>; + //~^ ERROR associated type bindings are not allowed here +} + +trait Q {} + +trait S { + type C: Q; +} + +fn main() {} diff --git a/src/test/ui/generic-associated-types/issue-102335-gat.stderr b/src/test/ui/generic-associated-types/issue-102335-gat.stderr new file mode 100644 index 0000000000000..7a7900a1e656a --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-102335-gat.stderr @@ -0,0 +1,9 @@ +error[E0229]: associated type bindings are not allowed here + --> $DIR/issue-102335-gat.rs:2:21 + | +LL | type A: S = ()>; + | ^^^^^^^^ associated type not allowed here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0229`. diff --git a/src/test/ui/suggestions/issue-85347.rs b/src/test/ui/suggestions/issue-85347.rs index dd52b3150551a..02b5fb61894e9 100644 --- a/src/test/ui/suggestions/issue-85347.rs +++ b/src/test/ui/suggestions/issue-85347.rs @@ -2,6 +2,7 @@ use std::ops::Deref; trait Foo { type Bar<'a>: Deref::Bar>; //~^ ERROR this associated type takes 1 lifetime argument but 0 lifetime arguments were supplied + //~| ERROR associated type bindings are not allowed here //~| HELP add missing } diff --git a/src/test/ui/suggestions/issue-85347.stderr b/src/test/ui/suggestions/issue-85347.stderr index de853de27e40e..17c1b7dc4cce9 100644 --- a/src/test/ui/suggestions/issue-85347.stderr +++ b/src/test/ui/suggestions/issue-85347.stderr @@ -14,6 +14,13 @@ help: add missing lifetime argument LL | type Bar<'a>: Deref::Bar<'a, Target = Self>>; | +++ -error: aborting due to previous error +error[E0229]: associated type bindings are not allowed here + --> $DIR/issue-85347.rs:3:46 + | +LL | type Bar<'a>: Deref::Bar>; + | ^^^^^^^^^^^^^ associated type not allowed here + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0107`. +Some errors have detailed explanations: E0107, E0229. +For more information about an error, try `rustc --explain E0107`. From cca48285b87e44f34788773eef520f9e3f9b20c9 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 26 Sep 2022 23:39:27 +0000 Subject: [PATCH 321/586] Format type_of --- .../rustc_hir_analysis/src/collect/type_of.rs | 64 +++++++++++-------- 1 file changed, 36 insertions(+), 28 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index 24fb0b1fd26b5..ee7d0e84b57ad 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -333,7 +333,12 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { find_opaque_ty_constraints_for_tait(tcx, def_id) } // Opaque types desugared from `impl Trait`. - ItemKind::OpaqueTy(OpaqueTy { origin: hir::OpaqueTyOrigin::FnReturn(owner) | hir::OpaqueTyOrigin::AsyncFn(owner), in_trait, .. }) => { + ItemKind::OpaqueTy(OpaqueTy { + origin: + hir::OpaqueTyOrigin::FnReturn(owner) | hir::OpaqueTyOrigin::AsyncFn(owner), + in_trait, + .. + }) => { if in_trait { span_bug!(item.span, "impl-trait in trait has no default") } else { @@ -378,7 +383,9 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { Node::Field(field) => icx.to_ty(field.ty), - Node::Expr(&Expr { kind: ExprKind::Closure{..}, .. }) => tcx.typeck(def_id).node_type(hir_id), + Node::Expr(&Expr { kind: ExprKind::Closure { .. }, .. }) => { + tcx.typeck(def_id).node_type(hir_id) + } Node::AnonConst(_) if let Some(param) = tcx.opt_const_param_of(def_id) => { // We defer to `type_of` of the corresponding parameter @@ -410,40 +417,42 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { | Node::Item(&Item { kind: ItemKind::GlobalAsm(asm), .. }) if asm.operands.iter().any(|(op, _op_sp)| match op { hir::InlineAsmOperand::Const { anon_const } - | hir::InlineAsmOperand::SymFn { anon_const } => anon_const.hir_id == hir_id, + | hir::InlineAsmOperand::SymFn { anon_const } => { + anon_const.hir_id == hir_id + } _ => false, }) => { tcx.typeck(def_id).node_type(hir_id) } - Node::Variant(Variant { disr_expr: Some(ref e), .. }) if e.hir_id == hir_id => tcx - .adt_def(tcx.hir().get_parent_item(hir_id)) - .repr() - .discr_type() - .to_ty(tcx), + Node::Variant(Variant { disr_expr: Some(ref e), .. }) if e.hir_id == hir_id => { + tcx.adt_def(tcx.hir().get_parent_item(hir_id)).repr().discr_type().to_ty(tcx) + } - Node::TypeBinding(binding @ &TypeBinding { hir_id: binding_id, .. }) - if let Node::TraitRef(trait_ref) = tcx.hir().get( - tcx.hir().get_parent_node(binding_id) - ) => + Node::TypeBinding(binding @ &TypeBinding { hir_id: binding_id, .. }) + if let Node::TraitRef(trait_ref) = + tcx.hir().get(tcx.hir().get_parent_node(binding_id)) => { - let Some(trait_def_id) = trait_ref.trait_def_id() else { + let Some(trait_def_id) = trait_ref.trait_def_id() else { return tcx.ty_error_with_message(DUMMY_SP, "Could not find trait"); }; - let assoc_items = tcx.associated_items(trait_def_id); - let assoc_item = assoc_items.find_by_name_and_kind( - tcx, binding.ident, ty::AssocKind::Const, def_id.to_def_id(), - ); - if let Some(assoc_item) = assoc_item { - tcx.type_of(assoc_item.def_id) - } else { - // FIXME(associated_const_equality): add a useful error message here. - tcx.ty_error_with_message( - DUMMY_SP, - "Could not find associated const on trait", - ) - } + let assoc_items = tcx.associated_items(trait_def_id); + let assoc_item = assoc_items.find_by_name_and_kind( + tcx, + binding.ident, + ty::AssocKind::Const, + def_id.to_def_id(), + ); + if let Some(assoc_item) = assoc_item { + tcx.type_of(assoc_item.def_id) + } else { + // FIXME(associated_const_equality): add a useful error message here. + tcx.ty_error_with_message( + DUMMY_SP, + "Could not find associated const on trait", + ) + } } Node::GenericParam(&GenericParam { @@ -452,8 +461,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { .. }) if ct.hir_id == hir_id => tcx.type_of(tcx.hir().local_def_id(param_hir_id)), - x => - tcx.ty_error_with_message( + x => tcx.ty_error_with_message( DUMMY_SP, &format!("unexpected const parent in type_of(): {x:?}"), ), From 05267b5a50bfa3952fe2a4433f4e12a93e15dd22 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 26 Sep 2022 23:44:43 +0000 Subject: [PATCH 322/586] Make type_of work correctly for const arg bindings --- compiler/rustc_hir_analysis/src/collect/type_of.rs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index ee7d0e84b57ad..227d633a1e44c 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -430,9 +430,15 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { tcx.adt_def(tcx.hir().get_parent_item(hir_id)).repr().discr_type().to_ty(tcx) } - Node::TypeBinding(binding @ &TypeBinding { hir_id: binding_id, .. }) - if let Node::TraitRef(trait_ref) = - tcx.hir().get(tcx.hir().get_parent_node(binding_id)) => + Node::TypeBinding( + binding @ &TypeBinding { + hir_id: binding_id, + kind: TypeBindingKind::Equality { term: Term::Const(ref e) }, + .. + }, + ) if let Node::TraitRef(trait_ref) = + tcx.hir().get(tcx.hir().get_parent_node(binding_id)) + && e.hir_id == hir_id => { let Some(trait_def_id) = trait_ref.trait_def_id() else { return tcx.ty_error_with_message(DUMMY_SP, "Could not find trait"); From 92561f43f185b54c81167ddc89fbe2dcd94b4efb Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 26 Sep 2022 23:57:33 +0000 Subject: [PATCH 323/586] Support bindings with anon consts in generics --- .../rustc_hir_analysis/src/collect/type_of.rs | 47 ++++++++++++++++++- .../generic-associated-types/issue-102333.rs | 15 ++++++ 2 files changed, 60 insertions(+), 2 deletions(-) create mode 100644 src/test/ui/generic-associated-types/issue-102333.rs diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index 227d633a1e44c..f8a62c8491076 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -441,8 +441,8 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { && e.hir_id == hir_id => { let Some(trait_def_id) = trait_ref.trait_def_id() else { - return tcx.ty_error_with_message(DUMMY_SP, "Could not find trait"); - }; + return tcx.ty_error_with_message(DUMMY_SP, "Could not find trait"); + }; let assoc_items = tcx.associated_items(trait_def_id); let assoc_item = assoc_items.find_by_name_and_kind( tcx, @@ -461,6 +461,49 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { } } + Node::TypeBinding( + binding @ &TypeBinding { hir_id: binding_id, gen_args, ref kind, .. }, + ) if let Node::TraitRef(trait_ref) = + tcx.hir().get(tcx.hir().get_parent_node(binding_id)) + && let Some((idx, _)) = + gen_args.args.iter().enumerate().find(|(_, arg)| { + if let GenericArg::Const(ct) = arg { + ct.value.hir_id == hir_id + } else { + false + } + }) => + { + let Some(trait_def_id) = trait_ref.trait_def_id() else { + return tcx.ty_error_with_message(DUMMY_SP, "Could not find trait"); + }; + let assoc_items = tcx.associated_items(trait_def_id); + let assoc_item = assoc_items.find_by_name_and_kind( + tcx, + binding.ident, + match kind { + // I think `` type bindings requires that `A` is a type + TypeBindingKind::Constraint { .. } + | TypeBindingKind::Equality { term: Term::Ty(..) } => { + ty::AssocKind::Type + } + TypeBindingKind::Equality { term: Term::Const(..) } => { + ty::AssocKind::Const + } + }, + def_id.to_def_id(), + ); + if let Some(assoc_item) = assoc_item { + tcx.type_of(tcx.generics_of(assoc_item.def_id).params[idx].def_id) + } else { + // FIXME(associated_const_equality): add a useful error message here. + tcx.ty_error_with_message( + DUMMY_SP, + "Could not find associated const on trait", + ) + } + } + Node::GenericParam(&GenericParam { hir_id: param_hir_id, kind: GenericParamKind::Const { default: Some(ct), .. }, diff --git a/src/test/ui/generic-associated-types/issue-102333.rs b/src/test/ui/generic-associated-types/issue-102333.rs new file mode 100644 index 0000000000000..6c72563322f55 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-102333.rs @@ -0,0 +1,15 @@ +// check-pass + +trait A { + type T: B = ()>; +} + +trait B { + type U; +} + +fn f() { + let _: <::T as B>::U<1i32> = (); +} + +fn main() {} From b5b77a295972307c24dc0095ce693102c8e4884c Mon Sep 17 00:00:00 2001 From: Jacob Hoffman-Andrews Date: Tue, 27 Sep 2022 10:25:25 -0700 Subject: [PATCH 324/586] Update src/test/rustdoc-gui/sidebar-mobile-scroll.goml Co-authored-by: Michael Howell --- src/test/rustdoc-gui/sidebar-mobile-scroll.goml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/test/rustdoc-gui/sidebar-mobile-scroll.goml b/src/test/rustdoc-gui/sidebar-mobile-scroll.goml index 3259c02fa4920..9af7c636a0cac 100644 --- a/src/test/rustdoc-gui/sidebar-mobile-scroll.goml +++ b/src/test/rustdoc-gui/sidebar-mobile-scroll.goml @@ -6,7 +6,7 @@ assert-css: (".sidebar", {"display": "block", "left": "-1000px"}) // Scroll down. scroll-to: "//h2[@id='blanket-implementations']" -assert-window-property: {"pageYOffset": "645"} +assert-window-property: {"pageYOffset": "639"} // Open the sidebar menu. click: ".sidebar-menu-toggle" @@ -21,11 +21,11 @@ assert-window-property: {"pageYOffset": "0"} // Close the sidebar menu. Make sure the scroll position gets restored. click: ".sidebar-menu-toggle" wait-for-css: (".sidebar", {"left": "-1000px"}) -assert-window-property: {"pageYOffset": "645"} +assert-window-property: {"pageYOffset": "639"} // Now test that scrollability returns when the browser window is just resized. click: ".sidebar-menu-toggle" wait-for-css: (".sidebar", {"left": "0px"}) assert-window-property: {"pageYOffset": "0"} size: (900, 600) -assert-window-property: {"pageYOffset": "645"} +assert-window-property: {"pageYOffset": "639"} From 3bbb328e68fd38b7d5307d7df05aec1b78cee9d9 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Tue, 27 Sep 2022 10:52:08 -0700 Subject: [PATCH 325/586] rustdoc: remove redundant `#help-button` CSS When the separate top and bottom styles were added in cd3f4da244578a2ab4d17d10016c61b9191b21e4, some of the CSS rules were needlessly duplicated. The `text-align: initial` rule on `.side-by-side` was always redundant, since the rules that centered the text were set on children, not parents. --- src/librustdoc/html/static/css/rustdoc.css | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index e7a05b80c127f..31cd4dc011f89 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -1019,8 +1019,6 @@ so that we can apply CSS-filters to change the arrow color in themes */ font-size: 1.125rem; } #help-button span.top { - text-align: center; - display: block; margin: 10px 0; border-bottom: 1px solid var(--border-color); padding-bottom: 4px; @@ -1030,9 +1028,6 @@ so that we can apply CSS-filters to change the arrow color in themes */ clear: both; border-top: 1px solid var(--border-color); } -.side-by-side { - text-align: initial; -} .side-by-side > div { width: 50%; float: left; From ef410f1b01f1f3e54975b6142062c737875d6c22 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 27 Sep 2022 20:22:46 +0200 Subject: [PATCH 326/586] Fix regression for results colors --- src/librustdoc/html/static/css/rustdoc.css | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index e7a05b80c127f..ff95c20d950af 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -257,7 +257,9 @@ pre.rust a, } .content span.fn, .content a.fn, -.content .fnname { +.content .fnname, +.content span.method, .content a.method, +.content span.tymethod, .content a.tymethod { color: var(--function-link-color); } From a925e203d199daac8589efa2b5e9849474f1e3a1 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 27 Sep 2022 20:23:00 +0200 Subject: [PATCH 327/586] Add GUI regression test for search results colors --- src/test/rustdoc-gui/search-result-color.goml | 153 +++++++++++++++++- src/test/rustdoc-gui/src/lib2/lib.rs | 3 + 2 files changed, 152 insertions(+), 4 deletions(-) diff --git a/src/test/rustdoc-gui/search-result-color.goml b/src/test/rustdoc-gui/search-result-color.goml index 5e328133e62a1..c4b5fdf53dd6b 100644 --- a/src/test/rustdoc-gui/search-result-color.goml +++ b/src/test/rustdoc-gui/search-result-color.goml @@ -7,7 +7,6 @@ show-text: true // Ayu theme local-storage: { "rustdoc-theme": "ayu", - "rustdoc-preferred-dark-theme": "ayu", "rustdoc-use-system-theme": "false", } reload: @@ -23,16 +22,66 @@ assert-css: ( {"color": "rgb(0, 150, 207)"}, ) -// Checking the color for "keyword". +// Checking the color of "keyword" text. assert-css: ( "//*[@class='result-name']//*[text()='(keyword)']", {"color": "rgb(120, 135, 151)"}, ) +// Checking the color of "keyword". +assert-css: ( + ".result-name .keyword", + {"color": "rgb(57, 175, 215)"}, + ALL, +) +// Check the color of "struct". +assert-css: ( + ".result-name .struct", + {"color": "rgb(255, 160, 165)"}, + ALL, +) +// Check the color of "associated type". +assert-css: ( + ".result-name .associatedtype", + {"color": "rgb(57, 175, 215)"}, + ALL, +) +// Check the color of "type method". +assert-css: ( + ".result-name .tymethod", + {"color": "rgb(253, 214, 135)"}, + ALL, +) +// Check the color of "method". +assert-css: ( + ".result-name .method", + {"color": "rgb(253, 214, 135)"}, + ALL, +) +// Check the color of "struct field". +assert-css: ( + ".result-name .structfield", + {"color": "rgb(0, 150, 207)"}, + ALL, +) +// Check the color of "macro". +assert-css: ( + ".result-name .macro", + {"color": "rgb(163, 122, 204)"}, + ALL, +) +// Check the color of "fn". +assert-css: ( + ".result-name .fn", + {"color": "rgb(253, 214, 135)"}, + ALL, +) + // Checking the `` container. assert-css: ( "//*[@class='result-name']/*[text()='test_docs::']/ancestor::a", {"color": "rgb(0, 150, 207)", "background-color": "rgba(0, 0, 0, 0)"}, + ALL, ) // Checking color and background on hover. @@ -49,7 +98,6 @@ assert-css: ( // Dark theme local-storage: { "rustdoc-theme": "dark", - "rustdoc-preferred-dark-theme": "dark", "rustdoc-use-system-theme": "false", } reload: @@ -71,6 +119,55 @@ assert-css: ( {"color": "rgb(221, 221, 221)"}, ) +// Checking the color of "keyword". +assert-css: ( + ".result-name .keyword", + {"color": "rgb(210, 153, 29)"}, + ALL, +) +// Check the color of "struct". +assert-css: ( + ".result-name .struct", + {"color": "rgb(45, 191, 184)"}, + ALL, +) +// Check the color of "associated type". +assert-css: ( + ".result-name .associatedtype", + {"color": "rgb(210, 153, 29)"}, + ALL, +) +// Check the color of "type method". +assert-css: ( + ".result-name .tymethod", + {"color": "rgb(43, 171, 99)"}, + ALL, +) +// Check the color of "method". +assert-css: ( + ".result-name .method", + {"color": "rgb(43, 171, 99)"}, + ALL, +) +// Check the color of "struct field". +assert-css: ( + ".result-name .structfield", + {"color": "rgb(221, 221, 221)"}, + ALL, +) +// Check the color of "macro". +assert-css: ( + ".result-name .macro", + {"color": "rgb(9, 189, 0)"}, + ALL, +) +// Check the color of "fn". +assert-css: ( + ".result-name .fn", + {"color": "rgb(43, 171, 99)"}, + ALL, +) + // Checking the `` container. assert-css: ( "//*[@class='result-name']/*[text()='test_docs::']/ancestor::a", @@ -109,6 +206,55 @@ assert-css: ( {"color": "rgb(0, 0, 0)"}, ) +// Checking the color of "keyword". +assert-css: ( + ".result-name .keyword", + {"color": "rgb(56, 115, 173)"}, + ALL, +) +// Check the color of "struct". +assert-css: ( + ".result-name .struct", + {"color": "rgb(173, 55, 138)"}, + ALL, +) +// Check the color of "associated type". +assert-css: ( + ".result-name .associatedtype", + {"color": "rgb(56, 115, 173)"}, + ALL, +) +// Check the color of "type method". +assert-css: ( + ".result-name .tymethod", + {"color": "rgb(173, 124, 55)"}, + ALL, +) +// Check the color of "method". +assert-css: ( + ".result-name .method", + {"color": "rgb(173, 124, 55)"}, + ALL, +) +// Check the color of "struct field". +assert-css: ( + ".result-name .structfield", + {"color": "rgb(0, 0, 0)"}, + ALL, +) +// Check the color of "macro". +assert-css: ( + ".result-name .macro", + {"color": "rgb(6, 128, 0)"}, + ALL, +) +// Check the color of "fn". +assert-css: ( + ".result-name .fn", + {"color": "rgb(173, 124, 55)"}, + ALL, +) + // Checking the `` container. assert-css: ( "//*[@class='result-name']/*[text()='test_docs::']/ancestor::a", @@ -132,7 +278,6 @@ goto: file://|DOC_PATH|/test_docs/index.html // this test is running on. local-storage: { "rustdoc-theme": "dark", - "rustdoc-preferred-dark-theme": "dark", "rustdoc-use-system-theme": "false", } // If the text isn't displayed, the browser doesn't compute color style correctly... diff --git a/src/test/rustdoc-gui/src/lib2/lib.rs b/src/test/rustdoc-gui/src/lib2/lib.rs index 5a151ed7b687a..24aecc70d65e0 100644 --- a/src/test/rustdoc-gui/src/lib2/lib.rs +++ b/src/test/rustdoc-gui/src/lib2/lib.rs @@ -38,11 +38,14 @@ pub trait Trait { #[deprecated = "Whatever [`Foo`](#tadam)"] fn foo() {} + fn fooo(); } impl Trait for Foo { type X = u32; const Y: u32 = 0; + + fn fooo() {} } impl implementors::Whatever for Foo { From 495e271883188ece09b80ae7f405e8062853f2d3 Mon Sep 17 00:00:00 2001 From: Xiretza Date: Thu, 25 Aug 2022 10:58:53 +0200 Subject: [PATCH 328/586] Migrate rustc_session::expr_parentheses_needed to Subdiagnostic struct --- .../locales/en-US/session.ftl | 2 ++ compiler/rustc_session/src/errors.rs | 15 +++++++++++++++ compiler/rustc_session/src/parse.rs | 12 +++++------- 3 files changed, 22 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_error_messages/locales/en-US/session.ftl b/compiler/rustc_error_messages/locales/en-US/session.ftl index 76cae3c81e451..3ea9429a23ab1 100644 --- a/compiler/rustc_error_messages/locales/en-US/session.ftl +++ b/compiler/rustc_error_messages/locales/en-US/session.ftl @@ -66,3 +66,5 @@ session_crate_name_invalid = crate names cannot start with a `-`, but `{$s}` has session_crate_name_empty = crate name must not be empty session_invalid_character_in_create_name = invalid character `{$character}` in crate name: `{$crate_name}` + +session_expr_parentheses_needed = parentheses are required to parse this as an expression diff --git a/compiler/rustc_session/src/errors.rs b/compiler/rustc_session/src/errors.rs index e01dafe2102b8..b5962f76b7f4a 100644 --- a/compiler/rustc_session/src/errors.rs +++ b/compiler/rustc_session/src/errors.rs @@ -219,3 +219,18 @@ impl IntoDiagnostic<'_> for InvalidCharacterInCrateName<'_> { diag } } + +#[derive(Subdiagnostic)] +#[multipart_suggestion(session::expr_parentheses_needed, applicability = "machine-applicable")] +pub struct ExprParenthesesNeeded { + #[suggestion_part(code = "(")] + pub left: Span, + #[suggestion_part(code = ")")] + pub right: Span, +} + +impl ExprParenthesesNeeded { + pub fn surrounding(s: Span) -> Self { + ExprParenthesesNeeded { left: s.shrink_to_lo(), right: s.shrink_to_hi() } + } +} diff --git a/compiler/rustc_session/src/parse.rs b/compiler/rustc_session/src/parse.rs index b9202af2a6765..a278a7b5509ae 100644 --- a/compiler/rustc_session/src/parse.rs +++ b/compiler/rustc_session/src/parse.rs @@ -2,7 +2,9 @@ //! It also serves as an input to the parser itself. use crate::config::CheckCfg; -use crate::errors::{FeatureDiagnosticForIssue, FeatureDiagnosticHelp, FeatureGateError}; +use crate::errors::{ + ExprParenthesesNeeded, FeatureDiagnosticForIssue, FeatureDiagnosticHelp, FeatureGateError, +}; use crate::lint::{ builtin::UNSTABLE_SYNTAX_PRE_EXPANSION, BufferedEarlyLint, BuiltinLintDiagnostics, Lint, LintId, }; @@ -11,7 +13,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet}; use rustc_data_structures::sync::{Lock, Lrc}; use rustc_errors::{emitter::SilentEmitter, ColorConfig, Handler}; use rustc_errors::{ - fallback_fluent_bundle, Applicability, Diagnostic, DiagnosticBuilder, DiagnosticId, + fallback_fluent_bundle, AddToDiagnostic, Diagnostic, DiagnosticBuilder, DiagnosticId, DiagnosticMessage, EmissionGuarantee, ErrorGuaranteed, IntoDiagnostic, MultiSpan, StashKey, }; use rustc_feature::{find_feature_issue, GateIssue, UnstableFeatures}; @@ -325,11 +327,7 @@ impl ParseSess { /// Extend an error with a suggestion to wrap an expression with parentheses to allow the /// parser to continue parsing the following operation as part of the same expression. pub fn expr_parentheses_needed(&self, err: &mut Diagnostic, span: Span) { - err.multipart_suggestion( - "parentheses are required to parse this as an expression", - vec![(span.shrink_to_lo(), "(".to_string()), (span.shrink_to_hi(), ")".to_string())], - Applicability::MachineApplicable, - ); + ExprParenthesesNeeded::surrounding(span).add_to_diagnostic(err); } pub fn save_proc_macro_span(&self, span: Span) -> usize { From 8489a67f0b0ca5a973d48b27d609c91cb93cf343 Mon Sep 17 00:00:00 2001 From: Xiretza Date: Wed, 14 Sep 2022 19:22:20 +0200 Subject: [PATCH 329/586] Implement IntoDiagnosticArg for rustc_ast::Path --- Cargo.lock | 2 ++ compiler/rustc_errors/Cargo.toml | 2 ++ compiler/rustc_errors/src/diagnostic.rs | 8 ++++++++ 3 files changed, 12 insertions(+) diff --git a/Cargo.lock b/Cargo.lock index c99a07f40b2e5..6432a0426b7de 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3438,6 +3438,8 @@ version = "0.0.0" dependencies = [ "annotate-snippets", "atty", + "rustc_ast", + "rustc_ast_pretty", "rustc_data_structures", "rustc_error_messages", "rustc_hir", diff --git a/compiler/rustc_errors/Cargo.toml b/compiler/rustc_errors/Cargo.toml index c36ca11fad6f2..1eb9dca2a2b91 100644 --- a/compiler/rustc_errors/Cargo.toml +++ b/compiler/rustc_errors/Cargo.toml @@ -8,6 +8,8 @@ doctest = false [dependencies] tracing = "0.1" +rustc_ast = { path = "../rustc_ast" } +rustc_ast_pretty = { path = "../rustc_ast_pretty" } rustc_error_messages = { path = "../rustc_error_messages" } rustc_serialize = { path = "../rustc_serialize" } rustc_span = { path = "../rustc_span" } diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index 1c440a0a07efc..fb409c578f6d5 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -3,6 +3,8 @@ use crate::{ CodeSuggestion, DiagnosticMessage, EmissionGuarantee, Level, LintDiagnosticBuilder, MultiSpan, SubdiagnosticMessage, Substitution, SubstitutionPart, SuggestionStyle, }; +use rustc_ast as ast; +use rustc_ast_pretty::pprust; use rustc_data_structures::fx::FxHashMap; use rustc_error_messages::FluentValue; use rustc_hir as hir; @@ -175,6 +177,12 @@ impl IntoDiagnosticArg for hir::ConstContext { } } +impl IntoDiagnosticArg for ast::Path { + fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { + DiagnosticArgValue::Str(Cow::Owned(pprust::path_to_string(&self))) + } +} + /// Trait implemented by error types. This should not be implemented manually. Instead, use /// `#[derive(Subdiagnostic)]` -- see [rustc_macros::Subdiagnostic]. #[cfg_attr(bootstrap, rustc_diagnostic_item = "AddSubdiagnostic")] From 4d02892acfdb43490db815010d718bd324f853ad Mon Sep 17 00:00:00 2001 From: Xiretza Date: Wed, 14 Sep 2022 20:12:22 +0200 Subject: [PATCH 330/586] Allow raw identifiers to be used as fluent arguments --- .../rustc_macros/src/diagnostics/diagnostic_builder.rs | 2 ++ compiler/rustc_macros/src/diagnostics/subdiagnostic.rs | 3 +++ .../ui-fulldeps/session-diagnostic/diagnostic-derive.rs | 6 ++++++ .../session-diagnostic/subdiagnostic-derive.rs | 8 ++++++++ 4 files changed, 19 insertions(+) diff --git a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs index 38bd986f76fb9..9e88dc7a913a2 100644 --- a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs +++ b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs @@ -281,6 +281,8 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> { if should_generate_set_arg(&field) { let diag = &self.parent.diag; let ident = field.ident.as_ref().unwrap(); + // strip `r#` prefix, if present + let ident = format_ident!("{}", ident); return quote! { #diag.set_arg( stringify!(#ident), diff --git a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs index adb4902ebc172..9a2588513f06d 100644 --- a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs +++ b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs @@ -189,6 +189,9 @@ impl<'a> SubdiagnosticDeriveBuilder<'a> { let diag = &self.diag; let ident = ast.ident.as_ref().unwrap(); + // strip `r#` prefix, if present + let ident = format_ident!("{}", ident); + quote! { #diag.set_arg( stringify!(#ident), diff --git a/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs b/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs index cf04e05095f0a..3d363cae47310 100644 --- a/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs +++ b/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs @@ -671,3 +671,9 @@ enum ExampleEnum { #[diag(typeck::ambiguous_lifetime_bound)] Baz, } + +#[derive(Diagnostic)] +#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")] +struct RawIdentDiagnosticArg { + pub r#type: String, +} diff --git a/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs b/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs index 606b3b5e5ebca..84ee5af42dea5 100644 --- a/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs +++ b/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs @@ -633,3 +633,11 @@ struct BI { #[suggestion_part(code = "")] spans: Vec, } + +#[derive(Subdiagnostic)] +#[label(parser::add_paren)] +struct BJ { + #[primary_span] + span: Span, + r#type: String, +} From ab7c7dc7ce422bfa2cdaf8ddd41b6260736a2e9f Mon Sep 17 00:00:00 2001 From: Xiretza Date: Wed, 24 Aug 2022 22:41:51 +0200 Subject: [PATCH 331/586] Migrate more diagnostics in rustc_parse to diagnostic structs --- .../locales/en-US/parser.ftl | 61 ++++ .../rustc_parse/src/parser/diagnostics.rs | 250 ++++++++++++- compiler/rustc_parse/src/parser/expr.rs | 327 ++++++++---------- compiler/rustc_parse/src/parser/mod.rs | 43 +-- src/test/ui/issues/issue-22644.rs | 2 +- src/test/ui/issues/issue-22644.stderr | 2 +- 6 files changed, 465 insertions(+), 220 deletions(-) diff --git a/compiler/rustc_error_messages/locales/en-US/parser.ftl b/compiler/rustc_error_messages/locales/en-US/parser.ftl index 07dd03e6e504e..2a0d16f58a574 100644 --- a/compiler/rustc_error_messages/locales/en-US/parser.ftl +++ b/compiler/rustc_error_messages/locales/en-US/parser.ftl @@ -71,6 +71,8 @@ parser_field_expression_with_generic = field expressions cannot have generic arg parser_macro_invocation_with_qualified_path = macros cannot use qualified paths parser_unexpected_token_after_label = expected `while`, `for`, `loop` or `{"{"}` after a label + .suggestion_remove_label = consider removing the label + .suggestion_enclose_in_block = consider enclosing expression in a block parser_require_colon_after_labeled_expression = labeled expression must be followed by `:` .note = labels are used before loops and blocks, allowing e.g., `break 'label` to them @@ -161,3 +163,62 @@ parser_use_eq_instead = unexpected `==` parser_use_empty_block_not_semi = expected { "`{}`" }, found `;` .suggestion = try using { "`{}`" } instead + +parser_comparison_interpreted_as_generic = + `<` is interpreted as a start of generic arguments for `{$typename}`, not a comparison + .label_args = interpreted as generic arguments + .label_comparison = not interpreted as comparison + .suggestion = try comparing the cast value + +parser_shift_interpreted_as_generic = + `<<` is interpreted as a start of generic arguments for `{$typename}`, not a shift + .label_args = interpreted as generic arguments + .label_comparison = not interpreted as shift + .suggestion = try shifting the cast value + +parser_found_expr_would_be_stmt = expected expression, found `{$token}` + .label = expected expression + +parser_leading_plus_not_supported = leading `+` is not supported + .label = unexpected `+` + .suggestion_remove_plus = try removing the `+` + +parser_parentheses_with_struct_fields = invalid `struct` delimiters or `fn` call arguments + .suggestion_braces_for_struct = if `{$name}` is a struct, use braces as delimiters + .suggestion_no_fields_for_fn = if `{$name}` is a function, use the arguments directly + +parser_labeled_loop_in_break = parentheses are required around this expression to avoid confusion with a labeled break expression + .suggestion = wrap the expression in parentheses + +parser_array_brackets_instead_of_braces = this is a block expression, not an array + .suggestion = to make an array, use square brackets instead of curly braces + +parser_match_arm_body_without_braces = `match` arm body without braces + .label_statements = {$num_statements -> + [one] this statement is not surrounded by a body + *[other] these statements are not surrounded by a body + } + .label_arrow = while parsing the `match` arm starting here + .suggestion_add_braces = surround the {$num_statements -> + [one] statement + *[other] statements + } with a body + .suggestion_use_comma_not_semicolon = use a comma to end a `match` arm expression + +parser_struct_literal_not_allowed_here = struct literals are not allowed here + .suggestion = surround the struct literal with parentheses + +parser_invalid_interpolated_expression = invalid interpolated expression + +parser_hexadecimal_float_literal_not_supported = hexadecimal float literal is not supported +parser_octal_float_literal_not_supported = octal float literal is not supported +parser_binary_float_literal_not_supported = binary float literal is not supported +parser_not_supported = not supported + +parser_non_string_abi_literal = non-string ABI literal + .suggestion = specify the ABI with a string literal + +parser_mismatched_closing_delimiter = mismatched closing delimiter: `{$delimiter}` + .label_unmatched = mismatched closing delimiter + .label_opening_candidate = closing delimiter possibly meant for this + .label_unclosed = unclosed delimiter diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index ccdffb8ce07b9..d8e1382d7432a 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -21,6 +21,7 @@ use rustc_errors::{ }; use rustc_errors::{pluralize, struct_span_err, Diagnostic, ErrorGuaranteed}; use rustc_macros::{Diagnostic, Subdiagnostic}; +use rustc_session::errors::ExprParenthesesNeeded; use rustc_span::source_map::Spanned; use rustc_span::symbol::{kw, sym, Ident}; use rustc_span::{Span, SpanSnippetError, DUMMY_SP}; @@ -487,11 +488,24 @@ pub(crate) struct MacroInvocationWithQualifiedPath(#[primary_span] pub Span); #[derive(Diagnostic)] #[diag(parser::unexpected_token_after_label)] -pub(crate) struct UnexpectedTokenAfterLabel( +pub(crate) struct UnexpectedTokenAfterLabel { #[primary_span] #[label(parser::unexpected_token_after_label)] - pub Span, -); + pub span: Span, + #[suggestion_verbose(parser::suggestion_remove_label, code = "")] + pub remove_label: Option, + #[subdiagnostic] + pub enclose_in_block: Option, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion(parser::suggestion_enclose_in_block, applicability = "machine-applicable")] +pub(crate) struct UnexpectedTokenAfterLabelSugg { + #[suggestion_part(code = "{{ ")] + pub left: Span, + #[suggestion_part(code = " }}")] + pub right: Span, +} #[derive(Diagnostic)] #[diag(parser::require_colon_after_labeled_expression)] @@ -753,6 +767,236 @@ pub(crate) struct UseEmptyBlockNotSemi { pub span: Span, } +#[derive(Diagnostic)] +#[diag(parser::comparison_interpreted_as_generic)] +pub(crate) struct ComparisonInterpretedAsGeneric { + #[primary_span] + #[label(parser::label_comparison)] + pub comparison: Span, + pub typename: String, + #[label(parser::label_args)] + pub args: Span, + #[subdiagnostic] + pub suggestion: ComparisonOrShiftInterpretedAsGenericSugg, +} + +#[derive(Diagnostic)] +#[diag(parser::shift_interpreted_as_generic)] +pub(crate) struct ShiftInterpretedAsGeneric { + #[primary_span] + #[label(parser::label_comparison)] + pub shift: Span, + pub typename: String, + #[label(parser::label_args)] + pub args: Span, + #[subdiagnostic] + pub suggestion: ComparisonOrShiftInterpretedAsGenericSugg, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion(parser::suggestion, applicability = "machine-applicable")] +pub(crate) struct ComparisonOrShiftInterpretedAsGenericSugg { + #[suggestion_part(code = "(")] + pub left: Span, + #[suggestion_part(code = ")")] + pub right: Span, +} + +#[derive(Diagnostic)] +#[diag(parser::found_expr_would_be_stmt)] +pub(crate) struct FoundExprWouldBeStmt { + #[primary_span] + #[label] + pub span: Span, + pub token: String, + #[subdiagnostic] + pub suggestion: ExprParenthesesNeeded, +} + +#[derive(Diagnostic)] +#[diag(parser::leading_plus_not_supported)] +pub(crate) struct LeadingPlusNotSupported { + #[primary_span] + #[label] + pub span: Span, + #[suggestion_verbose( + parser::suggestion_remove_plus, + code = "", + applicability = "machine-applicable" + )] + pub remove_plus: Option, + #[subdiagnostic] + pub add_parentheses: Option, +} + +#[derive(Diagnostic)] +#[diag(parser::parentheses_with_struct_fields)] +pub(crate) struct ParenthesesWithStructFields { + #[primary_span] + pub span: Span, + pub name: String, + #[subdiagnostic] + pub braces_for_struct: BracesForStructLiteral, + #[subdiagnostic] + pub no_fields_for_fn: NoFieldsForFnCall, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion(parser::suggestion_braces_for_struct, applicability = "maybe-incorrect")] +pub(crate) struct BracesForStructLiteral { + #[suggestion_part(code = " {{ ")] + pub first: Span, + #[suggestion_part(code = " }}")] + pub second: Span, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion(parser::suggestion_no_fields_for_fn, applicability = "maybe-incorrect")] +pub(crate) struct NoFieldsForFnCall { + #[suggestion_part(code = "")] + pub fields: Vec, +} + +#[derive(Diagnostic)] +#[diag(parser::labeled_loop_in_break)] +pub(crate) struct LabeledLoopInBreak { + #[primary_span] + pub span: Span, + #[subdiagnostic] + pub sub: LabeledLoopInBreakSub, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion(parser::suggestion, applicability = "machine-applicable")] +pub(crate) struct LabeledLoopInBreakSub { + #[suggestion_part(code = "(")] + pub first: Span, + #[suggestion_part(code = ")")] + pub second: Span, +} + +#[derive(Diagnostic)] +#[diag(parser::array_brackets_instead_of_braces)] +pub(crate) struct ArrayBracketsInsteadOfSpaces { + #[primary_span] + pub span: Span, + #[subdiagnostic] + pub sub: ArrayBracketsInsteadOfSpacesSugg, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion(parser::suggestion, applicability = "maybe-incorrect")] +pub(crate) struct ArrayBracketsInsteadOfSpacesSugg { + #[suggestion_part(code = "[")] + pub left: Span, + #[suggestion_part(code = "]")] + pub right: Span, +} + +#[derive(Diagnostic)] +#[diag(parser::match_arm_body_without_braces)] +pub(crate) struct MatchArmBodyWithoutBraces { + #[primary_span] + #[label(parser::label_statements)] + pub statements: Span, + #[label(parser::label_arrow)] + pub arrow: Span, + pub num_statements: usize, + #[subdiagnostic] + pub sub: MatchArmBodyWithoutBracesSugg, +} + +#[derive(Subdiagnostic)] +pub(crate) enum MatchArmBodyWithoutBracesSugg { + #[multipart_suggestion(parser::suggestion_add_braces, applicability = "machine-applicable")] + AddBraces { + #[suggestion_part(code = "{{ ")] + left: Span, + #[suggestion_part(code = " }}")] + right: Span, + }, + #[suggestion( + parser::suggestion_use_comma_not_semicolon, + code = ",", + applicability = "machine-applicable" + )] + UseComma { + #[primary_span] + semicolon: Span, + }, +} + +#[derive(Diagnostic)] +#[diag(parser::struct_literal_not_allowed_here)] +pub(crate) struct StructLiteralNotAllowedHere { + #[primary_span] + pub span: Span, + #[subdiagnostic] + pub sub: StructLiteralNotAllowedHereSugg, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion(parser::suggestion, applicability = "machine-applicable")] +pub(crate) struct StructLiteralNotAllowedHereSugg { + #[suggestion_part(code = "(")] + pub left: Span, + #[suggestion_part(code = ")")] + pub right: Span, +} + +#[derive(Diagnostic)] +#[diag(parser::invalid_interpolated_expression)] +pub(crate) struct InvalidInterpolatedExpression { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(parser::hexadecimal_float_literal_not_supported)] +pub(crate) struct HexadecimalFloatLiteralNotSupported { + #[primary_span] + #[label(parser::not_supported)] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(parser::octal_float_literal_not_supported)] +pub(crate) struct OctalFloatLiteralNotSupported { + #[primary_span] + #[label(parser::not_supported)] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(parser::binary_float_literal_not_supported)] +pub(crate) struct BinaryFloatLiteralNotSupported { + #[primary_span] + #[label(parser::not_supported)] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(parser::non_string_abi_literal)] +pub(crate) struct NonStringAbiLiteral { + #[primary_span] + #[suggestion(code = "\"C\"", applicability = "maybe-incorrect")] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(parser::mismatched_closing_delimiter)] +pub(crate) struct MismatchedClosingDelimiter { + #[primary_span] + pub spans: Vec, + pub delimiter: String, + #[label(parser::label_unmatched)] + pub unmatched: Span, + #[label(parser::label_opening_candidate)] + pub opening_candidate: Option, + #[label(parser::label_unclosed)] + pub unclosed: Option, +} + // SnapshotParser is used to create a snapshot of the parser // without causing duplicate errors being emitted when the `Parser` // is dropped. diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index ae77961b7bc28..6e77475fbe61f 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -1,14 +1,19 @@ use super::diagnostics::{ - CatchAfterTry, CommaAfterBaseStruct, DoCatchSyntaxRemoved, DotDotDot, EqFieldInit, + ArrayBracketsInsteadOfSpaces, ArrayBracketsInsteadOfSpacesSugg, BracesForStructLiteral, + CatchAfterTry, CommaAfterBaseStruct, ComparisonInterpretedAsGeneric, + ComparisonOrShiftInterpretedAsGenericSugg, DoCatchSyntaxRemoved, DotDotDot, EqFieldInit, ExpectedElseBlock, ExpectedExpressionFoundLet, FieldExpressionWithGeneric, - FloatLiteralRequiresIntegerPart, IfExpressionMissingCondition, IfExpressionMissingThenBlock, - IfExpressionMissingThenBlockSub, InvalidBlockMacroSegment, InvalidComparisonOperator, - InvalidComparisonOperatorSub, InvalidLogicalOperator, InvalidLogicalOperatorSub, - LeftArrowOperator, LifetimeInBorrowExpression, MacroInvocationWithQualifiedPath, - MalformedLoopLabel, MissingInInForLoop, MissingInInForLoopSub, MissingSemicolonBeforeArray, - NotAsNegationOperator, NotAsNegationOperatorSub, OuterAttributeNotAllowedOnIfElse, - RequireColonAfterLabeledExpression, SnapshotParser, TildeAsUnaryOperator, - UnexpectedTokenAfterLabel, + FloatLiteralRequiresIntegerPart, FoundExprWouldBeStmt, IfExpressionMissingCondition, + IfExpressionMissingThenBlock, IfExpressionMissingThenBlockSub, InvalidBlockMacroSegment, + InvalidComparisonOperator, InvalidComparisonOperatorSub, InvalidInterpolatedExpression, + InvalidLogicalOperator, InvalidLogicalOperatorSub, LabeledLoopInBreak, LeftArrowOperator, + LifetimeInBorrowExpression, MacroInvocationWithQualifiedPath, MalformedLoopLabel, + MatchArmBodyWithoutBraces, MissingInInForLoop, MissingInInForLoopSub, + MissingSemicolonBeforeArray, NoFieldsForFnCall, NotAsNegationOperator, + NotAsNegationOperatorSub, OuterAttributeNotAllowedOnIfElse, ParenthesesWithStructFields, + RequireColonAfterLabeledExpression, ShiftInterpretedAsGeneric, SnapshotParser, + StructLiteralNotAllowedHere, TildeAsUnaryOperator, UnexpectedTokenAfterLabel, + UnexpectedTokenAfterLabelSugg, }; use super::pat::{CommaRecoveryMode, RecoverColon, RecoverComma, PARAM_EXPECTED}; use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign}; @@ -18,9 +23,11 @@ use super::{ }; use crate::maybe_recover_from_interpolated_ty_qpath; use crate::parser::diagnostics::{ - IntLiteralTooLarge, InvalidFloatLiteralSuffix, InvalidFloatLiteralWidth, - InvalidIntLiteralWidth, InvalidNumLiteralBasePrefix, InvalidNumLiteralSuffix, - MissingCommaAfterMatchArm, + BinaryFloatLiteralNotSupported, HexadecimalFloatLiteralNotSupported, IntLiteralTooLarge, + InvalidFloatLiteralSuffix, InvalidFloatLiteralWidth, InvalidIntLiteralWidth, + InvalidNumLiteralBasePrefix, InvalidNumLiteralSuffix, LabeledLoopInBreakSub, + LeadingPlusNotSupported, MatchArmBodyWithoutBracesSugg, MissingCommaAfterMatchArm, + OctalFloatLiteralNotSupported, StructLiteralNotAllowedHereSugg, }; use core::mem; @@ -38,6 +45,7 @@ use rustc_ast::{ClosureBinder, StmtKind}; use rustc_ast_pretty::pprust; use rustc_errors::IntoDiagnostic; use rustc_errors::{Applicability, Diagnostic, PResult}; +use rustc_session::errors::ExprParenthesesNeeded; use rustc_session::lint::builtin::BREAK_WITH_LABEL_AND_LOOP; use rustc_session::lint::BuiltinLintDiagnostics; use rustc_span::source_map::{self, Span, Spanned}; @@ -421,13 +429,12 @@ impl<'a> Parser<'a> { /// but the next token implies this should be parsed as an expression. /// For example: `if let Some(x) = x { x } else { 0 } / 2`. fn error_found_expr_would_be_stmt(&self, lhs: &Expr) { - let mut err = self.struct_span_err( - self.token.span, - &format!("expected expression, found `{}`", pprust::token_to_string(&self.token),), - ); - err.span_label(self.token.span, "expected expression"); - self.sess.expr_parentheses_needed(&mut err, lhs.span); - err.emit(); + self.sess.emit_err(FoundExprWouldBeStmt { + span: self.token.span, + // FIXME(#100717) + token: pprust::token_to_string(&self.token).to_string(), + suggestion: ExprParenthesesNeeded::surrounding(lhs.span), + }); } /// Possibly translate the current token to an associative operator. @@ -578,21 +585,16 @@ impl<'a> Parser<'a> { make_it!(this, attrs, |this, _| this.parse_borrow_expr(lo)) } token::BinOp(token::Plus) if this.look_ahead(1, |tok| tok.is_numeric_lit()) => { - let mut err = this.struct_span_err(lo, "leading `+` is not supported"); - err.span_label(lo, "unexpected `+`"); + let mut err = + LeadingPlusNotSupported { span: lo, remove_plus: None, add_parentheses: None }; // a block on the LHS might have been intended to be an expression instead if let Some(sp) = this.sess.ambiguous_block_expr_parse.borrow().get(&lo) { - this.sess.expr_parentheses_needed(&mut err, *sp); + err.add_parentheses = Some(ExprParenthesesNeeded::surrounding(*sp)); } else { - err.span_suggestion_verbose( - lo, - "try removing the `+`", - "", - Applicability::MachineApplicable, - ); + err.remove_plus = Some(lo); } - err.emit(); + this.sess.emit_err(err); this.bump(); this.parse_prefix_expr(None) @@ -755,9 +757,33 @@ impl<'a> Parser<'a> { match self.parse_path(PathStyle::Expr) { Ok(path) => { - let (op_noun, op_verb) = match self.token.kind { - token::Lt => ("comparison", "comparing"), - token::BinOp(token::Shl) => ("shift", "shifting"), + let typename = pprust::path_to_string(&path); + + let span_after_type = parser_snapshot_after_type.token.span; + let expr = + mk_expr(self, lhs, self.mk_ty(path.span, TyKind::Path(None, path))); + + let args_span = self.look_ahead(1, |t| t.span).to(span_after_type); + let suggestion = ComparisonOrShiftInterpretedAsGenericSugg { + left: expr.span.shrink_to_lo(), + right: expr.span.shrink_to_hi(), + }; + + match self.token.kind { + token::Lt => self.sess.emit_err(ComparisonInterpretedAsGeneric { + comparison: self.token.span, + typename, + args: args_span, + suggestion, + }), + token::BinOp(token::Shl) => { + self.sess.emit_err(ShiftInterpretedAsGeneric { + shift: self.token.span, + typename, + args: args_span, + suggestion, + }) + } _ => { // We can end up here even without `<` being the next token, for // example because `parse_ty_no_plus` returns `Err` on keywords, @@ -771,33 +797,7 @@ impl<'a> Parser<'a> { // Successfully parsed the type path leaving a `<` yet to parse. type_err.cancel(); - // Report non-fatal diagnostics, keep `x as usize` as an expression - // in AST and continue parsing. - let msg = format!( - "`<` is interpreted as a start of generic arguments for `{}`, not a {}", - pprust::path_to_string(&path), - op_noun, - ); - let span_after_type = parser_snapshot_after_type.token.span; - let expr = - mk_expr(self, lhs, self.mk_ty(path.span, TyKind::Path(None, path))); - - self.struct_span_err(self.token.span, &msg) - .span_label( - self.look_ahead(1, |t| t.span).to(span_after_type), - "interpreted as generic arguments", - ) - .span_label(self.token.span, format!("not interpreted as {op_noun}")) - .multipart_suggestion( - &format!("try {op_verb} the cast value"), - vec![ - (expr.span.shrink_to_lo(), "(".to_string()), - (expr.span.shrink_to_hi(), ")".to_string()), - ], - Applicability::MachineApplicable, - ) - .emit(); - + // Keep `x as usize` as an expression in AST and continue parsing. expr } Err(path_err) => { @@ -1208,29 +1208,25 @@ impl<'a> Parser<'a> { let close_paren = self.prev_token.span; let span = lo.to(self.prev_token.span); if !fields.is_empty() { - let replacement_err = self.struct_span_err( + let mut replacement_err = ParenthesesWithStructFields { span, - "invalid `struct` delimiters or `fn` call arguments", - ); - mem::replace(err, replacement_err).cancel(); - - err.multipart_suggestion( - &format!("if `{name}` is a struct, use braces as delimiters"), - vec![ - (open_paren, " { ".to_string()), - (close_paren, " }".to_string()), - ], - Applicability::MaybeIncorrect, - ); - err.multipart_suggestion( - &format!("if `{name}` is a function, use the arguments directly"), - fields - .into_iter() - .map(|field| (field.span.until(field.expr.span), String::new())) - .collect(), - Applicability::MaybeIncorrect, - ); - err.emit(); + name, + braces_for_struct: BracesForStructLiteral { + first: open_paren, + second: close_paren, + }, + no_fields_for_fn: NoFieldsForFnCall { + fields: fields + .into_iter() + .map(|field| field.span.until(field.expr.span)) + .collect(), + }, + } + .into_diagnostic(&self.sess.span_diagnostic); + replacement_err.emit(); + + let old_err = mem::replace(err, replacement_err); + old_err.cancel(); } else { err.emit(); } @@ -1537,15 +1533,19 @@ impl<'a> Parser<'a> { && (self.check_noexpect(&TokenKind::Comma) || self.check_noexpect(&TokenKind::Gt)) { // We're probably inside of a `Path<'a>` that needs a turbofish - self.sess.emit_err(UnexpectedTokenAfterLabel(self.token.span)); + self.sess.emit_err(UnexpectedTokenAfterLabel { + span: self.token.span, + remove_label: None, + enclose_in_block: None, + }); consume_colon = false; Ok(self.mk_expr_err(lo)) } else { - // FIXME: use UnexpectedTokenAfterLabel, needs multipart suggestions - let msg = "expected `while`, `for`, `loop` or `{` after a label"; - - let mut err = self.struct_span_err(self.token.span, msg); - err.span_label(self.token.span, msg); + let mut err = UnexpectedTokenAfterLabel { + span: self.token.span, + remove_label: None, + enclose_in_block: None, + }; // Continue as an expression in an effort to recover on `'label: non_block_expr`. let expr = self.parse_expr().map(|expr| { @@ -1572,28 +1572,15 @@ impl<'a> Parser<'a> { // If there are no breaks that may use this label, suggest removing the label and // recover to the unmodified expression. if !found_labeled_breaks { - let msg = "consider removing the label"; - err.span_suggestion_verbose( - lo.until(span), - msg, - "", - Applicability::MachineApplicable, - ); + err.remove_label = Some(lo.until(span)); return expr; } - let sugg_msg = "consider enclosing expression in a block"; - let suggestions = vec![ - (span.shrink_to_lo(), "{ ".to_owned()), - (span.shrink_to_hi(), " }".to_owned()), - ]; - - err.multipart_suggestion_verbose( - sugg_msg, - suggestions, - Applicability::MachineApplicable, - ); + err.enclose_in_block = Some(UnexpectedTokenAfterLabelSugg { + left: span.shrink_to_lo(), + right: span.shrink_to_hi(), + }); // Replace `'label: non_block_expr` with `'label: {non_block_expr}` in order to suppress future errors about `break 'label`. let stmt = self.mk_stmt(span, StmtKind::Expr(expr)); @@ -1601,7 +1588,7 @@ impl<'a> Parser<'a> { self.mk_expr(span, ExprKind::Block(blk, label)) }); - err.emit(); + self.sess.emit_err(err); expr }?; @@ -1672,19 +1659,13 @@ impl<'a> Parser<'a> { // The value expression can be a labeled loop, see issue #86948, e.g.: // `loop { break 'label: loop { break 'label 42; }; }` let lexpr = self.parse_labeled_expr(label.take().unwrap(), true)?; - self.struct_span_err( - lexpr.span, - "parentheses are required around this expression to avoid confusion with a labeled break expression", - ) - .multipart_suggestion( - "wrap the expression in parentheses", - vec![ - (lexpr.span.shrink_to_lo(), "(".to_string()), - (lexpr.span.shrink_to_hi(), ")".to_string()), - ], - Applicability::MachineApplicable, - ) - .emit(); + self.sess.emit_err(LabeledLoopInBreak { + span: lexpr.span, + sub: LabeledLoopInBreakSub { + first: lexpr.span.shrink_to_lo(), + second: lexpr.span.shrink_to_hi(), + }, + }); Some(lexpr) } else if self.token != token::OpenDelim(Delimiter::Brace) || !self.restrictions.contains(Restrictions::NO_STRUCT_LITERAL) @@ -1756,9 +1737,8 @@ impl<'a> Parser<'a> { }; if let Some(expr) = expr { if matches!(expr.kind, ExprKind::Err) { - let mut err = self - .diagnostic() - .struct_span_err(self.token.span, "invalid interpolated expression"); + let mut err = InvalidInterpolatedExpression { span: self.token.span } + .into_diagnostic(&self.sess.span_diagnostic); err.downgrade_to_delayed_bug(); return err; } @@ -1790,7 +1770,10 @@ impl<'a> Parser<'a> { }); if let Some(token) = &recovered { self.bump(); - self.error_float_lits_must_have_int_part(&token); + self.sess.emit_err(FloatLiteralRequiresIntegerPart { + span: token.span, + correct: pprust::token_to_string(token).into_owned(), + }); } } @@ -1818,13 +1801,6 @@ impl<'a> Parser<'a> { } } - fn error_float_lits_must_have_int_part(&self, token: &Token) { - self.sess.emit_err(FloatLiteralRequiresIntegerPart { - span: token.span, - correct: pprust::token_to_string(token).into_owned(), - }); - } - fn report_lit_error(&self, err: LitError, lit: token::Lit, span: Span) { // Checks if `s` looks like i32 or u1234 etc. fn looks_like_width_suffix(first_chars: &[char], s: &str) -> bool { @@ -1883,15 +1859,12 @@ impl<'a> Parser<'a> { } } LitError::NonDecimalFloat(base) => { - let descr = match base { - 16 => "hexadecimal", - 8 => "octal", - 2 => "binary", + match base { + 16 => self.sess.emit_err(HexadecimalFloatLiteralNotSupported { span }), + 8 => self.sess.emit_err(OctalFloatLiteralNotSupported { span }), + 2 => self.sess.emit_err(BinaryFloatLiteralNotSupported { span }), _ => unreachable!(), }; - self.struct_span_err(span, &format!("{descr} float literal is not supported")) - .span_label(span, "not supported") - .emit(); } LitError::IntTooLarge => { self.sess.emit_err(IntLiteralTooLarge { span }); @@ -1964,14 +1937,13 @@ impl<'a> Parser<'a> { let mut snapshot = self.create_snapshot_for_diagnostic(); match snapshot.parse_array_or_repeat_expr(Delimiter::Brace) { Ok(arr) => { - let hi = snapshot.prev_token.span; - self.struct_span_err(arr.span, "this is a block expression, not an array") - .multipart_suggestion( - "to make an array, use square brackets instead of curly braces", - vec![(lo, "[".to_owned()), (hi, "]".to_owned())], - Applicability::MaybeIncorrect, - ) - .emit(); + self.sess.emit_err(ArrayBracketsInsteadOfSpaces { + span: arr.span, + sub: ArrayBracketsInsteadOfSpacesSugg { + left: lo, + right: snapshot.prev_token.span, + }, + }); self.restore_snapshot(snapshot); Some(self.mk_expr_err(arr.span)) @@ -2515,39 +2487,22 @@ impl<'a> Parser<'a> { self.bump(); // `;` let mut stmts = vec![self.mk_stmt(first_expr.span, ast::StmtKind::Expr(first_expr.clone()))]; - let err = |this: &mut Parser<'_>, stmts: Vec| { + let err = |this: &Parser<'_>, stmts: Vec| { let span = stmts[0].span.to(stmts[stmts.len() - 1].span); - let mut err = this.struct_span_err(span, "`match` arm body without braces"); - let (these, s, are) = - if stmts.len() > 1 { ("these", "s", "are") } else { ("this", "", "is") }; - err.span_label( - span, - &format!( - "{these} statement{s} {are} not surrounded by a body", - these = these, - s = s, - are = are - ), - ); - err.span_label(arrow_span, "while parsing the `match` arm starting here"); - if stmts.len() > 1 { - err.multipart_suggestion( - &format!("surround the statement{s} with a body"), - vec![ - (span.shrink_to_lo(), "{ ".to_string()), - (span.shrink_to_hi(), " }".to_string()), - ], - Applicability::MachineApplicable, - ); - } else { - err.span_suggestion( - semi_sp, - "use a comma to end a `match` arm expression", - ",", - Applicability::MachineApplicable, - ); - } - err.emit(); + + this.sess.emit_err(MatchArmBodyWithoutBraces { + statements: span, + arrow: arrow_span, + num_statements: stmts.len(), + sub: if stmts.len() > 1 { + MatchArmBodyWithoutBracesSugg::AddBraces { + left: span.shrink_to_lo(), + right: span.shrink_to_hi(), + } + } else { + MatchArmBodyWithoutBracesSugg::UseComma { semicolon: semi_sp } + }, + }); this.mk_expr_err(span) }; // We might have either a `,` -> `;` typo, or a block without braces. We need @@ -2836,23 +2791,19 @@ impl<'a> Parser<'a> { let expr = self.parse_struct_expr(qself.cloned(), path.clone(), true); if let (Ok(expr), false) = (&expr, struct_allowed) { // This is a struct literal, but we don't can't accept them here. - self.error_struct_lit_not_allowed_here(path.span, expr.span); + self.sess.emit_err(StructLiteralNotAllowedHere { + span: expr.span, + sub: StructLiteralNotAllowedHereSugg { + left: path.span.shrink_to_lo(), + right: expr.span.shrink_to_hi(), + }, + }); } return Some(expr); } None } - fn error_struct_lit_not_allowed_here(&self, lo: Span, sp: Span) { - self.struct_span_err(sp, "struct literals are not allowed here") - .multipart_suggestion( - "surround the struct literal with parentheses", - vec![(lo.shrink_to_lo(), "(".to_string()), (sp.shrink_to_hi(), ")".to_string())], - Applicability::MachineApplicable, - ) - .emit(); - } - pub(super) fn parse_struct_fields( &mut self, pth: ast::Path, diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 4cb198561e0ad..f2f6f1feda3f4 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -32,7 +32,8 @@ use rustc_ast_pretty::pprust; use rustc_data_structures::fx::FxHashMap; use rustc_errors::PResult; use rustc_errors::{ - struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed, FatalError, MultiSpan, + struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed, FatalError, IntoDiagnostic, + MultiSpan, }; use rustc_session::parse::ParseSess; use rustc_span::source_map::{Span, DUMMY_SP}; @@ -41,6 +42,8 @@ use rustc_span::symbol::{kw, sym, Ident, Symbol}; use std::ops::Range; use std::{cmp, mem, slice}; +use self::diagnostics::{MismatchedClosingDelimiter, NonStringAbiLiteral}; + bitflags::bitflags! { struct Restrictions: u8 { const STMT_EXPR = 1 << 0; @@ -1384,14 +1387,7 @@ impl<'a> Parser<'a> { Err(Some(lit)) => match lit.kind { ast::LitKind::Err => None, _ => { - self.struct_span_err(lit.span, "non-string ABI literal") - .span_suggestion( - lit.span, - "specify the ABI with a string literal", - "\"C\"", - Applicability::MaybeIncorrect, - ) - .emit(); + self.sess.emit_err(NonStringAbiLiteral { span: lit.span }); None } }, @@ -1432,25 +1428,18 @@ pub(crate) fn make_unclosed_delims_error( // `None` here means an `Eof` was found. We already emit those errors elsewhere, we add them to // `unmatched_braces` only for error recovery in the `Parser`. let found_delim = unmatched.found_delim?; - let span: MultiSpan = if let Some(sp) = unmatched.unclosed_span { - vec![unmatched.found_span, sp].into() - } else { - unmatched.found_span.into() - }; - let mut err = sess.span_diagnostic.struct_span_err( - span, - &format!( - "mismatched closing delimiter: `{}`", - pprust::token_kind_to_string(&token::CloseDelim(found_delim)), - ), - ); - err.span_label(unmatched.found_span, "mismatched closing delimiter"); - if let Some(sp) = unmatched.candidate_span { - err.span_label(sp, "closing delimiter possibly meant for this"); - } + let mut spans = vec![unmatched.found_span]; if let Some(sp) = unmatched.unclosed_span { - err.span_label(sp, "unclosed delimiter"); - } + spans.push(sp); + }; + let err = MismatchedClosingDelimiter { + spans, + delimiter: pprust::token_kind_to_string(&token::CloseDelim(found_delim)).to_string(), + unmatched: unmatched.found_span, + opening_candidate: unmatched.candidate_span, + unclosed: unmatched.unclosed_span, + } + .into_diagnostic(&sess.span_diagnostic); Some(err) } diff --git a/src/test/ui/issues/issue-22644.rs b/src/test/ui/issues/issue-22644.rs index 9244ff5931d3e..b1d69dcd86260 100644 --- a/src/test/ui/issues/issue-22644.rs +++ b/src/test/ui/issues/issue-22644.rs @@ -29,7 +29,7 @@ fn main() { < //~ ERROR `<` is interpreted as a start of generic 5); - println!("{}", a as usize << long_name); //~ ERROR `<` is interpreted as a start of generic + println!("{}", a as usize << long_name); //~ ERROR `<<` is interpreted as a start of generic println!("{}", a: &mut 4); //~ ERROR expected type, found `4` } diff --git a/src/test/ui/issues/issue-22644.stderr b/src/test/ui/issues/issue-22644.stderr index 039ffbfd3d89f..45027afa7b62b 100644 --- a/src/test/ui/issues/issue-22644.stderr +++ b/src/test/ui/issues/issue-22644.stderr @@ -95,7 +95,7 @@ LL | LL ~ usize) | -error: `<` is interpreted as a start of generic arguments for `usize`, not a shift +error: `<<` is interpreted as a start of generic arguments for `usize`, not a shift --> $DIR/issue-22644.rs:32:31 | LL | println!("{}", a as usize << long_name); From 6ae7a30927704fd2b48d72b2119d4c0185542e56 Mon Sep 17 00:00:00 2001 From: Xiretza Date: Thu, 15 Sep 2022 10:12:09 +0200 Subject: [PATCH 332/586] Migrate "invalid literal suffix" diagnostic to diagnostic structs --- .../locales/en-US/parser.ftl | 9 +++ .../rustc_parse/src/parser/diagnostics.rs | 26 ++++++- compiler/rustc_parse/src/parser/expr.rs | 73 +++++++------------ compiler/rustc_parse/src/parser/mod.rs | 4 +- src/test/ui/extenv/issue-55897.rs | 2 +- src/test/ui/extenv/issue-55897.stderr | 2 +- src/test/ui/parser/bad-lit-suffixes.rs | 16 ++-- src/test/ui/parser/bad-lit-suffixes.stderr | 16 ++-- 8 files changed, 83 insertions(+), 65 deletions(-) diff --git a/compiler/rustc_error_messages/locales/en-US/parser.ftl b/compiler/rustc_error_messages/locales/en-US/parser.ftl index 2a0d16f58a574..b93c5e7591325 100644 --- a/compiler/rustc_error_messages/locales/en-US/parser.ftl +++ b/compiler/rustc_error_messages/locales/en-US/parser.ftl @@ -215,6 +215,15 @@ parser_octal_float_literal_not_supported = octal float literal is not supported parser_binary_float_literal_not_supported = binary float literal is not supported parser_not_supported = not supported +parser_invalid_literal_suffix = suffixes on {$kind} literals are invalid + .label = invalid suffix `{$suffix}` + +parser_invalid_literal_suffix_on_tuple_index = suffixes on a tuple index are invalid + .label = invalid suffix `{$suffix}` + .tuple_exception_line_1 = `{$suffix}` is *temporarily* accepted on tuple index fields as it was incorrectly accepted on stable for a few releases + .tuple_exception_line_2 = on proc macros, you'll want to use `syn::Index::from` or `proc_macro::Literal::*_unsuffixed` for code that will desugar to tuple field access + .tuple_exception_line_3 = see issue #60210 for more information + parser_non_string_abi_literal = non-string ABI literal .suggestion = specify the ABI with a string literal diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index d8e1382d7432a..c50ca9a2933ee 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -24,7 +24,7 @@ use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_session::errors::ExprParenthesesNeeded; use rustc_span::source_map::Spanned; use rustc_span::symbol::{kw, sym, Ident}; -use rustc_span::{Span, SpanSnippetError, DUMMY_SP}; +use rustc_span::{Span, SpanSnippetError, Symbol, DUMMY_SP}; use std::ops::{Deref, DerefMut}; use std::mem::take; @@ -975,6 +975,30 @@ pub(crate) struct BinaryFloatLiteralNotSupported { pub span: Span, } +#[derive(Diagnostic)] +#[diag(parser::invalid_literal_suffix)] +pub(crate) struct InvalidLiteralSuffix { + #[primary_span] + #[label] + pub span: Span, + // FIXME(#100717) + pub kind: String, + pub suffix: Symbol, +} + +#[derive(Diagnostic)] +#[diag(parser::invalid_literal_suffix_on_tuple_index)] +pub(crate) struct InvalidLiteralSuffixOnTupleIndex { + #[primary_span] + #[label] + pub span: Span, + pub suffix: Symbol, + #[help(parser::tuple_exception_line_1)] + #[help(parser::tuple_exception_line_2)] + #[help(parser::tuple_exception_line_3)] + pub exception: Option<()>, +} + #[derive(Diagnostic)] #[diag(parser::non_string_abi_literal)] pub(crate) struct NonStringAbiLiteral { diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 6e77475fbe61f..f954dff9394f1 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -6,13 +6,13 @@ use super::diagnostics::{ FloatLiteralRequiresIntegerPart, FoundExprWouldBeStmt, IfExpressionMissingCondition, IfExpressionMissingThenBlock, IfExpressionMissingThenBlockSub, InvalidBlockMacroSegment, InvalidComparisonOperator, InvalidComparisonOperatorSub, InvalidInterpolatedExpression, - InvalidLogicalOperator, InvalidLogicalOperatorSub, LabeledLoopInBreak, LeftArrowOperator, - LifetimeInBorrowExpression, MacroInvocationWithQualifiedPath, MalformedLoopLabel, - MatchArmBodyWithoutBraces, MissingInInForLoop, MissingInInForLoopSub, - MissingSemicolonBeforeArray, NoFieldsForFnCall, NotAsNegationOperator, - NotAsNegationOperatorSub, OuterAttributeNotAllowedOnIfElse, ParenthesesWithStructFields, - RequireColonAfterLabeledExpression, ShiftInterpretedAsGeneric, SnapshotParser, - StructLiteralNotAllowedHere, TildeAsUnaryOperator, UnexpectedTokenAfterLabel, + InvalidLiteralSuffix, InvalidLiteralSuffixOnTupleIndex, InvalidLogicalOperator, + InvalidLogicalOperatorSub, LabeledLoopInBreak, LeftArrowOperator, LifetimeInBorrowExpression, + MacroInvocationWithQualifiedPath, MalformedLoopLabel, MatchArmBodyWithoutBraces, + MissingInInForLoop, MissingInInForLoopSub, MissingSemicolonBeforeArray, NoFieldsForFnCall, + NotAsNegationOperator, NotAsNegationOperatorSub, OuterAttributeNotAllowedOnIfElse, + ParenthesesWithStructFields, RequireColonAfterLabeledExpression, ShiftInterpretedAsGeneric, + SnapshotParser, StructLiteralNotAllowedHere, TildeAsUnaryOperator, UnexpectedTokenAfterLabel, UnexpectedTokenAfterLabelSugg, }; use super::pat::{CommaRecoveryMode, RecoverColon, RecoverComma, PARAM_EXPECTED}; @@ -1158,7 +1158,9 @@ impl<'a> Parser<'a> { } let span = self.prev_token.span; let field = ExprKind::Field(base, Ident::new(field, span)); - self.expect_no_suffix(span, "a tuple index", suffix); + if let Some(suffix) = suffix { + self.expect_no_tuple_index_suffix(span, suffix); + } self.mk_expr(lo.to(span), field) } @@ -1829,11 +1831,13 @@ impl<'a> Parser<'a> { // by lexer, so here we don't report it the second time. LitError::LexerError => {} LitError::InvalidSuffix => { - self.expect_no_suffix( - span, - &format!("{} {} literal", kind.article(), kind.descr()), - suffix, - ); + if let Some(suffix) = suffix { + self.sess.emit_err(InvalidLiteralSuffix { + span, + kind: format!("{}", kind.descr()), + suffix, + }); + } } LitError::InvalidIntSuffix => { let suf = suffix.expect("suffix error with no suffix"); @@ -1872,38 +1876,17 @@ impl<'a> Parser<'a> { } } - pub(super) fn expect_no_suffix(&self, sp: Span, kind: &str, suffix: Option) { - if let Some(suf) = suffix { - let mut err = if kind == "a tuple index" - && [sym::i32, sym::u32, sym::isize, sym::usize].contains(&suf) - { - // #59553: warn instead of reject out of hand to allow the fix to percolate - // through the ecosystem when people fix their macros - let mut err = self - .sess - .span_diagnostic - .struct_span_warn(sp, &format!("suffixes on {kind} are invalid")); - err.note(&format!( - "`{}` is *temporarily* accepted on tuple index fields as it was \ - incorrectly accepted on stable for a few releases", - suf, - )); - err.help( - "on proc macros, you'll want to use `syn::Index::from` or \ - `proc_macro::Literal::*_unsuffixed` for code that will desugar \ - to tuple field access", - ); - err.note( - "see issue #60210 \ - for more information", - ); - err - } else { - self.struct_span_err(sp, &format!("suffixes on {kind} are invalid")) - .forget_guarantee() - }; - err.span_label(sp, format!("invalid suffix `{suf}`")); - err.emit(); + pub(super) fn expect_no_tuple_index_suffix(&self, span: Span, suffix: Symbol) { + if [sym::i32, sym::u32, sym::isize, sym::usize].contains(&suffix) { + // #59553: warn instead of reject out of hand to allow the fix to percolate + // through the ecosystem when people fix their macros + self.sess.emit_warning(InvalidLiteralSuffixOnTupleIndex { + span, + suffix, + exception: Some(()), + }); + } else { + self.sess.emit_err(InvalidLiteralSuffixOnTupleIndex { span, suffix, exception: None }); } } diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index f2f6f1feda3f4..123e6ce7ab5be 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -1147,7 +1147,9 @@ impl<'a> Parser<'a> { fn parse_field_name(&mut self) -> PResult<'a, Ident> { if let token::Literal(token::Lit { kind: token::Integer, symbol, suffix }) = self.token.kind { - self.expect_no_suffix(self.token.span, "a tuple index", suffix); + if let Some(suffix) = suffix { + self.expect_no_tuple_index_suffix(self.token.span, suffix); + } self.bump(); Ok(Ident::new(symbol, self.prev_token.span)) } else { diff --git a/src/test/ui/extenv/issue-55897.rs b/src/test/ui/extenv/issue-55897.rs index 64c4107e89875..b7533f41351da 100644 --- a/src/test/ui/extenv/issue-55897.rs +++ b/src/test/ui/extenv/issue-55897.rs @@ -14,7 +14,7 @@ mod nonexistent_env { mod erroneous_literal { include!(concat!("NON_EXISTENT"suffix, "/data.rs")); - //~^ ERROR suffixes on a string literal are invalid + //~^ ERROR suffixes on string literals are invalid } fn main() {} diff --git a/src/test/ui/extenv/issue-55897.stderr b/src/test/ui/extenv/issue-55897.stderr index d2ac0b83016f2..e2afe6f34c121 100644 --- a/src/test/ui/extenv/issue-55897.stderr +++ b/src/test/ui/extenv/issue-55897.stderr @@ -6,7 +6,7 @@ LL | include!(concat!(env!("NON_EXISTENT"), "/data.rs")); | = note: this error originates in the macro `env` (in Nightly builds, run with -Z macro-backtrace for more info) -error: suffixes on a string literal are invalid +error: suffixes on string literals are invalid --> $DIR/issue-55897.rs:16:22 | LL | include!(concat!("NON_EXISTENT"suffix, "/data.rs")); diff --git a/src/test/ui/parser/bad-lit-suffixes.rs b/src/test/ui/parser/bad-lit-suffixes.rs index 446a0940559b3..9724533c420c2 100644 --- a/src/test/ui/parser/bad-lit-suffixes.rs +++ b/src/test/ui/parser/bad-lit-suffixes.rs @@ -1,18 +1,18 @@ extern - "C"suffix //~ ERROR suffixes on a string literal are invalid + "C"suffix //~ ERROR suffixes on string literals are invalid fn foo() {} extern - "C"suffix //~ ERROR suffixes on a string literal are invalid + "C"suffix //~ ERROR suffixes on string literals are invalid {} fn main() { - ""suffix; //~ ERROR suffixes on a string literal are invalid - b""suffix; //~ ERROR suffixes on a byte string literal are invalid - r#""#suffix; //~ ERROR suffixes on a string literal are invalid - br#""#suffix; //~ ERROR suffixes on a byte string literal are invalid - 'a'suffix; //~ ERROR suffixes on a char literal are invalid - b'a'suffix; //~ ERROR suffixes on a byte literal are invalid + ""suffix; //~ ERROR suffixes on string literals are invalid + b""suffix; //~ ERROR suffixes on byte string literals are invalid + r#""#suffix; //~ ERROR suffixes on string literals are invalid + br#""#suffix; //~ ERROR suffixes on byte string literals are invalid + 'a'suffix; //~ ERROR suffixes on char literals are invalid + b'a'suffix; //~ ERROR suffixes on byte literals are invalid 1234u1024; //~ ERROR invalid width `1024` for integer literal 1234i1024; //~ ERROR invalid width `1024` for integer literal diff --git a/src/test/ui/parser/bad-lit-suffixes.stderr b/src/test/ui/parser/bad-lit-suffixes.stderr index 9b596571481b9..f74eef324450d 100644 --- a/src/test/ui/parser/bad-lit-suffixes.stderr +++ b/src/test/ui/parser/bad-lit-suffixes.stderr @@ -1,46 +1,46 @@ -error: suffixes on a string literal are invalid +error: suffixes on string literals are invalid --> $DIR/bad-lit-suffixes.rs:2:5 | LL | "C"suffix | ^^^^^^^^^ invalid suffix `suffix` -error: suffixes on a string literal are invalid +error: suffixes on string literals are invalid --> $DIR/bad-lit-suffixes.rs:6:5 | LL | "C"suffix | ^^^^^^^^^ invalid suffix `suffix` -error: suffixes on a string literal are invalid +error: suffixes on string literals are invalid --> $DIR/bad-lit-suffixes.rs:10:5 | LL | ""suffix; | ^^^^^^^^ invalid suffix `suffix` -error: suffixes on a byte string literal are invalid +error: suffixes on byte string literals are invalid --> $DIR/bad-lit-suffixes.rs:11:5 | LL | b""suffix; | ^^^^^^^^^ invalid suffix `suffix` -error: suffixes on a string literal are invalid +error: suffixes on string literals are invalid --> $DIR/bad-lit-suffixes.rs:12:5 | LL | r#""#suffix; | ^^^^^^^^^^^ invalid suffix `suffix` -error: suffixes on a byte string literal are invalid +error: suffixes on byte string literals are invalid --> $DIR/bad-lit-suffixes.rs:13:5 | LL | br#""#suffix; | ^^^^^^^^^^^^ invalid suffix `suffix` -error: suffixes on a char literal are invalid +error: suffixes on char literals are invalid --> $DIR/bad-lit-suffixes.rs:14:5 | LL | 'a'suffix; | ^^^^^^^^^ invalid suffix `suffix` -error: suffixes on a byte literal are invalid +error: suffixes on byte literals are invalid --> $DIR/bad-lit-suffixes.rs:15:5 | LL | b'a'suffix; From e56d6a68dbda754b414abff41517f3fad9e547b0 Mon Sep 17 00:00:00 2001 From: Xiretza Date: Tue, 30 Aug 2022 13:19:17 +0200 Subject: [PATCH 333/586] Move rustc_parse diagnostic structs to separate module --- compiler/rustc_parse/src/errors.rs | 783 +++++++++++++++++ compiler/rustc_parse/src/lib.rs | 2 + .../rustc_parse/src/parser/diagnostics.rs | 786 +----------------- compiler/rustc_parse/src/parser/expr.rs | 46 +- compiler/rustc_parse/src/parser/item.rs | 4 +- compiler/rustc_parse/src/parser/mod.rs | 2 +- compiler/rustc_parse/src/parser/pat.rs | 2 +- compiler/rustc_parse/src/parser/stmt.rs | 5 +- 8 files changed, 819 insertions(+), 811 deletions(-) create mode 100644 compiler/rustc_parse/src/errors.rs diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs new file mode 100644 index 0000000000000..dc7a39457a0c0 --- /dev/null +++ b/compiler/rustc_parse/src/errors.rs @@ -0,0 +1,783 @@ +use rustc_errors::Applicability; +use rustc_macros::{Diagnostic, Subdiagnostic}; +use rustc_session::errors::ExprParenthesesNeeded; +use rustc_span::symbol::Ident; +use rustc_span::{Span, Symbol}; + +#[derive(Diagnostic)] +#[diag(parser::maybe_report_ambiguous_plus)] +pub(crate) struct AmbiguousPlus { + pub sum_ty: String, + #[primary_span] + #[suggestion(code = "({sum_ty})")] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(parser::maybe_recover_from_bad_type_plus, code = "E0178")] +pub(crate) struct BadTypePlus { + pub ty: String, + #[primary_span] + pub span: Span, + #[subdiagnostic] + pub sub: BadTypePlusSub, +} + +#[derive(Subdiagnostic)] +pub(crate) enum BadTypePlusSub { + #[suggestion( + parser::add_paren, + code = "{sum_with_parens}", + applicability = "machine-applicable" + )] + AddParen { + sum_with_parens: String, + #[primary_span] + span: Span, + }, + #[label(parser::forgot_paren)] + ForgotParen { + #[primary_span] + span: Span, + }, + #[label(parser::expect_path)] + ExpectPath { + #[primary_span] + span: Span, + }, +} + +#[derive(Diagnostic)] +#[diag(parser::maybe_recover_from_bad_qpath_stage_2)] +pub(crate) struct BadQPathStage2 { + #[primary_span] + #[suggestion(code = "", applicability = "maybe-incorrect")] + pub span: Span, + pub ty: String, +} + +#[derive(Diagnostic)] +#[diag(parser::incorrect_semicolon)] +pub(crate) struct IncorrectSemicolon<'a> { + #[primary_span] + #[suggestion_short(code = "", applicability = "machine-applicable")] + pub span: Span, + #[help] + pub opt_help: Option<()>, + pub name: &'a str, +} + +#[derive(Diagnostic)] +#[diag(parser::incorrect_use_of_await)] +pub(crate) struct IncorrectUseOfAwait { + #[primary_span] + #[suggestion(parser::parentheses_suggestion, code = "", applicability = "machine-applicable")] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(parser::incorrect_use_of_await)] +pub(crate) struct IncorrectAwait { + #[primary_span] + pub span: Span, + #[suggestion(parser::postfix_suggestion, code = "{expr}.await{question_mark}")] + pub sugg_span: (Span, Applicability), + pub expr: String, + pub question_mark: &'static str, +} + +#[derive(Diagnostic)] +#[diag(parser::in_in_typo)] +pub(crate) struct InInTypo { + #[primary_span] + pub span: Span, + #[suggestion(code = "", applicability = "machine-applicable")] + pub sugg_span: Span, +} + +#[derive(Diagnostic)] +#[diag(parser::invalid_variable_declaration)] +pub(crate) struct InvalidVariableDeclaration { + #[primary_span] + pub span: Span, + #[subdiagnostic] + pub sub: InvalidVariableDeclarationSub, +} + +#[derive(Subdiagnostic)] +pub(crate) enum InvalidVariableDeclarationSub { + #[suggestion( + parser::switch_mut_let_order, + applicability = "maybe-incorrect", + code = "let mut" + )] + SwitchMutLetOrder(#[primary_span] Span), + #[suggestion( + parser::missing_let_before_mut, + applicability = "machine-applicable", + code = "let mut" + )] + MissingLet(#[primary_span] Span), + #[suggestion(parser::use_let_not_auto, applicability = "machine-applicable", code = "let")] + UseLetNotAuto(#[primary_span] Span), + #[suggestion(parser::use_let_not_var, applicability = "machine-applicable", code = "let")] + UseLetNotVar(#[primary_span] Span), +} + +#[derive(Diagnostic)] +#[diag(parser::invalid_comparison_operator)] +pub(crate) struct InvalidComparisonOperator { + #[primary_span] + pub span: Span, + pub invalid: String, + #[subdiagnostic] + pub sub: InvalidComparisonOperatorSub, +} + +#[derive(Subdiagnostic)] +pub(crate) enum InvalidComparisonOperatorSub { + #[suggestion_short( + parser::use_instead, + applicability = "machine-applicable", + code = "{correct}" + )] + Correctable { + #[primary_span] + span: Span, + invalid: String, + correct: String, + }, + #[label(parser::spaceship_operator_invalid)] + Spaceship(#[primary_span] Span), +} + +#[derive(Diagnostic)] +#[diag(parser::invalid_logical_operator)] +#[note] +pub(crate) struct InvalidLogicalOperator { + #[primary_span] + pub span: Span, + pub incorrect: String, + #[subdiagnostic] + pub sub: InvalidLogicalOperatorSub, +} + +#[derive(Subdiagnostic)] +pub(crate) enum InvalidLogicalOperatorSub { + #[suggestion_short( + parser::use_amp_amp_for_conjunction, + applicability = "machine-applicable", + code = "&&" + )] + Conjunction(#[primary_span] Span), + #[suggestion_short( + parser::use_pipe_pipe_for_disjunction, + applicability = "machine-applicable", + code = "||" + )] + Disjunction(#[primary_span] Span), +} + +#[derive(Diagnostic)] +#[diag(parser::tilde_is_not_unary_operator)] +pub(crate) struct TildeAsUnaryOperator( + #[primary_span] + #[suggestion_short(applicability = "machine-applicable", code = "!")] + pub Span, +); + +#[derive(Diagnostic)] +#[diag(parser::unexpected_token_after_not)] +pub(crate) struct NotAsNegationOperator { + #[primary_span] + pub negated: Span, + pub negated_desc: String, + #[subdiagnostic] + pub sub: NotAsNegationOperatorSub, +} + +#[derive(Subdiagnostic)] +pub enum NotAsNegationOperatorSub { + #[suggestion_short( + parser::unexpected_token_after_not_default, + applicability = "machine-applicable", + code = "!" + )] + SuggestNotDefault(#[primary_span] Span), + + #[suggestion_short( + parser::unexpected_token_after_not_bitwise, + applicability = "machine-applicable", + code = "!" + )] + SuggestNotBitwise(#[primary_span] Span), + + #[suggestion_short( + parser::unexpected_token_after_not_logical, + applicability = "machine-applicable", + code = "!" + )] + SuggestNotLogical(#[primary_span] Span), +} + +#[derive(Diagnostic)] +#[diag(parser::malformed_loop_label)] +pub(crate) struct MalformedLoopLabel { + #[primary_span] + #[suggestion(applicability = "machine-applicable", code = "{correct_label}")] + pub span: Span, + pub correct_label: Ident, +} + +#[derive(Diagnostic)] +#[diag(parser::lifetime_in_borrow_expression)] +pub(crate) struct LifetimeInBorrowExpression { + #[primary_span] + pub span: Span, + #[suggestion(applicability = "machine-applicable", code = "")] + #[label] + pub lifetime_span: Span, +} + +#[derive(Diagnostic)] +#[diag(parser::field_expression_with_generic)] +pub(crate) struct FieldExpressionWithGeneric(#[primary_span] pub Span); + +#[derive(Diagnostic)] +#[diag(parser::macro_invocation_with_qualified_path)] +pub(crate) struct MacroInvocationWithQualifiedPath(#[primary_span] pub Span); + +#[derive(Diagnostic)] +#[diag(parser::unexpected_token_after_label)] +pub(crate) struct UnexpectedTokenAfterLabel { + #[primary_span] + #[label(parser::unexpected_token_after_label)] + pub span: Span, + #[suggestion_verbose(parser::suggestion_remove_label, code = "")] + pub remove_label: Option, + #[subdiagnostic] + pub enclose_in_block: Option, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion(parser::suggestion_enclose_in_block, applicability = "machine-applicable")] +pub(crate) struct UnexpectedTokenAfterLabelSugg { + #[suggestion_part(code = "{{ ")] + pub left: Span, + #[suggestion_part(code = " }}")] + pub right: Span, +} + +#[derive(Diagnostic)] +#[diag(parser::require_colon_after_labeled_expression)] +#[note] +pub(crate) struct RequireColonAfterLabeledExpression { + #[primary_span] + pub span: Span, + #[label] + pub label: Span, + #[suggestion_short(applicability = "machine-applicable", code = ": ")] + pub label_end: Span, +} + +#[derive(Diagnostic)] +#[diag(parser::do_catch_syntax_removed)] +#[note] +pub(crate) struct DoCatchSyntaxRemoved { + #[primary_span] + #[suggestion(applicability = "machine-applicable", code = "try")] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(parser::float_literal_requires_integer_part)] +pub(crate) struct FloatLiteralRequiresIntegerPart { + #[primary_span] + #[suggestion(applicability = "machine-applicable", code = "{correct}")] + pub span: Span, + pub correct: String, +} + +#[derive(Diagnostic)] +#[diag(parser::invalid_int_literal_width)] +#[help] +pub(crate) struct InvalidIntLiteralWidth { + #[primary_span] + pub span: Span, + pub width: String, +} + +#[derive(Diagnostic)] +#[diag(parser::invalid_num_literal_base_prefix)] +#[note] +pub(crate) struct InvalidNumLiteralBasePrefix { + #[primary_span] + #[suggestion(applicability = "maybe-incorrect", code = "{fixed}")] + pub span: Span, + pub fixed: String, +} + +#[derive(Diagnostic)] +#[diag(parser::invalid_num_literal_suffix)] +#[help] +pub(crate) struct InvalidNumLiteralSuffix { + #[primary_span] + #[label] + pub span: Span, + pub suffix: String, +} + +#[derive(Diagnostic)] +#[diag(parser::invalid_float_literal_width)] +#[help] +pub(crate) struct InvalidFloatLiteralWidth { + #[primary_span] + pub span: Span, + pub width: String, +} + +#[derive(Diagnostic)] +#[diag(parser::invalid_float_literal_suffix)] +#[help] +pub(crate) struct InvalidFloatLiteralSuffix { + #[primary_span] + #[label] + pub span: Span, + pub suffix: String, +} + +#[derive(Diagnostic)] +#[diag(parser::int_literal_too_large)] +pub(crate) struct IntLiteralTooLarge { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(parser::missing_semicolon_before_array)] +pub(crate) struct MissingSemicolonBeforeArray { + #[primary_span] + pub open_delim: Span, + #[suggestion_verbose(applicability = "maybe-incorrect", code = ";")] + pub semicolon: Span, +} + +#[derive(Diagnostic)] +#[diag(parser::invalid_block_macro_segment)] +pub(crate) struct InvalidBlockMacroSegment { + #[primary_span] + pub span: Span, + #[label] + pub context: Span, +} + +#[derive(Diagnostic)] +#[diag(parser::if_expression_missing_then_block)] +pub(crate) struct IfExpressionMissingThenBlock { + #[primary_span] + pub if_span: Span, + #[subdiagnostic] + pub sub: IfExpressionMissingThenBlockSub, +} + +#[derive(Subdiagnostic)] +pub(crate) enum IfExpressionMissingThenBlockSub { + #[help(parser::condition_possibly_unfinished)] + UnfinishedCondition(#[primary_span] Span), + #[help(parser::add_then_block)] + AddThenBlock(#[primary_span] Span), +} + +#[derive(Diagnostic)] +#[diag(parser::if_expression_missing_condition)] +pub(crate) struct IfExpressionMissingCondition { + #[primary_span] + #[label(parser::condition_label)] + pub if_span: Span, + #[label(parser::block_label)] + pub block_span: Span, +} + +#[derive(Diagnostic)] +#[diag(parser::expected_expression_found_let)] +pub(crate) struct ExpectedExpressionFoundLet { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(parser::expected_else_block)] +pub(crate) struct ExpectedElseBlock { + #[primary_span] + pub first_tok_span: Span, + pub first_tok: String, + #[label] + pub else_span: Span, + #[suggestion(applicability = "maybe-incorrect", code = "if ")] + pub condition_start: Span, +} + +#[derive(Diagnostic)] +#[diag(parser::outer_attribute_not_allowed_on_if_else)] +pub(crate) struct OuterAttributeNotAllowedOnIfElse { + #[primary_span] + pub last: Span, + + #[label(parser::branch_label)] + pub branch_span: Span, + + #[label(parser::ctx_label)] + pub ctx_span: Span, + pub ctx: String, + + #[suggestion(applicability = "machine-applicable", code = "")] + pub attributes: Span, +} + +#[derive(Diagnostic)] +#[diag(parser::missing_in_in_for_loop)] +pub(crate) struct MissingInInForLoop { + #[primary_span] + pub span: Span, + #[subdiagnostic] + pub sub: MissingInInForLoopSub, +} + +#[derive(Subdiagnostic)] +pub(crate) enum MissingInInForLoopSub { + // Has been misleading, at least in the past (closed Issue #48492), thus maybe-incorrect + #[suggestion_short(parser::use_in_not_of, applicability = "maybe-incorrect", code = "in")] + InNotOf(#[primary_span] Span), + #[suggestion_short(parser::add_in, applicability = "maybe-incorrect", code = " in ")] + AddIn(#[primary_span] Span), +} + +#[derive(Diagnostic)] +#[diag(parser::missing_comma_after_match_arm)] +pub(crate) struct MissingCommaAfterMatchArm { + #[primary_span] + #[suggestion(applicability = "machine-applicable", code = ",")] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(parser::catch_after_try)] +#[help] +pub(crate) struct CatchAfterTry { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(parser::comma_after_base_struct)] +#[note] +pub(crate) struct CommaAfterBaseStruct { + #[primary_span] + pub span: Span, + #[suggestion_short(applicability = "machine-applicable", code = "")] + pub comma: Span, +} + +#[derive(Diagnostic)] +#[diag(parser::eq_field_init)] +pub(crate) struct EqFieldInit { + #[primary_span] + pub span: Span, + #[suggestion(applicability = "machine-applicable", code = ":")] + pub eq: Span, +} + +#[derive(Diagnostic)] +#[diag(parser::dotdotdot)] +pub(crate) struct DotDotDot { + #[primary_span] + #[suggestion(parser::suggest_exclusive_range, applicability = "maybe-incorrect", code = "..")] + #[suggestion(parser::suggest_inclusive_range, applicability = "maybe-incorrect", code = "..=")] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(parser::left_arrow_operator)] +pub(crate) struct LeftArrowOperator { + #[primary_span] + #[suggestion(applicability = "maybe-incorrect", code = "< -")] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(parser::remove_let)] +pub(crate) struct RemoveLet { + #[primary_span] + #[suggestion(applicability = "machine-applicable", code = "")] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(parser::use_eq_instead)] +pub(crate) struct UseEqInstead { + #[primary_span] + #[suggestion_short(applicability = "machine-applicable", code = "=")] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(parser::use_empty_block_not_semi)] +pub(crate) struct UseEmptyBlockNotSemi { + #[primary_span] + #[suggestion_hidden(applicability = "machine-applicable", code = "{{}}")] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(parser::comparison_interpreted_as_generic)] +pub(crate) struct ComparisonInterpretedAsGeneric { + #[primary_span] + #[label(parser::label_comparison)] + pub comparison: Span, + pub typename: String, + #[label(parser::label_args)] + pub args: Span, + #[subdiagnostic] + pub suggestion: ComparisonOrShiftInterpretedAsGenericSugg, +} + +#[derive(Diagnostic)] +#[diag(parser::shift_interpreted_as_generic)] +pub(crate) struct ShiftInterpretedAsGeneric { + #[primary_span] + #[label(parser::label_comparison)] + pub shift: Span, + pub typename: String, + #[label(parser::label_args)] + pub args: Span, + #[subdiagnostic] + pub suggestion: ComparisonOrShiftInterpretedAsGenericSugg, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion(parser::suggestion, applicability = "machine-applicable")] +pub(crate) struct ComparisonOrShiftInterpretedAsGenericSugg { + #[suggestion_part(code = "(")] + pub left: Span, + #[suggestion_part(code = ")")] + pub right: Span, +} + +#[derive(Diagnostic)] +#[diag(parser::found_expr_would_be_stmt)] +pub(crate) struct FoundExprWouldBeStmt { + #[primary_span] + #[label] + pub span: Span, + pub token: String, + #[subdiagnostic] + pub suggestion: ExprParenthesesNeeded, +} + +#[derive(Diagnostic)] +#[diag(parser::leading_plus_not_supported)] +pub(crate) struct LeadingPlusNotSupported { + #[primary_span] + #[label] + pub span: Span, + #[suggestion_verbose( + parser::suggestion_remove_plus, + code = "", + applicability = "machine-applicable" + )] + pub remove_plus: Option, + #[subdiagnostic] + pub add_parentheses: Option, +} + +#[derive(Diagnostic)] +#[diag(parser::parentheses_with_struct_fields)] +pub(crate) struct ParenthesesWithStructFields { + #[primary_span] + pub span: Span, + pub name: String, + #[subdiagnostic] + pub braces_for_struct: BracesForStructLiteral, + #[subdiagnostic] + pub no_fields_for_fn: NoFieldsForFnCall, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion(parser::suggestion_braces_for_struct, applicability = "maybe-incorrect")] +pub(crate) struct BracesForStructLiteral { + #[suggestion_part(code = " {{ ")] + pub first: Span, + #[suggestion_part(code = " }}")] + pub second: Span, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion(parser::suggestion_no_fields_for_fn, applicability = "maybe-incorrect")] +pub(crate) struct NoFieldsForFnCall { + #[suggestion_part(code = "")] + pub fields: Vec, +} + +#[derive(Diagnostic)] +#[diag(parser::labeled_loop_in_break)] +pub(crate) struct LabeledLoopInBreak { + #[primary_span] + pub span: Span, + #[subdiagnostic] + pub sub: LabeledLoopInBreakSub, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion(parser::suggestion, applicability = "machine-applicable")] +pub(crate) struct LabeledLoopInBreakSub { + #[suggestion_part(code = "(")] + pub first: Span, + #[suggestion_part(code = ")")] + pub second: Span, +} + +#[derive(Diagnostic)] +#[diag(parser::array_brackets_instead_of_braces)] +pub(crate) struct ArrayBracketsInsteadOfSpaces { + #[primary_span] + pub span: Span, + #[subdiagnostic] + pub sub: ArrayBracketsInsteadOfSpacesSugg, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion(parser::suggestion, applicability = "maybe-incorrect")] +pub(crate) struct ArrayBracketsInsteadOfSpacesSugg { + #[suggestion_part(code = "[")] + pub left: Span, + #[suggestion_part(code = "]")] + pub right: Span, +} + +#[derive(Diagnostic)] +#[diag(parser::match_arm_body_without_braces)] +pub(crate) struct MatchArmBodyWithoutBraces { + #[primary_span] + #[label(parser::label_statements)] + pub statements: Span, + #[label(parser::label_arrow)] + pub arrow: Span, + pub num_statements: usize, + #[subdiagnostic] + pub sub: MatchArmBodyWithoutBracesSugg, +} + +#[derive(Subdiagnostic)] +pub(crate) enum MatchArmBodyWithoutBracesSugg { + #[multipart_suggestion(parser::suggestion_add_braces, applicability = "machine-applicable")] + AddBraces { + #[suggestion_part(code = "{{ ")] + left: Span, + #[suggestion_part(code = " }}")] + right: Span, + }, + #[suggestion( + parser::suggestion_use_comma_not_semicolon, + code = ",", + applicability = "machine-applicable" + )] + UseComma { + #[primary_span] + semicolon: Span, + }, +} + +#[derive(Diagnostic)] +#[diag(parser::struct_literal_not_allowed_here)] +pub(crate) struct StructLiteralNotAllowedHere { + #[primary_span] + pub span: Span, + #[subdiagnostic] + pub sub: StructLiteralNotAllowedHereSugg, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion(parser::suggestion, applicability = "machine-applicable")] +pub(crate) struct StructLiteralNotAllowedHereSugg { + #[suggestion_part(code = "(")] + pub left: Span, + #[suggestion_part(code = ")")] + pub right: Span, +} + +#[derive(Diagnostic)] +#[diag(parser::invalid_interpolated_expression)] +pub(crate) struct InvalidInterpolatedExpression { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(parser::hexadecimal_float_literal_not_supported)] +pub(crate) struct HexadecimalFloatLiteralNotSupported { + #[primary_span] + #[label(parser::not_supported)] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(parser::octal_float_literal_not_supported)] +pub(crate) struct OctalFloatLiteralNotSupported { + #[primary_span] + #[label(parser::not_supported)] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(parser::binary_float_literal_not_supported)] +pub(crate) struct BinaryFloatLiteralNotSupported { + #[primary_span] + #[label(parser::not_supported)] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(parser::invalid_literal_suffix)] +pub(crate) struct InvalidLiteralSuffix { + #[primary_span] + #[label] + pub span: Span, + // FIXME(#100717) + pub kind: String, + pub suffix: Symbol, +} + +#[derive(Diagnostic)] +#[diag(parser::invalid_literal_suffix_on_tuple_index)] +pub(crate) struct InvalidLiteralSuffixOnTupleIndex { + #[primary_span] + #[label] + pub span: Span, + pub suffix: Symbol, + #[help(parser::tuple_exception_line_1)] + #[help(parser::tuple_exception_line_2)] + #[help(parser::tuple_exception_line_3)] + pub exception: Option<()>, +} + +#[derive(Diagnostic)] +#[diag(parser::non_string_abi_literal)] +pub(crate) struct NonStringAbiLiteral { + #[primary_span] + #[suggestion(code = "\"C\"", applicability = "maybe-incorrect")] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(parser::mismatched_closing_delimiter)] +pub(crate) struct MismatchedClosingDelimiter { + #[primary_span] + pub spans: Vec, + pub delimiter: String, + #[label(parser::label_unmatched)] + pub unmatched: Span, + #[label(parser::label_opening_candidate)] + pub opening_candidate: Option, + #[label(parser::label_unclosed)] + pub unclosed: Option, +} diff --git a/compiler/rustc_parse/src/lib.rs b/compiler/rustc_parse/src/lib.rs index 06245380927c3..0bdfe10359c0b 100644 --- a/compiler/rustc_parse/src/lib.rs +++ b/compiler/rustc_parse/src/lib.rs @@ -32,6 +32,8 @@ use parser::{emit_unclosed_delims, make_unclosed_delims_error, Parser}; pub mod lexer; pub mod validate_attr; +mod errors; + // A bunch of utility functions of the form `parse__from_` // where includes crate, expr, item, stmt, tts, and one that // uses a HOF to parse anything, and includes file and diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index c50ca9a2933ee..0fdde29175758 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -3,6 +3,10 @@ use super::{ BlockMode, CommaRecoveryMode, Parser, PathStyle, Restrictions, SemiColonMode, SeqSep, TokenExpectType, TokenType, }; +use crate::errors::{ + AmbiguousPlus, BadQPathStage2, BadTypePlus, BadTypePlusSub, InInTypo, IncorrectAwait, + IncorrectSemicolon, IncorrectUseOfAwait, UseEqInstead, +}; use crate::lexer::UnmatchedBrace; use rustc_ast as ast; @@ -20,11 +24,9 @@ use rustc_errors::{ fluent, Applicability, DiagnosticBuilder, DiagnosticMessage, Handler, MultiSpan, PResult, }; use rustc_errors::{pluralize, struct_span_err, Diagnostic, ErrorGuaranteed}; -use rustc_macros::{Diagnostic, Subdiagnostic}; -use rustc_session::errors::ExprParenthesesNeeded; use rustc_span::source_map::Spanned; use rustc_span::symbol::{kw, sym, Ident}; -use rustc_span::{Span, SpanSnippetError, Symbol, DUMMY_SP}; +use rustc_span::{Span, SpanSnippetError, DUMMY_SP}; use std::ops::{Deref, DerefMut}; use std::mem::take; @@ -243,784 +245,6 @@ impl MultiSugg { } } -#[derive(Diagnostic)] -#[diag(parser::maybe_report_ambiguous_plus)] -struct AmbiguousPlus { - pub sum_ty: String, - #[primary_span] - #[suggestion(code = "({sum_ty})")] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag(parser::maybe_recover_from_bad_type_plus, code = "E0178")] -struct BadTypePlus { - pub ty: String, - #[primary_span] - pub span: Span, - #[subdiagnostic] - pub sub: BadTypePlusSub, -} - -#[derive(Subdiagnostic)] -pub enum BadTypePlusSub { - #[suggestion( - parser::add_paren, - code = "{sum_with_parens}", - applicability = "machine-applicable" - )] - AddParen { - sum_with_parens: String, - #[primary_span] - span: Span, - }, - #[label(parser::forgot_paren)] - ForgotParen { - #[primary_span] - span: Span, - }, - #[label(parser::expect_path)] - ExpectPath { - #[primary_span] - span: Span, - }, -} - -#[derive(Diagnostic)] -#[diag(parser::maybe_recover_from_bad_qpath_stage_2)] -struct BadQPathStage2 { - #[primary_span] - #[suggestion(code = "", applicability = "maybe-incorrect")] - span: Span, - ty: String, -} - -#[derive(Diagnostic)] -#[diag(parser::incorrect_semicolon)] -struct IncorrectSemicolon<'a> { - #[primary_span] - #[suggestion_short(code = "", applicability = "machine-applicable")] - span: Span, - #[help] - opt_help: Option<()>, - name: &'a str, -} - -#[derive(Diagnostic)] -#[diag(parser::incorrect_use_of_await)] -struct IncorrectUseOfAwait { - #[primary_span] - #[suggestion(parser::parentheses_suggestion, code = "", applicability = "machine-applicable")] - span: Span, -} - -#[derive(Diagnostic)] -#[diag(parser::incorrect_use_of_await)] -struct IncorrectAwait { - #[primary_span] - span: Span, - #[suggestion(parser::postfix_suggestion, code = "{expr}.await{question_mark}")] - sugg_span: (Span, Applicability), - expr: String, - question_mark: &'static str, -} - -#[derive(Diagnostic)] -#[diag(parser::in_in_typo)] -struct InInTypo { - #[primary_span] - span: Span, - #[suggestion(code = "", applicability = "machine-applicable")] - sugg_span: Span, -} - -#[derive(Diagnostic)] -#[diag(parser::invalid_variable_declaration)] -pub struct InvalidVariableDeclaration { - #[primary_span] - pub span: Span, - #[subdiagnostic] - pub sub: InvalidVariableDeclarationSub, -} - -#[derive(Subdiagnostic)] -pub enum InvalidVariableDeclarationSub { - #[suggestion( - parser::switch_mut_let_order, - applicability = "maybe-incorrect", - code = "let mut" - )] - SwitchMutLetOrder(#[primary_span] Span), - #[suggestion( - parser::missing_let_before_mut, - applicability = "machine-applicable", - code = "let mut" - )] - MissingLet(#[primary_span] Span), - #[suggestion(parser::use_let_not_auto, applicability = "machine-applicable", code = "let")] - UseLetNotAuto(#[primary_span] Span), - #[suggestion(parser::use_let_not_var, applicability = "machine-applicable", code = "let")] - UseLetNotVar(#[primary_span] Span), -} - -#[derive(Diagnostic)] -#[diag(parser::invalid_comparison_operator)] -pub(crate) struct InvalidComparisonOperator { - #[primary_span] - pub span: Span, - pub invalid: String, - #[subdiagnostic] - pub sub: InvalidComparisonOperatorSub, -} - -#[derive(Subdiagnostic)] -pub(crate) enum InvalidComparisonOperatorSub { - #[suggestion_short( - parser::use_instead, - applicability = "machine-applicable", - code = "{correct}" - )] - Correctable { - #[primary_span] - span: Span, - invalid: String, - correct: String, - }, - #[label(parser::spaceship_operator_invalid)] - Spaceship(#[primary_span] Span), -} - -#[derive(Diagnostic)] -#[diag(parser::invalid_logical_operator)] -#[note] -pub(crate) struct InvalidLogicalOperator { - #[primary_span] - pub span: Span, - pub incorrect: String, - #[subdiagnostic] - pub sub: InvalidLogicalOperatorSub, -} - -#[derive(Subdiagnostic)] -pub(crate) enum InvalidLogicalOperatorSub { - #[suggestion_short( - parser::use_amp_amp_for_conjunction, - applicability = "machine-applicable", - code = "&&" - )] - Conjunction(#[primary_span] Span), - #[suggestion_short( - parser::use_pipe_pipe_for_disjunction, - applicability = "machine-applicable", - code = "||" - )] - Disjunction(#[primary_span] Span), -} - -#[derive(Diagnostic)] -#[diag(parser::tilde_is_not_unary_operator)] -pub(crate) struct TildeAsUnaryOperator( - #[primary_span] - #[suggestion_short(applicability = "machine-applicable", code = "!")] - pub Span, -); - -#[derive(Diagnostic)] -#[diag(parser::unexpected_token_after_not)] -pub(crate) struct NotAsNegationOperator { - #[primary_span] - pub negated: Span, - pub negated_desc: String, - #[subdiagnostic] - pub sub: NotAsNegationOperatorSub, -} - -#[derive(Subdiagnostic)] -pub enum NotAsNegationOperatorSub { - #[suggestion_short( - parser::unexpected_token_after_not_default, - applicability = "machine-applicable", - code = "!" - )] - SuggestNotDefault(#[primary_span] Span), - - #[suggestion_short( - parser::unexpected_token_after_not_bitwise, - applicability = "machine-applicable", - code = "!" - )] - SuggestNotBitwise(#[primary_span] Span), - - #[suggestion_short( - parser::unexpected_token_after_not_logical, - applicability = "machine-applicable", - code = "!" - )] - SuggestNotLogical(#[primary_span] Span), -} - -#[derive(Diagnostic)] -#[diag(parser::malformed_loop_label)] -pub(crate) struct MalformedLoopLabel { - #[primary_span] - #[suggestion(applicability = "machine-applicable", code = "{correct_label}")] - pub span: Span, - pub correct_label: Ident, -} - -#[derive(Diagnostic)] -#[diag(parser::lifetime_in_borrow_expression)] -pub(crate) struct LifetimeInBorrowExpression { - #[primary_span] - pub span: Span, - #[suggestion(applicability = "machine-applicable", code = "")] - #[label] - pub lifetime_span: Span, -} - -#[derive(Diagnostic)] -#[diag(parser::field_expression_with_generic)] -pub(crate) struct FieldExpressionWithGeneric(#[primary_span] pub Span); - -#[derive(Diagnostic)] -#[diag(parser::macro_invocation_with_qualified_path)] -pub(crate) struct MacroInvocationWithQualifiedPath(#[primary_span] pub Span); - -#[derive(Diagnostic)] -#[diag(parser::unexpected_token_after_label)] -pub(crate) struct UnexpectedTokenAfterLabel { - #[primary_span] - #[label(parser::unexpected_token_after_label)] - pub span: Span, - #[suggestion_verbose(parser::suggestion_remove_label, code = "")] - pub remove_label: Option, - #[subdiagnostic] - pub enclose_in_block: Option, -} - -#[derive(Subdiagnostic)] -#[multipart_suggestion(parser::suggestion_enclose_in_block, applicability = "machine-applicable")] -pub(crate) struct UnexpectedTokenAfterLabelSugg { - #[suggestion_part(code = "{{ ")] - pub left: Span, - #[suggestion_part(code = " }}")] - pub right: Span, -} - -#[derive(Diagnostic)] -#[diag(parser::require_colon_after_labeled_expression)] -#[note] -pub(crate) struct RequireColonAfterLabeledExpression { - #[primary_span] - pub span: Span, - #[label] - pub label: Span, - #[suggestion_short(applicability = "machine-applicable", code = ": ")] - pub label_end: Span, -} - -#[derive(Diagnostic)] -#[diag(parser::do_catch_syntax_removed)] -#[note] -pub(crate) struct DoCatchSyntaxRemoved { - #[primary_span] - #[suggestion(applicability = "machine-applicable", code = "try")] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag(parser::float_literal_requires_integer_part)] -pub(crate) struct FloatLiteralRequiresIntegerPart { - #[primary_span] - #[suggestion(applicability = "machine-applicable", code = "{correct}")] - pub span: Span, - pub correct: String, -} - -#[derive(Diagnostic)] -#[diag(parser::invalid_int_literal_width)] -#[help] -pub(crate) struct InvalidIntLiteralWidth { - #[primary_span] - pub span: Span, - pub width: String, -} - -#[derive(Diagnostic)] -#[diag(parser::invalid_num_literal_base_prefix)] -#[note] -pub(crate) struct InvalidNumLiteralBasePrefix { - #[primary_span] - #[suggestion(applicability = "maybe-incorrect", code = "{fixed}")] - pub span: Span, - pub fixed: String, -} - -#[derive(Diagnostic)] -#[diag(parser::invalid_num_literal_suffix)] -#[help] -pub(crate) struct InvalidNumLiteralSuffix { - #[primary_span] - #[label] - pub span: Span, - pub suffix: String, -} - -#[derive(Diagnostic)] -#[diag(parser::invalid_float_literal_width)] -#[help] -pub(crate) struct InvalidFloatLiteralWidth { - #[primary_span] - pub span: Span, - pub width: String, -} - -#[derive(Diagnostic)] -#[diag(parser::invalid_float_literal_suffix)] -#[help] -pub(crate) struct InvalidFloatLiteralSuffix { - #[primary_span] - #[label] - pub span: Span, - pub suffix: String, -} - -#[derive(Diagnostic)] -#[diag(parser::int_literal_too_large)] -pub(crate) struct IntLiteralTooLarge { - #[primary_span] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag(parser::missing_semicolon_before_array)] -pub(crate) struct MissingSemicolonBeforeArray { - #[primary_span] - pub open_delim: Span, - #[suggestion_verbose(applicability = "maybe-incorrect", code = ";")] - pub semicolon: Span, -} - -#[derive(Diagnostic)] -#[diag(parser::invalid_block_macro_segment)] -pub(crate) struct InvalidBlockMacroSegment { - #[primary_span] - pub span: Span, - #[label] - pub context: Span, -} - -#[derive(Diagnostic)] -#[diag(parser::if_expression_missing_then_block)] -pub(crate) struct IfExpressionMissingThenBlock { - #[primary_span] - pub if_span: Span, - #[subdiagnostic] - pub sub: IfExpressionMissingThenBlockSub, -} - -#[derive(Subdiagnostic)] -pub(crate) enum IfExpressionMissingThenBlockSub { - #[help(parser::condition_possibly_unfinished)] - UnfinishedCondition(#[primary_span] Span), - #[help(parser::add_then_block)] - AddThenBlock(#[primary_span] Span), -} - -#[derive(Diagnostic)] -#[diag(parser::if_expression_missing_condition)] -pub(crate) struct IfExpressionMissingCondition { - #[primary_span] - #[label(parser::condition_label)] - pub if_span: Span, - #[label(parser::block_label)] - pub block_span: Span, -} - -#[derive(Diagnostic)] -#[diag(parser::expected_expression_found_let)] -pub(crate) struct ExpectedExpressionFoundLet { - #[primary_span] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag(parser::expected_else_block)] -pub(crate) struct ExpectedElseBlock { - #[primary_span] - pub first_tok_span: Span, - pub first_tok: String, - #[label] - pub else_span: Span, - #[suggestion(applicability = "maybe-incorrect", code = "if ")] - pub condition_start: Span, -} - -#[derive(Diagnostic)] -#[diag(parser::outer_attribute_not_allowed_on_if_else)] -pub(crate) struct OuterAttributeNotAllowedOnIfElse { - #[primary_span] - pub last: Span, - - #[label(parser::branch_label)] - pub branch_span: Span, - - #[label(parser::ctx_label)] - pub ctx_span: Span, - pub ctx: String, - - #[suggestion(applicability = "machine-applicable", code = "")] - pub attributes: Span, -} - -#[derive(Diagnostic)] -#[diag(parser::missing_in_in_for_loop)] -pub(crate) struct MissingInInForLoop { - #[primary_span] - pub span: Span, - #[subdiagnostic] - pub sub: MissingInInForLoopSub, -} - -#[derive(Subdiagnostic)] -pub(crate) enum MissingInInForLoopSub { - // Has been misleading, at least in the past (closed Issue #48492), thus maybe-incorrect - #[suggestion_short(parser::use_in_not_of, applicability = "maybe-incorrect", code = "in")] - InNotOf(#[primary_span] Span), - #[suggestion_short(parser::add_in, applicability = "maybe-incorrect", code = " in ")] - AddIn(#[primary_span] Span), -} - -#[derive(Diagnostic)] -#[diag(parser::missing_comma_after_match_arm)] -pub(crate) struct MissingCommaAfterMatchArm { - #[primary_span] - #[suggestion(applicability = "machine-applicable", code = ",")] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag(parser::catch_after_try)] -#[help] -pub(crate) struct CatchAfterTry { - #[primary_span] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag(parser::comma_after_base_struct)] -#[note] -pub(crate) struct CommaAfterBaseStruct { - #[primary_span] - pub span: Span, - #[suggestion_short(applicability = "machine-applicable", code = "")] - pub comma: Span, -} - -#[derive(Diagnostic)] -#[diag(parser::eq_field_init)] -pub(crate) struct EqFieldInit { - #[primary_span] - pub span: Span, - #[suggestion(applicability = "machine-applicable", code = ":")] - pub eq: Span, -} - -#[derive(Diagnostic)] -#[diag(parser::dotdotdot)] -pub(crate) struct DotDotDot { - #[primary_span] - #[suggestion(parser::suggest_exclusive_range, applicability = "maybe-incorrect", code = "..")] - #[suggestion(parser::suggest_inclusive_range, applicability = "maybe-incorrect", code = "..=")] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag(parser::left_arrow_operator)] -pub(crate) struct LeftArrowOperator { - #[primary_span] - #[suggestion(applicability = "maybe-incorrect", code = "< -")] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag(parser::remove_let)] -pub(crate) struct RemoveLet { - #[primary_span] - #[suggestion(applicability = "machine-applicable", code = "")] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag(parser::use_eq_instead)] -pub(crate) struct UseEqInstead { - #[primary_span] - #[suggestion_short(applicability = "machine-applicable", code = "=")] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag(parser::use_empty_block_not_semi)] -pub(crate) struct UseEmptyBlockNotSemi { - #[primary_span] - #[suggestion_hidden(applicability = "machine-applicable", code = "{{}}")] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag(parser::comparison_interpreted_as_generic)] -pub(crate) struct ComparisonInterpretedAsGeneric { - #[primary_span] - #[label(parser::label_comparison)] - pub comparison: Span, - pub typename: String, - #[label(parser::label_args)] - pub args: Span, - #[subdiagnostic] - pub suggestion: ComparisonOrShiftInterpretedAsGenericSugg, -} - -#[derive(Diagnostic)] -#[diag(parser::shift_interpreted_as_generic)] -pub(crate) struct ShiftInterpretedAsGeneric { - #[primary_span] - #[label(parser::label_comparison)] - pub shift: Span, - pub typename: String, - #[label(parser::label_args)] - pub args: Span, - #[subdiagnostic] - pub suggestion: ComparisonOrShiftInterpretedAsGenericSugg, -} - -#[derive(Subdiagnostic)] -#[multipart_suggestion(parser::suggestion, applicability = "machine-applicable")] -pub(crate) struct ComparisonOrShiftInterpretedAsGenericSugg { - #[suggestion_part(code = "(")] - pub left: Span, - #[suggestion_part(code = ")")] - pub right: Span, -} - -#[derive(Diagnostic)] -#[diag(parser::found_expr_would_be_stmt)] -pub(crate) struct FoundExprWouldBeStmt { - #[primary_span] - #[label] - pub span: Span, - pub token: String, - #[subdiagnostic] - pub suggestion: ExprParenthesesNeeded, -} - -#[derive(Diagnostic)] -#[diag(parser::leading_plus_not_supported)] -pub(crate) struct LeadingPlusNotSupported { - #[primary_span] - #[label] - pub span: Span, - #[suggestion_verbose( - parser::suggestion_remove_plus, - code = "", - applicability = "machine-applicable" - )] - pub remove_plus: Option, - #[subdiagnostic] - pub add_parentheses: Option, -} - -#[derive(Diagnostic)] -#[diag(parser::parentheses_with_struct_fields)] -pub(crate) struct ParenthesesWithStructFields { - #[primary_span] - pub span: Span, - pub name: String, - #[subdiagnostic] - pub braces_for_struct: BracesForStructLiteral, - #[subdiagnostic] - pub no_fields_for_fn: NoFieldsForFnCall, -} - -#[derive(Subdiagnostic)] -#[multipart_suggestion(parser::suggestion_braces_for_struct, applicability = "maybe-incorrect")] -pub(crate) struct BracesForStructLiteral { - #[suggestion_part(code = " {{ ")] - pub first: Span, - #[suggestion_part(code = " }}")] - pub second: Span, -} - -#[derive(Subdiagnostic)] -#[multipart_suggestion(parser::suggestion_no_fields_for_fn, applicability = "maybe-incorrect")] -pub(crate) struct NoFieldsForFnCall { - #[suggestion_part(code = "")] - pub fields: Vec, -} - -#[derive(Diagnostic)] -#[diag(parser::labeled_loop_in_break)] -pub(crate) struct LabeledLoopInBreak { - #[primary_span] - pub span: Span, - #[subdiagnostic] - pub sub: LabeledLoopInBreakSub, -} - -#[derive(Subdiagnostic)] -#[multipart_suggestion(parser::suggestion, applicability = "machine-applicable")] -pub(crate) struct LabeledLoopInBreakSub { - #[suggestion_part(code = "(")] - pub first: Span, - #[suggestion_part(code = ")")] - pub second: Span, -} - -#[derive(Diagnostic)] -#[diag(parser::array_brackets_instead_of_braces)] -pub(crate) struct ArrayBracketsInsteadOfSpaces { - #[primary_span] - pub span: Span, - #[subdiagnostic] - pub sub: ArrayBracketsInsteadOfSpacesSugg, -} - -#[derive(Subdiagnostic)] -#[multipart_suggestion(parser::suggestion, applicability = "maybe-incorrect")] -pub(crate) struct ArrayBracketsInsteadOfSpacesSugg { - #[suggestion_part(code = "[")] - pub left: Span, - #[suggestion_part(code = "]")] - pub right: Span, -} - -#[derive(Diagnostic)] -#[diag(parser::match_arm_body_without_braces)] -pub(crate) struct MatchArmBodyWithoutBraces { - #[primary_span] - #[label(parser::label_statements)] - pub statements: Span, - #[label(parser::label_arrow)] - pub arrow: Span, - pub num_statements: usize, - #[subdiagnostic] - pub sub: MatchArmBodyWithoutBracesSugg, -} - -#[derive(Subdiagnostic)] -pub(crate) enum MatchArmBodyWithoutBracesSugg { - #[multipart_suggestion(parser::suggestion_add_braces, applicability = "machine-applicable")] - AddBraces { - #[suggestion_part(code = "{{ ")] - left: Span, - #[suggestion_part(code = " }}")] - right: Span, - }, - #[suggestion( - parser::suggestion_use_comma_not_semicolon, - code = ",", - applicability = "machine-applicable" - )] - UseComma { - #[primary_span] - semicolon: Span, - }, -} - -#[derive(Diagnostic)] -#[diag(parser::struct_literal_not_allowed_here)] -pub(crate) struct StructLiteralNotAllowedHere { - #[primary_span] - pub span: Span, - #[subdiagnostic] - pub sub: StructLiteralNotAllowedHereSugg, -} - -#[derive(Subdiagnostic)] -#[multipart_suggestion(parser::suggestion, applicability = "machine-applicable")] -pub(crate) struct StructLiteralNotAllowedHereSugg { - #[suggestion_part(code = "(")] - pub left: Span, - #[suggestion_part(code = ")")] - pub right: Span, -} - -#[derive(Diagnostic)] -#[diag(parser::invalid_interpolated_expression)] -pub(crate) struct InvalidInterpolatedExpression { - #[primary_span] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag(parser::hexadecimal_float_literal_not_supported)] -pub(crate) struct HexadecimalFloatLiteralNotSupported { - #[primary_span] - #[label(parser::not_supported)] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag(parser::octal_float_literal_not_supported)] -pub(crate) struct OctalFloatLiteralNotSupported { - #[primary_span] - #[label(parser::not_supported)] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag(parser::binary_float_literal_not_supported)] -pub(crate) struct BinaryFloatLiteralNotSupported { - #[primary_span] - #[label(parser::not_supported)] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag(parser::invalid_literal_suffix)] -pub(crate) struct InvalidLiteralSuffix { - #[primary_span] - #[label] - pub span: Span, - // FIXME(#100717) - pub kind: String, - pub suffix: Symbol, -} - -#[derive(Diagnostic)] -#[diag(parser::invalid_literal_suffix_on_tuple_index)] -pub(crate) struct InvalidLiteralSuffixOnTupleIndex { - #[primary_span] - #[label] - pub span: Span, - pub suffix: Symbol, - #[help(parser::tuple_exception_line_1)] - #[help(parser::tuple_exception_line_2)] - #[help(parser::tuple_exception_line_3)] - pub exception: Option<()>, -} - -#[derive(Diagnostic)] -#[diag(parser::non_string_abi_literal)] -pub(crate) struct NonStringAbiLiteral { - #[primary_span] - #[suggestion(code = "\"C\"", applicability = "maybe-incorrect")] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag(parser::mismatched_closing_delimiter)] -pub(crate) struct MismatchedClosingDelimiter { - #[primary_span] - pub spans: Vec, - pub delimiter: String, - #[label(parser::label_unmatched)] - pub unmatched: Span, - #[label(parser::label_opening_candidate)] - pub opening_candidate: Option, - #[label(parser::label_unclosed)] - pub unclosed: Option, -} - // SnapshotParser is used to create a snapshot of the parser // without causing duplicate errors being emitted when the `Parser` // is dropped. diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index f954dff9394f1..784a8ae4c2ef6 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -1,34 +1,32 @@ -use super::diagnostics::{ - ArrayBracketsInsteadOfSpaces, ArrayBracketsInsteadOfSpacesSugg, BracesForStructLiteral, - CatchAfterTry, CommaAfterBaseStruct, ComparisonInterpretedAsGeneric, - ComparisonOrShiftInterpretedAsGenericSugg, DoCatchSyntaxRemoved, DotDotDot, EqFieldInit, - ExpectedElseBlock, ExpectedExpressionFoundLet, FieldExpressionWithGeneric, - FloatLiteralRequiresIntegerPart, FoundExprWouldBeStmt, IfExpressionMissingCondition, - IfExpressionMissingThenBlock, IfExpressionMissingThenBlockSub, InvalidBlockMacroSegment, - InvalidComparisonOperator, InvalidComparisonOperatorSub, InvalidInterpolatedExpression, - InvalidLiteralSuffix, InvalidLiteralSuffixOnTupleIndex, InvalidLogicalOperator, - InvalidLogicalOperatorSub, LabeledLoopInBreak, LeftArrowOperator, LifetimeInBorrowExpression, - MacroInvocationWithQualifiedPath, MalformedLoopLabel, MatchArmBodyWithoutBraces, - MissingInInForLoop, MissingInInForLoopSub, MissingSemicolonBeforeArray, NoFieldsForFnCall, - NotAsNegationOperator, NotAsNegationOperatorSub, OuterAttributeNotAllowedOnIfElse, - ParenthesesWithStructFields, RequireColonAfterLabeledExpression, ShiftInterpretedAsGeneric, - SnapshotParser, StructLiteralNotAllowedHere, TildeAsUnaryOperator, UnexpectedTokenAfterLabel, - UnexpectedTokenAfterLabelSugg, -}; +use super::diagnostics::SnapshotParser; use super::pat::{CommaRecoveryMode, RecoverColon, RecoverComma, PARAM_EXPECTED}; use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign}; use super::{ AttrWrapper, BlockMode, ClosureSpans, ForceCollect, Parser, PathStyle, Restrictions, SemiColonMode, SeqSep, TokenExpectType, TokenType, TrailingToken, }; -use crate::maybe_recover_from_interpolated_ty_qpath; -use crate::parser::diagnostics::{ - BinaryFloatLiteralNotSupported, HexadecimalFloatLiteralNotSupported, IntLiteralTooLarge, - InvalidFloatLiteralSuffix, InvalidFloatLiteralWidth, InvalidIntLiteralWidth, - InvalidNumLiteralBasePrefix, InvalidNumLiteralSuffix, LabeledLoopInBreakSub, - LeadingPlusNotSupported, MatchArmBodyWithoutBracesSugg, MissingCommaAfterMatchArm, - OctalFloatLiteralNotSupported, StructLiteralNotAllowedHereSugg, +use crate::errors::{ + ArrayBracketsInsteadOfSpaces, ArrayBracketsInsteadOfSpacesSugg, BinaryFloatLiteralNotSupported, + BracesForStructLiteral, CatchAfterTry, CommaAfterBaseStruct, ComparisonInterpretedAsGeneric, + ComparisonOrShiftInterpretedAsGenericSugg, DoCatchSyntaxRemoved, DotDotDot, EqFieldInit, + ExpectedElseBlock, ExpectedExpressionFoundLet, FieldExpressionWithGeneric, + FloatLiteralRequiresIntegerPart, FoundExprWouldBeStmt, HexadecimalFloatLiteralNotSupported, + IfExpressionMissingCondition, IfExpressionMissingThenBlock, IfExpressionMissingThenBlockSub, + IntLiteralTooLarge, InvalidBlockMacroSegment, InvalidComparisonOperator, + InvalidComparisonOperatorSub, InvalidFloatLiteralSuffix, InvalidFloatLiteralWidth, + InvalidIntLiteralWidth, InvalidInterpolatedExpression, InvalidLiteralSuffix, + InvalidLiteralSuffixOnTupleIndex, InvalidLogicalOperator, InvalidLogicalOperatorSub, + InvalidNumLiteralBasePrefix, InvalidNumLiteralSuffix, LabeledLoopInBreak, + LabeledLoopInBreakSub, LeadingPlusNotSupported, LeftArrowOperator, LifetimeInBorrowExpression, + MacroInvocationWithQualifiedPath, MalformedLoopLabel, MatchArmBodyWithoutBraces, + MatchArmBodyWithoutBracesSugg, MissingCommaAfterMatchArm, MissingInInForLoop, + MissingInInForLoopSub, MissingSemicolonBeforeArray, NoFieldsForFnCall, NotAsNegationOperator, + NotAsNegationOperatorSub, OctalFloatLiteralNotSupported, OuterAttributeNotAllowedOnIfElse, + ParenthesesWithStructFields, RequireColonAfterLabeledExpression, ShiftInterpretedAsGeneric, + StructLiteralNotAllowedHere, StructLiteralNotAllowedHereSugg, TildeAsUnaryOperator, + UnexpectedTokenAfterLabel, UnexpectedTokenAfterLabelSugg, }; +use crate::maybe_recover_from_interpolated_ty_qpath; use core::mem; use rustc_ast::ptr::P; diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 6c4cfcf6ddf4c..37d12f783975c 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -1,4 +1,6 @@ -use super::diagnostics::{dummy_arg, ConsumeClosingDelim, Error, UseEmptyBlockNotSemi}; +use crate::errors::UseEmptyBlockNotSemi; + +use super::diagnostics::{dummy_arg, ConsumeClosingDelim, Error}; use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign}; use super::{AttrWrapper, FollowedByType, ForceCollect, Parser, PathStyle, TrailingToken}; diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 123e6ce7ab5be..af6c0e34e2fee 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -42,7 +42,7 @@ use rustc_span::symbol::{kw, sym, Ident, Symbol}; use std::ops::Range; use std::{cmp, mem, slice}; -use self::diagnostics::{MismatchedClosingDelimiter, NonStringAbiLiteral}; +use crate::errors::{MismatchedClosingDelimiter, NonStringAbiLiteral}; bitflags::bitflags! { struct Restrictions: u8 { diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index 120a3c267f106..542a1ac5dc65c 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -1,5 +1,5 @@ use super::{ForceCollect, Parser, PathStyle, TrailingToken}; -use crate::parser::diagnostics::RemoveLet; +use crate::errors::RemoveLet; use crate::{maybe_recover_from_interpolated_ty_qpath, maybe_whole}; use rustc_ast::mut_visit::{noop_visit_pat, MutVisitor}; use rustc_ast::ptr::P; diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index 3d957406b19d8..03ced75d7633b 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -1,7 +1,5 @@ use super::attr::DEFAULT_INNER_ATTR_FORBIDDEN; -use super::diagnostics::{ - AttemptLocalParseRecovery, Error, InvalidVariableDeclaration, InvalidVariableDeclarationSub, -}; +use super::diagnostics::{AttemptLocalParseRecovery, Error}; use super::expr::LhsExpr; use super::pat::RecoverComma; use super::path::PathStyle; @@ -9,6 +7,7 @@ use super::TrailingToken; use super::{ AttrWrapper, BlockMode, FnParseMode, ForceCollect, Parser, Restrictions, SemiColonMode, }; +use crate::errors::{InvalidVariableDeclaration, InvalidVariableDeclarationSub}; use crate::maybe_whole; use rustc_ast as ast; From e1b1d7b029f8a8e6bade71cb03ae59b364745c31 Mon Sep 17 00:00:00 2001 From: Xiretza Date: Thu, 1 Sep 2022 19:29:23 +0200 Subject: [PATCH 334/586] Migrate more rustc_parse diagnostics to diagnostic structs --- .../locales/en-US/parser.ftl | 33 ++++++- compiler/rustc_parse/src/errors.rs | 99 ++++++++++++++++++- compiler/rustc_parse/src/parser/attr.rs | 17 ++-- .../rustc_parse/src/parser/diagnostics.rs | 37 ------- compiler/rustc_parse/src/parser/expr.rs | 10 +- compiler/rustc_parse/src/parser/item.rs | 22 ++--- compiler/rustc_parse/src/parser/mod.rs | 32 ++---- compiler/rustc_parse/src/parser/stmt.rs | 94 ++++++------------ .../let-else-brace-before-else.stderr | 8 +- 9 files changed, 192 insertions(+), 160 deletions(-) diff --git a/compiler/rustc_error_messages/locales/en-US/parser.ftl b/compiler/rustc_error_messages/locales/en-US/parser.ftl index b93c5e7591325..36b03a2db775b 100644 --- a/compiler/rustc_error_messages/locales/en-US/parser.ftl +++ b/compiler/rustc_error_messages/locales/en-US/parser.ftl @@ -188,7 +188,8 @@ parser_parentheses_with_struct_fields = invalid `struct` delimiters or `fn` call .suggestion_no_fields_for_fn = if `{$name}` is a function, use the arguments directly parser_labeled_loop_in_break = parentheses are required around this expression to avoid confusion with a labeled break expression - .suggestion = wrap the expression in parentheses + +parser_sugg_wrap_expression_in_parentheses = wrap the expression in parentheses parser_array_brackets_instead_of_braces = this is a block expression, not an array .suggestion = to make an array, use square brackets instead of curly braces @@ -231,3 +232,33 @@ parser_mismatched_closing_delimiter = mismatched closing delimiter: `{$delimiter .label_unmatched = mismatched closing delimiter .label_opening_candidate = closing delimiter possibly meant for this .label_unclosed = unclosed delimiter + +parser_incorrect_visibility_restriction = incorrect visibility restriction + .help = some possible visibility restrictions are: + `pub(crate)`: visible only on the current crate + `pub(super)`: visible only in the current module's parent + `pub(in path::to::module)`: visible only on the specified path + .suggestion = make this visible only to module `{$inner_str}` with `in` + +parser_assignment_else_not_allowed = ... else {"{"} ... {"}"} is not allowed + +parser_expected_statement_after_outer_attr = expected statement after outer attribute + +parser_doc_comment_does_not_document_anything = found a documentation comment that doesn't document anything + .help = doc comments must come before what they document, maybe a comment was intended with `//`? + .suggestion = missing comma here + +parser_const_let_mutually_exclusive = `const` and `let` are mutually exclusive + .suggestion = remove `let` + +parser_invalid_expression_in_let_else = a `{$operator}` expression cannot be directly assigned in `let...else` +parser_invalid_curly_in_let_else = right curly brace `{"}"}` before `else` in a `let...else` statement not allowed + +parser_compound_assignment_expression_in_let = can't reassign to an uninitialized variable + .suggestion = initialize the variable + .help = if you meant to overwrite, remove the `let` binding + +parser_suffixed_literal_in_attribute = suffixed literals are not allowed in attributes + .help = instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.) + +parser_invalid_meta_item = expected unsuffixed literal or identifier, found `{$token}` diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index dc7a39457a0c0..968d0be5b4294 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -624,16 +624,19 @@ pub(crate) struct LabeledLoopInBreak { #[primary_span] pub span: Span, #[subdiagnostic] - pub sub: LabeledLoopInBreakSub, + pub sub: WrapExpressionInParentheses, } #[derive(Subdiagnostic)] -#[multipart_suggestion(parser::suggestion, applicability = "machine-applicable")] -pub(crate) struct LabeledLoopInBreakSub { +#[multipart_suggestion( + parser::sugg_wrap_expression_in_parentheses, + applicability = "machine-applicable" +)] +pub(crate) struct WrapExpressionInParentheses { #[suggestion_part(code = "(")] - pub first: Span, + pub left: Span, #[suggestion_part(code = ")")] - pub second: Span, + pub right: Span, } #[derive(Diagnostic)] @@ -781,3 +784,89 @@ pub(crate) struct MismatchedClosingDelimiter { #[label(parser::label_unclosed)] pub unclosed: Option, } + +#[derive(Diagnostic)] +#[diag(parser::incorrect_visibility_restriction, code = "E0704")] +#[help] +pub(crate) struct IncorrectVisibilityRestriction { + #[primary_span] + #[suggestion(code = "in {inner_str}", applicability = "machine-applicable")] + pub span: Span, + pub inner_str: String, +} + +#[derive(Diagnostic)] +#[diag(parser::assignment_else_not_allowed)] +pub(crate) struct AssignmentElseNotAllowed { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(parser::expected_statement_after_outer_attr)] +pub(crate) struct ExpectedStatementAfterOuterAttr { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(parser::doc_comment_does_not_document_anything, code = "E0585")] +#[help] +pub(crate) struct DocCommentDoesNotDocumentAnything { + #[primary_span] + pub span: Span, + #[suggestion(code = ",", applicability = "machine-applicable")] + pub missing_comma: Option, +} + +#[derive(Diagnostic)] +#[diag(parser::const_let_mutually_exclusive)] +pub(crate) struct ConstLetMutuallyExclusive { + #[primary_span] + #[suggestion(code = "const", applicability = "maybe-incorrect")] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(parser::invalid_expression_in_let_else)] +pub(crate) struct InvalidExpressionInLetElse { + #[primary_span] + pub span: Span, + pub operator: &'static str, + #[subdiagnostic] + pub sugg: WrapExpressionInParentheses, +} + +#[derive(Diagnostic)] +#[diag(parser::invalid_curly_in_let_else)] +pub(crate) struct InvalidCurlyInLetElse { + #[primary_span] + pub span: Span, + #[subdiagnostic] + pub sugg: WrapExpressionInParentheses, +} + +#[derive(Diagnostic)] +#[diag(parser::compound_assignment_expression_in_let)] +#[help] +pub(crate) struct CompoundAssignmentExpressionInLet { + #[primary_span] + #[suggestion_short(code = "=", applicability = "maybe-incorrect")] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(parser::suffixed_literal_in_attribute)] +#[help] +pub(crate) struct SuffixedLiteralInAttribute { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(parser::invalid_meta_item)] +pub(crate) struct InvalidMetaItem { + #[primary_span] + pub span: Span, + pub token: String, +} diff --git a/compiler/rustc_parse/src/parser/attr.rs b/compiler/rustc_parse/src/parser/attr.rs index 5fd69b15ecc04..1966345f19f3a 100644 --- a/compiler/rustc_parse/src/parser/attr.rs +++ b/compiler/rustc_parse/src/parser/attr.rs @@ -1,9 +1,11 @@ +use crate::errors::{InvalidMetaItem, SuffixedLiteralInAttribute}; + use super::{AttrWrapper, Capturing, FnParseMode, ForceCollect, Parser, PathStyle}; use rustc_ast as ast; use rustc_ast::attr; use rustc_ast::token::{self, Delimiter, Nonterminal}; use rustc_ast_pretty::pprust; -use rustc_errors::{error_code, Diagnostic, PResult}; +use rustc_errors::{error_code, Diagnostic, IntoDiagnostic, PResult}; use rustc_span::{sym, BytePos, Span}; use std::convert::TryInto; @@ -337,12 +339,7 @@ impl<'a> Parser<'a> { debug!("checking if {:?} is unusuffixed", lit); if !lit.kind.is_unsuffixed() { - self.struct_span_err(lit.span, "suffixed literals are not allowed in attributes") - .help( - "instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), \ - use an unsuffixed version (`1`, `1.0`, etc.)", - ) - .emit(); + self.sess.emit_err(SuffixedLiteralInAttribute { span: lit.span }); } Ok(lit) @@ -435,9 +432,9 @@ impl<'a> Parser<'a> { Err(err) => err.cancel(), } - let found = pprust::token_to_string(&self.token); - let msg = format!("expected unsuffixed literal or identifier, found `{found}`"); - Err(self.struct_span_err(self.token.span, &msg)) + let token = pprust::token_to_string(&self.token).to_string(); + Err(InvalidMetaItem { span: self.token.span, token } + .into_diagnostic(&self.sess.span_diagnostic)) } } diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index 0fdde29175758..326b2553eaf1c 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -55,34 +55,6 @@ pub(super) fn dummy_arg(ident: Ident) -> Param { } } -pub enum Error { - UselessDocComment, -} - -impl Error { - fn span_err( - self, - sp: impl Into, - handler: &Handler, - ) -> DiagnosticBuilder<'_, ErrorGuaranteed> { - match self { - Error::UselessDocComment => { - let mut err = struct_span_err!( - handler, - sp, - E0585, - "found a documentation comment that doesn't document anything", - ); - err.help( - "doc comments must come before what they document, maybe a comment was \ - intended with `//`?", - ); - err - } - } - } -} - pub(super) trait RecoverQPath: Sized + 'static { const PATH_STYLE: PathStyle = PathStyle::Expr; fn to_ty(&self) -> Option>; @@ -268,15 +240,6 @@ impl<'a> DerefMut for SnapshotParser<'a> { } impl<'a> Parser<'a> { - #[rustc_lint_diagnostics] - pub(super) fn span_err>( - &self, - sp: S, - err: Error, - ) -> DiagnosticBuilder<'a, ErrorGuaranteed> { - err.span_err(sp, self.diagnostic()) - } - #[rustc_lint_diagnostics] pub fn struct_span_err>( &self, diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 784a8ae4c2ef6..751951dcaaeec 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -17,14 +17,14 @@ use crate::errors::{ InvalidIntLiteralWidth, InvalidInterpolatedExpression, InvalidLiteralSuffix, InvalidLiteralSuffixOnTupleIndex, InvalidLogicalOperator, InvalidLogicalOperatorSub, InvalidNumLiteralBasePrefix, InvalidNumLiteralSuffix, LabeledLoopInBreak, - LabeledLoopInBreakSub, LeadingPlusNotSupported, LeftArrowOperator, LifetimeInBorrowExpression, + LeadingPlusNotSupported, LeftArrowOperator, LifetimeInBorrowExpression, MacroInvocationWithQualifiedPath, MalformedLoopLabel, MatchArmBodyWithoutBraces, MatchArmBodyWithoutBracesSugg, MissingCommaAfterMatchArm, MissingInInForLoop, MissingInInForLoopSub, MissingSemicolonBeforeArray, NoFieldsForFnCall, NotAsNegationOperator, NotAsNegationOperatorSub, OctalFloatLiteralNotSupported, OuterAttributeNotAllowedOnIfElse, ParenthesesWithStructFields, RequireColonAfterLabeledExpression, ShiftInterpretedAsGeneric, StructLiteralNotAllowedHere, StructLiteralNotAllowedHereSugg, TildeAsUnaryOperator, - UnexpectedTokenAfterLabel, UnexpectedTokenAfterLabelSugg, + UnexpectedTokenAfterLabel, UnexpectedTokenAfterLabelSugg, WrapExpressionInParentheses, }; use crate::maybe_recover_from_interpolated_ty_qpath; @@ -1661,9 +1661,9 @@ impl<'a> Parser<'a> { let lexpr = self.parse_labeled_expr(label.take().unwrap(), true)?; self.sess.emit_err(LabeledLoopInBreak { span: lexpr.span, - sub: LabeledLoopInBreakSub { - first: lexpr.span.shrink_to_lo(), - second: lexpr.span.shrink_to_hi(), + sub: WrapExpressionInParentheses { + left: lexpr.span.shrink_to_lo(), + right: lexpr.span.shrink_to_hi(), }, }); Some(lexpr) diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 37d12f783975c..b7454d7bfc18e 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -1,6 +1,6 @@ -use crate::errors::UseEmptyBlockNotSemi; +use crate::errors::{DocCommentDoesNotDocumentAnything, UseEmptyBlockNotSemi}; -use super::diagnostics::{dummy_arg, ConsumeClosingDelim, Error}; +use super::diagnostics::{dummy_arg, ConsumeClosingDelim}; use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign}; use super::{AttrWrapper, FollowedByType, ForceCollect, Parser, PathStyle, TrailingToken}; @@ -15,7 +15,7 @@ use rustc_ast::{EnumDef, FieldDef, Generics, TraitRef, Ty, TyKind, Variant, Vari use rustc_ast::{FnHeader, ForeignItem, Path, PathSegment, Visibility, VisibilityKind}; use rustc_ast::{MacArgs, MacCall, MacDelimiter}; use rustc_ast_pretty::pprust; -use rustc_errors::{struct_span_err, Applicability, PResult, StashKey}; +use rustc_errors::{struct_span_err, Applicability, IntoDiagnostic, PResult, StashKey}; use rustc_span::edition::Edition; use rustc_span::lev_distance::lev_distance; use rustc_span::source_map::{self, Span}; @@ -1586,7 +1586,10 @@ impl<'a> Parser<'a> { token::CloseDelim(Delimiter::Brace) => {} token::DocComment(..) => { let previous_span = self.prev_token.span; - let mut err = self.span_err(self.token.span, Error::UselessDocComment); + let mut err = DocCommentDoesNotDocumentAnything { + span: self.token.span, + missing_comma: None, + }; self.bump(); // consume the doc comment let comma_after_doc_seen = self.eat(&token::Comma); // `seen_comma` is always false, because we are inside doc block @@ -1595,18 +1598,13 @@ impl<'a> Parser<'a> { seen_comma = true; } if comma_after_doc_seen || self.token == token::CloseDelim(Delimiter::Brace) { - err.emit(); + self.sess.emit_err(err); } else { if !seen_comma { let sp = self.sess.source_map().next_point(previous_span); - err.span_suggestion( - sp, - "missing comma here", - ",", - Applicability::MachineApplicable, - ); + err.missing_comma = Some(sp); } - return Err(err); + return Err(err.into_diagnostic(&self.sess.span_diagnostic)); } } _ => { diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index af6c0e34e2fee..07fa909e71b27 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -13,7 +13,6 @@ mod ty; use crate::lexer::UnmatchedBrace; pub use attr_wrapper::AttrWrapper; pub use diagnostics::AttemptLocalParseRecovery; -use diagnostics::Error; pub(crate) use item::FnParseMode; pub use pat::{CommaRecoveryMode, RecoverColon, RecoverComma}; pub use path::PathStyle; @@ -32,8 +31,7 @@ use rustc_ast_pretty::pprust; use rustc_data_structures::fx::FxHashMap; use rustc_errors::PResult; use rustc_errors::{ - struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed, FatalError, IntoDiagnostic, - MultiSpan, + Applicability, DiagnosticBuilder, ErrorGuaranteed, FatalError, IntoDiagnostic, MultiSpan, }; use rustc_session::parse::ParseSess; use rustc_span::source_map::{Span, DUMMY_SP}; @@ -42,7 +40,10 @@ use rustc_span::symbol::{kw, sym, Ident, Symbol}; use std::ops::Range; use std::{cmp, mem, slice}; -use crate::errors::{MismatchedClosingDelimiter, NonStringAbiLiteral}; +use crate::errors::{ + DocCommentDoesNotDocumentAnything, IncorrectVisibilityRestriction, MismatchedClosingDelimiter, + NonStringAbiLiteral, +}; bitflags::bitflags! { struct Restrictions: u8 { @@ -521,9 +522,11 @@ impl<'a> Parser<'a> { fn ident_or_err(&mut self) -> PResult<'a, (Ident, /* is_raw */ bool)> { self.token.ident().ok_or_else(|| match self.prev_token.kind { - TokenKind::DocComment(..) => { - self.span_err(self.prev_token.span, Error::UselessDocComment) + TokenKind::DocComment(..) => DocCommentDoesNotDocumentAnything { + span: self.prev_token.span, + missing_comma: None, } + .into_diagnostic(&self.sess.span_diagnostic), _ => self.expected_ident_found(), }) } @@ -1347,23 +1350,8 @@ impl<'a> Parser<'a> { let path = self.parse_path(PathStyle::Mod)?; self.expect(&token::CloseDelim(Delimiter::Parenthesis))?; // `)` - let msg = "incorrect visibility restriction"; - let suggestion = r##"some possible visibility restrictions are: -`pub(crate)`: visible only on the current crate -`pub(super)`: visible only in the current module's parent -`pub(in path::to::module)`: visible only on the specified path"##; - let path_str = pprust::path_to_string(&path); - - struct_span_err!(self.sess.span_diagnostic, path.span, E0704, "{}", msg) - .help(suggestion) - .span_suggestion( - path.span, - &format!("make this visible only to module `{}` with `in`", path_str), - format!("in {}", path_str), - Applicability::MachineApplicable, - ) - .emit(); + self.sess.emit_err(IncorrectVisibilityRestriction { span: path.span, inner_str: path_str }); Ok(()) } diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index 03ced75d7633b..155173f120c8b 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -1,5 +1,5 @@ use super::attr::DEFAULT_INNER_ATTR_FORBIDDEN; -use super::diagnostics::{AttemptLocalParseRecovery, Error}; +use super::diagnostics::AttemptLocalParseRecovery; use super::expr::LhsExpr; use super::pat::RecoverComma; use super::path::PathStyle; @@ -7,7 +7,12 @@ use super::TrailingToken; use super::{ AttrWrapper, BlockMode, FnParseMode, ForceCollect, Parser, Restrictions, SemiColonMode, }; -use crate::errors::{InvalidVariableDeclaration, InvalidVariableDeclarationSub}; +use crate::errors::{ + AssignmentElseNotAllowed, CompoundAssignmentExpressionInLet, ConstLetMutuallyExclusive, + DocCommentDoesNotDocumentAnything, ExpectedStatementAfterOuterAttr, InvalidCurlyInLetElse, + InvalidExpressionInLetElse, InvalidVariableDeclaration, InvalidVariableDeclarationSub, + WrapExpressionInParentheses, +}; use crate::maybe_whole; use rustc_ast as ast; @@ -111,11 +116,7 @@ impl<'a> Parser<'a> { let bl = self.parse_block()?; // Destructuring assignment ... else. // This is not allowed, but point it out in a nice way. - let mut err = self.struct_span_err( - e.span.to(bl.span), - " ... else { ... } is not allowed", - ); - err.emit(); + self.sess.emit_err(AssignmentElseNotAllowed { span: e.span.to(bl.span) }); } self.mk_stmt(lo.to(e.span), StmtKind::Expr(e)) } else { @@ -201,9 +202,12 @@ impl<'a> Parser<'a> { fn error_outer_attrs(&self, attrs: &[Attribute]) { if let [.., last] = attrs { if last.is_doc_comment() { - self.span_err(last.span, Error::UselessDocComment).emit(); + self.sess.emit_err(DocCommentDoesNotDocumentAnything { + span: last.span, + missing_comma: None, + }); } else if attrs.iter().any(|a| a.style == AttrStyle::Outer) { - self.struct_span_err(last.span, "expected statement after outer attribute").emit(); + self.sess.emit_err(ExpectedStatementAfterOuterAttr { span: last.span }); } } } @@ -254,17 +258,7 @@ impl<'a> Parser<'a> { let lo = self.prev_token.span; if self.token.is_keyword(kw::Const) && self.look_ahead(1, |t| t.is_ident()) { - self.struct_span_err( - lo.to(self.token.span), - "`const` and `let` are mutually exclusive", - ) - .span_suggestion( - lo.to(self.token.span), - "remove `let`", - "const", - Applicability::MaybeIncorrect, - ) - .emit(); + self.sess.emit_err(ConstLetMutuallyExclusive { span: lo.to(self.token.span) }); self.bump(); } @@ -362,44 +356,27 @@ impl<'a> Parser<'a> { fn check_let_else_init_bool_expr(&self, init: &ast::Expr) { if let ast::ExprKind::Binary(op, ..) = init.kind { if op.node.lazy() { - let suggs = vec![ - (init.span.shrink_to_lo(), "(".to_string()), - (init.span.shrink_to_hi(), ")".to_string()), - ]; - self.struct_span_err( - init.span, - &format!( - "a `{}` expression cannot be directly assigned in `let...else`", - op.node.to_string() - ), - ) - .multipart_suggestion( - "wrap the expression in parentheses", - suggs, - Applicability::MachineApplicable, - ) - .emit(); + self.sess.emit_err(InvalidExpressionInLetElse { + span: init.span, + operator: op.node.to_string(), + sugg: WrapExpressionInParentheses { + left: init.span.shrink_to_lo(), + right: init.span.shrink_to_hi(), + }, + }); } } } fn check_let_else_init_trailing_brace(&self, init: &ast::Expr) { if let Some(trailing) = classify::expr_trailing_brace(init) { - let err_span = trailing.span.with_lo(trailing.span.hi() - BytePos(1)); - let suggs = vec![ - (trailing.span.shrink_to_lo(), "(".to_string()), - (trailing.span.shrink_to_hi(), ")".to_string()), - ]; - self.struct_span_err( - err_span, - "right curly brace `}` before `else` in a `let...else` statement not allowed", - ) - .multipart_suggestion( - "try wrapping the expression in parentheses", - suggs, - Applicability::MachineApplicable, - ) - .emit(); + self.sess.emit_err(InvalidCurlyInLetElse { + span: trailing.span.with_lo(trailing.span.hi() - BytePos(1)), + sugg: WrapExpressionInParentheses { + left: trailing.span.shrink_to_lo(), + right: trailing.span.shrink_to_hi(), + }, + }); } } @@ -408,18 +385,7 @@ impl<'a> Parser<'a> { let eq_consumed = match self.token.kind { token::BinOpEq(..) => { // Recover `let x = 1` as `let x = 1` - self.struct_span_err( - self.token.span, - "can't reassign to an uninitialized variable", - ) - .span_suggestion_short( - self.token.span, - "initialize the variable", - "=", - Applicability::MaybeIncorrect, - ) - .help("if you meant to overwrite, remove the `let` binding") - .emit(); + self.sess.emit_err(CompoundAssignmentExpressionInLet { span: self.token.span }); self.bump(); true } diff --git a/src/test/ui/let-else/let-else-brace-before-else.stderr b/src/test/ui/let-else/let-else-brace-before-else.stderr index 51051bbd4d8d6..cb01e4c18a114 100644 --- a/src/test/ui/let-else/let-else-brace-before-else.stderr +++ b/src/test/ui/let-else/let-else-brace-before-else.stderr @@ -4,7 +4,7 @@ error: right curly brace `}` before `else` in a `let...else` statement not allow LL | let Some(1) = { Some(1) } else { | ^ | -help: try wrapping the expression in parentheses +help: wrap the expression in parentheses | LL | let Some(1) = ({ Some(1) }) else { | + + @@ -15,7 +15,7 @@ error: right curly brace `}` before `else` in a `let...else` statement not allow LL | let Some(1) = loop { break Some(1) } else { | ^ | -help: try wrapping the expression in parentheses +help: wrap the expression in parentheses | LL | let Some(1) = (loop { break Some(1) }) else { | + + @@ -26,7 +26,7 @@ error: right curly brace `}` before `else` in a `let...else` statement not allow LL | let 2 = 1 + match 1 { n => n } else { | ^ | -help: try wrapping the expression in parentheses +help: wrap the expression in parentheses | LL | let 2 = 1 + (match 1 { n => n }) else { | + + @@ -37,7 +37,7 @@ error: right curly brace `}` before `else` in a `let...else` statement not allow LL | let Some(1) = unsafe { unsafe_fn() } else { | ^ | -help: try wrapping the expression in parentheses +help: wrap the expression in parentheses | LL | let Some(1) = (unsafe { unsafe_fn() }) else { | + + From 4d0519a4e75e16afe08ca6da36c65c9b7dfe5cee Mon Sep 17 00:00:00 2001 From: Xiretza Date: Thu, 1 Sep 2022 19:29:59 +0200 Subject: [PATCH 335/586] Remove error condition in parse_attribute This function is only ever called when the `#` has already been consumed, no need to produce an error message here. --- compiler/rustc_parse/src/parser/attr.rs | 37 ++++++++----------------- 1 file changed, 12 insertions(+), 25 deletions(-) diff --git a/compiler/rustc_parse/src/parser/attr.rs b/compiler/rustc_parse/src/parser/attr.rs index 1966345f19f3a..297f4964116f0 100644 --- a/compiler/rustc_parse/src/parser/attr.rs +++ b/compiler/rustc_parse/src/parser/attr.rs @@ -124,35 +124,22 @@ impl<'a> Parser<'a> { let lo = self.token.span; // Attributes can't have attributes of their own [Editor's note: not with that attitude] self.collect_tokens_no_attrs(|this| { - if this.eat(&token::Pound) { - let style = if this.eat(&token::Not) { - ast::AttrStyle::Inner - } else { - ast::AttrStyle::Outer - }; + assert!(this.eat(&token::Pound), "parse_attribute called in non-attribute position"); - this.expect(&token::OpenDelim(Delimiter::Bracket))?; - let item = this.parse_attr_item(false)?; - this.expect(&token::CloseDelim(Delimiter::Bracket))?; - let attr_sp = lo.to(this.prev_token.span); + let style = + if this.eat(&token::Not) { ast::AttrStyle::Inner } else { ast::AttrStyle::Outer }; - // Emit error if inner attribute is encountered and forbidden. - if style == ast::AttrStyle::Inner { - this.error_on_forbidden_inner_attr(attr_sp, inner_parse_policy); - } + this.expect(&token::OpenDelim(Delimiter::Bracket))?; + let item = this.parse_attr_item(false)?; + this.expect(&token::CloseDelim(Delimiter::Bracket))?; + let attr_sp = lo.to(this.prev_token.span); - Ok(attr::mk_attr_from_item( - &self.sess.attr_id_generator, - item, - None, - style, - attr_sp, - )) - } else { - let token_str = pprust::token_to_string(&this.token); - let msg = &format!("expected `#`, found `{token_str}`"); - Err(this.struct_span_err(this.token.span, msg)) + // Emit error if inner attribute is encountered and forbidden. + if style == ast::AttrStyle::Inner { + this.error_on_forbidden_inner_attr(attr_sp, inner_parse_policy); } + + Ok(attr::mk_attr_from_item(&self.sess.attr_id_generator, item, None, style, attr_sp)) }) } From 21b5194a3a0ff5179d4afb6886fc8816243574f0 Mon Sep 17 00:00:00 2001 From: Xiretza Date: Wed, 31 Aug 2022 13:20:59 +0200 Subject: [PATCH 336/586] Rework "inner attribute not permitted" errors --- .../locales/en-US/parser.ftl | 28 +++++ compiler/rustc_parse/src/parser/attr.rs | 107 +++++++++--------- compiler/rustc_parse/src/parser/stmt.rs | 9 +- .../inner-attr-after-doc-comment.stderr | 2 +- 4 files changed, 87 insertions(+), 59 deletions(-) diff --git a/compiler/rustc_error_messages/locales/en-US/parser.ftl b/compiler/rustc_error_messages/locales/en-US/parser.ftl index 36b03a2db775b..9773cbe5517eb 100644 --- a/compiler/rustc_error_messages/locales/en-US/parser.ftl +++ b/compiler/rustc_error_messages/locales/en-US/parser.ftl @@ -262,3 +262,31 @@ parser_suffixed_literal_in_attribute = suffixed literals are not allowed in attr .help = instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.) parser_invalid_meta_item = expected unsuffixed literal or identifier, found `{$token}` + +parser_label_inner_attr_does_not_annotate_this = the inner attribute doesn't annotate this {$item} +parser_sugg_change_inner_attr_to_outer = to annotate the {$item}, change the attribute from inner to outer style + +parser_inner_attr_not_permitted_after_outer_doc_comment = an inner attribute is not permitted following an outer doc comment + .label_attr = not permitted following an outer doc comment + .label_prev_doc_comment = previous doc comment + .label_does_not_annotate_this = {parser_label_inner_attr_does_not_annotate_this} + .sugg_change_inner_to_outer = {parser_sugg_change_inner_attr_to_outer} + +parser_inner_attr_not_permitted_after_outer_attr = an inner attribute is not permitted following an outer attribute + .label_attr = not permitted following an outer attribute + .label_prev_attr = previous outer attribute + .label_does_not_annotate_this = {parser_label_inner_attr_does_not_annotate_this} + .sugg_change_inner_to_outer = {parser_sugg_change_inner_attr_to_outer} + +parser_inner_attr_not_permitted = an inner attribute is not permitted in this context + .label_does_not_annotate_this = {parser_label_inner_attr_does_not_annotate_this} + .sugg_change_inner_to_outer = {parser_sugg_change_inner_attr_to_outer} + +parser_inner_attr_explanation = inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files +parser_outer_attr_explanation = outer attributes, like `#[test]`, annotate the item following them + +parser_inner_doc_comment_not_permitted = expected outer doc comment + .note = inner doc comments like this (starting with `//!` or `/*!`) can only appear before items + .suggestion = you might have meant to write a regular comment + .label_does_not_annotate_this = the inner doc comment doesn't annotate this {$item} + .sugg_change_inner_to_outer = to annotate the {$item}, change the doc comment from inner to outer style diff --git a/compiler/rustc_parse/src/parser/attr.rs b/compiler/rustc_parse/src/parser/attr.rs index 297f4964116f0..ee3f7dbbc398e 100644 --- a/compiler/rustc_parse/src/parser/attr.rs +++ b/compiler/rustc_parse/src/parser/attr.rs @@ -5,25 +5,23 @@ use rustc_ast as ast; use rustc_ast::attr; use rustc_ast::token::{self, Delimiter, Nonterminal}; use rustc_ast_pretty::pprust; -use rustc_errors::{error_code, Diagnostic, IntoDiagnostic, PResult}; +use rustc_errors::{error_code, fluent, Diagnostic, IntoDiagnostic, PResult}; use rustc_span::{sym, BytePos, Span}; use std::convert::TryInto; // Public for rustfmt usage #[derive(Debug)] -pub enum InnerAttrPolicy<'a> { +pub enum InnerAttrPolicy { Permitted, - Forbidden { reason: &'a str, saw_doc_comment: bool, prev_outer_attr_sp: Option }, + Forbidden(Option), } -const DEFAULT_UNEXPECTED_INNER_ATTR_ERR_MSG: &str = "an inner attribute is not \ - permitted in this context"; - -pub(super) const DEFAULT_INNER_ATTR_FORBIDDEN: InnerAttrPolicy<'_> = InnerAttrPolicy::Forbidden { - reason: DEFAULT_UNEXPECTED_INNER_ATTR_ERR_MSG, - saw_doc_comment: false, - prev_outer_attr_sp: None, -}; +#[derive(Clone, Copy, Debug)] +pub enum InnerAttrForbiddenReason { + InCodeBlock, + AfterOuterDocComment { prev_doc_comment_span: Span }, + AfterOuterAttribute { prev_outer_attr_sp: Span }, +} enum OuterAttributeType { DocComment, @@ -42,17 +40,15 @@ impl<'a> Parser<'a> { let prev_outer_attr_sp = outer_attrs.last().map(|attr| attr.span); let inner_error_reason = if just_parsed_doc_comment { - "an inner attribute is not permitted following an outer doc comment" - } else if prev_outer_attr_sp.is_some() { - "an inner attribute is not permitted following an outer attribute" + Some(InnerAttrForbiddenReason::AfterOuterDocComment { + prev_doc_comment_span: prev_outer_attr_sp.unwrap(), + }) + } else if let Some(prev_outer_attr_sp) = prev_outer_attr_sp { + Some(InnerAttrForbiddenReason::AfterOuterAttribute { prev_outer_attr_sp }) } else { - DEFAULT_UNEXPECTED_INNER_ATTR_ERR_MSG - }; - let inner_parse_policy = InnerAttrPolicy::Forbidden { - reason: inner_error_reason, - saw_doc_comment: just_parsed_doc_comment, - prev_outer_attr_sp, + None }; + let inner_parse_policy = InnerAttrPolicy::Forbidden(inner_error_reason); just_parsed_doc_comment = false; Some(self.parse_attribute(inner_parse_policy)?) } else if let token::DocComment(comment_kind, attr_style, data) = self.token.kind { @@ -60,7 +56,7 @@ impl<'a> Parser<'a> { let span = self.token.span; let mut err = self.sess.span_diagnostic.struct_span_err_with_code( span, - "expected outer doc comment", + fluent::parser::inner_doc_comment_not_permitted, error_code!(E0753), ); if let Some(replacement_span) = self.annotate_following_item_if_applicable( @@ -71,13 +67,10 @@ impl<'a> Parser<'a> { token::CommentKind::Block => OuterAttributeType::DocBlockComment, }, ) { - err.note( - "inner doc comments like this (starting with `//!` or `/*!`) can \ - only appear before items", - ); + err.note(fluent::parser::note); err.span_suggestion_verbose( replacement_span, - "you might have meant to write a regular comment", + fluent::parser::suggestion, "", rustc_errors::Applicability::MachineApplicable, ); @@ -115,7 +108,7 @@ impl<'a> Parser<'a> { // Public for rustfmt usage. pub fn parse_attribute( &mut self, - inner_parse_policy: InnerAttrPolicy<'_>, + inner_parse_policy: InnerAttrPolicy, ) -> PResult<'a, ast::Attribute> { debug!( "parse_attribute: inner_parse_policy={:?} self.token={:?}", @@ -179,21 +172,12 @@ impl<'a> Parser<'a> { ForceCollect::No, ) { Ok(Some(item)) => { - let attr_name = match attr_type { - OuterAttributeType::Attribute => "attribute", - _ => "doc comment", - }; - err.span_label( - item.span, - &format!("the inner {} doesn't annotate this {}", attr_name, item.kind.descr()), - ); + // FIXME(#100717) + err.set_arg("item", item.kind.descr()); + err.span_label(item.span, fluent::parser::label_does_not_annotate_this); err.span_suggestion_verbose( replacement_span, - &format!( - "to annotate the {}, change the {} from inner to outer style", - item.kind.descr(), - attr_name - ), + fluent::parser::sugg_change_inner_to_outer, match attr_type { OuterAttributeType::Attribute => "", OuterAttributeType::DocBlockComment => "*", @@ -211,22 +195,33 @@ impl<'a> Parser<'a> { Some(replacement_span) } - pub(super) fn error_on_forbidden_inner_attr(&self, attr_sp: Span, policy: InnerAttrPolicy<'_>) { - if let InnerAttrPolicy::Forbidden { reason, saw_doc_comment, prev_outer_attr_sp } = policy { - let prev_outer_attr_note = - if saw_doc_comment { "previous doc comment" } else { "previous outer attribute" }; - - let mut diag = self.struct_span_err(attr_sp, reason); - - if let Some(prev_outer_attr_sp) = prev_outer_attr_sp { - diag.span_label(attr_sp, "not permitted following an outer attribute") - .span_label(prev_outer_attr_sp, prev_outer_attr_note); - } + pub(super) fn error_on_forbidden_inner_attr(&self, attr_sp: Span, policy: InnerAttrPolicy) { + if let InnerAttrPolicy::Forbidden(reason) = policy { + let mut diag = match reason.as_ref().copied() { + Some(InnerAttrForbiddenReason::AfterOuterDocComment { prev_doc_comment_span }) => { + let mut diag = self.struct_span_err( + attr_sp, + fluent::parser::inner_attr_not_permitted_after_outer_doc_comment, + ); + diag.span_label(attr_sp, fluent::parser::label_attr) + .span_label(prev_doc_comment_span, fluent::parser::label_prev_doc_comment); + diag + } + Some(InnerAttrForbiddenReason::AfterOuterAttribute { prev_outer_attr_sp }) => { + let mut diag = self.struct_span_err( + attr_sp, + fluent::parser::inner_attr_not_permitted_after_outer_attr, + ); + diag.span_label(attr_sp, fluent::parser::label_attr) + .span_label(prev_outer_attr_sp, fluent::parser::label_prev_attr); + diag + } + Some(InnerAttrForbiddenReason::InCodeBlock) | None => { + self.struct_span_err(attr_sp, fluent::parser::inner_attr_not_permitted) + } + }; - diag.note( - "inner attributes, like `#![no_std]`, annotate the item enclosing them, and \ - are usually found at the beginning of source files", - ); + diag.note(fluent::parser::inner_attr_explanation); if self .annotate_following_item_if_applicable( &mut diag, @@ -235,7 +230,7 @@ impl<'a> Parser<'a> { ) .is_some() { - diag.note("outer attributes, like `#[test]`, annotate the item following them"); + diag.note(fluent::parser::outer_attr_explanation); }; diag.emit(); } diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index 155173f120c8b..a61e77b7c3bfb 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -1,4 +1,4 @@ -use super::attr::DEFAULT_INNER_ATTR_FORBIDDEN; +use super::attr::InnerAttrForbiddenReason; use super::diagnostics::AttemptLocalParseRecovery; use super::expr::LhsExpr; use super::pat::RecoverComma; @@ -399,7 +399,12 @@ impl<'a> Parser<'a> { pub(super) fn parse_block(&mut self) -> PResult<'a, P> { let (attrs, block) = self.parse_inner_attrs_and_block()?; if let [.., last] = &*attrs { - self.error_on_forbidden_inner_attr(last.span, DEFAULT_INNER_ATTR_FORBIDDEN); + self.error_on_forbidden_inner_attr( + last.span, + super::attr::InnerAttrPolicy::Forbidden(Some( + InnerAttrForbiddenReason::InCodeBlock, + )), + ); } Ok(block) } diff --git a/src/test/ui/parser/inner-attr-after-doc-comment.stderr b/src/test/ui/parser/inner-attr-after-doc-comment.stderr index 2cfafac779426..3ec3ad8e977a8 100644 --- a/src/test/ui/parser/inner-attr-after-doc-comment.stderr +++ b/src/test/ui/parser/inner-attr-after-doc-comment.stderr @@ -7,7 +7,7 @@ LL | | */ | |___- previous doc comment LL | LL | #![recursion_limit="100"] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ not permitted following an outer attribute + | ^^^^^^^^^^^^^^^^^^^^^^^^^ not permitted following an outer doc comment LL | LL | fn main() {} | ------------ the inner attribute doesn't annotate this function From 7507ee29fcee3dea2819dc113434ba97d7716422 Mon Sep 17 00:00:00 2001 From: Xiretza Date: Sun, 4 Sep 2022 10:14:00 +0200 Subject: [PATCH 337/586] Migrate "expected identifier" diagnostics to diagnostic structs --- .../locales/en-US/parser.ftl | 16 ++++ compiler/rustc_parse/src/errors.rs | 95 ++++++++++++++++++- .../rustc_parse/src/parser/diagnostics.rs | 54 +++++------ compiler/rustc_parse/src/parser/mod.rs | 48 +++++++--- 4 files changed, 170 insertions(+), 43 deletions(-) diff --git a/compiler/rustc_error_messages/locales/en-US/parser.ftl b/compiler/rustc_error_messages/locales/en-US/parser.ftl index 9773cbe5517eb..61450e288b4eb 100644 --- a/compiler/rustc_error_messages/locales/en-US/parser.ftl +++ b/compiler/rustc_error_messages/locales/en-US/parser.ftl @@ -290,3 +290,19 @@ parser_inner_doc_comment_not_permitted = expected outer doc comment .suggestion = you might have meant to write a regular comment .label_does_not_annotate_this = the inner doc comment doesn't annotate this {$item} .sugg_change_inner_to_outer = to annotate the {$item}, change the doc comment from inner to outer style + +parser_expected_identifier_found_reserved_identifier_str = expected identifier, found reserved identifier `{$token_str}` +parser_expected_identifier_found_keyword_str = expected identifier, found keyword `{$token_str}` +parser_expected_identifier_found_reserved_keyword_str = expected identifier, found reserved keyword `{$token_str}` +parser_expected_identifier_found_doc_comment_str = expected identifier, found doc comment `{$token_str}` +parser_expected_identifier_found_str = expected identifier, found `{$token_str}` + +parser_expected_identifier_found_reserved_identifier = expected identifier, found reserved identifier +parser_expected_identifier_found_keyword = expected identifier, found keyword +parser_expected_identifier_found_reserved_keyword = expected identifier, found reserved keyword +parser_expected_identifier_found_doc_comment = expected identifier, found doc comment +parser_expected_identifier = expected identifier + +parser_sugg_escape_to_use_as_identifier = escape `{$ident_name}` to use it as an identifier + +parser_sugg_remove_comma = remove this comma diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index 968d0be5b4294..3b86dd1574715 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -1,9 +1,11 @@ -use rustc_errors::Applicability; +use rustc_errors::{fluent, AddToDiagnostic, Applicability, EmissionGuarantee, IntoDiagnostic}; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_session::errors::ExprParenthesesNeeded; use rustc_span::symbol::Ident; use rustc_span::{Span, Symbol}; +use crate::parser::{TokenDescription, TokenDescriptionKind}; + #[derive(Diagnostic)] #[diag(parser::maybe_report_ambiguous_plus)] pub(crate) struct AmbiguousPlus { @@ -870,3 +872,94 @@ pub(crate) struct InvalidMetaItem { pub span: Span, pub token: String, } + +#[derive(Subdiagnostic)] +#[suggestion_verbose( + parser::sugg_escape_to_use_as_identifier, + applicability = "maybe-incorrect", + code = "r#" +)] +pub(crate) struct SuggEscapeToUseAsIdentifier { + #[primary_span] + pub span: Span, + pub ident_name: String, +} + +#[derive(Subdiagnostic)] +#[suggestion(parser::sugg_remove_comma, applicability = "machine-applicable", code = "")] +pub(crate) struct SuggRemoveComma { + #[primary_span] + pub span: Span, +} + +#[derive(Subdiagnostic)] +pub(crate) enum ExpectedIdentifierFound { + #[label(parser::expected_identifier_found_reserved_identifier)] + ReservedIdentifier(#[primary_span] Span), + #[label(parser::expected_identifier_found_keyword)] + Keyword(#[primary_span] Span), + #[label(parser::expected_identifier_found_reserved_keyword)] + ReservedKeyword(#[primary_span] Span), + #[label(parser::expected_identifier_found_doc_comment)] + DocComment(#[primary_span] Span), + #[label(parser::expected_identifier)] + Other(#[primary_span] Span), +} + +impl ExpectedIdentifierFound { + pub fn new(token_descr_kind: Option, span: Span) -> Self { + (match token_descr_kind { + Some(TokenDescriptionKind::ReservedIdentifier) => { + ExpectedIdentifierFound::ReservedIdentifier + } + Some(TokenDescriptionKind::Keyword) => ExpectedIdentifierFound::Keyword, + Some(TokenDescriptionKind::ReservedKeyword) => ExpectedIdentifierFound::ReservedKeyword, + Some(TokenDescriptionKind::DocComment) => ExpectedIdentifierFound::DocComment, + None => ExpectedIdentifierFound::Other, + })(span) + } +} + +pub(crate) struct ExpectedIdentifier { + pub span: Span, + pub token_descr: TokenDescription, + pub suggest_raw: Option, + pub suggest_remove_comma: Option, +} + +impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for ExpectedIdentifier { + fn into_diagnostic( + self, + handler: &'a rustc_errors::Handler, + ) -> rustc_errors::DiagnosticBuilder<'a, G> { + let mut diag = handler.struct_diagnostic(match self.token_descr.kind { + Some(TokenDescriptionKind::ReservedIdentifier) => { + fluent::parser::expected_identifier_found_reserved_identifier_str + } + Some(TokenDescriptionKind::Keyword) => { + fluent::parser::expected_identifier_found_keyword_str + } + Some(TokenDescriptionKind::ReservedKeyword) => { + fluent::parser::expected_identifier_found_reserved_keyword_str + } + Some(TokenDescriptionKind::DocComment) => { + fluent::parser::expected_identifier_found_doc_comment_str + } + None => fluent::parser::expected_identifier_found_str, + }); + diag.set_span(self.span); + diag.set_arg("token_str", self.token_descr.name); + + if let Some(sugg) = self.suggest_raw { + sugg.add_to_diagnostic(&mut diag); + } + + ExpectedIdentifierFound::new(self.token_descr.kind, self.span).add_to_diagnostic(&mut diag); + + if let Some(sugg) = self.suggest_remove_comma { + sugg.add_to_diagnostic(&mut diag); + } + + diag + } +} diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index 326b2553eaf1c..8c2a925a23168 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -4,8 +4,9 @@ use super::{ TokenExpectType, TokenType, }; use crate::errors::{ - AmbiguousPlus, BadQPathStage2, BadTypePlus, BadTypePlusSub, InInTypo, IncorrectAwait, - IncorrectSemicolon, IncorrectUseOfAwait, UseEqInstead, + AmbiguousPlus, BadQPathStage2, BadTypePlus, BadTypePlusSub, ExpectedIdentifier, InInTypo, + IncorrectAwait, IncorrectSemicolon, IncorrectUseOfAwait, SuggEscapeToUseAsIdentifier, + SuggRemoveComma, UseEqInstead, }; use crate::lexer::UnmatchedBrace; @@ -23,7 +24,7 @@ use rustc_data_structures::fx::FxHashSet; use rustc_errors::{ fluent, Applicability, DiagnosticBuilder, DiagnosticMessage, Handler, MultiSpan, PResult, }; -use rustc_errors::{pluralize, struct_span_err, Diagnostic, ErrorGuaranteed}; +use rustc_errors::{pluralize, struct_span_err, Diagnostic, ErrorGuaranteed, IntoDiagnostic}; use rustc_span::source_map::Spanned; use rustc_span::symbol::{kw, sym, Ident}; use rustc_span::{Span, SpanSnippetError, DUMMY_SP}; @@ -285,10 +286,6 @@ impl<'a> Parser<'a> { } pub(super) fn expected_ident_found(&self) -> DiagnosticBuilder<'a, ErrorGuaranteed> { - let mut err = self.struct_span_err( - self.token.span, - &format!("expected identifier, found {}", super::token_descr(&self.token)), - ); let valid_follow = &[ TokenKind::Eq, TokenKind::Colon, @@ -300,34 +297,33 @@ impl<'a> Parser<'a> { TokenKind::CloseDelim(Delimiter::Brace), TokenKind::CloseDelim(Delimiter::Parenthesis), ]; - match self.token.ident() { + let suggest_raw = match self.token.ident() { Some((ident, false)) if ident.is_raw_guess() && self.look_ahead(1, |t| valid_follow.contains(&t.kind)) => { - err.span_suggestion_verbose( - ident.span.shrink_to_lo(), - &format!("escape `{}` to use it as an identifier", ident.name), - "r#", - Applicability::MaybeIncorrect, - ); + Some(SuggEscapeToUseAsIdentifier { + span: ident.span.shrink_to_lo(), + ident_name: ident.name.to_string(), + }) } - _ => {} - } - if let Some(token_descr) = super::token_descr_opt(&self.token) { - err.span_label(self.token.span, format!("expected identifier, found {}", token_descr)); - } else { - err.span_label(self.token.span, "expected identifier"); + _ => None, + }; + + let suggest_remove_comma = if self.token == token::Comma && self.look_ahead(1, |t| t.is_ident()) { - err.span_suggestion( - self.token.span, - "remove this comma", - "", - Applicability::MachineApplicable, - ); - } - } - err + Some(SuggRemoveComma { span: self.token.span }) + } else { + None + }; + + let err = ExpectedIdentifier { + span: self.token.span, + token_descr: super::token_descr_struct(&self.token), + suggest_raw, + suggest_remove_comma, + }; + err.into_diagnostic(&self.sess.span_diagnostic) } pub(super) fn expected_one_of_not_found( diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 07fa909e71b27..a1a224e8524cd 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -410,22 +410,44 @@ pub enum FollowedByType { No, } -fn token_descr_opt(token: &Token) -> Option<&'static str> { - Some(match token.kind { - _ if token.is_special_ident() => "reserved identifier", - _ if token.is_used_keyword() => "keyword", - _ if token.is_unused_keyword() => "reserved keyword", - token::DocComment(..) => "doc comment", - _ => return None, - }) +#[derive(Clone, Copy, PartialEq, Eq)] +pub enum TokenDescriptionKind { + ReservedIdentifier, + Keyword, + ReservedKeyword, + DocComment, +} + +#[derive(Clone, PartialEq, Eq)] +pub struct TokenDescription { + pub kind: Option, + pub name: String, +} + +pub(super) fn token_descr_struct(token: &Token) -> TokenDescription { + let kind = match token.kind { + _ if token.is_special_ident() => Some(TokenDescriptionKind::ReservedIdentifier), + _ if token.is_used_keyword() => Some(TokenDescriptionKind::Keyword), + _ if token.is_unused_keyword() => Some(TokenDescriptionKind::ReservedKeyword), + token::DocComment(..) => Some(TokenDescriptionKind::DocComment), + _ => None, + }; + let name = pprust::token_to_string(token).to_string(); + + TokenDescription { kind, name } } pub(super) fn token_descr(token: &Token) -> String { - let token_str = pprust::token_to_string(token); - match token_descr_opt(token) { - Some(prefix) => format!("{} `{}`", prefix, token_str), - _ => format!("`{}`", token_str), - } + let TokenDescription { kind, name } = token_descr_struct(token); + + let kind = kind.map(|kind| match kind { + TokenDescriptionKind::ReservedIdentifier => "reserved identifier", + TokenDescriptionKind::Keyword => "keyword", + TokenDescriptionKind::ReservedKeyword => "reserved keyword", + TokenDescriptionKind::DocComment => "doc comment", + }); + + if let Some(kind) = kind { format!("{} `{}`", kind, name) } else { format!("`{}`", name) } } impl<'a> Parser<'a> { From ba10f2c0f2548bafa2bbdca346921c6719f2e6ea Mon Sep 17 00:00:00 2001 From: Xiretza Date: Sun, 4 Sep 2022 20:12:00 +0200 Subject: [PATCH 338/586] Migrate "expected semicolon" diagnostics to diagnostic structs --- .../locales/en-US/parser.ftl | 10 ++++ compiler/rustc_parse/src/errors.rs | 51 +++++++++++++++++++ .../rustc_parse/src/parser/diagnostics.rs | 37 ++++++++------ 3 files changed, 82 insertions(+), 16 deletions(-) diff --git a/compiler/rustc_error_messages/locales/en-US/parser.ftl b/compiler/rustc_error_messages/locales/en-US/parser.ftl index 61450e288b4eb..22fb65f02680d 100644 --- a/compiler/rustc_error_messages/locales/en-US/parser.ftl +++ b/compiler/rustc_error_messages/locales/en-US/parser.ftl @@ -306,3 +306,13 @@ parser_expected_identifier = expected identifier parser_sugg_escape_to_use_as_identifier = escape `{$ident_name}` to use it as an identifier parser_sugg_remove_comma = remove this comma + +parser_expected_semi_found_reserved_identifier_str = expected `;`, found reserved identifier `{$token_str}` +parser_expected_semi_found_keyword_str = expected `;`, found keyword `{$token_str}` +parser_expected_semi_found_reserved_keyword_str = expected `;`, found reserved keyword `{$token_str}` +parser_expected_semi_found_doc_comment_str = expected `;`, found doc comment `{$token_str}` +parser_expected_semi_found_str = expected `;`, found `{$token_str}` + +parser_sugg_change_this_to_semi = change this to `;` +parser_sugg_add_semi = add `;` here +parser_label_unexpected_token = unexpected token diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index 3b86dd1574715..07785b7344f25 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -963,3 +963,54 @@ impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for ExpectedIdentifier { diag } } + +pub(crate) struct ExpectedSemi { + pub span: Span, + pub token_descr: TokenDescription, + + pub unexpected_token_label: Option, + pub sugg: ExpectedSemiSugg, +} + +impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for ExpectedSemi { + fn into_diagnostic( + self, + handler: &'a rustc_errors::Handler, + ) -> rustc_errors::DiagnosticBuilder<'a, G> { + let mut diag = handler.struct_diagnostic(match self.token_descr.kind { + Some(TokenDescriptionKind::ReservedIdentifier) => { + fluent::parser::expected_semi_found_reserved_identifier_str + } + Some(TokenDescriptionKind::Keyword) => fluent::parser::expected_semi_found_keyword_str, + Some(TokenDescriptionKind::ReservedKeyword) => { + fluent::parser::expected_semi_found_reserved_keyword_str + } + Some(TokenDescriptionKind::DocComment) => { + fluent::parser::expected_semi_found_doc_comment_str + } + None => fluent::parser::expected_semi_found_str, + }); + diag.set_span(self.span); + diag.set_arg("token_str", self.token_descr.name); + + if let Some(unexpected_token_label) = self.unexpected_token_label { + diag.span_label(unexpected_token_label, fluent::parser::label_unexpected_token); + } + + self.sugg.add_to_diagnostic(&mut diag); + + diag + } +} + +#[derive(Subdiagnostic)] +pub(crate) enum ExpectedSemiSugg { + #[suggestion( + parser::sugg_change_this_to_semi, + code = ";", + applicability = "machine-applicable" + )] + ChangeToSemi(#[primary_span] Span), + #[suggestion_short(parser::sugg_add_semi, code = ";", applicability = "machine-applicable")] + AddSemi(#[primary_span] Span), +} diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index 8c2a925a23168..ba48e4e1c2525 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -4,9 +4,9 @@ use super::{ TokenExpectType, TokenType, }; use crate::errors::{ - AmbiguousPlus, BadQPathStage2, BadTypePlus, BadTypePlusSub, ExpectedIdentifier, InInTypo, - IncorrectAwait, IncorrectSemicolon, IncorrectUseOfAwait, SuggEscapeToUseAsIdentifier, - SuggRemoveComma, UseEqInstead, + AmbiguousPlus, BadQPathStage2, BadTypePlus, BadTypePlusSub, ExpectedIdentifier, ExpectedSemi, + ExpectedSemiSugg, InInTypo, IncorrectAwait, IncorrectSemicolon, IncorrectUseOfAwait, + SuggEscapeToUseAsIdentifier, SuggRemoveComma, UseEqInstead, }; use crate::lexer::UnmatchedBrace; @@ -388,8 +388,8 @@ impl<'a> Parser<'a> { expected.dedup(); let sm = self.sess.source_map(); - let msg = format!("expected `;`, found {}", super::token_descr(&self.token)); - let appl = Applicability::MachineApplicable; + + // Special-case "expected `;`" errors if expected.contains(&TokenType::Token(token::Semi)) { if self.token.span == DUMMY_SP || self.prev_token.span == DUMMY_SP { // Likely inside a macro, can't provide meaningful suggestions. @@ -417,11 +417,13 @@ impl<'a> Parser<'a> { // // let x = 32: // let y = 42; + self.sess.emit_err(ExpectedSemi { + span: self.token.span, + token_descr: super::token_descr_struct(&self.token), + unexpected_token_label: None, + sugg: ExpectedSemiSugg::ChangeToSemi(self.token.span), + }); self.bump(); - let sp = self.prev_token.span; - self.struct_span_err(sp, &msg) - .span_suggestion_short(sp, "change this to `;`", ";", appl) - .emit(); return Ok(true); } else if self.look_ahead(0, |t| { t == &token::CloseDelim(Delimiter::Brace) @@ -439,11 +441,13 @@ impl<'a> Parser<'a> { // // let x = 32 // let y = 42; - let sp = self.prev_token.span.shrink_to_hi(); - self.struct_span_err(sp, &msg) - .span_label(self.token.span, "unexpected token") - .span_suggestion_short(sp, "add `;` here", ";", appl) - .emit(); + let span = self.prev_token.span.shrink_to_hi(); + self.sess.emit_err(ExpectedSemi { + span, + token_descr: super::token_descr_struct(&self.token), + unexpected_token_label: Some(self.token.span), + sugg: ExpectedSemiSugg::AddSemi(span), + }); return Ok(true); } } @@ -480,6 +484,7 @@ impl<'a> Parser<'a> { ) }; self.last_unexpected_token_span = Some(self.token.span); + // FIXME: translation requires list formatting (for `expect`) let mut err = self.struct_span_err(self.token.span, &msg_exp); if let TokenKind::Ident(symbol, _) = &self.prev_token.kind { @@ -488,7 +493,7 @@ impl<'a> Parser<'a> { self.prev_token.span, &format!("write `fn` instead of `{symbol}` to declare a function"), "fn", - appl, + Applicability::MachineApplicable, ); } } @@ -502,7 +507,7 @@ impl<'a> Parser<'a> { self.prev_token.span, "write `pub` instead of `public` to make the item public", "pub", - appl, + Applicability::MachineApplicable, ); } From 760c4352d6c8a85bc3d692769fac6a3e14b9c053 Mon Sep 17 00:00:00 2001 From: Xiretza Date: Sun, 4 Sep 2022 20:19:49 +0200 Subject: [PATCH 339/586] Migrate "struct literal body without path" error to diagnostic struct --- compiler/rustc_parse/src/errors.rs | 18 +++++++++++++ .../rustc_parse/src/parser/diagnostics.rs | 27 ++++++++----------- 2 files changed, 29 insertions(+), 16 deletions(-) diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index 07785b7344f25..e49661bd4e524 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -1014,3 +1014,21 @@ pub(crate) enum ExpectedSemiSugg { #[suggestion_short(parser::sugg_add_semi, code = ";", applicability = "machine-applicable")] AddSemi(#[primary_span] Span), } + +#[derive(Diagnostic)] +#[diag(parser::struct_literal_body_without_path)] +pub(crate) struct StructLiteralBodyWithoutPath { + #[primary_span] + pub span: Span, + #[subdiagnostic] + pub sugg: StructLiteralBodyWithoutPathSugg, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion(parser::suggestion, applicability = "has-placeholders")] +pub(crate) struct StructLiteralBodyWithoutPathSugg { + #[suggestion_part(code = "{{ SomeStruct ")] + pub before: Span, + #[suggestion_part(code = " }}")] + pub after: Span, +} diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index ba48e4e1c2525..c18a13ef778eb 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -6,7 +6,8 @@ use super::{ use crate::errors::{ AmbiguousPlus, BadQPathStage2, BadTypePlus, BadTypePlusSub, ExpectedIdentifier, ExpectedSemi, ExpectedSemiSugg, InInTypo, IncorrectAwait, IncorrectSemicolon, IncorrectUseOfAwait, - SuggEscapeToUseAsIdentifier, SuggRemoveComma, UseEqInstead, + StructLiteralBodyWithoutPath, StructLiteralBodyWithoutPathSugg, SuggEscapeToUseAsIdentifier, + SuggRemoveComma, UseEqInstead, }; use crate::lexer::UnmatchedBrace; @@ -21,10 +22,10 @@ use rustc_ast::{ }; use rustc_ast_pretty::pprust; use rustc_data_structures::fx::FxHashSet; +use rustc_errors::{pluralize, struct_span_err, Diagnostic, ErrorGuaranteed, IntoDiagnostic}; use rustc_errors::{ - fluent, Applicability, DiagnosticBuilder, DiagnosticMessage, Handler, MultiSpan, PResult, + Applicability, DiagnosticBuilder, DiagnosticMessage, Handler, MultiSpan, PResult, }; -use rustc_errors::{pluralize, struct_span_err, Diagnostic, ErrorGuaranteed, IntoDiagnostic}; use rustc_span::source_map::Spanned; use rustc_span::symbol::{kw, sym, Ident}; use rustc_span::{Span, SpanSnippetError, DUMMY_SP}; @@ -645,19 +646,13 @@ impl<'a> Parser<'a> { // field: value, // } } err.delay_as_bug(); - self.struct_span_err( - expr.span, - fluent::parser::struct_literal_body_without_path, - ) - .multipart_suggestion( - fluent::parser::suggestion, - vec![ - (expr.span.shrink_to_lo(), "{ SomeStruct ".to_string()), - (expr.span.shrink_to_hi(), " }".to_string()), - ], - Applicability::MaybeIncorrect, - ) - .emit(); + self.sess.emit_err(StructLiteralBodyWithoutPath { + span: expr.span, + sugg: StructLiteralBodyWithoutPathSugg { + before: expr.span.shrink_to_lo(), + after: expr.span.shrink_to_hi(), + }, + }); self.restore_snapshot(snapshot); let mut tail = self.mk_block( vec![self.mk_stmt_err(expr.span)], From 00f95468c4abd82cf71dc17004e1fd2e6cc72213 Mon Sep 17 00:00:00 2001 From: Xiretza Date: Thu, 8 Sep 2022 18:23:31 +0200 Subject: [PATCH 340/586] Migrate even more diagnostics in rustc_parse to diagnostic structs --- .../locales/en-US/parser.ftl | 53 +++ compiler/rustc_parse/src/errors.rs | 211 ++++++++++++ .../rustc_parse/src/parser/diagnostics.rs | 302 +++++++----------- compiler/rustc_parse/src/parser/expr.rs | 42 +-- 4 files changed, 395 insertions(+), 213 deletions(-) diff --git a/compiler/rustc_error_messages/locales/en-US/parser.ftl b/compiler/rustc_error_messages/locales/en-US/parser.ftl index 22fb65f02680d..e45094d72bc3c 100644 --- a/compiler/rustc_error_messages/locales/en-US/parser.ftl +++ b/compiler/rustc_error_messages/locales/en-US/parser.ftl @@ -316,3 +316,56 @@ parser_expected_semi_found_str = expected `;`, found `{$token_str}` parser_sugg_change_this_to_semi = change this to `;` parser_sugg_add_semi = add `;` here parser_label_unexpected_token = unexpected token + +parser_unmatched_angle_brackets = {$num_extra_brackets -> + [one] unmatched angle bracket + *[other] unmatched angle brackets + } + .suggestion = {$num_extra_brackets -> + [one] remove extra angle bracket + *[other] remove extra angle brackets + } + +parser_generic_parameters_without_angle_brackets = generic parameters without surrounding angle brackets + .suggestion = surround the type parameters with angle brackets + +parser_comparison_operators_cannot_be_chained = comparison operators cannot be chained + .sugg_parentheses_for_function_args = or use `(...)` if you meant to specify fn arguments + .sugg_split_comparison = split the comparison into two + .sugg_parenthesize = parenthesize the comparison +parser_sugg_turbofish_syntax = use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments + +parser_question_mark_in_type = invalid `?` in type + .label = `?` is only allowed on expressions, not types + .suggestion = if you meant to express that the type might not contain a value, use the `Option` wrapper type + +parser_unexpected_parentheses_in_for_head = unexpected parentheses surrounding `for` loop head + .suggestion = remove parentheses in `for` loop + +parser_doc_comment_on_param_type = documentation comments cannot be applied to a function parameter's type + .label = doc comments are not allowed here + +parser_attribute_on_param_type = attributes cannot be applied to a function parameter's type + .label = attributes are not allowed here + +parser_pattern_method_param_without_body = patterns aren't allowed in methods without bodies + .suggestion = give this argument a name or use an underscore to ignore it + +parser_self_param_not_first = unexpected `self` parameter in function + .label = must be the first parameter of an associated function + +parser_const_generic_without_braces = expressions must be enclosed in braces to be used as const generic arguments + .suggestion = enclose the `const` expression in braces + +parser_unexpected_const_param_declaration = unexpected `const` parameter declaration + .label = expected a `const` expression, not a parameter declaration + .suggestion = `const` parameters must be declared for the `impl` + +parser_unexpected_const_in_generic_param = expected lifetime, type, or constant, found keyword `const` + .suggestion = the `const` keyword is only needed in the definition of the type + +parser_async_move_order_incorrect = the order of `move` and `async` is incorrect + .suggestion = try switching the order + +parser_double_colon_in_bound = expected `:` followed by trait or lifetime + .suggestion = use single colon diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index e49661bd4e524..f10b178049b8d 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -1032,3 +1032,214 @@ pub(crate) struct StructLiteralBodyWithoutPathSugg { #[suggestion_part(code = " }}")] pub after: Span, } + +#[derive(Diagnostic)] +#[diag(parser::unmatched_angle_brackets)] +pub(crate) struct UnmatchedAngleBrackets { + #[primary_span] + #[suggestion(code = "", applicability = "machine-applicable")] + pub span: Span, + pub num_extra_brackets: usize, +} + +#[derive(Diagnostic)] +#[diag(parser::generic_parameters_without_angle_brackets)] +pub(crate) struct GenericParamsWithoutAngleBrackets { + #[primary_span] + pub span: Span, + #[subdiagnostic] + pub sugg: GenericParamsWithoutAngleBracketsSugg, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion(parser::suggestion, applicability = "machine-applicable")] +pub(crate) struct GenericParamsWithoutAngleBracketsSugg { + #[suggestion_part(code = "<")] + pub left: Span, + #[suggestion_part(code = ">")] + pub right: Span, +} + +#[derive(Diagnostic)] +#[diag(parser::comparison_operators_cannot_be_chained)] +pub(crate) struct ComparisonOperatorsCannotBeChained { + #[primary_span] + pub span: Vec, + #[suggestion_verbose( + parser::sugg_turbofish_syntax, + code = "::", + applicability = "maybe-incorrect" + )] + pub suggest_turbofish: Option, + #[help(parser::sugg_turbofish_syntax)] + #[help(parser::sugg_parentheses_for_function_args)] + pub help_turbofish: Option<()>, + #[subdiagnostic] + pub chaining_sugg: Option, +} + +#[derive(Subdiagnostic)] +pub(crate) enum ComparisonOperatorsCannotBeChainedSugg { + #[suggestion_verbose( + parser::sugg_split_comparison, + code = " && {middle_term}", + applicability = "maybe-incorrect" + )] + SplitComparison { + #[primary_span] + span: Span, + middle_term: String, + }, + #[multipart_suggestion(parser::sugg_parenthesize, applicability = "maybe-incorrect")] + Parenthesize { + #[suggestion_part(code = "(")] + left: Span, + #[suggestion_part(code = ")")] + right: Span, + }, +} + +#[derive(Diagnostic)] +#[diag(parser::question_mark_in_type)] +pub(crate) struct QuestionMarkInType { + #[primary_span] + #[label] + pub span: Span, + #[subdiagnostic] + pub sugg: QuestionMarkInTypeSugg, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion(parser::suggestion, applicability = "machine-applicable")] +pub(crate) struct QuestionMarkInTypeSugg { + #[suggestion_part(code = "Option<")] + pub left: Span, + #[suggestion_part(code = ">")] + pub right: Span, +} + +#[derive(Diagnostic)] +#[diag(parser::unexpected_parentheses_in_for_head)] +pub(crate) struct ParenthesesInForHead { + #[primary_span] + pub span: Vec, + #[subdiagnostic] + pub sugg: ParenthesesInForHeadSugg, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion(parser::suggestion, applicability = "machine-applicable")] +pub(crate) struct ParenthesesInForHeadSugg { + #[suggestion_part(code = "")] + pub left: Span, + #[suggestion_part(code = "")] + pub right: Span, +} + +#[derive(Diagnostic)] +#[diag(parser::doc_comment_on_param_type)] +pub(crate) struct DocCommentOnParamType { + #[primary_span] + #[label] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(parser::attribute_on_param_type)] +pub(crate) struct AttributeOnParamType { + #[primary_span] + #[label] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(parser::pattern_method_param_without_body, code = "E0642")] +pub(crate) struct PatternMethodParamWithoutBody { + #[primary_span] + #[suggestion(code = "_", applicability = "machine-applicable")] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(parser::self_param_not_first)] +pub(crate) struct SelfParamNotFirst { + #[primary_span] + #[label] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(parser::const_generic_without_braces)] +pub(crate) struct ConstGenericWithoutBraces { + #[primary_span] + pub span: Span, + #[subdiagnostic] + pub sugg: ConstGenericWithoutBracesSugg, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion(parser::suggestion, applicability = "machine-applicable")] +pub(crate) struct ConstGenericWithoutBracesSugg { + #[suggestion_part(code = "{{ ")] + pub left: Span, + #[suggestion_part(code = " }}")] + pub right: Span, +} + +#[derive(Diagnostic)] +#[diag(parser::unexpected_const_param_declaration)] +pub(crate) struct UnexpectedConstParamDeclaration { + #[primary_span] + #[label] + pub span: Span, + #[subdiagnostic] + pub sugg: Option, +} + +#[derive(Subdiagnostic)] +pub(crate) enum UnexpectedConstParamDeclarationSugg { + #[multipart_suggestion(parser::suggestion, applicability = "machine-applicable")] + AddParam { + #[suggestion_part(code = "<{snippet}>")] + impl_generics: Span, + #[suggestion_part(code = "{ident}")] + incorrect_decl: Span, + snippet: String, + ident: String, + }, + #[multipart_suggestion(parser::suggestion, applicability = "machine-applicable")] + AppendParam { + #[suggestion_part(code = ", {snippet}")] + impl_generics_end: Span, + #[suggestion_part(code = "{ident}")] + incorrect_decl: Span, + snippet: String, + ident: String, + }, +} + +#[derive(Diagnostic)] +#[diag(parser::unexpected_const_in_generic_param)] +pub(crate) struct UnexpectedConstInGenericParam { + #[primary_span] + pub span: Span, + #[suggestion_verbose(code = "", applicability = "maybe-incorrect")] + pub to_remove: Option, +} + +#[derive(Diagnostic)] +#[diag(parser::async_move_order_incorrect)] +pub(crate) struct AsyncMoveOrderIncorrect { + #[primary_span] + #[suggestion_verbose(code = "async move", applicability = "maybe-incorrect")] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(parser::double_colon_in_bound)] +pub(crate) struct DoubleColonInBound { + #[primary_span] + pub span: Span, + #[suggestion(code = ": ", applicability = "machine-applicable")] + pub between: Span, +} diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index c18a13ef778eb..ccba01630be16 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -4,10 +4,17 @@ use super::{ TokenExpectType, TokenType, }; use crate::errors::{ - AmbiguousPlus, BadQPathStage2, BadTypePlus, BadTypePlusSub, ExpectedIdentifier, ExpectedSemi, - ExpectedSemiSugg, InInTypo, IncorrectAwait, IncorrectSemicolon, IncorrectUseOfAwait, - StructLiteralBodyWithoutPath, StructLiteralBodyWithoutPathSugg, SuggEscapeToUseAsIdentifier, - SuggRemoveComma, UseEqInstead, + AmbiguousPlus, AttributeOnParamType, BadQPathStage2, BadTypePlus, BadTypePlusSub, + ComparisonOperatorsCannotBeChained, ComparisonOperatorsCannotBeChainedSugg, + ConstGenericWithoutBraces, ConstGenericWithoutBracesSugg, DocCommentOnParamType, + DoubleColonInBound, ExpectedIdentifier, ExpectedSemi, ExpectedSemiSugg, + GenericParamsWithoutAngleBrackets, GenericParamsWithoutAngleBracketsSugg, InInTypo, + IncorrectAwait, IncorrectSemicolon, IncorrectUseOfAwait, ParenthesesInForHead, + ParenthesesInForHeadSugg, PatternMethodParamWithoutBody, QuestionMarkInType, + QuestionMarkInTypeSugg, SelfParamNotFirst, StructLiteralBodyWithoutPath, + StructLiteralBodyWithoutPathSugg, SuggEscapeToUseAsIdentifier, SuggRemoveComma, + UnexpectedConstInGenericParam, UnexpectedConstParamDeclaration, + UnexpectedConstParamDeclarationSugg, UnmatchedAngleBrackets, UseEqInstead, }; use crate::lexer::UnmatchedBrace; @@ -22,10 +29,10 @@ use rustc_ast::{ }; use rustc_ast_pretty::pprust; use rustc_data_structures::fx::FxHashSet; -use rustc_errors::{pluralize, struct_span_err, Diagnostic, ErrorGuaranteed, IntoDiagnostic}; use rustc_errors::{ - Applicability, DiagnosticBuilder, DiagnosticMessage, Handler, MultiSpan, PResult, + fluent, Applicability, DiagnosticBuilder, DiagnosticMessage, Handler, MultiSpan, PResult, }; +use rustc_errors::{pluralize, Diagnostic, ErrorGuaranteed, IntoDiagnostic}; use rustc_span::source_map::Spanned; use rustc_span::symbol::{kw, sym, Ident}; use rustc_span::{Span, SpanSnippetError, DUMMY_SP}; @@ -35,9 +42,6 @@ use std::mem::take; use crate::parser; -const TURBOFISH_SUGGESTION_STR: &str = - "use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments"; - /// Creates a placeholder argument. pub(super) fn dummy_arg(ident: Ident) -> Param { let pat = P(Pat { @@ -846,18 +850,8 @@ impl<'a> Parser<'a> { self.eat_to_tokens(end); let span = lo.until(self.token.span); - let total_num_of_gt = number_of_gt + number_of_shr * 2; - self.struct_span_err( - span, - &format!("unmatched angle bracket{}", pluralize!(total_num_of_gt)), - ) - .span_suggestion( - span, - &format!("remove extra angle bracket{}", pluralize!(total_num_of_gt)), - "", - Applicability::MachineApplicable, - ) - .emit(); + let num_extra_brackets = number_of_gt + number_of_shr * 2; + self.sess.emit_err(UnmatchedAngleBrackets { span, num_extra_brackets }); return true; } false @@ -886,19 +880,13 @@ impl<'a> Parser<'a> { let args = AngleBracketedArgs { args, span }.into(); segment.args = args; - self.struct_span_err( + self.sess.emit_err(GenericParamsWithoutAngleBrackets { span, - "generic parameters without surrounding angle brackets", - ) - .multipart_suggestion( - "surround the type parameters with angle brackets", - vec![ - (span.shrink_to_lo(), "<".to_string()), - (trailing_span, ">".to_string()), - ], - Applicability::MachineApplicable, - ) - .emit(); + sugg: GenericParamsWithoutAngleBracketsSugg { + left: span.shrink_to_lo(), + right: trailing_span, + }, + }); } else { // This doesn't look like an invalid turbofish, can't recover parse state. self.restore_snapshot(snapshot); @@ -935,7 +923,7 @@ impl<'a> Parser<'a> { if self.eat(&token::Gt) { e.span_suggestion_verbose( binop.span.shrink_to_lo(), - TURBOFISH_SUGGESTION_STR, + fluent::parser::sugg_turbofish_syntax, "::", Applicability::MaybeIncorrect, ) @@ -967,7 +955,7 @@ impl<'a> Parser<'a> { /// parenthesising the leftmost comparison. fn attempt_chained_comparison_suggestion( &mut self, - err: &mut Diagnostic, + err: &mut ComparisonOperatorsCannotBeChained, inner_op: &Expr, outer_op: &Spanned, ) -> bool /* advanced the cursor */ { @@ -980,16 +968,6 @@ impl<'a> Parser<'a> { // suggestion being the only one to apply is high. return false; } - let mut enclose = |left: Span, right: Span| { - err.multipart_suggestion( - "parenthesize the comparison", - vec![ - (left.shrink_to_lo(), "(".to_string()), - (right.shrink_to_hi(), ")".to_string()), - ], - Applicability::MaybeIncorrect, - ); - }; return match (op.node, &outer_op.node) { // `x == y == z` (BinOpKind::Eq, AssocOp::Equal) | @@ -1003,12 +981,10 @@ impl<'a> Parser<'a> { self.span_to_snippet(e.span) .unwrap_or_else(|_| pprust::expr_to_string(&e)) }; - err.span_suggestion_verbose( - inner_op.span.shrink_to_hi(), - "split the comparison into two", - format!(" && {}", expr_to_str(&r1)), - Applicability::MaybeIncorrect, - ); + err.chaining_sugg = Some(ComparisonOperatorsCannotBeChainedSugg::SplitComparison { + span: inner_op.span.shrink_to_hi(), + middle_term: expr_to_str(&r1), + }); false // Keep the current parse behavior, where the AST is `(x < y) < z`. } // `x == y < z` @@ -1019,7 +995,10 @@ impl<'a> Parser<'a> { Ok(r2) => { // We are sure that outer-op-rhs could be consumed, the suggestion is // likely correct. - enclose(r1.span, r2.span); + err.chaining_sugg = Some(ComparisonOperatorsCannotBeChainedSugg::Parenthesize { + left: r1.span.shrink_to_lo(), + right: r2.span.shrink_to_hi(), + }); true } Err(expr_err) => { @@ -1036,7 +1015,10 @@ impl<'a> Parser<'a> { // further checks are necessary. match self.parse_expr() { Ok(_) => { - enclose(l1.span, r1.span); + err.chaining_sugg = Some(ComparisonOperatorsCannotBeChainedSugg::Parenthesize { + left: l1.span.shrink_to_lo(), + right: r1.span.shrink_to_hi(), + }); true } Err(expr_err) => { @@ -1085,18 +1067,11 @@ impl<'a> Parser<'a> { match inner_op.kind { ExprKind::Binary(op, ref l1, ref r1) if op.node.is_comparison() => { - let mut err = self.struct_span_err( - vec![op.span, self.prev_token.span], - "comparison operators cannot be chained", - ); - - let suggest = |err: &mut Diagnostic| { - err.span_suggestion_verbose( - op.span.shrink_to_lo(), - TURBOFISH_SUGGESTION_STR, - "::", - Applicability::MaybeIncorrect, - ); + let mut err = ComparisonOperatorsCannotBeChained { + span: vec![op.span, self.prev_token.span], + suggest_turbofish: None, + help_turbofish: None, + chaining_sugg: None, }; // Include `<` to provide this recommendation even in a case like @@ -1123,7 +1098,7 @@ impl<'a> Parser<'a> { return if token::ModSep == self.token.kind { // We have some certainty that this was a bad turbofish at this point. // `foo< bar >::` - suggest(&mut err); + err.suggest_turbofish = Some(op.span.shrink_to_lo()); let snapshot = self.create_snapshot_for_diagnostic(); self.bump(); // `::` @@ -1132,7 +1107,7 @@ impl<'a> Parser<'a> { match self.parse_expr() { Ok(_) => { // 99% certain that the suggestion is correct, continue parsing. - err.emit(); + self.sess.emit_err(err); // FIXME: actually check that the two expressions in the binop are // paths and resynthesize new fn call expression instead of using // `ExprKind::Err` placeholder. @@ -1143,18 +1118,18 @@ impl<'a> Parser<'a> { // Not entirely sure now, but we bubble the error up with the // suggestion. self.restore_snapshot(snapshot); - Err(err) + Err(err.into_diagnostic(&self.sess.span_diagnostic)) } } } else if token::OpenDelim(Delimiter::Parenthesis) == self.token.kind { // We have high certainty that this was a bad turbofish at this point. // `foo< bar >(` - suggest(&mut err); + err.suggest_turbofish = Some(op.span.shrink_to_lo()); // Consume the fn call arguments. match self.consume_fn_args() { - Err(()) => Err(err), + Err(()) => Err(err.into_diagnostic(&self.sess.span_diagnostic)), Ok(()) => { - err.emit(); + self.sess.emit_err(err); // FIXME: actually check that the two expressions in the binop are // paths and resynthesize new fn call expression instead of using // `ExprKind::Err` placeholder. @@ -1167,25 +1142,24 @@ impl<'a> Parser<'a> { { // All we know is that this is `foo < bar >` and *nothing* else. Try to // be helpful, but don't attempt to recover. - err.help(TURBOFISH_SUGGESTION_STR); - err.help("or use `(...)` if you meant to specify fn arguments"); + err.help_turbofish = Some(()); } // If it looks like a genuine attempt to chain operators (as opposed to a // misformatted turbofish, for instance), suggest a correct form. if self.attempt_chained_comparison_suggestion(&mut err, inner_op, outer_op) { - err.emit(); + self.sess.emit_err(err); mk_err_expr(self, inner_op.span.to(self.prev_token.span)) } else { // These cases cause too many knock-down errors, bail out (#61329). - Err(err) + Err(err.into_diagnostic(&self.sess.span_diagnostic)) } }; } let recover = self.attempt_chained_comparison_suggestion(&mut err, inner_op, outer_op); - err.emit(); + self.sess.emit_err(err); if recover { return mk_err_expr(self, inner_op.span.to(self.prev_token.span)); } @@ -1226,17 +1200,13 @@ impl<'a> Parser<'a> { pub(super) fn maybe_recover_from_question_mark(&mut self, ty: P) -> P { if self.token == token::Question { self.bump(); - self.struct_span_err(self.prev_token.span, "invalid `?` in type") - .span_label(self.prev_token.span, "`?` is only allowed on expressions, not types") - .multipart_suggestion( - "if you meant to express that the type might not contain a value, use the `Option` wrapper type", - vec![ - (ty.span.shrink_to_lo(), "Option<".to_string()), - (self.prev_token.span, ">".to_string()), - ], - Applicability::MachineApplicable, - ) - .emit(); + self.sess.emit_err(QuestionMarkInType { + span: self.prev_token.span, + sugg: QuestionMarkInTypeSugg { + left: ty.span.shrink_to_lo(), + right: self.prev_token.span, + }, + }); self.mk_ty(ty.span.to(self.prev_token.span), TyKind::Err) } else { ty @@ -1660,19 +1630,16 @@ impl<'a> Parser<'a> { (token::CloseDelim(Delimiter::Parenthesis), Some(begin_par_sp)) => { self.bump(); - self.struct_span_err( - MultiSpan::from_spans(vec![begin_par_sp, self.prev_token.span]), - "unexpected parentheses surrounding `for` loop head", - ) - .multipart_suggestion( - "remove parentheses in `for` loop", - vec![(begin_par_sp, String::new()), (self.prev_token.span, String::new())], + self.sess.emit_err(ParenthesesInForHead { + span: vec![begin_par_sp, self.prev_token.span], // With e.g. `for (x) in y)` this would replace `(x) in y)` // with `x) in y)` which is syntactically invalid. // However, this is prevented before we get here. - Applicability::MachineApplicable, - ) - .emit(); + sugg: ParenthesesInForHeadSugg { + left: begin_par_sp, + right: self.prev_token.span, + }, + }); // Unwrap `(pat)` into `pat` to avoid the `unused_parens` lint. pat.and_then(|pat| match pat.kind { @@ -1891,12 +1858,7 @@ impl<'a> Parser<'a> { pub(super) fn eat_incorrect_doc_comment_for_param_type(&mut self) { if let token::DocComment(..) = self.token.kind { - self.struct_span_err( - self.token.span, - "documentation comments cannot be applied to a function parameter's type", - ) - .span_label(self.token.span, "doc comments are not allowed here") - .emit(); + self.sess.emit_err(DocCommentOnParamType { span: self.token.span }); self.bump(); } else if self.token == token::Pound && self.look_ahead(1, |t| *t == token::OpenDelim(Delimiter::Bracket)) @@ -1908,9 +1870,7 @@ impl<'a> Parser<'a> { } let sp = lo.to(self.token.span); self.bump(); - self.struct_span_err(sp, "attributes cannot be applied to a function parameter's type") - .span_label(sp, "attributes are not allowed here") - .emit(); + self.sess.emit_err(AttributeOnParamType { span: sp }); } } @@ -2031,19 +1991,7 @@ impl<'a> Parser<'a> { self.expect(&token::Colon)?; let ty = self.parse_ty()?; - struct_span_err!( - self.diagnostic(), - pat.span, - E0642, - "patterns aren't allowed in methods without bodies", - ) - .span_suggestion_short( - pat.span, - "give this argument a name or use an underscore to ignore it", - "_", - Applicability::MachineApplicable, - ) - .emit(); + self.sess.emit_err(PatternMethodParamWithoutBody { span: pat.span }); // Pretend the pattern is `_`, to avoid duplicate errors from AST validation. let pat = @@ -2052,11 +2000,9 @@ impl<'a> Parser<'a> { } pub(super) fn recover_bad_self_param(&mut self, mut param: Param) -> PResult<'a, Param> { - let sp = param.pat.span; + let span = param.pat.span; param.ty.kind = TyKind::Err; - self.struct_span_err(sp, "unexpected `self` parameter in function") - .span_label(sp, "must be the first parameter of an associated function") - .emit(); + self.sess.emit_err(SelfParamNotFirst { span }); Ok(param) } @@ -2205,20 +2151,13 @@ impl<'a> Parser<'a> { err })?; if !self.expr_is_valid_const_arg(&expr) { - self.struct_span_err( - expr.span, - "expressions must be enclosed in braces to be used as const generic \ - arguments", - ) - .multipart_suggestion( - "enclose the `const` expression in braces", - vec![ - (expr.span.shrink_to_lo(), "{ ".to_string()), - (expr.span.shrink_to_hi(), " }".to_string()), - ], - Applicability::MachineApplicable, - ) - .emit(); + self.sess.emit_err(ConstGenericWithoutBraces { + span: expr.span, + sugg: ConstGenericWithoutBracesSugg { + left: expr.span.shrink_to_lo(), + right: expr.span.shrink_to_hi(), + }, + }); } Ok(expr) } @@ -2233,24 +2172,30 @@ impl<'a> Parser<'a> { return None; } }; - let mut err = - self.struct_span_err(param.span(), "unexpected `const` parameter declaration"); - err.span_label(param.span(), "expected a `const` expression, not a parameter declaration"); - if let (Some(generics), Ok(snippet)) = - (ty_generics, self.sess.source_map().span_to_snippet(param.span())) - { - let (span, sugg) = match &generics.params[..] { - [] => (generics.span, format!("<{snippet}>")), - [.., generic] => (generic.span().shrink_to_hi(), format!(", {snippet}")), - }; - err.multipart_suggestion( - "`const` parameters must be declared for the `impl`", - vec![(span, sugg), (param.span(), param.ident.to_string())], - Applicability::MachineApplicable, - ); - } + + let ident = param.ident.to_string(); + let sugg = match (ty_generics, self.sess.source_map().span_to_snippet(param.span())) { + (Some(Generics { params, span: impl_generics, .. }), Ok(snippet)) => { + Some(match ¶ms[..] { + [] => UnexpectedConstParamDeclarationSugg::AddParam { + impl_generics: *impl_generics, + incorrect_decl: param.span(), + snippet, + ident, + }, + [.., generic] => UnexpectedConstParamDeclarationSugg::AppendParam { + impl_generics_end: generic.span().shrink_to_hi(), + incorrect_decl: param.span(), + snippet, + ident, + }, + }) + } + _ => None, + }; + self.sess.emit_err(UnexpectedConstParamDeclaration { span: param.span(), sugg }); + let value = self.mk_expr_err(param.span()); - err.emit(); Some(GenericArg::Const(AnonConst { id: ast::DUMMY_NODE_ID, value })) } @@ -2268,20 +2213,15 @@ impl<'a> Parser<'a> { self.bump(); // `const` // Detect and recover from the old, pre-RFC2000 syntax for const generics. - let mut err = self - .struct_span_err(start, "expected lifetime, type, or constant, found keyword `const`"); + let mut err = UnexpectedConstInGenericParam { span: start, to_remove: None }; if self.check_const_arg() { - err.span_suggestion_verbose( - start.until(self.token.span), - "the `const` keyword is only needed in the definition of the type", - "", - Applicability::MaybeIncorrect, - ); - err.emit(); + err.to_remove = Some(start.until(self.token.span)); + self.sess.emit_err(err); Ok(Some(GenericArg::Const(self.parse_const_arg()?))) } else { let after_kw_const = self.token.span; - self.recover_const_arg(after_kw_const, err).map(Some) + self.recover_const_arg(after_kw_const, err.into_diagnostic(&self.sess.span_diagnostic)) + .map(Some) } } @@ -2387,24 +2327,6 @@ impl<'a> Parser<'a> { GenericArg::Const(AnonConst { id: ast::DUMMY_NODE_ID, value }) } - /// Get the diagnostics for the cases where `move async` is found. - /// - /// `move_async_span` starts at the 'm' of the move keyword and ends with the 'c' of the async keyword - pub(super) fn incorrect_move_async_order_found( - &self, - move_async_span: Span, - ) -> DiagnosticBuilder<'a, ErrorGuaranteed> { - let mut err = - self.struct_span_err(move_async_span, "the order of `move` and `async` is incorrect"); - err.span_suggestion_verbose( - move_async_span, - "try switching the order", - "async move", - Applicability::MaybeIncorrect, - ); - err - } - /// Some special error handling for the "top-level" patterns in a match arm, /// `for` loop, `let`, &c. (in contrast to subpatterns within such). pub(crate) fn maybe_recover_colon_colon_in_pat_typo( @@ -2600,17 +2522,11 @@ impl<'a> Parser<'a> { let (a_span, b_span) = (a.span(), b.span()); let between_span = a_span.shrink_to_hi().to(b_span.shrink_to_lo()); if self.span_to_snippet(between_span).as_ref().map(|a| &a[..]) == Ok(":: ") { - let mut err = self.struct_span_err( - path.span.shrink_to_hi(), - "expected `:` followed by trait or lifetime", - ); - err.span_suggestion( - between_span, - "use single colon", - ": ", - Applicability::MachineApplicable, - ); - return Err(err); + return Err(DoubleColonInBound { + span: path.span.shrink_to_hi(), + between: between_span, + } + .into_diagnostic(&self.sess.span_diagnostic)); } } } diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 751951dcaaeec..ee9676c8054ee 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -6,25 +6,26 @@ use super::{ SemiColonMode, SeqSep, TokenExpectType, TokenType, TrailingToken, }; use crate::errors::{ - ArrayBracketsInsteadOfSpaces, ArrayBracketsInsteadOfSpacesSugg, BinaryFloatLiteralNotSupported, - BracesForStructLiteral, CatchAfterTry, CommaAfterBaseStruct, ComparisonInterpretedAsGeneric, - ComparisonOrShiftInterpretedAsGenericSugg, DoCatchSyntaxRemoved, DotDotDot, EqFieldInit, - ExpectedElseBlock, ExpectedExpressionFoundLet, FieldExpressionWithGeneric, - FloatLiteralRequiresIntegerPart, FoundExprWouldBeStmt, HexadecimalFloatLiteralNotSupported, - IfExpressionMissingCondition, IfExpressionMissingThenBlock, IfExpressionMissingThenBlockSub, - IntLiteralTooLarge, InvalidBlockMacroSegment, InvalidComparisonOperator, - InvalidComparisonOperatorSub, InvalidFloatLiteralSuffix, InvalidFloatLiteralWidth, - InvalidIntLiteralWidth, InvalidInterpolatedExpression, InvalidLiteralSuffix, - InvalidLiteralSuffixOnTupleIndex, InvalidLogicalOperator, InvalidLogicalOperatorSub, - InvalidNumLiteralBasePrefix, InvalidNumLiteralSuffix, LabeledLoopInBreak, - LeadingPlusNotSupported, LeftArrowOperator, LifetimeInBorrowExpression, - MacroInvocationWithQualifiedPath, MalformedLoopLabel, MatchArmBodyWithoutBraces, - MatchArmBodyWithoutBracesSugg, MissingCommaAfterMatchArm, MissingInInForLoop, - MissingInInForLoopSub, MissingSemicolonBeforeArray, NoFieldsForFnCall, NotAsNegationOperator, - NotAsNegationOperatorSub, OctalFloatLiteralNotSupported, OuterAttributeNotAllowedOnIfElse, - ParenthesesWithStructFields, RequireColonAfterLabeledExpression, ShiftInterpretedAsGeneric, - StructLiteralNotAllowedHere, StructLiteralNotAllowedHereSugg, TildeAsUnaryOperator, - UnexpectedTokenAfterLabel, UnexpectedTokenAfterLabelSugg, WrapExpressionInParentheses, + ArrayBracketsInsteadOfSpaces, ArrayBracketsInsteadOfSpacesSugg, AsyncMoveOrderIncorrect, + BinaryFloatLiteralNotSupported, BracesForStructLiteral, CatchAfterTry, CommaAfterBaseStruct, + ComparisonInterpretedAsGeneric, ComparisonOrShiftInterpretedAsGenericSugg, + DoCatchSyntaxRemoved, DotDotDot, EqFieldInit, ExpectedElseBlock, ExpectedExpressionFoundLet, + FieldExpressionWithGeneric, FloatLiteralRequiresIntegerPart, FoundExprWouldBeStmt, + HexadecimalFloatLiteralNotSupported, IfExpressionMissingCondition, + IfExpressionMissingThenBlock, IfExpressionMissingThenBlockSub, IntLiteralTooLarge, + InvalidBlockMacroSegment, InvalidComparisonOperator, InvalidComparisonOperatorSub, + InvalidFloatLiteralSuffix, InvalidFloatLiteralWidth, InvalidIntLiteralWidth, + InvalidInterpolatedExpression, InvalidLiteralSuffix, InvalidLiteralSuffixOnTupleIndex, + InvalidLogicalOperator, InvalidLogicalOperatorSub, InvalidNumLiteralBasePrefix, + InvalidNumLiteralSuffix, LabeledLoopInBreak, LeadingPlusNotSupported, LeftArrowOperator, + LifetimeInBorrowExpression, MacroInvocationWithQualifiedPath, MalformedLoopLabel, + MatchArmBodyWithoutBraces, MatchArmBodyWithoutBracesSugg, MissingCommaAfterMatchArm, + MissingInInForLoop, MissingInInForLoopSub, MissingSemicolonBeforeArray, NoFieldsForFnCall, + NotAsNegationOperator, NotAsNegationOperatorSub, OctalFloatLiteralNotSupported, + OuterAttributeNotAllowedOnIfElse, ParenthesesWithStructFields, + RequireColonAfterLabeledExpression, ShiftInterpretedAsGeneric, StructLiteralNotAllowedHere, + StructLiteralNotAllowedHereSugg, TildeAsUnaryOperator, UnexpectedTokenAfterLabel, + UnexpectedTokenAfterLabelSugg, WrapExpressionInParentheses, }; use crate::maybe_recover_from_interpolated_ty_qpath; @@ -2087,7 +2088,8 @@ impl<'a> Parser<'a> { // Check for `move async` and recover if self.check_keyword(kw::Async) { let move_async_span = self.token.span.with_lo(self.prev_token.span.data().lo); - Err(self.incorrect_move_async_order_found(move_async_span)) + Err(AsyncMoveOrderIncorrect { span: move_async_span } + .into_diagnostic(&self.sess.span_diagnostic)) } else { Ok(CaptureBy::Value) } From caefac034e55b3cd0568a493c85308e1fc518cda Mon Sep 17 00:00:00 2001 From: Xiretza Date: Wed, 14 Sep 2022 18:35:22 +0200 Subject: [PATCH 341/586] Document use of Symbol::to_string() --- compiler/rustc_parse/src/parser/diagnostics.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index ccba01630be16..5df94331d7bb9 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -309,6 +309,8 @@ impl<'a> Parser<'a> { { Some(SuggEscapeToUseAsIdentifier { span: ident.span.shrink_to_lo(), + // `Symbol::to_string()` is different from `Symbol::into_diagnostic_arg()`, + // which uses `Symbol::to_ident_string()` and "helpfully" adds an implicit `r#` ident_name: ident.name.to_string(), }) } From 37fdcb4b364aeb8164a21a39dac984eb1e772872 Mon Sep 17 00:00:00 2001 From: Xiretza Date: Wed, 14 Sep 2022 20:11:42 +0200 Subject: [PATCH 342/586] Don't unnecessarily stringify paths in diagnostics --- .../locales/en-US/parser.ftl | 8 ++++---- compiler/rustc_parse/src/errors.rs | 7 ++++--- compiler/rustc_parse/src/parser/expr.rs | 18 +++++++++--------- 3 files changed, 17 insertions(+), 16 deletions(-) diff --git a/compiler/rustc_error_messages/locales/en-US/parser.ftl b/compiler/rustc_error_messages/locales/en-US/parser.ftl index e45094d72bc3c..dea85d8e7f489 100644 --- a/compiler/rustc_error_messages/locales/en-US/parser.ftl +++ b/compiler/rustc_error_messages/locales/en-US/parser.ftl @@ -165,13 +165,13 @@ parser_use_empty_block_not_semi = expected { "`{}`" }, found `;` .suggestion = try using { "`{}`" } instead parser_comparison_interpreted_as_generic = - `<` is interpreted as a start of generic arguments for `{$typename}`, not a comparison + `<` is interpreted as a start of generic arguments for `{$type}`, not a comparison .label_args = interpreted as generic arguments .label_comparison = not interpreted as comparison .suggestion = try comparing the cast value parser_shift_interpreted_as_generic = - `<<` is interpreted as a start of generic arguments for `{$typename}`, not a shift + `<<` is interpreted as a start of generic arguments for `{$type}`, not a shift .label_args = interpreted as generic arguments .label_comparison = not interpreted as shift .suggestion = try shifting the cast value @@ -184,8 +184,8 @@ parser_leading_plus_not_supported = leading `+` is not supported .suggestion_remove_plus = try removing the `+` parser_parentheses_with_struct_fields = invalid `struct` delimiters or `fn` call arguments - .suggestion_braces_for_struct = if `{$name}` is a struct, use braces as delimiters - .suggestion_no_fields_for_fn = if `{$name}` is a function, use the arguments directly + .suggestion_braces_for_struct = if `{$type}` is a struct, use braces as delimiters + .suggestion_no_fields_for_fn = if `{$type}` is a function, use the arguments directly parser_labeled_loop_in_break = parentheses are required around this expression to avoid confusion with a labeled break expression diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index f10b178049b8d..3d364a956d3ec 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -1,3 +1,4 @@ +use rustc_ast::Path; use rustc_errors::{fluent, AddToDiagnostic, Applicability, EmissionGuarantee, IntoDiagnostic}; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_session::errors::ExprParenthesesNeeded; @@ -536,7 +537,7 @@ pub(crate) struct ComparisonInterpretedAsGeneric { #[primary_span] #[label(parser::label_comparison)] pub comparison: Span, - pub typename: String, + pub r#type: Path, #[label(parser::label_args)] pub args: Span, #[subdiagnostic] @@ -549,7 +550,7 @@ pub(crate) struct ShiftInterpretedAsGeneric { #[primary_span] #[label(parser::label_comparison)] pub shift: Span, - pub typename: String, + pub r#type: Path, #[label(parser::label_args)] pub args: Span, #[subdiagnostic] @@ -597,7 +598,7 @@ pub(crate) struct LeadingPlusNotSupported { pub(crate) struct ParenthesesWithStructFields { #[primary_span] pub span: Span, - pub name: String, + pub r#type: Path, #[subdiagnostic] pub braces_for_struct: BracesForStructLiteral, #[subdiagnostic] diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index ee9676c8054ee..02cee75a0f58a 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -756,11 +756,12 @@ impl<'a> Parser<'a> { match self.parse_path(PathStyle::Expr) { Ok(path) => { - let typename = pprust::path_to_string(&path); - let span_after_type = parser_snapshot_after_type.token.span; - let expr = - mk_expr(self, lhs, self.mk_ty(path.span, TyKind::Path(None, path))); + let expr = mk_expr( + self, + lhs, + self.mk_ty(path.span, TyKind::Path(None, path.clone())), + ); let args_span = self.look_ahead(1, |t| t.span).to(span_after_type); let suggestion = ComparisonOrShiftInterpretedAsGenericSugg { @@ -771,14 +772,14 @@ impl<'a> Parser<'a> { match self.token.kind { token::Lt => self.sess.emit_err(ComparisonInterpretedAsGeneric { comparison: self.token.span, - typename, + r#type: path, args: args_span, suggestion, }), token::BinOp(token::Shl) => { self.sess.emit_err(ShiftInterpretedAsGeneric { shift: self.token.span, - typename, + r#type: path, args: args_span, suggestion, }) @@ -1197,9 +1198,8 @@ impl<'a> Parser<'a> { ) -> Option> { match (seq.as_mut(), snapshot) { (Err(err), Some((mut snapshot, ExprKind::Path(None, path)))) => { - let name = pprust::path_to_string(&path); snapshot.bump(); // `(` - match snapshot.parse_struct_fields(path, false, Delimiter::Parenthesis) { + match snapshot.parse_struct_fields(path.clone(), false, Delimiter::Parenthesis) { Ok((fields, ..)) if snapshot.eat(&token::CloseDelim(Delimiter::Parenthesis)) => { @@ -1211,7 +1211,7 @@ impl<'a> Parser<'a> { if !fields.is_empty() { let mut replacement_err = ParenthesesWithStructFields { span, - name, + r#type: path, braces_for_struct: BracesForStructLiteral { first: open_paren, second: close_paren, From d7c64574e03f1d44c0a9e200b7dbeba98c50d8b3 Mon Sep 17 00:00:00 2001 From: Xiretza Date: Thu, 22 Sep 2022 18:39:17 +0200 Subject: [PATCH 343/586] Implement IntoDiagnosticArg for rustc_ast::token::Token(Kind) --- .../locales/en-US/parser.ftl | 20 +++---- compiler/rustc_errors/src/diagnostic.rs | 12 +++++ compiler/rustc_parse/src/errors.rs | 53 ++++++++++--------- compiler/rustc_parse/src/parser/attr.rs | 4 +- .../rustc_parse/src/parser/diagnostics.rs | 6 +-- compiler/rustc_parse/src/parser/expr.rs | 3 +- compiler/rustc_parse/src/parser/mod.rs | 41 ++++++-------- 7 files changed, 73 insertions(+), 66 deletions(-) diff --git a/compiler/rustc_error_messages/locales/en-US/parser.ftl b/compiler/rustc_error_messages/locales/en-US/parser.ftl index dea85d8e7f489..6d34cdce3408f 100644 --- a/compiler/rustc_error_messages/locales/en-US/parser.ftl +++ b/compiler/rustc_error_messages/locales/en-US/parser.ftl @@ -291,11 +291,11 @@ parser_inner_doc_comment_not_permitted = expected outer doc comment .label_does_not_annotate_this = the inner doc comment doesn't annotate this {$item} .sugg_change_inner_to_outer = to annotate the {$item}, change the doc comment from inner to outer style -parser_expected_identifier_found_reserved_identifier_str = expected identifier, found reserved identifier `{$token_str}` -parser_expected_identifier_found_keyword_str = expected identifier, found keyword `{$token_str}` -parser_expected_identifier_found_reserved_keyword_str = expected identifier, found reserved keyword `{$token_str}` -parser_expected_identifier_found_doc_comment_str = expected identifier, found doc comment `{$token_str}` -parser_expected_identifier_found_str = expected identifier, found `{$token_str}` +parser_expected_identifier_found_reserved_identifier_str = expected identifier, found reserved identifier `{$token}` +parser_expected_identifier_found_keyword_str = expected identifier, found keyword `{$token}` +parser_expected_identifier_found_reserved_keyword_str = expected identifier, found reserved keyword `{$token}` +parser_expected_identifier_found_doc_comment_str = expected identifier, found doc comment `{$token}` +parser_expected_identifier_found_str = expected identifier, found `{$token}` parser_expected_identifier_found_reserved_identifier = expected identifier, found reserved identifier parser_expected_identifier_found_keyword = expected identifier, found keyword @@ -307,11 +307,11 @@ parser_sugg_escape_to_use_as_identifier = escape `{$ident_name}` to use it as an parser_sugg_remove_comma = remove this comma -parser_expected_semi_found_reserved_identifier_str = expected `;`, found reserved identifier `{$token_str}` -parser_expected_semi_found_keyword_str = expected `;`, found keyword `{$token_str}` -parser_expected_semi_found_reserved_keyword_str = expected `;`, found reserved keyword `{$token_str}` -parser_expected_semi_found_doc_comment_str = expected `;`, found doc comment `{$token_str}` -parser_expected_semi_found_str = expected `;`, found `{$token_str}` +parser_expected_semi_found_reserved_identifier_str = expected `;`, found reserved identifier `{$token}` +parser_expected_semi_found_keyword_str = expected `;`, found keyword `{$token}` +parser_expected_semi_found_reserved_keyword_str = expected `;`, found reserved keyword `{$token}` +parser_expected_semi_found_doc_comment_str = expected `;`, found doc comment `{$token}` +parser_expected_semi_found_str = expected `;`, found `{$token}` parser_sugg_change_this_to_semi = change this to `;` parser_sugg_add_semi = add `;` here diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index fb409c578f6d5..5520e22e4767c 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -183,6 +183,18 @@ impl IntoDiagnosticArg for ast::Path { } } +impl IntoDiagnosticArg for ast::token::Token { + fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { + DiagnosticArgValue::Str(pprust::token_to_string(&self)) + } +} + +impl IntoDiagnosticArg for ast::token::TokenKind { + fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { + DiagnosticArgValue::Str(pprust::token_kind_to_string(&self)) + } +} + /// Trait implemented by error types. This should not be implemented manually. Instead, use /// `#[derive(Subdiagnostic)]` -- see [rustc_macros::Subdiagnostic]. #[cfg_attr(bootstrap, rustc_diagnostic_item = "AddSubdiagnostic")] diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index 3d364a956d3ec..98fee99742727 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -1,3 +1,4 @@ +use rustc_ast::token::Token; use rustc_ast::Path; use rustc_errors::{fluent, AddToDiagnostic, Applicability, EmissionGuarantee, IntoDiagnostic}; use rustc_macros::{Diagnostic, Subdiagnostic}; @@ -5,7 +6,7 @@ use rustc_session::errors::ExprParenthesesNeeded; use rustc_span::symbol::Ident; use rustc_span::{Span, Symbol}; -use crate::parser::{TokenDescription, TokenDescriptionKind}; +use crate::parser::TokenDescription; #[derive(Diagnostic)] #[diag(parser::maybe_report_ambiguous_plus)] @@ -572,7 +573,7 @@ pub(crate) struct FoundExprWouldBeStmt { #[primary_span] #[label] pub span: Span, - pub token: String, + pub token: Token, #[subdiagnostic] pub suggestion: ExprParenthesesNeeded, } @@ -871,7 +872,7 @@ pub(crate) struct SuffixedLiteralInAttribute { pub(crate) struct InvalidMetaItem { #[primary_span] pub span: Span, - pub token: String, + pub token: Token, } #[derive(Subdiagnostic)] @@ -908,14 +909,14 @@ pub(crate) enum ExpectedIdentifierFound { } impl ExpectedIdentifierFound { - pub fn new(token_descr_kind: Option, span: Span) -> Self { - (match token_descr_kind { - Some(TokenDescriptionKind::ReservedIdentifier) => { + pub fn new(token_descr: Option, span: Span) -> Self { + (match token_descr { + Some(TokenDescription::ReservedIdentifier) => { ExpectedIdentifierFound::ReservedIdentifier } - Some(TokenDescriptionKind::Keyword) => ExpectedIdentifierFound::Keyword, - Some(TokenDescriptionKind::ReservedKeyword) => ExpectedIdentifierFound::ReservedKeyword, - Some(TokenDescriptionKind::DocComment) => ExpectedIdentifierFound::DocComment, + Some(TokenDescription::Keyword) => ExpectedIdentifierFound::Keyword, + Some(TokenDescription::ReservedKeyword) => ExpectedIdentifierFound::ReservedKeyword, + Some(TokenDescription::DocComment) => ExpectedIdentifierFound::DocComment, None => ExpectedIdentifierFound::Other, })(span) } @@ -923,7 +924,7 @@ impl ExpectedIdentifierFound { pub(crate) struct ExpectedIdentifier { pub span: Span, - pub token_descr: TokenDescription, + pub token: Token, pub suggest_raw: Option, pub suggest_remove_comma: Option, } @@ -933,29 +934,31 @@ impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for ExpectedIdentifier { self, handler: &'a rustc_errors::Handler, ) -> rustc_errors::DiagnosticBuilder<'a, G> { - let mut diag = handler.struct_diagnostic(match self.token_descr.kind { - Some(TokenDescriptionKind::ReservedIdentifier) => { + let token_descr = super::parser::TokenDescription::from_token(&self.token); + + let mut diag = handler.struct_diagnostic(match token_descr { + Some(TokenDescription::ReservedIdentifier) => { fluent::parser::expected_identifier_found_reserved_identifier_str } - Some(TokenDescriptionKind::Keyword) => { + Some(TokenDescription::Keyword) => { fluent::parser::expected_identifier_found_keyword_str } - Some(TokenDescriptionKind::ReservedKeyword) => { + Some(TokenDescription::ReservedKeyword) => { fluent::parser::expected_identifier_found_reserved_keyword_str } - Some(TokenDescriptionKind::DocComment) => { + Some(TokenDescription::DocComment) => { fluent::parser::expected_identifier_found_doc_comment_str } None => fluent::parser::expected_identifier_found_str, }); diag.set_span(self.span); - diag.set_arg("token_str", self.token_descr.name); + diag.set_arg("token", self.token); if let Some(sugg) = self.suggest_raw { sugg.add_to_diagnostic(&mut diag); } - ExpectedIdentifierFound::new(self.token_descr.kind, self.span).add_to_diagnostic(&mut diag); + ExpectedIdentifierFound::new(token_descr, self.span).add_to_diagnostic(&mut diag); if let Some(sugg) = self.suggest_remove_comma { sugg.add_to_diagnostic(&mut diag); @@ -967,7 +970,7 @@ impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for ExpectedIdentifier { pub(crate) struct ExpectedSemi { pub span: Span, - pub token_descr: TokenDescription, + pub token: Token, pub unexpected_token_label: Option, pub sugg: ExpectedSemiSugg, @@ -978,21 +981,23 @@ impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for ExpectedSemi { self, handler: &'a rustc_errors::Handler, ) -> rustc_errors::DiagnosticBuilder<'a, G> { - let mut diag = handler.struct_diagnostic(match self.token_descr.kind { - Some(TokenDescriptionKind::ReservedIdentifier) => { + let token_descr = super::parser::TokenDescription::from_token(&self.token); + + let mut diag = handler.struct_diagnostic(match token_descr { + Some(TokenDescription::ReservedIdentifier) => { fluent::parser::expected_semi_found_reserved_identifier_str } - Some(TokenDescriptionKind::Keyword) => fluent::parser::expected_semi_found_keyword_str, - Some(TokenDescriptionKind::ReservedKeyword) => { + Some(TokenDescription::Keyword) => fluent::parser::expected_semi_found_keyword_str, + Some(TokenDescription::ReservedKeyword) => { fluent::parser::expected_semi_found_reserved_keyword_str } - Some(TokenDescriptionKind::DocComment) => { + Some(TokenDescription::DocComment) => { fluent::parser::expected_semi_found_doc_comment_str } None => fluent::parser::expected_semi_found_str, }); diag.set_span(self.span); - diag.set_arg("token_str", self.token_descr.name); + diag.set_arg("token", self.token); if let Some(unexpected_token_label) = self.unexpected_token_label { diag.span_label(unexpected_token_label, fluent::parser::label_unexpected_token); diff --git a/compiler/rustc_parse/src/parser/attr.rs b/compiler/rustc_parse/src/parser/attr.rs index ee3f7dbbc398e..58be348883c0c 100644 --- a/compiler/rustc_parse/src/parser/attr.rs +++ b/compiler/rustc_parse/src/parser/attr.rs @@ -4,7 +4,6 @@ use super::{AttrWrapper, Capturing, FnParseMode, ForceCollect, Parser, PathStyle use rustc_ast as ast; use rustc_ast::attr; use rustc_ast::token::{self, Delimiter, Nonterminal}; -use rustc_ast_pretty::pprust; use rustc_errors::{error_code, fluent, Diagnostic, IntoDiagnostic, PResult}; use rustc_span::{sym, BytePos, Span}; use std::convert::TryInto; @@ -414,8 +413,7 @@ impl<'a> Parser<'a> { Err(err) => err.cancel(), } - let token = pprust::token_to_string(&self.token).to_string(); - Err(InvalidMetaItem { span: self.token.span, token } + Err(InvalidMetaItem { span: self.token.span, token: self.token.clone() } .into_diagnostic(&self.sess.span_diagnostic)) } } diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index 5df94331d7bb9..b512f26335f6c 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -326,7 +326,7 @@ impl<'a> Parser<'a> { let err = ExpectedIdentifier { span: self.token.span, - token_descr: super::token_descr_struct(&self.token), + token: self.token.clone(), suggest_raw, suggest_remove_comma, }; @@ -426,7 +426,7 @@ impl<'a> Parser<'a> { // let y = 42; self.sess.emit_err(ExpectedSemi { span: self.token.span, - token_descr: super::token_descr_struct(&self.token), + token: self.token.clone(), unexpected_token_label: None, sugg: ExpectedSemiSugg::ChangeToSemi(self.token.span), }); @@ -451,7 +451,7 @@ impl<'a> Parser<'a> { let span = self.prev_token.span.shrink_to_hi(); self.sess.emit_err(ExpectedSemi { span, - token_descr: super::token_descr_struct(&self.token), + token: self.token.clone(), unexpected_token_label: Some(self.token.span), sugg: ExpectedSemiSugg::AddSemi(span), }); diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 02cee75a0f58a..8b328e593ae80 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -430,8 +430,7 @@ impl<'a> Parser<'a> { fn error_found_expr_would_be_stmt(&self, lhs: &Expr) { self.sess.emit_err(FoundExprWouldBeStmt { span: self.token.span, - // FIXME(#100717) - token: pprust::token_to_string(&self.token).to_string(), + token: self.token.clone(), suggestion: ExprParenthesesNeeded::surrounding(lhs.span), }); } diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index a1a224e8524cd..2aebaf7c3af2a 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -411,40 +411,33 @@ pub enum FollowedByType { } #[derive(Clone, Copy, PartialEq, Eq)] -pub enum TokenDescriptionKind { +pub enum TokenDescription { ReservedIdentifier, Keyword, ReservedKeyword, DocComment, } -#[derive(Clone, PartialEq, Eq)] -pub struct TokenDescription { - pub kind: Option, - pub name: String, -} - -pub(super) fn token_descr_struct(token: &Token) -> TokenDescription { - let kind = match token.kind { - _ if token.is_special_ident() => Some(TokenDescriptionKind::ReservedIdentifier), - _ if token.is_used_keyword() => Some(TokenDescriptionKind::Keyword), - _ if token.is_unused_keyword() => Some(TokenDescriptionKind::ReservedKeyword), - token::DocComment(..) => Some(TokenDescriptionKind::DocComment), - _ => None, - }; - let name = pprust::token_to_string(token).to_string(); - - TokenDescription { kind, name } +impl TokenDescription { + pub fn from_token(token: &Token) -> Option { + match token.kind { + _ if token.is_special_ident() => Some(TokenDescription::ReservedIdentifier), + _ if token.is_used_keyword() => Some(TokenDescription::Keyword), + _ if token.is_unused_keyword() => Some(TokenDescription::ReservedKeyword), + token::DocComment(..) => Some(TokenDescription::DocComment), + _ => None, + } + } } pub(super) fn token_descr(token: &Token) -> String { - let TokenDescription { kind, name } = token_descr_struct(token); + let name = pprust::token_to_string(token).to_string(); - let kind = kind.map(|kind| match kind { - TokenDescriptionKind::ReservedIdentifier => "reserved identifier", - TokenDescriptionKind::Keyword => "keyword", - TokenDescriptionKind::ReservedKeyword => "reserved keyword", - TokenDescriptionKind::DocComment => "doc comment", + let kind = TokenDescription::from_token(token).map(|kind| match kind { + TokenDescription::ReservedIdentifier => "reserved identifier", + TokenDescription::Keyword => "keyword", + TokenDescription::ReservedKeyword => "reserved keyword", + TokenDescription::DocComment => "doc comment", }); if let Some(kind) = kind { format!("{} `{}`", kind, name) } else { format!("`{}`", name) } From 8a96884981c97c4c35e304004290271308a67637 Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Tue, 27 Sep 2022 20:56:05 +0200 Subject: [PATCH 344/586] Flush delayed bugs before codegen Sometimes it can happen that invalid code like a TyKind::Error makes its way through the compiler without triggering any errors (this is always a bug in rustc but bugs do happen sometimes :)). These ICEs will manifest in the backend like as cg_llvm not being able to get the layout of `[type error]`, which makes it hard to debug. By flushing before codegen, we display all the delayed bugs, making it easier to trace it to the root of the problem. --- compiler/rustc_errors/src/lib.rs | 6 ++++++ compiler/rustc_interface/src/queries.rs | 2 ++ 2 files changed, 8 insertions(+) diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 4d262ae0f5ec8..b4e99225f811f 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -1133,6 +1133,12 @@ impl Handler { ); std::mem::take(&mut self.inner.borrow_mut().fulfilled_expectations) } + + pub fn flush_delayed(&self) { + let mut inner = self.inner.lock(); + let bugs = std::mem::replace(&mut inner.delayed_span_bugs, Vec::new()); + inner.flush_delayed(bugs, "no errors encountered even though `delay_span_bug` issued"); + } } impl HandlerInner { diff --git a/compiler/rustc_interface/src/queries.rs b/compiler/rustc_interface/src/queries.rs index 6c725a01b5315..60ed48d89886f 100644 --- a/compiler/rustc_interface/src/queries.rs +++ b/compiler/rustc_interface/src/queries.rs @@ -246,6 +246,8 @@ impl<'tcx> Queries<'tcx> { // Don't do code generation if there were any errors self.session().compile_status()?; + self.session().diagnostic().flush_delayed(); + // Hook for UI tests. Self::check_for_rustc_errors_attr(tcx); From dd69ce3b27332c771f61f5cd7cc983424183aaa4 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Tue, 27 Sep 2022 20:29:24 +0200 Subject: [PATCH 345/586] Bless stats. --- src/test/ui/stats/hir-stats.stderr | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/test/ui/stats/hir-stats.stderr b/src/test/ui/stats/hir-stats.stderr index 8d97760653081..8fe84bf776fae 100644 --- a/src/test/ui/stats/hir-stats.stderr +++ b/src/test/ui/stats/hir-stats.stderr @@ -140,11 +140,11 @@ hir-stats - Expr 32 ( 0.3%) 1 hir-stats FnDecl 120 ( 1.2%) 3 40 hir-stats Attribute 128 ( 1.3%) 4 32 hir-stats GenericArgs 144 ( 1.5%) 3 48 -hir-stats Variant 160 ( 1.7%) 2 80 -hir-stats WherePredicate 168 ( 1.7%) 3 56 -hir-stats - BoundPredicate 168 ( 1.7%) 3 +hir-stats Variant 160 ( 1.6%) 2 80 hir-stats GenericBound 192 ( 2.0%) 4 48 hir-stats - Trait 192 ( 2.0%) 4 +hir-stats WherePredicate 192 ( 2.0%) 3 64 +hir-stats - BoundPredicate 192 ( 2.0%) 3 hir-stats Block 288 ( 3.0%) 6 48 hir-stats Pat 360 ( 3.7%) 5 72 hir-stats - Wild 72 ( 0.7%) 1 @@ -169,10 +169,10 @@ hir-stats - Enum 80 ( 0.8%) 1 hir-stats - ExternCrate 80 ( 0.8%) 1 hir-stats - ForeignMod 80 ( 0.8%) 1 hir-stats - Impl 80 ( 0.8%) 1 -hir-stats - Fn 160 ( 1.7%) 2 +hir-stats - Fn 160 ( 1.6%) 2 hir-stats - Use 400 ( 4.1%) 5 -hir-stats Path 1_536 (15.9%) 32 48 +hir-stats Path 1_536 (15.8%) 32 48 hir-stats PathSegment 2_240 (23.1%) 40 56 hir-stats ---------------------------------------------------------------- -hir-stats Total 9_680 +hir-stats Total 9_704 hir-stats From a63a03dc5442b604cb58ce2aafd2a051072e623f Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Tue, 27 Sep 2022 12:27:04 -0700 Subject: [PATCH 346/586] rustdoc: remove `clean::TraitWithExtraInfo` Instead, it gathers the extra info later, when it's actually requested. --- src/librustdoc/clean/inline.rs | 4 ---- src/librustdoc/clean/types.rs | 14 +++++--------- src/librustdoc/core.rs | 8 +++----- src/librustdoc/fold.rs | 2 +- src/librustdoc/formats/cache.rs | 11 +++-------- src/librustdoc/html/render/mod.rs | 11 ++++++++--- src/librustdoc/json/mod.rs | 1 - src/librustdoc/visit.rs | 2 +- 8 files changed, 21 insertions(+), 32 deletions(-) diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index c8aa51c3a49a3..7893429f26f80 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -718,10 +718,6 @@ pub(crate) fn record_extern_trait(cx: &mut DocContext<'_>, did: DefId) { debug!("record_extern_trait: {:?}", did); let trait_ = build_external_trait(cx, did); - let trait_ = clean::TraitWithExtraInfo { - trait_, - is_notable: clean::utils::has_doc_flag(cx.tcx, did, sym::notable_trait), - }; cx.external_traits.borrow_mut().insert(did, trait_); cx.active_extern_traits.remove(&did); } diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index e53e93c4defb1..1e63d0e46bde1 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -37,7 +37,7 @@ use crate::clean::cfg::Cfg; use crate::clean::clean_visibility; use crate::clean::external_path; use crate::clean::inline::{self, print_inlined_const}; -use crate::clean::utils::{is_literal_expr, print_const_expr, print_evaluated_const}; +use crate::clean::utils::{has_doc_flag, is_literal_expr, print_const_expr, print_evaluated_const}; use crate::core::DocContext; use crate::formats::cache::Cache; use crate::formats::item_type::ItemType; @@ -119,7 +119,7 @@ pub(crate) struct Crate { pub(crate) module: Item, pub(crate) primitives: ThinVec<(DefId, PrimitiveType)>, /// Only here so that they can be filtered through the rustdoc passes. - pub(crate) external_traits: Rc>>, + pub(crate) external_traits: Rc>>, } impl Crate { @@ -132,13 +132,6 @@ impl Crate { } } -/// This struct is used to wrap additional information added by rustdoc on a `trait` item. -#[derive(Clone, Debug)] -pub(crate) struct TraitWithExtraInfo { - pub(crate) trait_: Trait, - pub(crate) is_notable: bool, -} - #[derive(Copy, Clone, Debug)] pub(crate) struct ExternalCrate { pub(crate) crate_num: CrateNum, @@ -1530,6 +1523,9 @@ impl Trait { pub(crate) fn is_auto(&self, tcx: TyCtxt<'_>) -> bool { tcx.trait_is_auto(self.def_id) } + pub(crate) fn is_notable_trait(&self, tcx: TyCtxt<'_>) -> bool { + has_doc_flag(tcx, self.def_id, sym::notable_trait) + } pub(crate) fn unsafety(&self, tcx: TyCtxt<'_>) -> hir::Unsafety { tcx.trait_def(self.def_id).unsafety } diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 09a26cbac3e49..f00dff9828dd2 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -25,7 +25,7 @@ use std::rc::Rc; use std::sync::LazyLock; use crate::clean::inline::build_external_trait; -use crate::clean::{self, ItemId, TraitWithExtraInfo}; +use crate::clean::{self, ItemId}; use crate::config::{Options as RustdocOptions, OutputFormat, RenderOptions}; use crate::formats::cache::Cache; use crate::passes::collect_intra_doc_links::PreprocessedMarkdownLink; @@ -58,7 +58,7 @@ pub(crate) struct DocContext<'tcx> { /// Most of this logic is copied from rustc_lint::late. pub(crate) param_env: ParamEnv<'tcx>, /// Later on moved through `clean::Crate` into `cache` - pub(crate) external_traits: Rc>>, + pub(crate) external_traits: Rc>>, /// Used while populating `external_traits` to ensure we don't process the same trait twice at /// the same time. pub(crate) active_extern_traits: FxHashSet, @@ -388,9 +388,7 @@ pub(crate) fn run_global_ctxt( // Note that in case of `#![no_core]`, the trait is not available. if let Some(sized_trait_did) = ctxt.tcx.lang_items().sized_trait() { let sized_trait = build_external_trait(&mut ctxt, sized_trait_did); - ctxt.external_traits - .borrow_mut() - .insert(sized_trait_did, TraitWithExtraInfo { trait_: sized_trait, is_notable: false }); + ctxt.external_traits.borrow_mut().insert(sized_trait_did, sized_trait); } debug!("crate: {:?}", tcx.hir().krate()); diff --git a/src/librustdoc/fold.rs b/src/librustdoc/fold.rs index ed702f5c4a9cc..c6f1f9de51a49 100644 --- a/src/librustdoc/fold.rs +++ b/src/librustdoc/fold.rs @@ -94,7 +94,7 @@ pub(crate) trait DocFolder: Sized { let external_traits = { std::mem::take(&mut *c.external_traits.borrow_mut()) }; for (k, mut v) in external_traits { - v.trait_.items = v.trait_.items.into_iter().filter_map(|i| self.fold_item(i)).collect(); + v.items = v.items.into_iter().filter_map(|i| self.fold_item(i)).collect(); c.external_traits.borrow_mut().insert(k, v); } diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs index 86392610d2c28..2e428cfddcf0a 100644 --- a/src/librustdoc/formats/cache.rs +++ b/src/librustdoc/formats/cache.rs @@ -4,7 +4,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_hir::def_id::{CrateNum, DefId}; use rustc_middle::middle::privacy::AccessLevels; use rustc_middle::ty::{self, TyCtxt}; -use rustc_span::{sym, Symbol}; +use rustc_span::Symbol; use crate::clean::{self, types::ExternalLocation, ExternalCrate, ItemId, PrimitiveType}; use crate::core::DocContext; @@ -62,7 +62,7 @@ pub(crate) struct Cache { /// Implementations of a crate should inherit the documentation of the /// parent trait if no extra documentation is specified, and default methods /// should show up in documentation about trait implementations. - pub(crate) traits: FxHashMap, + pub(crate) traits: FxHashMap, /// When rendering traits, it's often useful to be able to list all /// implementors of the trait, and this mapping is exactly, that: a mapping @@ -225,12 +225,7 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> { // Propagate a trait method's documentation to all implementors of the // trait. if let clean::TraitItem(ref t) = *item.kind { - self.cache.traits.entry(item.item_id.expect_def_id()).or_insert_with(|| { - clean::TraitWithExtraInfo { - trait_: *t.clone(), - is_notable: item.attrs.has_doc_flag(sym::notable_trait), - } - }); + self.cache.traits.entry(item.item_id.expect_def_id()).or_insert_with(|| (**t).clone()); } // Collect all the implementors of traits. diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 75ac11a3a886e..aa9788fad2b6c 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -1294,7 +1294,12 @@ fn notable_traits_decl(decl: &clean::FnDecl, cx: &Context<'_>) -> String { if let Some(trait_) = &impl_.trait_ { let trait_did = trait_.def_id(); - if cx.cache().traits.get(&trait_did).map_or(false, |t| t.is_notable) { + if cx + .cache() + .traits + .get(&trait_did) + .map_or(false, |t| t.is_notable_trait(cx.tcx())) + { if out.is_empty() { write!( &mut out, @@ -1598,7 +1603,7 @@ fn render_impl( link, render_mode, false, - trait_.map(|t| &t.trait_), + trait_, rendering_params, ); } @@ -1658,7 +1663,7 @@ fn render_impl( &mut default_impl_items, &mut impl_items, cx, - &t.trait_, + t, i.inner_impl(), &i.impl_item, parent, diff --git a/src/librustdoc/json/mod.rs b/src/librustdoc/json/mod.rs index 8d6450838c1d0..d13efe6c113be 100644 --- a/src/librustdoc/json/mod.rs +++ b/src/librustdoc/json/mod.rs @@ -108,7 +108,6 @@ impl<'tcx> JsonRenderer<'tcx> { .filter_map(|(&id, trait_item)| { // only need to synthesize items for external traits if !id.is_local() { - let trait_item = &trait_item.trait_; for item in &trait_item.items { trace!("Adding subitem to {id:?}: {:?}", item.item_id); self.item(item.clone()).unwrap(); diff --git a/src/librustdoc/visit.rs b/src/librustdoc/visit.rs index c40274394f344..d29ceead4f3a5 100644 --- a/src/librustdoc/visit.rs +++ b/src/librustdoc/visit.rs @@ -65,7 +65,7 @@ pub(crate) trait DocVisitor: Sized { // FIXME: make this a simple by-ref for loop once external_traits is cleaned up let external_traits = { std::mem::take(&mut *c.external_traits.borrow_mut()) }; for (k, v) in external_traits { - v.trait_.items.iter().for_each(|i| self.visit_item(i)); + v.items.iter().for_each(|i| self.visit_item(i)); c.external_traits.borrow_mut().insert(k, v); } } From c4c94151321b8018ceb06ccff359109b8fed6bfe Mon Sep 17 00:00:00 2001 From: mejrs <> Date: Mon, 26 Sep 2022 00:55:35 +0200 Subject: [PATCH 347/586] Wrapper suggestions --- .../src/check/method/suggest.rs | 213 ++++++++++++------ compiler/rustc_span/src/symbol.rs | 2 + library/core/src/cell.rs | 1 + library/std/src/thread/local.rs | 1 + src/test/ui/suggestions/inner_type.fixed | 30 +++ src/test/ui/suggestions/inner_type.rs | 30 +++ src/test/ui/suggestions/inner_type.stderr | 51 +++++ src/test/ui/suggestions/inner_type2.rs | 26 +++ src/test/ui/suggestions/inner_type2.stderr | 29 +++ 9 files changed, 316 insertions(+), 67 deletions(-) create mode 100644 src/test/ui/suggestions/inner_type.fixed create mode 100644 src/test/ui/suggestions/inner_type.rs create mode 100644 src/test/ui/suggestions/inner_type.stderr create mode 100644 src/test/ui/suggestions/inner_type2.rs create mode 100644 src/test/ui/suggestions/inner_type2.stderr diff --git a/compiler/rustc_hir_analysis/src/check/method/suggest.rs b/compiler/rustc_hir_analysis/src/check/method/suggest.rs index 0e77ed0a4fe28..1ff2575bcc5dd 100644 --- a/compiler/rustc_hir_analysis/src/check/method/suggest.rs +++ b/compiler/rustc_hir_analysis/src/check/method/suggest.rs @@ -2,6 +2,7 @@ //! found or is otherwise invalid. use crate::check::FnCtxt; +use rustc_ast::ast::Mutability; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::{ pluralize, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, @@ -30,7 +31,7 @@ use rustc_trait_selection::traits::{ use std::cmp::Ordering; use std::iter; -use super::probe::{IsSuggestion, Mode, ProbeScope}; +use super::probe::{AutorefOrPtrAdjustment, IsSuggestion, Mode, ProbeScope}; use super::{CandidateSource, MethodError, NoMatchData}; impl<'a, 'tcx> FnCtxt<'a, 'tcx> { @@ -983,7 +984,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.check_for_field_method(&mut err, source, span, actual, item_name); } - self.check_for_unwrap_self(&mut err, source, span, actual, item_name); + self.check_for_inner_self(&mut err, source, span, actual, item_name); bound_spans.sort(); bound_spans.dedup(); @@ -1395,7 +1396,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - fn check_for_unwrap_self( + fn check_for_inner_self( &self, err: &mut Diagnostic, source: SelfSource<'tcx>, @@ -1408,81 +1409,159 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let call_expr = tcx.hir().expect_expr(tcx.hir().get_parent_node(expr.hir_id)); let ty::Adt(kind, substs) = actual.kind() else { return; }; - if !kind.is_enum() { - return; - } + match kind.adt_kind() { + ty::AdtKind::Enum => { + let matching_variants: Vec<_> = kind + .variants() + .iter() + .flat_map(|variant| { + let [field] = &variant.fields[..] else { return None; }; + let field_ty = field.ty(tcx, substs); + + // Skip `_`, since that'll just lead to ambiguity. + if self.resolve_vars_if_possible(field_ty).is_ty_var() { + return None; + } - let matching_variants: Vec<_> = kind - .variants() - .iter() - .flat_map(|variant| { - let [field] = &variant.fields[..] else { return None; }; - let field_ty = field.ty(tcx, substs); + self.lookup_probe( + span, + item_name, + field_ty, + call_expr, + ProbeScope::AllTraits, + ) + .ok() + .map(|pick| (variant, field, pick)) + }) + .collect(); + + let ret_ty_matches = |diagnostic_item| { + if let Some(ret_ty) = self + .ret_coercion + .as_ref() + .map(|c| self.resolve_vars_if_possible(c.borrow().expected_ty())) + && let ty::Adt(kind, _) = ret_ty.kind() + && tcx.get_diagnostic_item(diagnostic_item) == Some(kind.did()) + { + true + } else { + false + } + }; - // Skip `_`, since that'll just lead to ambiguity. - if self.resolve_vars_if_possible(field_ty).is_ty_var() { - return None; + match &matching_variants[..] { + [(_, field, pick)] => { + let self_ty = field.ty(tcx, substs); + err.span_note( + tcx.def_span(pick.item.def_id), + &format!("the method `{item_name}` exists on the type `{self_ty}`"), + ); + let (article, kind, variant, question) = + if tcx.is_diagnostic_item(sym::Result, kind.did()) { + ("a", "Result", "Err", ret_ty_matches(sym::Result)) + } else if tcx.is_diagnostic_item(sym::Option, kind.did()) { + ("an", "Option", "None", ret_ty_matches(sym::Option)) + } else { + return; + }; + if question { + err.span_suggestion_verbose( + expr.span.shrink_to_hi(), + format!( + "use the `?` operator to extract the `{self_ty}` value, propagating \ + {article} `{kind}::{variant}` value to the caller" + ), + "?", + Applicability::MachineApplicable, + ); + } else { + err.span_suggestion_verbose( + expr.span.shrink_to_hi(), + format!( + "consider using `{kind}::expect` to unwrap the `{self_ty}` value, \ + panicking if the value is {article} `{kind}::{variant}`" + ), + ".expect(\"REASON\")", + Applicability::HasPlaceholders, + ); + } + } + // FIXME(compiler-errors): Support suggestions for other matching enum variants + _ => {} } - - self.lookup_probe(span, item_name, field_ty, call_expr, ProbeScope::AllTraits) - .ok() - .map(|pick| (variant, field, pick)) - }) - .collect(); - - let ret_ty_matches = |diagnostic_item| { - if let Some(ret_ty) = self - .ret_coercion - .as_ref() - .map(|c| self.resolve_vars_if_possible(c.borrow().expected_ty())) - && let ty::Adt(kind, _) = ret_ty.kind() - && tcx.get_diagnostic_item(diagnostic_item) == Some(kind.did()) - { - true - } else { - false } - }; - - match &matching_variants[..] { - [(_, field, pick)] => { - let self_ty = field.ty(tcx, substs); - err.span_note( - tcx.def_span(pick.item.def_id), - &format!("the method `{item_name}` exists on the type `{self_ty}`"), - ); - let (article, kind, variant, question) = - if Some(kind.did()) == tcx.get_diagnostic_item(sym::Result) { - ("a", "Result", "Err", ret_ty_matches(sym::Result)) - } else if Some(kind.did()) == tcx.get_diagnostic_item(sym::Option) { - ("an", "Option", "None", ret_ty_matches(sym::Option)) - } else { - return; - }; - if question { + // Target wrapper types - types that wrap or pretend to wrap another type, + // perhaps this inner type is meant to be called? + ty::AdtKind::Struct | ty::AdtKind::Union => { + let [first] = ***substs else { return; }; + let ty::GenericArgKind::Type(ty) = first.unpack() else { return; }; + let Ok(pick) = self.lookup_probe( + span, + item_name, + ty, + call_expr, + ProbeScope::AllTraits, + ) else { return; }; + + let name = self.ty_to_value_string(actual); + let inner_id = kind.did(); + + if tcx.is_diagnostic_item(sym::LocalKey, inner_id) { + err.help("use `with` or `try_with` to access the contents of threadlocals"); + } else if Some(kind.did()) == tcx.lang_items().maybe_uninit() { + err.help(format!( + "if this `{name}` has been initialized, \ + use one of the `assume_init` methods to access the inner value" + )); + } else if tcx.is_diagnostic_item(sym::RefCell, inner_id) { + match pick.autoref_or_ptr_adjustment { + Some(AutorefOrPtrAdjustment::Autoref { + mutbl: Mutability::Not, .. + }) => { + err.span_suggestion_verbose( + expr.span.shrink_to_hi(), + format!( + "use `.borrow()` to borrow the {ty}, \ + panicking if any outstanding mutable borrows exist." + ), + ".borrow()", + Applicability::MaybeIncorrect, + ); + } + Some(AutorefOrPtrAdjustment::Autoref { + mutbl: Mutability::Mut, .. + }) => { + err.span_suggestion_verbose( + expr.span.shrink_to_hi(), + format!( + "use `.borrow_mut()` to mutably borrow the {ty}, \ + panicking if any outstanding borrows exist." + ), + ".borrow_mut()", + Applicability::MaybeIncorrect, + ); + } + _ => return, + } + } else if tcx.is_diagnostic_item(sym::Mutex, inner_id) { err.span_suggestion_verbose( expr.span.shrink_to_hi(), format!( - "use the `?` operator to extract the `{self_ty}` value, propagating \ - {article} `{kind}::{variant}` value to the caller" + "use `.lock()` to borrow the {ty}, \ + blocking the current thread until it can be acquired" ), - "?", - Applicability::MachineApplicable, + ".lock().unwrap()", + Applicability::MaybeIncorrect, ); } else { - err.span_suggestion_verbose( - expr.span.shrink_to_hi(), - format!( - "consider using `{kind}::expect` to unwrap the `{self_ty}` value, \ - panicking if the value is {article} `{kind}::{variant}`" - ), - ".expect(\"REASON\")", - Applicability::HasPlaceholders, - ); - } + return; + }; + + err.span_note( + tcx.def_span(pick.item.def_id), + &format!("the method `{item_name}` exists on the type `{ty}`"), + ); } - // FIXME(compiler-errors): Support suggestions for other matching enum variants - _ => {} } } diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 502ef67fc6767..6101c1c47e380 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -224,6 +224,7 @@ symbols! { Left, LinkedList, LintPass, + LocalKey, Mutex, MutexGuard, N, @@ -266,6 +267,7 @@ symbols! { Rc, Ready, Receiver, + RefCell, Relaxed, Release, Result, diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index 1abbb39497a0f..cf7b1b358c940 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -614,6 +614,7 @@ impl Cell<[T; N]> { /// A mutable memory location with dynamically checked borrow rules /// /// See the [module-level documentation](self) for more. +#[rustc_diagnostic_item = "RefCell"] #[stable(feature = "rust1", since = "1.0.0")] pub struct RefCell { borrow: Cell, diff --git a/library/std/src/thread/local.rs b/library/std/src/thread/local.rs index 8aedfc4a6b819..1d728349951bf 100644 --- a/library/std/src/thread/local.rs +++ b/library/std/src/thread/local.rs @@ -95,6 +95,7 @@ use crate::fmt; /// [loader lock]: https://docs.microsoft.com/en-us/windows/win32/dlls/dynamic-link-library-best-practices /// [`JoinHandle::join`]: crate::thread::JoinHandle::join /// [`with`]: LocalKey::with +#[rustc_diagnostic_item = "LocalKey"] #[stable(feature = "rust1", since = "1.0.0")] pub struct LocalKey { // This outer `LocalKey` type is what's going to be stored in statics, diff --git a/src/test/ui/suggestions/inner_type.fixed b/src/test/ui/suggestions/inner_type.fixed new file mode 100644 index 0000000000000..f6dc7c4ce1722 --- /dev/null +++ b/src/test/ui/suggestions/inner_type.fixed @@ -0,0 +1,30 @@ +// compile-flags: --edition=2021 +// run-rustfix + +pub struct Struct { + pub p: T, +} + +impl Struct { + pub fn method(&self) {} + + pub fn some_mutable_method(&mut self) {} +} + +fn main() { + let other_item = std::cell::RefCell::new(Struct { p: 42_u32 }); + + other_item.borrow().method(); + //~^ ERROR no method named `method` found for struct `RefCell` in the current scope [E0599] + //~| HELP use `.borrow()` to borrow the Struct, panicking if any outstanding mutable borrows exist. + + other_item.borrow_mut().some_mutable_method(); + //~^ ERROR no method named `some_mutable_method` found for struct `RefCell` in the current scope [E0599] + //~| HELP use `.borrow_mut()` to mutably borrow the Struct, panicking if any outstanding borrows exist. + + let another_item = std::sync::Mutex::new(Struct { p: 42_u32 }); + + another_item.lock().unwrap().method(); + //~^ ERROR no method named `method` found for struct `Mutex` in the current scope [E0599] + //~| HELP use `.lock()` to borrow the Struct, blocking the current thread until it can be acquired +} \ No newline at end of file diff --git a/src/test/ui/suggestions/inner_type.rs b/src/test/ui/suggestions/inner_type.rs new file mode 100644 index 0000000000000..b42067c047c04 --- /dev/null +++ b/src/test/ui/suggestions/inner_type.rs @@ -0,0 +1,30 @@ +// compile-flags: --edition=2021 +// run-rustfix + +pub struct Struct { + pub p: T, +} + +impl Struct { + pub fn method(&self) {} + + pub fn some_mutable_method(&mut self) {} +} + +fn main() { + let other_item = std::cell::RefCell::new(Struct { p: 42_u32 }); + + other_item.method(); + //~^ ERROR no method named `method` found for struct `RefCell` in the current scope [E0599] + //~| HELP use `.borrow()` to borrow the Struct, panicking if any outstanding mutable borrows exist. + + other_item.some_mutable_method(); + //~^ ERROR no method named `some_mutable_method` found for struct `RefCell` in the current scope [E0599] + //~| HELP use `.borrow_mut()` to mutably borrow the Struct, panicking if any outstanding borrows exist. + + let another_item = std::sync::Mutex::new(Struct { p: 42_u32 }); + + another_item.method(); + //~^ ERROR no method named `method` found for struct `Mutex` in the current scope [E0599] + //~| HELP use `.lock()` to borrow the Struct, blocking the current thread until it can be acquired +} \ No newline at end of file diff --git a/src/test/ui/suggestions/inner_type.stderr b/src/test/ui/suggestions/inner_type.stderr new file mode 100644 index 0000000000000..f2b25944c8b2d --- /dev/null +++ b/src/test/ui/suggestions/inner_type.stderr @@ -0,0 +1,51 @@ +error[E0599]: no method named `method` found for struct `RefCell` in the current scope + --> $DIR/inner_type.rs:17:16 + | +LL | other_item.method(); + | ^^^^^^ method not found in `RefCell>` + | +note: the method `method` exists on the type `Struct` + --> $DIR/inner_type.rs:9:5 + | +LL | pub fn method(&self) {} + | ^^^^^^^^^^^^^^^^^^^^ +help: use `.borrow()` to borrow the Struct, panicking if any outstanding mutable borrows exist. + | +LL | other_item.borrow().method(); + | +++++++++ + +error[E0599]: no method named `some_mutable_method` found for struct `RefCell` in the current scope + --> $DIR/inner_type.rs:21:16 + | +LL | other_item.some_mutable_method(); + | ^^^^^^^^^^^^^^^^^^^ method not found in `RefCell>` + | +note: the method `some_mutable_method` exists on the type `Struct` + --> $DIR/inner_type.rs:11:5 + | +LL | pub fn some_mutable_method(&mut self) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: use `.borrow_mut()` to mutably borrow the Struct, panicking if any outstanding borrows exist. + | +LL | other_item.borrow_mut().some_mutable_method(); + | +++++++++++++ + +error[E0599]: no method named `method` found for struct `Mutex` in the current scope + --> $DIR/inner_type.rs:27:18 + | +LL | another_item.method(); + | ^^^^^^ method not found in `Mutex>` + | +note: the method `method` exists on the type `Struct` + --> $DIR/inner_type.rs:9:5 + | +LL | pub fn method(&self) {} + | ^^^^^^^^^^^^^^^^^^^^ +help: use `.lock()` to borrow the Struct, blocking the current thread until it can be acquired + | +LL | another_item.lock().unwrap().method(); + | ++++++++++++++++ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/suggestions/inner_type2.rs b/src/test/ui/suggestions/inner_type2.rs new file mode 100644 index 0000000000000..694c0adfd06c2 --- /dev/null +++ b/src/test/ui/suggestions/inner_type2.rs @@ -0,0 +1,26 @@ +pub struct Struct { + pub p: T, +} + +impl Struct { + pub fn method(&self) {} + + pub fn some_mutable_method(&mut self) {} +} + +thread_local! { + static STRUCT: Struct = Struct { + p: 42_u32 + }; +} + +fn main() { + STRUCT.method(); + //~^ ERROR no method named `method` found for struct `LocalKey` in the current scope [E0599] + //~| HELP use `with` or `try_with` to access the contents of threadlocals + + let item = std::mem::MaybeUninit::new(Struct { p: 42_u32 }); + item.method(); + //~^ ERROR no method named `method` found for union `MaybeUninit` in the current scope [E0599] + //~| HELP if this `MaybeUninit::>` has been initialized, use one of the `assume_init` methods to access the inner value +} \ No newline at end of file diff --git a/src/test/ui/suggestions/inner_type2.stderr b/src/test/ui/suggestions/inner_type2.stderr new file mode 100644 index 0000000000000..40e7a7ab41e44 --- /dev/null +++ b/src/test/ui/suggestions/inner_type2.stderr @@ -0,0 +1,29 @@ +error[E0599]: no method named `method` found for struct `LocalKey` in the current scope + --> $DIR/inner_type2.rs:18:12 + | +LL | STRUCT.method(); + | ^^^^^^ method not found in `LocalKey>` + | + = help: use `with` or `try_with` to access the contents of threadlocals +note: the method `method` exists on the type `Struct` + --> $DIR/inner_type2.rs:6:5 + | +LL | pub fn method(&self) {} + | ^^^^^^^^^^^^^^^^^^^^ + +error[E0599]: no method named `method` found for union `MaybeUninit` in the current scope + --> $DIR/inner_type2.rs:23:10 + | +LL | item.method(); + | ^^^^^^ method not found in `MaybeUninit>` + | + = help: if this `MaybeUninit::>` has been initialized, use one of the `assume_init` methods to access the inner value +note: the method `method` exists on the type `Struct` + --> $DIR/inner_type2.rs:6:5 + | +LL | pub fn method(&self) {} + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0599`. From f3ac328d584b83bb7f0b4faa0f7a5699151b3ce9 Mon Sep 17 00:00:00 2001 From: mejrs <> Date: Tue, 27 Sep 2022 13:06:31 +0200 Subject: [PATCH 348/586] Address feedback --- .../src/check/method/suggest.rs | 61 ++++++++++++++----- compiler/rustc_span/src/symbol.rs | 1 + library/core/src/cell.rs | 2 +- library/std/src/sync/rwlock.rs | 1 + library/std/src/thread/local.rs | 2 +- src/test/ui/suggestions/inner_type.fixed | 16 ++++- src/test/ui/suggestions/inner_type.rs | 16 ++++- src/test/ui/suggestions/inner_type.stderr | 40 ++++++++++-- src/test/ui/suggestions/inner_type2.rs | 2 +- src/test/ui/suggestions/inner_type2.stderr | 2 +- 10 files changed, 113 insertions(+), 30 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/check/method/suggest.rs b/compiler/rustc_hir_analysis/src/check/method/suggest.rs index 1ff2575bcc5dd..c43dc8c134dd3 100644 --- a/compiler/rustc_hir_analysis/src/check/method/suggest.rs +++ b/compiler/rustc_hir_analysis/src/check/method/suggest.rs @@ -1428,7 +1428,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { item_name, field_ty, call_expr, - ProbeScope::AllTraits, + ProbeScope::TraitsInScope, ) .ok() .map(|pick| (variant, field, pick)) @@ -1500,59 +1500,88 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { item_name, ty, call_expr, - ProbeScope::AllTraits, + ProbeScope::TraitsInScope, ) else { return; }; let name = self.ty_to_value_string(actual); let inner_id = kind.did(); + let mutable = if let Some(AutorefOrPtrAdjustment::Autoref { mutbl, .. }) = + pick.autoref_or_ptr_adjustment + { + Some(mutbl) + } else { + None + }; if tcx.is_diagnostic_item(sym::LocalKey, inner_id) { - err.help("use `with` or `try_with` to access the contents of threadlocals"); + err.help("use `with` or `try_with` to access thread local storage"); } else if Some(kind.did()) == tcx.lang_items().maybe_uninit() { err.help(format!( "if this `{name}` has been initialized, \ use one of the `assume_init` methods to access the inner value" )); } else if tcx.is_diagnostic_item(sym::RefCell, inner_id) { - match pick.autoref_or_ptr_adjustment { - Some(AutorefOrPtrAdjustment::Autoref { - mutbl: Mutability::Not, .. - }) => { + match mutable { + Some(Mutability::Not) => { err.span_suggestion_verbose( expr.span.shrink_to_hi(), format!( - "use `.borrow()` to borrow the {ty}, \ - panicking if any outstanding mutable borrows exist." + "use `.borrow()` to borrow the `{ty}`, \ + panicking if any outstanding mutable borrows exist." ), ".borrow()", Applicability::MaybeIncorrect, ); } - Some(AutorefOrPtrAdjustment::Autoref { - mutbl: Mutability::Mut, .. - }) => { + Some(Mutability::Mut) => { err.span_suggestion_verbose( expr.span.shrink_to_hi(), format!( - "use `.borrow_mut()` to mutably borrow the {ty}, \ - panicking if any outstanding borrows exist." + "use `.borrow_mut()` to mutably borrow the `{ty}`, \ + panicking if any outstanding borrows exist." ), ".borrow_mut()", Applicability::MaybeIncorrect, ); } - _ => return, + None => return, } } else if tcx.is_diagnostic_item(sym::Mutex, inner_id) { err.span_suggestion_verbose( expr.span.shrink_to_hi(), format!( - "use `.lock()` to borrow the {ty}, \ + "use `.lock()` to borrow the `{ty}`, \ blocking the current thread until it can be acquired" ), ".lock().unwrap()", Applicability::MaybeIncorrect, ); + } else if tcx.is_diagnostic_item(sym::RwLock, inner_id) { + match mutable { + Some(Mutability::Not) => { + err.span_suggestion_verbose( + expr.span.shrink_to_hi(), + format!( + "use `.read()` to borrow the `{ty}`, \ + blocking the current thread until it can be acquired" + ), + ".read().unwrap()", + Applicability::MaybeIncorrect, + ); + } + Some(Mutability::Mut) => { + err.span_suggestion_verbose( + expr.span.shrink_to_hi(), + format!( + "use `.write()` to mutably borrow the `{ty}`, \ + blocking the current thread until it can be acquired" + ), + ".write().unwrap()", + Applicability::MaybeIncorrect, + ); + } + None => return, + } } else { return; }; diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 6101c1c47e380..67ffc573b990a 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -276,6 +276,7 @@ symbols! { Rust, RustcDecodable, RustcEncodable, + RwLock, RwLockReadGuard, RwLockWriteGuard, Send, diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index cf7b1b358c940..288cab1ef3994 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -614,7 +614,7 @@ impl Cell<[T; N]> { /// A mutable memory location with dynamically checked borrow rules /// /// See the [module-level documentation](self) for more. -#[rustc_diagnostic_item = "RefCell"] +#[cfg_attr(not(test), rustc_diagnostic_item = "RefCell")] #[stable(feature = "rust1", since = "1.0.0")] pub struct RefCell { borrow: Cell, diff --git a/library/std/src/sync/rwlock.rs b/library/std/src/sync/rwlock.rs index 9ab781561e9b1..ee2c79b6669b8 100644 --- a/library/std/src/sync/rwlock.rs +++ b/library/std/src/sync/rwlock.rs @@ -76,6 +76,7 @@ use crate::sys_common::rwlock as sys; /// /// [`Mutex`]: super::Mutex #[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(not(test), rustc_diagnostic_item = "RwLock")] pub struct RwLock { inner: sys::MovableRwLock, poison: poison::Flag, diff --git a/library/std/src/thread/local.rs b/library/std/src/thread/local.rs index 1d728349951bf..ffd17dc99093a 100644 --- a/library/std/src/thread/local.rs +++ b/library/std/src/thread/local.rs @@ -95,7 +95,7 @@ use crate::fmt; /// [loader lock]: https://docs.microsoft.com/en-us/windows/win32/dlls/dynamic-link-library-best-practices /// [`JoinHandle::join`]: crate::thread::JoinHandle::join /// [`with`]: LocalKey::with -#[rustc_diagnostic_item = "LocalKey"] +#[cfg_attr(not(test), rustc_diagnostic_item = "LocalKey")] #[stable(feature = "rust1", since = "1.0.0")] pub struct LocalKey { // This outer `LocalKey` type is what's going to be stored in statics, diff --git a/src/test/ui/suggestions/inner_type.fixed b/src/test/ui/suggestions/inner_type.fixed index f6dc7c4ce1722..327bf7caa7257 100644 --- a/src/test/ui/suggestions/inner_type.fixed +++ b/src/test/ui/suggestions/inner_type.fixed @@ -16,15 +16,25 @@ fn main() { other_item.borrow().method(); //~^ ERROR no method named `method` found for struct `RefCell` in the current scope [E0599] - //~| HELP use `.borrow()` to borrow the Struct, panicking if any outstanding mutable borrows exist. + //~| HELP use `.borrow()` to borrow the `Struct`, panicking if any outstanding mutable borrows exist. other_item.borrow_mut().some_mutable_method(); //~^ ERROR no method named `some_mutable_method` found for struct `RefCell` in the current scope [E0599] - //~| HELP use `.borrow_mut()` to mutably borrow the Struct, panicking if any outstanding borrows exist. + //~| HELP use `.borrow_mut()` to mutably borrow the `Struct`, panicking if any outstanding borrows exist. let another_item = std::sync::Mutex::new(Struct { p: 42_u32 }); another_item.lock().unwrap().method(); //~^ ERROR no method named `method` found for struct `Mutex` in the current scope [E0599] - //~| HELP use `.lock()` to borrow the Struct, blocking the current thread until it can be acquired + //~| HELP use `.lock()` to borrow the `Struct`, blocking the current thread until it can be acquired + + let another_item = std::sync::RwLock::new(Struct { p: 42_u32 }); + + another_item.read().unwrap().method(); + //~^ ERROR no method named `method` found for struct `RwLock` in the current scope [E0599] + //~| HELP use `.read()` to borrow the `Struct`, blocking the current thread until it can be acquired + + another_item.write().unwrap().some_mutable_method(); + //~^ ERROR no method named `some_mutable_method` found for struct `RwLock` in the current scope [E0599] + //~| HELP use `.write()` to mutably borrow the `Struct`, blocking the current thread until it can be acquired } \ No newline at end of file diff --git a/src/test/ui/suggestions/inner_type.rs b/src/test/ui/suggestions/inner_type.rs index b42067c047c04..a8c1c5d386a1e 100644 --- a/src/test/ui/suggestions/inner_type.rs +++ b/src/test/ui/suggestions/inner_type.rs @@ -16,15 +16,25 @@ fn main() { other_item.method(); //~^ ERROR no method named `method` found for struct `RefCell` in the current scope [E0599] - //~| HELP use `.borrow()` to borrow the Struct, panicking if any outstanding mutable borrows exist. + //~| HELP use `.borrow()` to borrow the `Struct`, panicking if any outstanding mutable borrows exist. other_item.some_mutable_method(); //~^ ERROR no method named `some_mutable_method` found for struct `RefCell` in the current scope [E0599] - //~| HELP use `.borrow_mut()` to mutably borrow the Struct, panicking if any outstanding borrows exist. + //~| HELP use `.borrow_mut()` to mutably borrow the `Struct`, panicking if any outstanding borrows exist. let another_item = std::sync::Mutex::new(Struct { p: 42_u32 }); another_item.method(); //~^ ERROR no method named `method` found for struct `Mutex` in the current scope [E0599] - //~| HELP use `.lock()` to borrow the Struct, blocking the current thread until it can be acquired + //~| HELP use `.lock()` to borrow the `Struct`, blocking the current thread until it can be acquired + + let another_item = std::sync::RwLock::new(Struct { p: 42_u32 }); + + another_item.method(); + //~^ ERROR no method named `method` found for struct `RwLock` in the current scope [E0599] + //~| HELP use `.read()` to borrow the `Struct`, blocking the current thread until it can be acquired + + another_item.some_mutable_method(); + //~^ ERROR no method named `some_mutable_method` found for struct `RwLock` in the current scope [E0599] + //~| HELP use `.write()` to mutably borrow the `Struct`, blocking the current thread until it can be acquired } \ No newline at end of file diff --git a/src/test/ui/suggestions/inner_type.stderr b/src/test/ui/suggestions/inner_type.stderr index f2b25944c8b2d..00d52f0f1d33a 100644 --- a/src/test/ui/suggestions/inner_type.stderr +++ b/src/test/ui/suggestions/inner_type.stderr @@ -9,7 +9,7 @@ note: the method `method` exists on the type `Struct` | LL | pub fn method(&self) {} | ^^^^^^^^^^^^^^^^^^^^ -help: use `.borrow()` to borrow the Struct, panicking if any outstanding mutable borrows exist. +help: use `.borrow()` to borrow the `Struct`, panicking if any outstanding mutable borrows exist. | LL | other_item.borrow().method(); | +++++++++ @@ -25,7 +25,7 @@ note: the method `some_mutable_method` exists on the type `Struct` | LL | pub fn some_mutable_method(&mut self) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -help: use `.borrow_mut()` to mutably borrow the Struct, panicking if any outstanding borrows exist. +help: use `.borrow_mut()` to mutably borrow the `Struct`, panicking if any outstanding borrows exist. | LL | other_item.borrow_mut().some_mutable_method(); | +++++++++++++ @@ -41,11 +41,43 @@ note: the method `method` exists on the type `Struct` | LL | pub fn method(&self) {} | ^^^^^^^^^^^^^^^^^^^^ -help: use `.lock()` to borrow the Struct, blocking the current thread until it can be acquired +help: use `.lock()` to borrow the `Struct`, blocking the current thread until it can be acquired | LL | another_item.lock().unwrap().method(); | ++++++++++++++++ -error: aborting due to 3 previous errors +error[E0599]: no method named `method` found for struct `RwLock` in the current scope + --> $DIR/inner_type.rs:33:18 + | +LL | another_item.method(); + | ^^^^^^ method not found in `RwLock>` + | +note: the method `method` exists on the type `Struct` + --> $DIR/inner_type.rs:9:5 + | +LL | pub fn method(&self) {} + | ^^^^^^^^^^^^^^^^^^^^ +help: use `.read()` to borrow the `Struct`, blocking the current thread until it can be acquired + | +LL | another_item.read().unwrap().method(); + | ++++++++++++++++ + +error[E0599]: no method named `some_mutable_method` found for struct `RwLock` in the current scope + --> $DIR/inner_type.rs:37:18 + | +LL | another_item.some_mutable_method(); + | ^^^^^^^^^^^^^^^^^^^ method not found in `RwLock>` + | +note: the method `some_mutable_method` exists on the type `Struct` + --> $DIR/inner_type.rs:11:5 + | +LL | pub fn some_mutable_method(&mut self) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: use `.write()` to mutably borrow the `Struct`, blocking the current thread until it can be acquired + | +LL | another_item.write().unwrap().some_mutable_method(); + | +++++++++++++++++ + +error: aborting due to 5 previous errors For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/suggestions/inner_type2.rs b/src/test/ui/suggestions/inner_type2.rs index 694c0adfd06c2..8dea8100c289c 100644 --- a/src/test/ui/suggestions/inner_type2.rs +++ b/src/test/ui/suggestions/inner_type2.rs @@ -17,7 +17,7 @@ thread_local! { fn main() { STRUCT.method(); //~^ ERROR no method named `method` found for struct `LocalKey` in the current scope [E0599] - //~| HELP use `with` or `try_with` to access the contents of threadlocals + //~| HELP use `with` or `try_with` to access thread local storage let item = std::mem::MaybeUninit::new(Struct { p: 42_u32 }); item.method(); diff --git a/src/test/ui/suggestions/inner_type2.stderr b/src/test/ui/suggestions/inner_type2.stderr index 40e7a7ab41e44..eddfd9d63409d 100644 --- a/src/test/ui/suggestions/inner_type2.stderr +++ b/src/test/ui/suggestions/inner_type2.stderr @@ -4,7 +4,7 @@ error[E0599]: no method named `method` found for struct `LocalKey` in the curren LL | STRUCT.method(); | ^^^^^^ method not found in `LocalKey>` | - = help: use `with` or `try_with` to access the contents of threadlocals + = help: use `with` or `try_with` to access thread local storage note: the method `method` exists on the type `Struct` --> $DIR/inner_type2.rs:6:5 | From e5776c690328a373ec812471f7a257e6c0920881 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 27 Sep 2022 20:00:24 +0000 Subject: [PATCH 349/586] Use already resolved self_ty in confirm_fn_pointer_candidate --- .../src/traits/select/confirmation.rs | 3 +- src/test/ui/function-pointer/issue-102289.rs | 54 +++++++++++++++++++ 2 files changed, 56 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/function-pointer/issue-102289.rs diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 27fbfb6dd21fb..dd49dcecf77e3 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -626,7 +626,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // the signature, as evidenced by how we treat it during projection. // The safe thing to do here is to liberate it, though, which should // have no worse effect than skipping the binder here. - let liberated_fn_ty = self.infcx.replace_bound_vars_with_placeholders(obligation.self_ty()); + let liberated_fn_ty = + self.infcx.replace_bound_vars_with_placeholders(obligation.predicate.rebind(self_ty)); let output_ty = self .infcx .replace_bound_vars_with_placeholders(liberated_fn_ty.fn_sig(self.tcx()).output()); diff --git a/src/test/ui/function-pointer/issue-102289.rs b/src/test/ui/function-pointer/issue-102289.rs new file mode 100644 index 0000000000000..de394ca9ad6d4 --- /dev/null +++ b/src/test/ui/function-pointer/issue-102289.rs @@ -0,0 +1,54 @@ +// check-pass + +pub(crate) trait Parser: Sized { + type Output; + fn parse(&mut self, _input: &str) -> Result<(), ()> { + loop {} + } + fn map(self, _f: F) -> Map + where + F: FnMut(Self::Output) -> B, + { + todo!() + } +} + +pub(crate) struct Chainl1(P, Op); +impl Parser for Chainl1 +where + P: Parser, + Op: Parser, + Op::Output: FnOnce(P::Output, P::Output) -> P::Output, +{ + type Output = P::Output; +} +pub(crate) fn chainl1(_parser: P, _op: Op) -> Chainl1 +where + P: Parser, + Op: Parser, + Op::Output: FnOnce(P::Output, P::Output) -> P::Output, +{ + loop {} +} + +pub(crate) struct Map(P, F); +impl Parser for Map +where + P: Parser, + F: FnMut(A) -> B, +{ + type Output = B; +} + +impl Parser for u32 { + type Output = (); +} + +pub fn chainl1_error_consume() { + fn first(t: T, _: U) -> T { + t + } + let _ = chainl1(1, 1.map(|_| first)).parse(""); +} + +fn main() {} From e9224b37968f8bf56c0bbac206312ef84dad3b74 Mon Sep 17 00:00:00 2001 From: mejrs <> Date: Tue, 27 Sep 2022 23:12:52 +0200 Subject: [PATCH 350/586] Add newline --- src/test/ui/suggestions/inner_type.fixed | 2 +- src/test/ui/suggestions/inner_type.rs | 2 +- src/test/ui/suggestions/inner_type2.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/test/ui/suggestions/inner_type.fixed b/src/test/ui/suggestions/inner_type.fixed index 327bf7caa7257..811b959b8c04d 100644 --- a/src/test/ui/suggestions/inner_type.fixed +++ b/src/test/ui/suggestions/inner_type.fixed @@ -37,4 +37,4 @@ fn main() { another_item.write().unwrap().some_mutable_method(); //~^ ERROR no method named `some_mutable_method` found for struct `RwLock` in the current scope [E0599] //~| HELP use `.write()` to mutably borrow the `Struct`, blocking the current thread until it can be acquired -} \ No newline at end of file +} diff --git a/src/test/ui/suggestions/inner_type.rs b/src/test/ui/suggestions/inner_type.rs index a8c1c5d386a1e..96c797a6d81d7 100644 --- a/src/test/ui/suggestions/inner_type.rs +++ b/src/test/ui/suggestions/inner_type.rs @@ -37,4 +37,4 @@ fn main() { another_item.some_mutable_method(); //~^ ERROR no method named `some_mutable_method` found for struct `RwLock` in the current scope [E0599] //~| HELP use `.write()` to mutably borrow the `Struct`, blocking the current thread until it can be acquired -} \ No newline at end of file +} diff --git a/src/test/ui/suggestions/inner_type2.rs b/src/test/ui/suggestions/inner_type2.rs index 8dea8100c289c..c56ea7c030d8e 100644 --- a/src/test/ui/suggestions/inner_type2.rs +++ b/src/test/ui/suggestions/inner_type2.rs @@ -23,4 +23,4 @@ fn main() { item.method(); //~^ ERROR no method named `method` found for union `MaybeUninit` in the current scope [E0599] //~| HELP if this `MaybeUninit::>` has been initialized, use one of the `assume_init` methods to access the inner value -} \ No newline at end of file +} From c0245b16baf98f88cba708c19b5a8fc514781b34 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Tue, 27 Sep 2022 14:25:48 -0700 Subject: [PATCH 351/586] rustdoc: remove redundant mobile `.source > .sidebar` CSS When the source sidebar and standard sidebar had most of their code merged in 07e3f998b1ceb4b8d2a7992782e60f5e776aa114, the properties `z-index: 11`, `margin: 0`, and `position: fixed` were already being set on the `.sidebar` class, so no need to repeat them. --- src/librustdoc/html/static/css/rustdoc.css | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index e7a05b80c127f..c4ce599aa559c 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -1770,9 +1770,6 @@ in storage.js plus the media query with (min-width: 701px) } .rustdoc.source > .sidebar { - position: fixed; - margin: 0; - z-index: 11; width: 0; } From fb5002d68aa22f23ced3e2b5265f622264e4840a Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Tue, 27 Sep 2022 15:21:31 -0700 Subject: [PATCH 352/586] Manually order `DefId` on 64-bit big-endian `DefId` uses different field orders on 64-bit big-endian vs. others, in order to optimize its `Hash` implementation. However, that also made it derive different lexical ordering for `PartialOrd` and `Ord`. That caused spurious differences wherever `DefId`s are sorted, like the candidate sources list in `report_method_error`. Now we manually implement `PartialOrd` and `Ord` on 64-bit big-endian to match the same lexical ordering as other targets, fixing at least one test, `src/test/ui/methods/method-ambig-two-traits-cross-crate.rs`. --- compiler/rustc_span/src/def_id.rs | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_span/src/def_id.rs b/compiler/rustc_span/src/def_id.rs index 37b8371a8fe28..bbeabdb55a72a 100644 --- a/compiler/rustc_span/src/def_id.rs +++ b/compiler/rustc_span/src/def_id.rs @@ -218,7 +218,9 @@ impl Decodable for DefIndex { /// index and a def index. /// /// You can create a `DefId` from a `LocalDefId` using `local_def_id.to_def_id()`. -#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Copy)] +#[derive(Clone, PartialEq, Eq, Copy)] +// Don't derive order on 64-bit big-endian, so we can be consistent regardless of field order. +#[cfg_attr(not(all(target_pointer_width = "64", target_endian = "big")), derive(PartialOrd, Ord))] // On below-64 bit systems we can simply use the derived `Hash` impl #[cfg_attr(not(target_pointer_width = "64"), derive(Hash))] #[repr(C)] @@ -260,6 +262,22 @@ impl Hash for DefId { } } +// Implement the same comparison as derived with the other field order. +#[cfg(all(target_pointer_width = "64", target_endian = "big"))] +impl Ord for DefId { + #[inline] + fn cmp(&self, other: &DefId) -> std::cmp::Ordering { + Ord::cmp(&(self.index, self.krate), &(other.index, other.krate)) + } +} +#[cfg(all(target_pointer_width = "64", target_endian = "big"))] +impl PartialOrd for DefId { + #[inline] + fn partial_cmp(&self, other: &DefId) -> Option { + Some(Ord::cmp(self, other)) + } +} + impl DefId { /// Makes a local `DefId` from the given `DefIndex`. #[inline] From 94cb5e86ea50ec878b1a5de9b0b64bb35e8027e3 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 27 Sep 2022 16:32:22 +1000 Subject: [PATCH 353/586] Small cleanups in unescaping code. - Rename `unescape_raw_str_or_raw_byte_str` as `unescape_raw_str_or_byte_str`, which is more accurate. - Remove the unused `Mode::in_single_quotes` method. - Make some assertions more precise, and add a missing one to `unescape_char_or_byte`. - Change all the assertions to `debug_assert!`, because this code is reasonably hot, and the assertions aren't required for memory safety, and any violations are likely to be sufficiently obvious that normal tests will trigger them. --- compiler/rustc_lexer/src/unescape.rs | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_lexer/src/unescape.rs b/compiler/rustc_lexer/src/unescape.rs index 25d5f2772de40..8f64b5f5158e4 100644 --- a/compiler/rustc_lexer/src/unescape.rs +++ b/compiler/rustc_lexer/src/unescape.rs @@ -93,7 +93,7 @@ where // NOTE: Raw strings do not perform any explicit character escaping, here we // only translate CRLF to LF and produce errors on bare CR. Mode::RawStr | Mode::RawByteStr => { - unescape_raw_str_or_byte_str(literal_text, mode, callback) + unescape_raw_str_or_raw_byte_str(literal_text, mode, callback) } } } @@ -105,7 +105,7 @@ pub fn unescape_byte_literal(literal_text: &str, mode: Mode, callback: &mut F where F: FnMut(Range, Result), { - assert!(mode.is_bytes()); + debug_assert!(mode.is_bytes()); unescape_literal(literal_text, mode, &mut |range, result| { callback(range, result.map(byte_from_char)); }) @@ -129,7 +129,7 @@ pub fn unescape_byte(literal_text: &str) -> Result { } /// What kind of literal do we parse. -#[derive(Debug, Clone, Copy)] +#[derive(Debug, Clone, Copy, PartialEq)] pub enum Mode { Char, Str, @@ -140,17 +140,13 @@ pub enum Mode { } impl Mode { - pub fn in_single_quotes(self) -> bool { + pub fn in_double_quotes(self) -> bool { match self { - Mode::Char | Mode::Byte => true, - Mode::Str | Mode::ByteStr | Mode::RawStr | Mode::RawByteStr => false, + Mode::Str | Mode::ByteStr | Mode::RawStr | Mode::RawByteStr => true, + Mode::Char | Mode::Byte => false, } } - pub fn in_double_quotes(self) -> bool { - !self.in_single_quotes() - } - pub fn is_bytes(self) -> bool { match self { Mode::Byte | Mode::ByteStr | Mode::RawByteStr => true, @@ -263,6 +259,7 @@ fn ascii_check(first_char: char, mode: Mode) -> Result { } fn unescape_char_or_byte(chars: &mut Chars<'_>, mode: Mode) -> Result { + debug_assert!(mode == Mode::Char || mode == Mode::Byte); let first_char = chars.next().ok_or(EscapeError::ZeroChars)?; let res = match first_char { '\\' => scan_escape(chars, mode), @@ -282,7 +279,7 @@ fn unescape_str_or_byte_str(src: &str, mode: Mode, callback: &mut F) where F: FnMut(Range, Result), { - assert!(mode.in_double_quotes()); + debug_assert!(mode == Mode::Str || mode == Mode::ByteStr); let initial_len = src.len(); let mut chars = src.chars(); while let Some(first_char) = chars.next() { @@ -344,11 +341,11 @@ where /// sequence of characters or errors. /// NOTE: Raw strings do not perform any explicit character escaping, here we /// only translate CRLF to LF and produce errors on bare CR. -fn unescape_raw_str_or_byte_str(literal_text: &str, mode: Mode, callback: &mut F) +fn unescape_raw_str_or_raw_byte_str(literal_text: &str, mode: Mode, callback: &mut F) where F: FnMut(Range, Result), { - assert!(mode.in_double_quotes()); + debug_assert!(mode == Mode::RawStr || mode == Mode::RawByteStr); let initial_len = literal_text.len(); let mut chars = literal_text.chars(); @@ -368,7 +365,7 @@ where fn byte_from_char(c: char) -> u8 { let res = c as u32; - assert!(res <= u8::MAX as u32, "guaranteed because of Mode::ByteStr"); + debug_assert!(res <= u8::MAX as u32, "guaranteed because of Mode::ByteStr"); res as u8 } From c0d32fd2cc4eafe4f621490e7c44b7af04d1f2be Mon Sep 17 00:00:00 2001 From: Matthew Kelly Date: Tue, 27 Sep 2022 19:23:59 -0400 Subject: [PATCH 354/586] review updates --- compiler/rustc_error_codes/src/error_codes/E0311.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_error_codes/src/error_codes/E0311.md b/compiler/rustc_error_codes/src/error_codes/E0311.md index 768b849817db5..08159d3f469ac 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0311.md +++ b/compiler/rustc_error_codes/src/error_codes/E0311.md @@ -1,5 +1,5 @@ This error occurs when there is an unsatisfied outlives bound involving an -elided region on a generic type parameter or associated type. +elided region and a generic type parameter or associated type. Erroneous code example: @@ -21,7 +21,7 @@ The compiler elides the lifetime of `x` and the return type to some arbitrary lifetime `'anon` in `no_restriction()`. The only information available to the compiler is that `'anon` is valid for the duration of the function. When calling `with_restriction()`, the compiler requires the completely unrelated -type parameter `T` to outlive `'anon` because of the `T: 'a bound` in +type parameter `T` to outlive `'anon` because of the `T: 'a` bound in `with_restriction()`. This causes an error because `T` is not required to outlive `'anon` in `no_restriction()`. From 4ff83cee95cf73708cc5455f4ecce5eb1c21ffc6 Mon Sep 17 00:00:00 2001 From: mejrs <> Date: Wed, 28 Sep 2022 02:36:58 +0200 Subject: [PATCH 355/586] Deduplicate some logic --- .../src/check/method/suggest.rs | 74 +++++++------------ src/test/ui/suggestions/inner_type.fixed | 10 +-- src/test/ui/suggestions/inner_type.rs | 10 +-- src/test/ui/suggestions/inner_type.stderr | 10 +-- 4 files changed, 42 insertions(+), 62 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/check/method/suggest.rs b/compiler/rustc_hir_analysis/src/check/method/suggest.rs index c43dc8c134dd3..0e82e4956c7c1 100644 --- a/compiler/rustc_hir_analysis/src/check/method/suggest.rs +++ b/compiler/rustc_hir_analysis/src/check/method/suggest.rs @@ -1521,67 +1521,47 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { use one of the `assume_init` methods to access the inner value" )); } else if tcx.is_diagnostic_item(sym::RefCell, inner_id) { - match mutable { - Some(Mutability::Not) => { - err.span_suggestion_verbose( - expr.span.shrink_to_hi(), - format!( - "use `.borrow()` to borrow the `{ty}`, \ - panicking if any outstanding mutable borrows exist." - ), - ".borrow()", - Applicability::MaybeIncorrect, - ); - } + let (suggestion, borrow_kind, panic_if) = match mutable { + Some(Mutability::Not) => (".borrow()", "borrow", "a mutable borrow exists"), Some(Mutability::Mut) => { - err.span_suggestion_verbose( - expr.span.shrink_to_hi(), - format!( - "use `.borrow_mut()` to mutably borrow the `{ty}`, \ - panicking if any outstanding borrows exist." - ), - ".borrow_mut()", - Applicability::MaybeIncorrect, - ); + (".borrow_mut()", "mutably borrow", "any borrows exist") } None => return, - } + }; + err.span_suggestion_verbose( + expr.span.shrink_to_hi(), + format!( + "use `{suggestion}` to {borrow_kind} the `{ty}`, \ + panicking if {panic_if}" + ), + suggestion, + Applicability::MaybeIncorrect, + ); } else if tcx.is_diagnostic_item(sym::Mutex, inner_id) { err.span_suggestion_verbose( expr.span.shrink_to_hi(), format!( - "use `.lock()` to borrow the `{ty}`, \ + "use `.lock().unwrap()` to borrow the `{ty}`, \ blocking the current thread until it can be acquired" ), ".lock().unwrap()", Applicability::MaybeIncorrect, ); } else if tcx.is_diagnostic_item(sym::RwLock, inner_id) { - match mutable { - Some(Mutability::Not) => { - err.span_suggestion_verbose( - expr.span.shrink_to_hi(), - format!( - "use `.read()` to borrow the `{ty}`, \ - blocking the current thread until it can be acquired" - ), - ".read().unwrap()", - Applicability::MaybeIncorrect, - ); - } - Some(Mutability::Mut) => { - err.span_suggestion_verbose( - expr.span.shrink_to_hi(), - format!( - "use `.write()` to mutably borrow the `{ty}`, \ - blocking the current thread until it can be acquired" - ), - ".write().unwrap()", - Applicability::MaybeIncorrect, - ); - } + let (suggestion, borrow_kind) = match mutable { + Some(Mutability::Not) => (".read().unwrap()", "borrow"), + Some(Mutability::Mut) => (".write().unwrap()", "mutably borrow"), None => return, - } + }; + err.span_suggestion_verbose( + expr.span.shrink_to_hi(), + format!( + "use `{suggestion}` to {borrow_kind} the `{ty}`, \ + blocking the current thread until it can be acquired" + ), + suggestion, + Applicability::MaybeIncorrect, + ); } else { return; }; diff --git a/src/test/ui/suggestions/inner_type.fixed b/src/test/ui/suggestions/inner_type.fixed index 811b959b8c04d..7af7391ca851d 100644 --- a/src/test/ui/suggestions/inner_type.fixed +++ b/src/test/ui/suggestions/inner_type.fixed @@ -16,25 +16,25 @@ fn main() { other_item.borrow().method(); //~^ ERROR no method named `method` found for struct `RefCell` in the current scope [E0599] - //~| HELP use `.borrow()` to borrow the `Struct`, panicking if any outstanding mutable borrows exist. + //~| HELP use `.borrow()` to borrow the `Struct`, panicking if a mutable borrow exists other_item.borrow_mut().some_mutable_method(); //~^ ERROR no method named `some_mutable_method` found for struct `RefCell` in the current scope [E0599] - //~| HELP use `.borrow_mut()` to mutably borrow the `Struct`, panicking if any outstanding borrows exist. + //~| HELP .borrow_mut()` to mutably borrow the `Struct`, panicking if any borrows exist let another_item = std::sync::Mutex::new(Struct { p: 42_u32 }); another_item.lock().unwrap().method(); //~^ ERROR no method named `method` found for struct `Mutex` in the current scope [E0599] - //~| HELP use `.lock()` to borrow the `Struct`, blocking the current thread until it can be acquired + //~| HELP use `.lock().unwrap()` to borrow the `Struct`, blocking the current thread until it can be acquired let another_item = std::sync::RwLock::new(Struct { p: 42_u32 }); another_item.read().unwrap().method(); //~^ ERROR no method named `method` found for struct `RwLock` in the current scope [E0599] - //~| HELP use `.read()` to borrow the `Struct`, blocking the current thread until it can be acquired + //~| HELP use `.read().unwrap()` to borrow the `Struct`, blocking the current thread until it can be acquired another_item.write().unwrap().some_mutable_method(); //~^ ERROR no method named `some_mutable_method` found for struct `RwLock` in the current scope [E0599] - //~| HELP use `.write()` to mutably borrow the `Struct`, blocking the current thread until it can be acquired + //~| HELP use `.write().unwrap()` to mutably borrow the `Struct`, blocking the current thread until it can be acquired } diff --git a/src/test/ui/suggestions/inner_type.rs b/src/test/ui/suggestions/inner_type.rs index 96c797a6d81d7..4aca50716258a 100644 --- a/src/test/ui/suggestions/inner_type.rs +++ b/src/test/ui/suggestions/inner_type.rs @@ -16,25 +16,25 @@ fn main() { other_item.method(); //~^ ERROR no method named `method` found for struct `RefCell` in the current scope [E0599] - //~| HELP use `.borrow()` to borrow the `Struct`, panicking if any outstanding mutable borrows exist. + //~| HELP use `.borrow()` to borrow the `Struct`, panicking if a mutable borrow exists other_item.some_mutable_method(); //~^ ERROR no method named `some_mutable_method` found for struct `RefCell` in the current scope [E0599] - //~| HELP use `.borrow_mut()` to mutably borrow the `Struct`, panicking if any outstanding borrows exist. + //~| HELP .borrow_mut()` to mutably borrow the `Struct`, panicking if any borrows exist let another_item = std::sync::Mutex::new(Struct { p: 42_u32 }); another_item.method(); //~^ ERROR no method named `method` found for struct `Mutex` in the current scope [E0599] - //~| HELP use `.lock()` to borrow the `Struct`, blocking the current thread until it can be acquired + //~| HELP use `.lock().unwrap()` to borrow the `Struct`, blocking the current thread until it can be acquired let another_item = std::sync::RwLock::new(Struct { p: 42_u32 }); another_item.method(); //~^ ERROR no method named `method` found for struct `RwLock` in the current scope [E0599] - //~| HELP use `.read()` to borrow the `Struct`, blocking the current thread until it can be acquired + //~| HELP use `.read().unwrap()` to borrow the `Struct`, blocking the current thread until it can be acquired another_item.some_mutable_method(); //~^ ERROR no method named `some_mutable_method` found for struct `RwLock` in the current scope [E0599] - //~| HELP use `.write()` to mutably borrow the `Struct`, blocking the current thread until it can be acquired + //~| HELP use `.write().unwrap()` to mutably borrow the `Struct`, blocking the current thread until it can be acquired } diff --git a/src/test/ui/suggestions/inner_type.stderr b/src/test/ui/suggestions/inner_type.stderr index 00d52f0f1d33a..5ac3d04f10414 100644 --- a/src/test/ui/suggestions/inner_type.stderr +++ b/src/test/ui/suggestions/inner_type.stderr @@ -9,7 +9,7 @@ note: the method `method` exists on the type `Struct` | LL | pub fn method(&self) {} | ^^^^^^^^^^^^^^^^^^^^ -help: use `.borrow()` to borrow the `Struct`, panicking if any outstanding mutable borrows exist. +help: use `.borrow()` to borrow the `Struct`, panicking if a mutable borrow exists | LL | other_item.borrow().method(); | +++++++++ @@ -25,7 +25,7 @@ note: the method `some_mutable_method` exists on the type `Struct` | LL | pub fn some_mutable_method(&mut self) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -help: use `.borrow_mut()` to mutably borrow the `Struct`, panicking if any outstanding borrows exist. +help: use `.borrow_mut()` to mutably borrow the `Struct`, panicking if any borrows exist | LL | other_item.borrow_mut().some_mutable_method(); | +++++++++++++ @@ -41,7 +41,7 @@ note: the method `method` exists on the type `Struct` | LL | pub fn method(&self) {} | ^^^^^^^^^^^^^^^^^^^^ -help: use `.lock()` to borrow the `Struct`, blocking the current thread until it can be acquired +help: use `.lock().unwrap()` to borrow the `Struct`, blocking the current thread until it can be acquired | LL | another_item.lock().unwrap().method(); | ++++++++++++++++ @@ -57,7 +57,7 @@ note: the method `method` exists on the type `Struct` | LL | pub fn method(&self) {} | ^^^^^^^^^^^^^^^^^^^^ -help: use `.read()` to borrow the `Struct`, blocking the current thread until it can be acquired +help: use `.read().unwrap()` to borrow the `Struct`, blocking the current thread until it can be acquired | LL | another_item.read().unwrap().method(); | ++++++++++++++++ @@ -73,7 +73,7 @@ note: the method `some_mutable_method` exists on the type `Struct` | LL | pub fn some_mutable_method(&mut self) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -help: use `.write()` to mutably borrow the `Struct`, blocking the current thread until it can be acquired +help: use `.write().unwrap()` to mutably borrow the `Struct`, blocking the current thread until it can be acquired | LL | another_item.write().unwrap().some_mutable_method(); | +++++++++++++++++ From 7f06d513fbbb01af78fae3586114abd9077b930e Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Tue, 27 Sep 2022 17:33:59 -0700 Subject: [PATCH 356/586] Don't export `__heap_base` and `__data_end` on wasm32-wasi. `__heap_base` and `__data_end` are exported for use by wasm-bindgen, which uses the wasm32-unknown-unknown target. On wasm32-wasi, as a step toward implementing the Canonical ABI, and as an aid to building speicalized WASI API polyfill wrappers, don't export `__heap_base` and `__data_end` on wasm32-wasi. --- compiler/rustc_codegen_ssa/src/back/linker.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs index e0bd7a33f7373..061053ef2ac97 100644 --- a/compiler/rustc_codegen_ssa/src/back/linker.rs +++ b/compiler/rustc_codegen_ssa/src/back/linker.rs @@ -1320,10 +1320,12 @@ impl<'a> Linker for WasmLd<'a> { // LLD will hide these otherwise-internal symbols since it only exports // symbols explicitly passed via the `--export` flags above and hides all - // others. Various bits and pieces of tooling use this, so be sure these - // symbols make their way out of the linker as well. - self.cmd.arg("--export=__heap_base"); - self.cmd.arg("--export=__data_end"); + // others. Various bits and pieces of wasm32-unknown-unknown tooling use + // this, so be sure these symbols make their way out of the linker as well. + if self.sess.target.os == "unknown" { + self.cmd.arg("--export=__heap_base"); + self.cmd.arg("--export=__data_end"); + } } fn subsystem(&mut self, _subsystem: &str) {} From 4bf789fba7b04c745b8d55b020903f7d64b2720d Mon Sep 17 00:00:00 2001 From: Noah Lev Date: Tue, 27 Sep 2022 17:06:38 -0700 Subject: [PATCH 357/586] rustdoc: Queryify `is_notable_trait` This might help with #102375. --- compiler/rustc_middle/src/query/mod.rs | 5 +++++ compiler/rustc_middle/src/ty/util.rs | 16 ++++++++++++++-- src/librustdoc/clean/types.rs | 4 ++-- 3 files changed, 21 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index eed44240f8357..fb867f8b46b10 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -1126,6 +1126,11 @@ rustc_queries! { desc { |tcx| "checking whether `{}` is `doc(hidden)`", tcx.def_path_str(def_id) } } + /// Determines whether an item is annotated with `doc(notable_trait)`. + query is_doc_notable_trait(def_id: DefId) -> bool { + desc { |tcx| "checking whether `{}` is `doc(notable_trait)`", tcx.def_path_str(def_id) } + } + /// Returns the attributes on the item at `def_id`. /// /// Do not use this directly, use `tcx.get_attrs` instead. diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index d93aab04e9921..713f9067a85e2 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -1289,12 +1289,24 @@ pub fn is_doc_hidden(tcx: TyCtxt<'_>, def_id: DefId) -> bool { .any(|items| items.iter().any(|item| item.has_name(sym::hidden))) } +/// Determines whether an item is annotated with `doc(notable_trait)`. +pub fn is_doc_notable_trait(tcx: TyCtxt<'_>, def_id: DefId) -> bool { + tcx.get_attrs(def_id, sym::doc) + .filter_map(|attr| attr.meta_item_list()) + .any(|items| items.iter().any(|item| item.has_name(sym::notable_trait))) +} + /// Determines whether an item is an intrinsic by Abi. pub fn is_intrinsic(tcx: TyCtxt<'_>, def_id: DefId) -> bool { matches!(tcx.fn_sig(def_id).abi(), Abi::RustIntrinsic | Abi::PlatformIntrinsic) } pub fn provide(providers: &mut ty::query::Providers) { - *providers = - ty::query::Providers { normalize_opaque_types, is_doc_hidden, is_intrinsic, ..*providers } + *providers = ty::query::Providers { + normalize_opaque_types, + is_doc_hidden, + is_doc_notable_trait, + is_intrinsic, + ..*providers + } } diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 1e63d0e46bde1..d379daca63bfd 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -37,7 +37,7 @@ use crate::clean::cfg::Cfg; use crate::clean::clean_visibility; use crate::clean::external_path; use crate::clean::inline::{self, print_inlined_const}; -use crate::clean::utils::{has_doc_flag, is_literal_expr, print_const_expr, print_evaluated_const}; +use crate::clean::utils::{is_literal_expr, print_const_expr, print_evaluated_const}; use crate::core::DocContext; use crate::formats::cache::Cache; use crate::formats::item_type::ItemType; @@ -1524,7 +1524,7 @@ impl Trait { tcx.trait_is_auto(self.def_id) } pub(crate) fn is_notable_trait(&self, tcx: TyCtxt<'_>) -> bool { - has_doc_flag(tcx, self.def_id, sym::notable_trait) + tcx.is_doc_notable_trait(self.def_id) } pub(crate) fn unsafety(&self, tcx: TyCtxt<'_>) -> hir::Unsafety { tcx.trait_def(self.def_id).unsafety From d0a26acb2ae2d000e516eca92ae8feb08d1f6ea0 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 28 Sep 2022 10:28:36 +1000 Subject: [PATCH 358/586] Address review comments. --- compiler/rustc_lexer/src/lib.rs | 6 ++++-- compiler/rustc_parse/src/lexer/mod.rs | 2 +- compiler/rustc_parse/src/lexer/tokentrees.rs | 14 +++++++------- src/librustdoc/html/highlight.rs | 2 +- 4 files changed, 13 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_lexer/src/lib.rs b/compiler/rustc_lexer/src/lib.rs index 18ebed7c70e15..c71e6ffe34d9b 100644 --- a/compiler/rustc_lexer/src/lib.rs +++ b/compiler/rustc_lexer/src/lib.rs @@ -23,15 +23,17 @@ // We want to be able to build this crate with a stable compiler, so no // `#![feature]` attributes should be added. -pub mod cursor; +mod cursor; pub mod unescape; #[cfg(test)] mod tests; +pub use crate::cursor::Cursor; + use self::LiteralKind::*; use self::TokenKind::*; -use crate::cursor::{Cursor, EOF_CHAR}; +use crate::cursor::EOF_CHAR; use std::convert::TryFrom; /// Parsed token. diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs index 151e80e2b3e9d..bcd078a89677e 100644 --- a/compiler/rustc_parse/src/lexer/mod.rs +++ b/compiler/rustc_parse/src/lexer/mod.rs @@ -4,8 +4,8 @@ use rustc_ast::token::{self, CommentKind, Delimiter, Token, TokenKind}; use rustc_ast::tokenstream::TokenStream; use rustc_ast::util::unicode::contains_text_flow_control_chars; use rustc_errors::{error_code, Applicability, DiagnosticBuilder, ErrorGuaranteed, PResult}; -use rustc_lexer::cursor::Cursor; use rustc_lexer::unescape::{self, Mode}; +use rustc_lexer::Cursor; use rustc_lexer::{Base, DocStyle, RawStrError}; use rustc_session::lint::builtin::{ RUST_2021_PREFIXES_INCOMPATIBLE_SYNTAX, TEXT_DIRECTION_CODEPOINT_IN_COMMENT, diff --git a/compiler/rustc_parse/src/lexer/tokentrees.rs b/compiler/rustc_parse/src/lexer/tokentrees.rs index 6f6ab16cb597b..364753154db05 100644 --- a/compiler/rustc_parse/src/lexer/tokentrees.rs +++ b/compiler/rustc_parse/src/lexer/tokentrees.rs @@ -53,7 +53,7 @@ impl<'a> TokenTreesReader<'a> { token::OpenDelim(delim) => buf.push(self.parse_token_tree_open_delim(delim)), token::CloseDelim(delim) => return Err(self.close_delim_err(delim)), token::Eof => return Ok(buf.into_token_stream()), - _ => buf.push(self.parse_token_tree_other()), + _ => buf.push(self.parse_token_tree_non_delim_non_eof()), } } } @@ -66,11 +66,10 @@ impl<'a> TokenTreesReader<'a> { token::OpenDelim(delim) => buf.push(self.parse_token_tree_open_delim(delim)), token::CloseDelim(..) => return buf.into_token_stream(), token::Eof => { - let mut err = self.eof_err(); - err.emit(); + self.eof_err().emit(); return buf.into_token_stream(); } - _ => buf.push(self.parse_token_tree_other()), + _ => buf.push(self.parse_token_tree_non_delim_non_eof()), } } } @@ -245,9 +244,10 @@ impl<'a> TokenTreesReader<'a> { } #[inline] - fn parse_token_tree_other(&mut self) -> TokenTree { - // `spacing` for the returned token is determined by the next token: - // its kind and its `preceded_by_whitespace` status. + fn parse_token_tree_non_delim_non_eof(&mut self) -> TokenTree { + // `this_spacing` for the returned token refers to whether the token is + // immediately followed by another op token. It is determined by the + // next token: its kind and its `preceded_by_whitespace` status. let (next_tok, is_next_tok_preceded_by_whitespace) = self.string_reader.next_token(); let this_spacing = if is_next_tok_preceded_by_whitespace || !next_tok.is_op() { Spacing::Alone diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs index ea65a6334c9e4..78b98431b190d 100644 --- a/src/librustdoc/html/highlight.rs +++ b/src/librustdoc/html/highlight.rs @@ -13,7 +13,7 @@ use std::collections::VecDeque; use std::fmt::{Display, Write}; use rustc_data_structures::fx::FxHashMap; -use rustc_lexer::cursor::Cursor; +use rustc_lexer::Cursor; use rustc_lexer::{LiteralKind, TokenKind}; use rustc_span::edition::Edition; use rustc_span::symbol::Symbol; From e665d20c020724fa356fef0214e14b4066563a29 Mon Sep 17 00:00:00 2001 From: Takayuki Maeda Date: Wed, 28 Sep 2022 11:42:52 +0900 Subject: [PATCH 359/586] fix a ui test --- src/test/ui/structs/incomplete-fn-in-struct-definition.rs | 2 +- .../ui/structs/incomplete-fn-in-struct-definition.stderr | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/test/ui/structs/incomplete-fn-in-struct-definition.rs b/src/test/ui/structs/incomplete-fn-in-struct-definition.rs index b43d1d4395a58..cd8a79ba68741 100644 --- a/src/test/ui/structs/incomplete-fn-in-struct-definition.rs +++ b/src/test/ui/structs/incomplete-fn-in-struct-definition.rs @@ -1,5 +1,5 @@ fn main() {} struct S { - fn //~ ERROR expected identifier, found keyword `fn` + fn: u8 //~ ERROR expected identifier, found keyword `fn` } diff --git a/src/test/ui/structs/incomplete-fn-in-struct-definition.stderr b/src/test/ui/structs/incomplete-fn-in-struct-definition.stderr index 2c86060671021..0d12ba9c91688 100644 --- a/src/test/ui/structs/incomplete-fn-in-struct-definition.stderr +++ b/src/test/ui/structs/incomplete-fn-in-struct-definition.stderr @@ -1,12 +1,14 @@ error: expected identifier, found keyword `fn` --> $DIR/incomplete-fn-in-struct-definition.rs:4:5 | -LL | fn +LL | struct S { + | - while parsing this struct +LL | fn: u8 | ^^ expected identifier, found keyword | help: escape `fn` to use it as an identifier | -LL | r#fn +LL | r#fn: u8 | ++ error: aborting due to previous error From 37bf8f888cb7b8a7cb461f0d41588e500b0bb9d1 Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Fri, 9 Sep 2022 16:38:33 +0200 Subject: [PATCH 360/586] rustc_safe_intrinsic: Keep list of safe intrinsics within the compiler --- .../rustc_hir_analysis/src/check/intrinsic.rs | 62 ++++++++++++++++++- 1 file changed, 59 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs index b43d492eb7aad..8be1cf04f8b69 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs @@ -8,7 +8,7 @@ use crate::errors::{ use crate::require_same_types; use hir::def_id::DefId; -use rustc_errors::struct_span_err; +use rustc_errors::{struct_span_err, DiagnosticMessage}; use rustc_hir as hir; use rustc_middle::traits::{ObligationCause, ObligationCauseCode}; use rustc_middle::ty::{self, TyCtxt}; @@ -63,10 +63,66 @@ fn equate_intrinsic_type<'tcx>( /// Returns the unsafety of the given intrinsic. pub fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: DefId) -> hir::Unsafety { - match tcx.has_attr(intrinsic_id, sym::rustc_safe_intrinsic) { + let has_safe_attr = match tcx.has_attr(intrinsic_id, sym::rustc_safe_intrinsic) { true => hir::Unsafety::Normal, false => hir::Unsafety::Unsafe, + }; + let is_in_list = match tcx.item_name(intrinsic_id) { + // When adding a new intrinsic to this list, + // it's usually worth updating that intrinsic's documentation + // to note that it's safe to call, since + // safe extern fns are otherwise unprecedented. + sym::abort + | sym::assert_inhabited + | sym::assert_zero_valid + | sym::assert_uninit_valid + | sym::size_of + | sym::min_align_of + | sym::needs_drop + | sym::caller_location + | sym::add_with_overflow + | sym::sub_with_overflow + | sym::mul_with_overflow + | sym::wrapping_add + | sym::wrapping_sub + | sym::wrapping_mul + | sym::saturating_add + | sym::saturating_sub + | sym::rotate_left + | sym::rotate_right + | sym::ctpop + | sym::ctlz + | sym::cttz + | sym::bswap + | sym::bitreverse + | sym::discriminant_value + | sym::type_id + | sym::likely + | sym::unlikely + | sym::ptr_guaranteed_cmp + | sym::minnumf32 + | sym::minnumf64 + | sym::maxnumf32 + | sym::rustc_peek + | sym::maxnumf64 + | sym::type_name + | sym::forget + | sym::black_box + | sym::variant_count + | sym::ptr_mask => hir::Unsafety::Normal, + _ => hir::Unsafety::Unsafe, + }; + + if has_safe_attr != is_in_list { + tcx.sess.struct_span_err( + tcx.def_span(intrinsic_id), + DiagnosticMessage::Str(format!( + "intrinsic safety mismatch between list of intrinsics within the compiler and core library intrinsics for intrinsic `{}`", + tcx.item_name(intrinsic_id) + ))).emit(); } + + is_in_list } /// Remember to add all intrinsics here, in `compiler/rustc_codegen_llvm/src/intrinsic.rs`, @@ -312,7 +368,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { ( 1, vec![ - tcx.mk_imm_ref(tcx.mk_region(ty::ReLateBound(ty::INNERMOST, br)), param(0)) + tcx.mk_imm_ref(tcx.mk_region(ty::ReLateBound(ty::INNERMOST, br)), param(0)), ], tcx.mk_projection(discriminant_def_id, tcx.mk_substs([param(0).into()].iter())), ) From b1b86491f1c2bb761a06b779a3a7a936a996977a Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Tue, 27 Sep 2022 07:22:07 +0200 Subject: [PATCH 361/586] rustc_safe_intrinsic: Add UI test --- src/test/ui/intrinsics/safe-intrinsic-mismatch.rs | 11 +++++++++++ .../ui/intrinsics/safe-intrinsic-mismatch.stderr | 14 ++++++++++++++ 2 files changed, 25 insertions(+) create mode 100644 src/test/ui/intrinsics/safe-intrinsic-mismatch.rs create mode 100644 src/test/ui/intrinsics/safe-intrinsic-mismatch.stderr diff --git a/src/test/ui/intrinsics/safe-intrinsic-mismatch.rs b/src/test/ui/intrinsics/safe-intrinsic-mismatch.rs new file mode 100644 index 0000000000000..50e12eaeb5cc0 --- /dev/null +++ b/src/test/ui/intrinsics/safe-intrinsic-mismatch.rs @@ -0,0 +1,11 @@ +#![feature(intrinsics)] +#![feature(rustc_attrs)] + +extern "rust-intrinsic" { + fn size_of() -> usize; //~ ERROR intrinsic safety mismatch + + #[rustc_safe_intrinsic] + fn assume(b: bool); //~ ERROR intrinsic safety mismatch +} + +fn main() {} diff --git a/src/test/ui/intrinsics/safe-intrinsic-mismatch.stderr b/src/test/ui/intrinsics/safe-intrinsic-mismatch.stderr new file mode 100644 index 0000000000000..0c2f3be491dd3 --- /dev/null +++ b/src/test/ui/intrinsics/safe-intrinsic-mismatch.stderr @@ -0,0 +1,14 @@ +error: intrinsic safety mismatch between list of intrinsics within the compiler and core library intrinsics for intrinsic `size_of` + --> $DIR/safe-intrinsic-mismatch.rs:5:5 + | +LL | fn size_of() -> usize; + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: intrinsic safety mismatch between list of intrinsics within the compiler and core library intrinsics for intrinsic `assume` + --> $DIR/safe-intrinsic-mismatch.rs:8:5 + | +LL | fn assume(b: bool); + | ^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + From 3acb505ee560770c62bad5362f6caf7567d467b9 Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Wed, 14 Sep 2022 19:33:00 -0500 Subject: [PATCH 362/586] Make the `c` feature for `compiler-builtins` opt-in instead of inferred The build script for `compiler_builtins` doesn't support cross-compilation. I tried fixing it, but the cc crate itself doesn't appear to support cross-compiling to windows either unless you use the -gnu toolchain: ``` error occurred: Failed to find tool. Is `lib.exe` installed? ``` Rather than trying to fix it or special-case the platforms without bugs, make it opt-in instead of automatic. --- config.toml.example | 4 +++ src/bootstrap/compile.rs | 15 ++++++--- src/bootstrap/config.rs | 4 +++ src/bootstrap/dist.rs | 32 +++++++++---------- .../disabled/dist-x86_64-haiku/Dockerfile | 2 ++ .../host-x86_64/dist-various-2/Dockerfile | 2 ++ .../x86_64-gnu-llvm-13-stage1/Dockerfile | 1 + .../host-x86_64/x86_64-gnu-llvm-13/Dockerfile | 1 + src/ci/run.sh | 5 +++ 9 files changed, 44 insertions(+), 22 deletions(-) diff --git a/config.toml.example b/config.toml.example index a967d881b029b..ff08dfc553d3b 100644 --- a/config.toml.example +++ b/config.toml.example @@ -291,6 +291,10 @@ changelog-seen = 2 # on this runtime, such as `-C profile-generate` or `-C instrument-coverage`). #profiler = false +# Use the optimized LLVM C intrinsics for `compiler_builtins`, rather than Rust intrinsics. +# Requires the LLVM submodule to be managed by bootstrap (i.e. not external). +#optimized-compiler-builtins = false + # Indicates whether the native libraries linked into Cargo will be statically # linked or not. #cargo-native-static = false diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index c13e83f6c8612..58cf3edc3171f 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -299,9 +299,7 @@ pub fn std_cargo(builder: &Builder<'_>, target: TargetSelection, stage: u32, car // Determine if we're going to compile in optimized C intrinsics to // the `compiler-builtins` crate. These intrinsics live in LLVM's - // `compiler-rt` repository, but our `src/llvm-project` submodule isn't - // always checked out, so we need to conditionally look for this. (e.g. if - // an external LLVM is used we skip the LLVM submodule checkout). + // `compiler-rt` repository. // // Note that this shouldn't affect the correctness of `compiler-builtins`, // but only its speed. Some intrinsics in C haven't been translated to Rust @@ -312,8 +310,15 @@ pub fn std_cargo(builder: &Builder<'_>, target: TargetSelection, stage: u32, car // If `compiler-rt` is available ensure that the `c` feature of the // `compiler-builtins` crate is enabled and it's configured to learn where // `compiler-rt` is located. - let compiler_builtins_root = builder.src.join("src/llvm-project/compiler-rt"); - let compiler_builtins_c_feature = if compiler_builtins_root.exists() { + let compiler_builtins_c_feature = if builder.config.optimized_compiler_builtins { + if !builder.is_rust_llvm(target) { + panic!( + "need a managed LLVM submodule for optimized intrinsics support; unset `llvm-config` or `optimized-compiler-builtins`" + ); + } + + builder.update_submodule(&Path::new("src").join("llvm-project")); + let compiler_builtins_root = builder.src.join("src/llvm-project/compiler-rt"); // Note that `libprofiler_builtins/build.rs` also computes this so if // you're changing something here please also change that. cargo.env("RUST_COMPILER_RT_ROOT", &compiler_builtins_root); diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index 7c062460c4f16..1924ff09d4997 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -73,6 +73,8 @@ pub struct Config { pub color: Color, pub patch_binaries_for_nix: bool, pub stage0_metadata: Stage0Metadata, + /// Whether to use the `c` feature of the `compiler_builtins` crate. + pub optimized_compiler_builtins: bool, pub on_fail: Option, pub stage: u32, @@ -597,6 +599,7 @@ define_config! { bench_stage: Option = "bench-stage", patch_binaries_for_nix: Option = "patch-binaries-for-nix", metrics: Option = "metrics", + optimized_compiler_builtins: Option = "optimized-compiler-builtins", } } @@ -916,6 +919,7 @@ impl Config { set(&mut config.print_step_timings, build.print_step_timings); set(&mut config.print_step_rusage, build.print_step_rusage); set(&mut config.patch_binaries_for_nix, build.patch_binaries_for_nix); + set(&mut config.optimized_compiler_builtins, build.optimized_compiler_builtins); config.verbose = cmp::max(config.verbose, flags.verbose); diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index 1a59b3958f106..b66c08ea4c47f 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -1838,23 +1838,21 @@ fn add_env(builder: &Builder<'_>, cmd: &mut Command, target: TargetSelection) { /// /// Returns whether the files were actually copied. fn maybe_install_llvm(builder: &Builder<'_>, target: TargetSelection, dst_libdir: &Path) -> bool { - if let Some(config) = builder.config.target_config.get(&target) { - if config.llvm_config.is_some() && !builder.config.llvm_from_ci { - // If the LLVM was externally provided, then we don't currently copy - // artifacts into the sysroot. This is not necessarily the right - // choice (in particular, it will require the LLVM dylib to be in - // the linker's load path at runtime), but the common use case for - // external LLVMs is distribution provided LLVMs, and in that case - // they're usually in the standard search path (e.g., /usr/lib) and - // copying them here is going to cause problems as we may end up - // with the wrong files and isn't what distributions want. - // - // This behavior may be revisited in the future though. - // - // If the LLVM is coming from ourselves (just from CI) though, we - // still want to install it, as it otherwise won't be available. - return false; - } + if !builder.is_rust_llvm(target) { + // If the LLVM was externally provided, then we don't currently copy + // artifacts into the sysroot. This is not necessarily the right + // choice (in particular, it will require the LLVM dylib to be in + // the linker's load path at runtime), but the common use case for + // external LLVMs is distribution provided LLVMs, and in that case + // they're usually in the standard search path (e.g., /usr/lib) and + // copying them here is going to cause problems as we may end up + // with the wrong files and isn't what distributions want. + // + // This behavior may be revisited in the future though. + // + // If the LLVM is coming from ourselves (just from CI) though, we + // still want to install it, as it otherwise won't be available. + return false; } // On macOS, rustc (and LLVM tools) link to an unversioned libLLVM.dylib diff --git a/src/ci/docker/host-x86_64/disabled/dist-x86_64-haiku/Dockerfile b/src/ci/docker/host-x86_64/disabled/dist-x86_64-haiku/Dockerfile index 5ddd3f1803964..637b5fa22f974 100644 --- a/src/ci/docker/host-x86_64/disabled/dist-x86_64-haiku/Dockerfile +++ b/src/ci/docker/host-x86_64/disabled/dist-x86_64-haiku/Dockerfile @@ -47,4 +47,6 @@ ENV RUST_CONFIGURE_ARGS --disable-jemalloc \ --set=$TARGET.cc=x86_64-unknown-haiku-gcc \ --set=$TARGET.cxx=x86_64-unknown-haiku-g++ \ --set=$TARGET.llvm-config=/bin/llvm-config-haiku +ENV EXTERNAL_LLVM 1 + ENV SCRIPT python3 ../x.py dist --host=$HOST --target=$HOST diff --git a/src/ci/docker/host-x86_64/dist-various-2/Dockerfile b/src/ci/docker/host-x86_64/dist-various-2/Dockerfile index 126c292b38ea1..8250ec0c3119b 100644 --- a/src/ci/docker/host-x86_64/dist-various-2/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-various-2/Dockerfile @@ -129,4 +129,6 @@ ENV RUST_CONFIGURE_ARGS --enable-extended --enable-lld --disable-docs \ --set target.wasm32-wasi.wasi-root=/wasm32-wasi \ --musl-root-armv7=/musl-armv7 +ENV EXTERNAL_LLVM 1 + ENV SCRIPT python3 ../x.py dist --host='' --target $TARGETS diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-13-stage1/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-13-stage1/Dockerfile index 23f2215c2d93c..1289f116fe9fc 100644 --- a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-13-stage1/Dockerfile +++ b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-13-stage1/Dockerfile @@ -29,6 +29,7 @@ RUN sh /scripts/sccache.sh # We are disabling CI LLVM since this builder is intentionally using a host # LLVM, rather than the typical src/llvm-project LLVM. ENV NO_DOWNLOAD_CI_LLVM 1 +ENV EXTERNAL_LLVM 1 # Using llvm-link-shared due to libffi issues -- see #34486 ENV RUST_CONFIGURE_ARGS \ diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-13/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-13/Dockerfile index 8f6831bc54e63..4b89a72baa1c5 100644 --- a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-13/Dockerfile +++ b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-13/Dockerfile @@ -40,6 +40,7 @@ RUN sh /scripts/sccache.sh # We are disabling CI LLVM since this builder is intentionally using a host # LLVM, rather than the typical src/llvm-project LLVM. ENV NO_DOWNLOAD_CI_LLVM 1 +ENV EXTERNAL_LLVM 1 # Using llvm-link-shared due to libffi issues -- see #34486 ENV RUST_CONFIGURE_ARGS \ diff --git a/src/ci/run.sh b/src/ci/run.sh index 9a247fb60a8ee..9d98ce22498cd 100755 --- a/src/ci/run.sh +++ b/src/ci/run.sh @@ -69,6 +69,11 @@ RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set rust.codegen-units-std=1" # space required for CI artifacts. RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --dist-compression-formats=xz" +# Enable the `c` feature for compiler_builtins, but only when the `compiler-rt` source is available. +if [ "$EXTERNAL_LLVM" = "" ]; then + RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set build.optimized-compiler-builtins" +fi + if [ "$DIST_SRC" = "" ]; then RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --disable-dist-src" fi From 356a52cca8747aeaf8e60e5521594e81b1ff69d1 Mon Sep 17 00:00:00 2001 From: Rageking8 Date: Wed, 28 Sep 2022 16:30:06 +0800 Subject: [PATCH 363/586] add regression test --- src/test/ui/generics/issue-94923.rs | 49 +++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 src/test/ui/generics/issue-94923.rs diff --git a/src/test/ui/generics/issue-94923.rs b/src/test/ui/generics/issue-94923.rs new file mode 100644 index 0000000000000..d337a5dffc934 --- /dev/null +++ b/src/test/ui/generics/issue-94923.rs @@ -0,0 +1,49 @@ +// run-pass +// regression test for issue #94923 +// min-llvm-version: 15.0.0 +// compile-flags: -C opt-level=3 + +fn f0(mut x: usize) -> usize { + for _ in 0..1000 { + x *= 123; + x %= 99 + } + x + 321 // function composition is not just longer iteration +} + +fn f1(x: usize) -> usize { + f0::<(i8, T)>(f0::<(u8, T)>(x)) +} + +fn f2(x: usize) -> usize { + f1::<(i8, T)>(f1::<(u8, T)>(x)) +} + +fn f3(x: usize) -> usize { + f2::<(i8, T)>(f2::<(u8, T)>(x)) +} + +fn f4(x: usize) -> usize { + f3::<(i8, T)>(f3::<(u8, T)>(x)) +} + +fn f5(x: usize) -> usize { + f4::<(i8, T)>(f4::<(u8, T)>(x)) +} + +fn f6(x: usize) -> usize { + f5::<(i8, T)>(f5::<(u8, T)>(x)) +} + +fn f7(x: usize) -> usize { + f6::<(i8, T)>(f6::<(u8, T)>(x)) +} + +fn f8(x: usize) -> usize { + f7::<(i8, T)>(f7::<(u8, T)>(x)) +} + +fn main() { + let y = f8::<()>(1); + assert_eq!(y, 348); +} From 4fdc78e6bf1c8cbe21aa113aed69b31578e857e8 Mon Sep 17 00:00:00 2001 From: b-naber Date: Wed, 28 Sep 2022 12:31:08 +0200 Subject: [PATCH 364/586] account for use of index-based lifetime names in print of binder --- compiler/rustc_middle/src/ty/print/pretty.rs | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 70efa748846ab..f69ac0768204a 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -2173,10 +2173,16 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { let mut region_index = self.region_index; let mut next_name = |this: &Self| { - let name = name_by_region_index(region_index, &mut available_names, num_available); - debug!(?name); - region_index += 1; - assert!(!this.used_region_names.contains(&name)); + let mut name; + + loop { + name = name_by_region_index(region_index, &mut available_names, num_available); + region_index += 1; + + if !this.used_region_names.contains(&name) { + break; + } + } name }; From a670897920c60c9f6632d4421b45bb30b0921df8 Mon Sep 17 00:00:00 2001 From: b-naber Date: Wed, 28 Sep 2022 12:31:19 +0200 Subject: [PATCH 365/586] add test --- src/test/ui/regions/issue-102374.rs | 20 ++++++++++++++++++++ src/test/ui/regions/issue-102374.stderr | 14 ++++++++++++++ 2 files changed, 34 insertions(+) create mode 100644 src/test/ui/regions/issue-102374.rs create mode 100644 src/test/ui/regions/issue-102374.stderr diff --git a/src/test/ui/regions/issue-102374.rs b/src/test/ui/regions/issue-102374.rs new file mode 100644 index 0000000000000..e0a1164211a2c --- /dev/null +++ b/src/test/ui/regions/issue-102374.rs @@ -0,0 +1,20 @@ +use std::cell::Cell; + +#[rustfmt::skip] +fn f( + f: for<'a, 'b, 'c, 'd, 'e, 'f, 'g, + 'h, 'i, 'j, 'k, 'l, 'm, 'n, + 'o, 'p, 'q, 'r, 's, 't, 'u, + 'v, 'w, 'x, 'y, 'z, 'z0> + fn(Cell<(& i32, &'a i32, &'b i32, &'c i32, &'d i32, + &'e i32, &'f i32, &'g i32, &'h i32, &'i i32, + &'j i32, &'k i32, &'l i32, &'m i32, &'n i32, + &'o i32, &'p i32, &'q i32, &'r i32, &'s i32, + &'t i32, &'u i32, &'v i32, &'w i32, &'x i32, + &'y i32, &'z i32, &'z0 i32)>), +) -> i32 { + f + //~^ ERROR mismatched types +} + +fn main() {} diff --git a/src/test/ui/regions/issue-102374.stderr b/src/test/ui/regions/issue-102374.stderr new file mode 100644 index 0000000000000..31b855c36bead --- /dev/null +++ b/src/test/ui/regions/issue-102374.stderr @@ -0,0 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/issue-102374.rs:16:5 + | +LL | ) -> i32 { + | --- expected `i32` because of return type +LL | f + | ^ expected `i32`, found fn pointer + | + = note: expected type `i32` + found fn pointer `for<'z1, 'a, 'b, 'c, 'd, 'e, 'f, 'g, 'h, 'i, 'j, 'k, 'l, 'm, 'n, 'o, 'p, 'q, 'r, 's, 't, 'u, 'v, 'w, 'x, 'y, 'z, 'z0> fn(Cell<(&'z1 i32, &'a i32, &'b i32, &'c i32, &'d i32, &'e i32, &'f i32, &'g i32, &'h i32, &'i i32, &'j i32, &'k i32, &'l i32, &'m i32, &'n i32, &'o i32, &'p i32, &'q i32, &'r i32, &'s i32, &'t i32, &'u i32, &'v i32, &'w i32, &'x i32, &'y i32, &'z i32, &'z0 i32)>)` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. From 4a2c1a12b662eb590dbe78f7f9d13c2f327d3bb6 Mon Sep 17 00:00:00 2001 From: Ding Xiang Fei Date: Wed, 28 Sep 2022 16:45:09 +0800 Subject: [PATCH 366/586] fix unwind drop glue for if-then scopes --- compiler/rustc_mir_build/src/build/block.rs | 5 -- .../rustc_mir_build/src/build/expr/into.rs | 4 +- .../rustc_mir_build/src/build/matches/mod.rs | 4 +- compiler/rustc_mir_build/src/build/scope.rs | 47 +++++++++++++++++-- src/test/ui/let-else/issue-102317.rs | 20 ++++++++ src/test/ui/mir/issue-99852.rs | 24 ++++++++++ 6 files changed, 90 insertions(+), 14 deletions(-) create mode 100644 src/test/ui/let-else/issue-102317.rs create mode 100644 src/test/ui/mir/issue-99852.rs diff --git a/compiler/rustc_mir_build/src/build/block.rs b/compiler/rustc_mir_build/src/build/block.rs index fc1b301402b73..183db56d7a08c 100644 --- a/compiler/rustc_mir_build/src/build/block.rs +++ b/compiler/rustc_mir_build/src/build/block.rs @@ -245,11 +245,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { OutsideGuard, true, ); - this.schedule_drop_for_binding( - node, - span, - OutsideGuard, - ); }, ); this.ast_let_else( diff --git a/compiler/rustc_mir_build/src/build/expr/into.rs b/compiler/rustc_mir_build/src/build/expr/into.rs index 4b8c134b9d0a8..24ecd0a539949 100644 --- a/compiler/rustc_mir_build/src/build/expr/into.rs +++ b/compiler/rustc_mir_build/src/build/expr/into.rs @@ -74,7 +74,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { this.source_info(then_expr.span) }; let (then_block, else_block) = - this.in_if_then_scope(condition_scope, |this| { + this.in_if_then_scope(condition_scope, then_expr.span, |this| { let then_blk = unpack!(this.then_else_break( block, &this.thir[cond], @@ -107,7 +107,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } ExprKind::Let { expr, ref pat } => { let scope = this.local_scope(); - let (true_block, false_block) = this.in_if_then_scope(scope, |this| { + let (true_block, false_block) = this.in_if_then_scope(scope, expr_span, |this| { this.lower_let_expr(block, &this.thir[expr], pat, scope, None, expr_span) }); diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs index 4fddc24301aba..3f813e0af0da3 100644 --- a/compiler/rustc_mir_build/src/build/matches/mod.rs +++ b/compiler/rustc_mir_build/src/build/matches/mod.rs @@ -1986,7 +1986,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let mut guard_span = rustc_span::DUMMY_SP; let (post_guard_block, otherwise_post_guard_block) = - self.in_if_then_scope(match_scope, |this| match *guard { + self.in_if_then_scope(match_scope, guard_span, |this| match *guard { Guard::If(e) => { let e = &this.thir[e]; guard_span = e.span; @@ -2301,7 +2301,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { pattern: &Pat<'tcx>, ) -> BlockAnd { let else_block_span = self.thir[else_block].span; - let (matching, failure) = self.in_if_then_scope(*let_else_scope, |this| { + let (matching, failure) = self.in_if_then_scope(*let_else_scope, else_block_span, |this| { let scrutinee = unpack!(block = this.lower_scrutinee(block, init, initializer_span)); let pat = Pat { ty: init.ty, span: else_block_span, kind: PatKind::Wild }; let mut wildcard = Candidate::new(scrutinee.clone(), &pat, false, this); diff --git a/compiler/rustc_mir_build/src/build/scope.rs b/compiler/rustc_mir_build/src/build/scope.rs index 2c7d6a572f45b..2d29d0b6928b6 100644 --- a/compiler/rustc_mir_build/src/build/scope.rs +++ b/compiler/rustc_mir_build/src/build/scope.rs @@ -466,9 +466,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let normal_exit_block = f(self); let breakable_scope = self.scopes.breakable_scopes.pop().unwrap(); assert!(breakable_scope.region_scope == region_scope); - let break_block = self.build_exit_tree(breakable_scope.break_drops, None); + let break_block = + self.build_exit_tree(breakable_scope.break_drops, region_scope, span, None); if let Some(drops) = breakable_scope.continue_drops { - self.build_exit_tree(drops, loop_block); + self.build_exit_tree(drops, region_scope, span, loop_block); } match (normal_exit_block, break_block) { (Some(block), None) | (None, Some(block)) => block, @@ -510,6 +511,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { pub(crate) fn in_if_then_scope( &mut self, region_scope: region::Scope, + span: Span, f: F, ) -> (BasicBlock, BasicBlock) where @@ -524,7 +526,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { assert!(if_then_scope.region_scope == region_scope); let else_block = self - .build_exit_tree(if_then_scope.else_drops, None) + .build_exit_tree(if_then_scope.else_drops, region_scope, span, None) .map_or_else(|| self.cfg.start_new_block(), |else_block_and| unpack!(else_block_and)); (then_block, else_block) @@ -1021,6 +1023,38 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { cached_drop } + /// This is similar to [diverge_cleanup_target] except its target is set to + /// some ancestor scope instead of the current scope. + /// It is possible to unwind to some ancestor scope if some drop panics as + /// the program breaks out of a if-then scope. + fn diverge_cleanup_target(&mut self, target_scope: region::Scope, span: Span) -> DropIdx { + let target = self.scopes.scope_index(target_scope, span); + let (uncached_scope, mut cached_drop) = self.scopes.scopes[..=target] + .iter() + .enumerate() + .rev() + .find_map(|(scope_idx, scope)| { + scope.cached_unwind_block.map(|cached_block| (scope_idx + 1, cached_block)) + }) + .unwrap_or((0, ROOT_NODE)); + + if uncached_scope > target { + return cached_drop; + } + + let is_generator = self.generator_kind.is_some(); + for scope in &mut self.scopes.scopes[uncached_scope..=target] { + for drop in &scope.drops { + if is_generator || drop.kind == DropKind::Value { + cached_drop = self.scopes.unwind_drops.add_drop(*drop, cached_drop); + } + } + scope.cached_unwind_block = Some(cached_drop); + } + + cached_drop + } + /// Prepares to create a path that performs all required cleanup for a /// terminator that can unwind at the given basic block. /// @@ -1222,21 +1256,24 @@ impl<'a, 'tcx: 'a> Builder<'a, 'tcx> { fn build_exit_tree( &mut self, mut drops: DropTree, + else_scope: region::Scope, + span: Span, continue_block: Option, ) -> Option> { let mut blocks = IndexVec::from_elem(None, &drops.drops); blocks[ROOT_NODE] = continue_block; drops.build_mir::(&mut self.cfg, &mut blocks); + let is_generator = self.generator_kind.is_some(); // Link the exit drop tree to unwind drop tree. if drops.drops.iter().any(|(drop, _)| drop.kind == DropKind::Value) { - let unwind_target = self.diverge_cleanup(); + let unwind_target = self.diverge_cleanup_target(else_scope, span); let mut unwind_indices = IndexVec::from_elem_n(unwind_target, 1); for (drop_idx, drop_data) in drops.drops.iter_enumerated().skip(1) { match drop_data.0.kind { DropKind::Storage => { - if self.generator_kind.is_some() { + if is_generator { let unwind_drop = self .scopes .unwind_drops diff --git a/src/test/ui/let-else/issue-102317.rs b/src/test/ui/let-else/issue-102317.rs new file mode 100644 index 0000000000000..7dfaf1358ae7d --- /dev/null +++ b/src/test/ui/let-else/issue-102317.rs @@ -0,0 +1,20 @@ +// issue #102317 +// run-pass +// compile-flags: --edition 2021 -C opt-level=3 -Zvalidate-mir + +struct SegmentJob; + +impl Drop for SegmentJob { + fn drop(&mut self) {} +} + +pub async fn run() -> Result<(), ()> { + let jobs = Vec::::new(); + let Some(_job) = jobs.into_iter().next() else { + return Ok(()) + }; + + Ok(()) +} + +fn main() {} diff --git a/src/test/ui/mir/issue-99852.rs b/src/test/ui/mir/issue-99852.rs new file mode 100644 index 0000000000000..1c675788ee933 --- /dev/null +++ b/src/test/ui/mir/issue-99852.rs @@ -0,0 +1,24 @@ +// check-pass +// compile-flags: -Z validate-mir +#![feature(let_chains)] + +fn lambda() -> U +where + T: Default, + U: Default, +{ + let foo: Result = Ok(T::default()); + let baz: U = U::default(); + + if let Ok(foo) = foo && let Ok(bar) = transform(foo) { + bar + } else { + baz + } +} + +fn transform(input: T) -> Result { + todo!() +} + +fn main() {} From ac310e6643872b7e0553d3c8a3357c835c335916 Mon Sep 17 00:00:00 2001 From: Marijn Schouten Date: Wed, 28 Sep 2022 14:52:59 +0200 Subject: [PATCH 367/586] Update result.rs Remove a FIXME whose code got moved away in https://github.com/rust-lang/rust/pull/62883. --- library/core/src/result.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/library/core/src/result.rs b/library/core/src/result.rs index dc90e90402c8e..41fcb14d42bec 100644 --- a/library/core/src/result.rs +++ b/library/core/src/result.rs @@ -2066,9 +2066,6 @@ impl> FromIterator> for Result { /// so the final value of `shared` is 6 (= `3 + 2 + 1`), not 16. #[inline] fn from_iter>>(iter: I) -> Result { - // FIXME(#11084): This could be replaced with Iterator::scan when this - // performance bug is closed. - iter::try_process(iter.into_iter(), |i| i.collect()) } } From 9ccb85118203d914b349e506916fe2fe0c907e86 Mon Sep 17 00:00:00 2001 From: lcnr Date: Wed, 28 Sep 2022 17:04:29 +0200 Subject: [PATCH 368/586] update fixme --- .../rustc_trait_selection/src/traits/select/mod.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 5e32a27cdb1da..0ed59223337a5 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -1737,12 +1737,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { (&ImplCandidate(other_def), &ImplCandidate(victim_def)) => { // See if we can toss out `victim` based on specialization. - // This requires us to know *for sure* that the `other` impl applies - // i.e., `EvaluatedToOk`. + // While this requires us to know *for sure* that the `other` impl applies + // we still use modulo regions here. // - // FIXME(@lcnr): Using `modulo_regions` here seems kind of scary - // to me but is required for `std` to compile, so I didn't change it - // for now. + // This is fine as specialization currently assumes that specializing + // impls have to be always applicable, meaning that the only allowed + // region constraints may be constraints also present on the default impl. let tcx = self.tcx(); if other.evaluation.must_apply_modulo_regions() { if tcx.specializes((other_def, victim_def)) { From 2ee2ffa9a7266b9a3b3b9fe599fde651cdd94ba6 Mon Sep 17 00:00:00 2001 From: Rageking8 Date: Tue, 27 Sep 2022 16:08:04 +0800 Subject: [PATCH 369/586] improve E0585 help --- compiler/rustc_error_messages/locales/en-US/parser.ftl | 2 +- compiler/rustc_parse/src/parser/item.rs | 4 ++-- src/test/ui/error-codes/E0585.stderr | 2 +- src/test/ui/parser/doc-after-struct-field.rs | 4 ++-- src/test/ui/parser/doc-after-struct-field.stderr | 4 ++-- src/test/ui/parser/doc-before-extern-rbrace.stderr | 2 +- src/test/ui/parser/doc-before-fn-rbrace.rs | 2 +- src/test/ui/parser/doc-before-fn-rbrace.stderr | 2 +- src/test/ui/parser/doc-before-rbrace.rs | 2 +- src/test/ui/parser/doc-before-rbrace.stderr | 2 +- src/test/ui/parser/doc-before-semi.rs | 2 +- src/test/ui/parser/doc-before-semi.stderr | 2 +- src/test/ui/parser/doc-before-struct-rbrace-1.rs | 2 +- src/test/ui/parser/doc-before-struct-rbrace-1.stderr | 2 +- src/test/ui/parser/doc-before-struct-rbrace-2.rs | 2 +- src/test/ui/parser/doc-before-struct-rbrace-2.stderr | 2 +- src/test/ui/parser/doc-inside-trait-item.stderr | 2 +- src/test/ui/parser/issues/issue-34222-1.stderr | 2 +- src/test/ui/parser/issues/issue-48636.stderr | 2 +- 19 files changed, 22 insertions(+), 22 deletions(-) diff --git a/compiler/rustc_error_messages/locales/en-US/parser.ftl b/compiler/rustc_error_messages/locales/en-US/parser.ftl index 6d34cdce3408f..13c368d1c5850 100644 --- a/compiler/rustc_error_messages/locales/en-US/parser.ftl +++ b/compiler/rustc_error_messages/locales/en-US/parser.ftl @@ -245,7 +245,7 @@ parser_assignment_else_not_allowed = ... else {"{"} ... {"}"} is no parser_expected_statement_after_outer_attr = expected statement after outer attribute parser_doc_comment_does_not_document_anything = found a documentation comment that doesn't document anything - .help = doc comments must come before what they document, maybe a comment was intended with `//`? + .help = doc comments must come before what they document, if a comment was intended use `//` .suggestion = missing comma here parser_const_let_mutually_exclusive = `const` and `let` are mutually exclusive diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index b7454d7bfc18e..c8a8e00b1fa03 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -760,8 +760,8 @@ impl<'a> Parser<'a> { ) .span_label(self.token.span, "this doc comment doesn't document anything") .help( - "doc comments must come before what they document, maybe a \ - comment was intended with `//`?", + "doc comments must come before what they document, if a comment was \ + intended use `//`", ) .emit(); self.bump(); diff --git a/src/test/ui/error-codes/E0585.stderr b/src/test/ui/error-codes/E0585.stderr index 7a31c4896ee8e..53c82fb416b81 100644 --- a/src/test/ui/error-codes/E0585.stderr +++ b/src/test/ui/error-codes/E0585.stderr @@ -4,7 +4,7 @@ error[E0585]: found a documentation comment that doesn't document anything LL | /// Hello! I'm useless... | ^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: doc comments must come before what they document, maybe a comment was intended with `//`? + = help: doc comments must come before what they document, if a comment was intended use `//` error: aborting due to previous error diff --git a/src/test/ui/parser/doc-after-struct-field.rs b/src/test/ui/parser/doc-after-struct-field.rs index 5b6f080360336..03faa6733e21f 100644 --- a/src/test/ui/parser/doc-after-struct-field.rs +++ b/src/test/ui/parser/doc-after-struct-field.rs @@ -1,13 +1,13 @@ struct X { a: u8 /** document a */, //~^ ERROR found a documentation comment that doesn't document anything - //~| HELP maybe a comment was intended + //~| HELP if a comment was intended use `//` } struct Y { a: u8 /// document a //~^ ERROR found a documentation comment that doesn't document anything - //~| HELP maybe a comment was intended + //~| HELP if a comment was intended use `//` } fn main() { diff --git a/src/test/ui/parser/doc-after-struct-field.stderr b/src/test/ui/parser/doc-after-struct-field.stderr index e3b32a7f03543..ae177f1a2d1eb 100644 --- a/src/test/ui/parser/doc-after-struct-field.stderr +++ b/src/test/ui/parser/doc-after-struct-field.stderr @@ -4,7 +4,7 @@ error[E0585]: found a documentation comment that doesn't document anything LL | a: u8 /** document a */, | ^^^^^^^^^^^^^^^^^ | - = help: doc comments must come before what they document, maybe a comment was intended with `//`? + = help: doc comments must come before what they document, if a comment was intended use `//` error[E0585]: found a documentation comment that doesn't document anything --> $DIR/doc-after-struct-field.rs:8:11 @@ -12,7 +12,7 @@ error[E0585]: found a documentation comment that doesn't document anything LL | a: u8 /// document a | ^^^^^^^^^^^^^^ | - = help: doc comments must come before what they document, maybe a comment was intended with `//`? + = help: doc comments must come before what they document, if a comment was intended use `//` error: aborting due to 2 previous errors diff --git a/src/test/ui/parser/doc-before-extern-rbrace.stderr b/src/test/ui/parser/doc-before-extern-rbrace.stderr index 0edceb268a7f5..8fa12ec261e09 100644 --- a/src/test/ui/parser/doc-before-extern-rbrace.stderr +++ b/src/test/ui/parser/doc-before-extern-rbrace.stderr @@ -4,7 +4,7 @@ error[E0584]: found a documentation comment that doesn't document anything LL | /// hi | ^^^^^^ this doc comment doesn't document anything | - = help: doc comments must come before what they document, maybe a comment was intended with `//`? + = help: doc comments must come before what they document, if a comment was intended use `//` error: aborting due to previous error diff --git a/src/test/ui/parser/doc-before-fn-rbrace.rs b/src/test/ui/parser/doc-before-fn-rbrace.rs index eb355136f1e66..c850216485452 100644 --- a/src/test/ui/parser/doc-before-fn-rbrace.rs +++ b/src/test/ui/parser/doc-before-fn-rbrace.rs @@ -1,5 +1,5 @@ fn main() { /// document //~^ ERROR found a documentation comment that doesn't document anything - //~| HELP maybe a comment was intended + //~| HELP if a comment was intended use `//` } diff --git a/src/test/ui/parser/doc-before-fn-rbrace.stderr b/src/test/ui/parser/doc-before-fn-rbrace.stderr index 56241de709247..6ea68e42b4cd3 100644 --- a/src/test/ui/parser/doc-before-fn-rbrace.stderr +++ b/src/test/ui/parser/doc-before-fn-rbrace.stderr @@ -4,7 +4,7 @@ error[E0585]: found a documentation comment that doesn't document anything LL | /// document | ^^^^^^^^^^^^ | - = help: doc comments must come before what they document, maybe a comment was intended with `//`? + = help: doc comments must come before what they document, if a comment was intended use `//` error: aborting due to previous error diff --git a/src/test/ui/parser/doc-before-rbrace.rs b/src/test/ui/parser/doc-before-rbrace.rs index 8ff946344aee8..570306f2cdf83 100644 --- a/src/test/ui/parser/doc-before-rbrace.rs +++ b/src/test/ui/parser/doc-before-rbrace.rs @@ -1,5 +1,5 @@ fn main() { println!("Hi"); /// hi //~^ ERROR found a documentation comment that doesn't document anything - //~| HELP maybe a comment was intended + //~| HELP if a comment was intended use `//` } diff --git a/src/test/ui/parser/doc-before-rbrace.stderr b/src/test/ui/parser/doc-before-rbrace.stderr index 55719cf641195..4d4741dfe59cd 100644 --- a/src/test/ui/parser/doc-before-rbrace.stderr +++ b/src/test/ui/parser/doc-before-rbrace.stderr @@ -4,7 +4,7 @@ error[E0585]: found a documentation comment that doesn't document anything LL | println!("Hi"); /// hi | ^^^^^^ | - = help: doc comments must come before what they document, maybe a comment was intended with `//`? + = help: doc comments must come before what they document, if a comment was intended use `//` error: aborting due to previous error diff --git a/src/test/ui/parser/doc-before-semi.rs b/src/test/ui/parser/doc-before-semi.rs index 405a7e1e2a33b..444b5874ea286 100644 --- a/src/test/ui/parser/doc-before-semi.rs +++ b/src/test/ui/parser/doc-before-semi.rs @@ -1,6 +1,6 @@ fn main() { /// hi //~^ ERROR found a documentation comment that doesn't document anything - //~| HELP maybe a comment was intended + //~| HELP if a comment was intended use `//` ; } diff --git a/src/test/ui/parser/doc-before-semi.stderr b/src/test/ui/parser/doc-before-semi.stderr index e6bade18d0a2d..a879e13ffbd62 100644 --- a/src/test/ui/parser/doc-before-semi.stderr +++ b/src/test/ui/parser/doc-before-semi.stderr @@ -4,7 +4,7 @@ error[E0585]: found a documentation comment that doesn't document anything LL | /// hi | ^^^^^^ | - = help: doc comments must come before what they document, maybe a comment was intended with `//`? + = help: doc comments must come before what they document, if a comment was intended use `//` error: aborting due to previous error diff --git a/src/test/ui/parser/doc-before-struct-rbrace-1.rs b/src/test/ui/parser/doc-before-struct-rbrace-1.rs index 3866a3105c25a..0c8d90c3b0371 100644 --- a/src/test/ui/parser/doc-before-struct-rbrace-1.rs +++ b/src/test/ui/parser/doc-before-struct-rbrace-1.rs @@ -2,7 +2,7 @@ struct X { a: u8, /// document //~^ ERROR found a documentation comment that doesn't document anything - //~| HELP maybe a comment was intended + //~| HELP if a comment was intended use `//` } fn main() { diff --git a/src/test/ui/parser/doc-before-struct-rbrace-1.stderr b/src/test/ui/parser/doc-before-struct-rbrace-1.stderr index 92b5133b74dd6..94934f734b394 100644 --- a/src/test/ui/parser/doc-before-struct-rbrace-1.stderr +++ b/src/test/ui/parser/doc-before-struct-rbrace-1.stderr @@ -7,7 +7,7 @@ LL | a: u8, LL | /// document | ^^^^^^^^^^^^ | - = help: doc comments must come before what they document, maybe a comment was intended with `//`? + = help: doc comments must come before what they document, if a comment was intended use `//` error: aborting due to previous error diff --git a/src/test/ui/parser/doc-before-struct-rbrace-2.rs b/src/test/ui/parser/doc-before-struct-rbrace-2.rs index dda138f1a8835..2b2aadf7984a2 100644 --- a/src/test/ui/parser/doc-before-struct-rbrace-2.rs +++ b/src/test/ui/parser/doc-before-struct-rbrace-2.rs @@ -1,7 +1,7 @@ struct X { a: u8 /// document //~^ ERROR found a documentation comment that doesn't document anything - //~| HELP maybe a comment was intended + //~| HELP if a comment was intended use `//` } fn main() { diff --git a/src/test/ui/parser/doc-before-struct-rbrace-2.stderr b/src/test/ui/parser/doc-before-struct-rbrace-2.stderr index b25ccab79f94a..6b5c8c1f8b531 100644 --- a/src/test/ui/parser/doc-before-struct-rbrace-2.stderr +++ b/src/test/ui/parser/doc-before-struct-rbrace-2.stderr @@ -4,7 +4,7 @@ error[E0585]: found a documentation comment that doesn't document anything LL | a: u8 /// document | ^^^^^^^^^^^^ | - = help: doc comments must come before what they document, maybe a comment was intended with `//`? + = help: doc comments must come before what they document, if a comment was intended use `//` error: aborting due to previous error diff --git a/src/test/ui/parser/doc-inside-trait-item.stderr b/src/test/ui/parser/doc-inside-trait-item.stderr index 246255a0a4675..900124adcc3b8 100644 --- a/src/test/ui/parser/doc-inside-trait-item.stderr +++ b/src/test/ui/parser/doc-inside-trait-item.stderr @@ -4,7 +4,7 @@ error[E0584]: found a documentation comment that doesn't document anything LL | /// empty doc | ^^^^^^^^^^^^^ this doc comment doesn't document anything | - = help: doc comments must come before what they document, maybe a comment was intended with `//`? + = help: doc comments must come before what they document, if a comment was intended use `//` error: aborting due to previous error diff --git a/src/test/ui/parser/issues/issue-34222-1.stderr b/src/test/ui/parser/issues/issue-34222-1.stderr index 0799656b06bd2..b451484ba224b 100644 --- a/src/test/ui/parser/issues/issue-34222-1.stderr +++ b/src/test/ui/parser/issues/issue-34222-1.stderr @@ -4,7 +4,7 @@ error[E0585]: found a documentation comment that doesn't document anything LL | /// comment | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: doc comments must come before what they document, maybe a comment was intended with `//`? + = help: doc comments must come before what they document, if a comment was intended use `//` error: aborting due to previous error diff --git a/src/test/ui/parser/issues/issue-48636.stderr b/src/test/ui/parser/issues/issue-48636.stderr index 1a6e4cfd2b203..6177870d1cee9 100644 --- a/src/test/ui/parser/issues/issue-48636.stderr +++ b/src/test/ui/parser/issues/issue-48636.stderr @@ -8,7 +8,7 @@ LL | x: u8 LL | /// The ID of the parent core | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: doc comments must come before what they document, maybe a comment was intended with `//`? + = help: doc comments must come before what they document, if a comment was intended use `//` error: aborting due to previous error From a91327782906885ccd8b8bf25e1e7f9ea46f8428 Mon Sep 17 00:00:00 2001 From: beetrees Date: Wed, 14 Sep 2022 11:43:02 +0100 Subject: [PATCH 370/586] Add a niche to `Duration`, unix `SystemTime`, and non-apple `Instant` --- library/core/src/time.rs | 98 +++++++++++++++++--------------- library/std/src/sys/unix/time.rs | 34 ++++++----- src/etc/natvis/libcore.natvis | 4 +- 3 files changed, 75 insertions(+), 61 deletions(-) diff --git a/library/core/src/time.rs b/library/core/src/time.rs index 4f29ecc0fba8b..2b85d6e22258f 100644 --- a/library/core/src/time.rs +++ b/library/core/src/time.rs @@ -29,6 +29,20 @@ const NANOS_PER_MICRO: u32 = 1_000; const MILLIS_PER_SEC: u64 = 1_000; const MICROS_PER_SEC: u64 = 1_000_000; +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[repr(transparent)] +#[rustc_layout_scalar_valid_range_start(0)] +#[rustc_layout_scalar_valid_range_end(999_999_999)] +struct Nanoseconds(u32); + +impl Default for Nanoseconds { + #[inline] + fn default() -> Self { + // SAFETY: 0 is within the valid range + unsafe { Nanoseconds(0) } + } +} + /// A `Duration` type to represent a span of time, typically used for system /// timeouts. /// @@ -71,7 +85,7 @@ const MICROS_PER_SEC: u64 = 1_000_000; #[cfg_attr(not(test), rustc_diagnostic_item = "Duration")] pub struct Duration { secs: u64, - nanos: u32, // Always 0 <= nanos < NANOS_PER_SEC + nanos: Nanoseconds, // Always 0 <= nanos < NANOS_PER_SEC } impl Duration { @@ -188,7 +202,8 @@ impl Duration { None => panic!("overflow in Duration::new"), }; let nanos = nanos % NANOS_PER_SEC; - Duration { secs, nanos } + // SAFETY: nanos % NANOS_PER_SEC < NANOS_PER_SEC, therefore nanos is within the valid range + Duration { secs, nanos: unsafe { Nanoseconds(nanos) } } } /// Creates a new `Duration` from the specified number of whole seconds. @@ -208,7 +223,7 @@ impl Duration { #[inline] #[rustc_const_stable(feature = "duration_consts", since = "1.32.0")] pub const fn from_secs(secs: u64) -> Duration { - Duration { secs, nanos: 0 } + Duration::new(secs, 0) } /// Creates a new `Duration` from the specified number of milliseconds. @@ -228,10 +243,7 @@ impl Duration { #[inline] #[rustc_const_stable(feature = "duration_consts", since = "1.32.0")] pub const fn from_millis(millis: u64) -> Duration { - Duration { - secs: millis / MILLIS_PER_SEC, - nanos: ((millis % MILLIS_PER_SEC) as u32) * NANOS_PER_MILLI, - } + Duration::new(millis / MILLIS_PER_SEC, ((millis % MILLIS_PER_SEC) as u32) * NANOS_PER_MILLI) } /// Creates a new `Duration` from the specified number of microseconds. @@ -251,10 +263,7 @@ impl Duration { #[inline] #[rustc_const_stable(feature = "duration_consts", since = "1.32.0")] pub const fn from_micros(micros: u64) -> Duration { - Duration { - secs: micros / MICROS_PER_SEC, - nanos: ((micros % MICROS_PER_SEC) as u32) * NANOS_PER_MICRO, - } + Duration::new(micros / MICROS_PER_SEC, ((micros % MICROS_PER_SEC) as u32) * NANOS_PER_MICRO) } /// Creates a new `Duration` from the specified number of nanoseconds. @@ -274,10 +283,7 @@ impl Duration { #[inline] #[rustc_const_stable(feature = "duration_consts", since = "1.32.0")] pub const fn from_nanos(nanos: u64) -> Duration { - Duration { - secs: nanos / (NANOS_PER_SEC as u64), - nanos: (nanos % (NANOS_PER_SEC as u64)) as u32, - } + Duration::new(nanos / (NANOS_PER_SEC as u64), (nanos % (NANOS_PER_SEC as u64)) as u32) } /// Returns true if this `Duration` spans no time. @@ -301,7 +307,7 @@ impl Duration { #[rustc_const_stable(feature = "duration_zero", since = "1.53.0")] #[inline] pub const fn is_zero(&self) -> bool { - self.secs == 0 && self.nanos == 0 + self.secs == 0 && self.nanos.0 == 0 } /// Returns the number of _whole_ seconds contained by this `Duration`. @@ -352,7 +358,7 @@ impl Duration { #[must_use] #[inline] pub const fn subsec_millis(&self) -> u32 { - self.nanos / NANOS_PER_MILLI + self.nanos.0 / NANOS_PER_MILLI } /// Returns the fractional part of this `Duration`, in whole microseconds. @@ -375,7 +381,7 @@ impl Duration { #[must_use] #[inline] pub const fn subsec_micros(&self) -> u32 { - self.nanos / NANOS_PER_MICRO + self.nanos.0 / NANOS_PER_MICRO } /// Returns the fractional part of this `Duration`, in nanoseconds. @@ -398,7 +404,7 @@ impl Duration { #[must_use] #[inline] pub const fn subsec_nanos(&self) -> u32 { - self.nanos + self.nanos.0 } /// Returns the total number of whole milliseconds contained by this `Duration`. @@ -416,7 +422,7 @@ impl Duration { #[must_use] #[inline] pub const fn as_millis(&self) -> u128 { - self.secs as u128 * MILLIS_PER_SEC as u128 + (self.nanos / NANOS_PER_MILLI) as u128 + self.secs as u128 * MILLIS_PER_SEC as u128 + (self.nanos.0 / NANOS_PER_MILLI) as u128 } /// Returns the total number of whole microseconds contained by this `Duration`. @@ -434,7 +440,7 @@ impl Duration { #[must_use] #[inline] pub const fn as_micros(&self) -> u128 { - self.secs as u128 * MICROS_PER_SEC as u128 + (self.nanos / NANOS_PER_MICRO) as u128 + self.secs as u128 * MICROS_PER_SEC as u128 + (self.nanos.0 / NANOS_PER_MICRO) as u128 } /// Returns the total number of nanoseconds contained by this `Duration`. @@ -452,7 +458,7 @@ impl Duration { #[must_use] #[inline] pub const fn as_nanos(&self) -> u128 { - self.secs as u128 * NANOS_PER_SEC as u128 + self.nanos as u128 + self.secs as u128 * NANOS_PER_SEC as u128 + self.nanos.0 as u128 } /// Checked `Duration` addition. Computes `self + other`, returning [`None`] @@ -475,7 +481,7 @@ impl Duration { #[rustc_const_stable(feature = "duration_consts_2", since = "1.58.0")] pub const fn checked_add(self, rhs: Duration) -> Option { if let Some(mut secs) = self.secs.checked_add(rhs.secs) { - let mut nanos = self.nanos + rhs.nanos; + let mut nanos = self.nanos.0 + rhs.nanos.0; if nanos >= NANOS_PER_SEC { nanos -= NANOS_PER_SEC; if let Some(new_secs) = secs.checked_add(1) { @@ -485,7 +491,7 @@ impl Duration { } } debug_assert!(nanos < NANOS_PER_SEC); - Some(Duration { secs, nanos }) + Some(Duration::new(secs, nanos)) } else { None } @@ -535,16 +541,16 @@ impl Duration { #[rustc_const_stable(feature = "duration_consts_2", since = "1.58.0")] pub const fn checked_sub(self, rhs: Duration) -> Option { if let Some(mut secs) = self.secs.checked_sub(rhs.secs) { - let nanos = if self.nanos >= rhs.nanos { - self.nanos - rhs.nanos + let nanos = if self.nanos.0 >= rhs.nanos.0 { + self.nanos.0 - rhs.nanos.0 } else if let Some(sub_secs) = secs.checked_sub(1) { secs = sub_secs; - self.nanos + NANOS_PER_SEC - rhs.nanos + self.nanos.0 + NANOS_PER_SEC - rhs.nanos.0 } else { return None; }; debug_assert!(nanos < NANOS_PER_SEC); - Some(Duration { secs, nanos }) + Some(Duration::new(secs, nanos)) } else { None } @@ -593,13 +599,13 @@ impl Duration { #[rustc_const_stable(feature = "duration_consts_2", since = "1.58.0")] pub const fn checked_mul(self, rhs: u32) -> Option { // Multiply nanoseconds as u64, because it cannot overflow that way. - let total_nanos = self.nanos as u64 * rhs as u64; + let total_nanos = self.nanos.0 as u64 * rhs as u64; let extra_secs = total_nanos / (NANOS_PER_SEC as u64); let nanos = (total_nanos % (NANOS_PER_SEC as u64)) as u32; if let Some(s) = self.secs.checked_mul(rhs as u64) { if let Some(secs) = s.checked_add(extra_secs) { debug_assert!(nanos < NANOS_PER_SEC); - return Some(Duration { secs, nanos }); + return Some(Duration::new(secs, nanos)); } } None @@ -653,9 +659,9 @@ impl Duration { let secs = self.secs / (rhs as u64); let carry = self.secs - secs * (rhs as u64); let extra_nanos = carry * (NANOS_PER_SEC as u64) / (rhs as u64); - let nanos = self.nanos / rhs + (extra_nanos as u32); + let nanos = self.nanos.0 / rhs + (extra_nanos as u32); debug_assert!(nanos < NANOS_PER_SEC); - Some(Duration { secs, nanos }) + Some(Duration::new(secs, nanos)) } else { None } @@ -677,7 +683,7 @@ impl Duration { #[inline] #[rustc_const_unstable(feature = "duration_consts_float", issue = "72440")] pub const fn as_secs_f64(&self) -> f64 { - (self.secs as f64) + (self.nanos as f64) / (NANOS_PER_SEC as f64) + (self.secs as f64) + (self.nanos.0 as f64) / (NANOS_PER_SEC as f64) } /// Returns the number of seconds contained by this `Duration` as `f32`. @@ -696,7 +702,7 @@ impl Duration { #[inline] #[rustc_const_unstable(feature = "duration_consts_float", issue = "72440")] pub const fn as_secs_f32(&self) -> f32 { - (self.secs as f32) + (self.nanos as f32) / (NANOS_PER_SEC as f32) + (self.secs as f32) + (self.nanos.0 as f32) / (NANOS_PER_SEC as f32) } /// Creates a new `Duration` from the specified number of seconds represented @@ -987,13 +993,13 @@ macro_rules! sum_durations { for entry in $iter { total_secs = total_secs.checked_add(entry.secs).expect("overflow in iter::sum over durations"); - total_nanos = match total_nanos.checked_add(entry.nanos as u64) { + total_nanos = match total_nanos.checked_add(entry.nanos.0 as u64) { Some(n) => n, None => { total_secs = total_secs .checked_add(total_nanos / NANOS_PER_SEC as u64) .expect("overflow in iter::sum over durations"); - (total_nanos % NANOS_PER_SEC as u64) + entry.nanos as u64 + (total_nanos % NANOS_PER_SEC as u64) + entry.nanos.0 as u64 } }; } @@ -1001,7 +1007,7 @@ macro_rules! sum_durations { .checked_add(total_nanos / NANOS_PER_SEC as u64) .expect("overflow in iter::sum over durations"); total_nanos = total_nanos % NANOS_PER_SEC as u64; - Duration { secs: total_secs, nanos: total_nanos as u32 } + Duration::new(total_secs, total_nanos as u32) }}; } @@ -1166,27 +1172,27 @@ impl fmt::Debug for Duration { let prefix = if f.sign_plus() { "+" } else { "" }; if self.secs > 0 { - fmt_decimal(f, self.secs, self.nanos, NANOS_PER_SEC / 10, prefix, "s") - } else if self.nanos >= NANOS_PER_MILLI { + fmt_decimal(f, self.secs, self.nanos.0, NANOS_PER_SEC / 10, prefix, "s") + } else if self.nanos.0 >= NANOS_PER_MILLI { fmt_decimal( f, - (self.nanos / NANOS_PER_MILLI) as u64, - self.nanos % NANOS_PER_MILLI, + (self.nanos.0 / NANOS_PER_MILLI) as u64, + self.nanos.0 % NANOS_PER_MILLI, NANOS_PER_MILLI / 10, prefix, "ms", ) - } else if self.nanos >= NANOS_PER_MICRO { + } else if self.nanos.0 >= NANOS_PER_MICRO { fmt_decimal( f, - (self.nanos / NANOS_PER_MICRO) as u64, - self.nanos % NANOS_PER_MICRO, + (self.nanos.0 / NANOS_PER_MICRO) as u64, + self.nanos.0 % NANOS_PER_MICRO, NANOS_PER_MICRO / 10, prefix, "µs", ) } else { - fmt_decimal(f, self.nanos as u64, 0, 1, prefix, "ns") + fmt_decimal(f, self.nanos.0 as u64, 0, 1, prefix, "ns") } } } @@ -1317,7 +1323,7 @@ macro_rules! try_from_secs { return Err(FromFloatSecsError { kind: FromFloatSecsErrorKind::OverflowOrNan }); }; - Ok(Duration { secs, nanos }) + Ok(Duration::new(secs, nanos)) }}; } diff --git a/library/std/src/sys/unix/time.rs b/library/std/src/sys/unix/time.rs index dff973f59d1a7..cca9c67670161 100644 --- a/library/std/src/sys/unix/time.rs +++ b/library/std/src/sys/unix/time.rs @@ -6,6 +6,12 @@ pub use self::inner::Instant; const NSEC_PER_SEC: u64 = 1_000_000_000; pub const UNIX_EPOCH: SystemTime = SystemTime { t: Timespec::zero() }; +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[repr(transparent)] +#[rustc_layout_scalar_valid_range_start(0)] +#[rustc_layout_scalar_valid_range_end(999_999_999)] +struct Nanoseconds(u32); + #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct SystemTime { pub(in crate::sys::unix) t: Timespec, @@ -14,7 +20,7 @@ pub struct SystemTime { #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] pub(in crate::sys::unix) struct Timespec { tv_sec: i64, - tv_nsec: i64, + tv_nsec: Nanoseconds, } impl SystemTime { @@ -46,18 +52,20 @@ impl fmt::Debug for SystemTime { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("SystemTime") .field("tv_sec", &self.t.tv_sec) - .field("tv_nsec", &self.t.tv_nsec) + .field("tv_nsec", &self.t.tv_nsec.0) .finish() } } impl Timespec { pub const fn zero() -> Timespec { - Timespec { tv_sec: 0, tv_nsec: 0 } + Timespec::new(0, 0) } - fn new(tv_sec: i64, tv_nsec: i64) -> Timespec { - Timespec { tv_sec, tv_nsec } + const fn new(tv_sec: i64, tv_nsec: i64) -> Timespec { + assert!(tv_nsec >= 0 && tv_nsec < NSEC_PER_SEC as i64); + // SAFETY: The assert above checks tv_nsec is within the valid range + Timespec { tv_sec, tv_nsec: unsafe { Nanoseconds(tv_nsec as u32) } } } pub fn sub_timespec(&self, other: &Timespec) -> Result { @@ -75,12 +83,12 @@ impl Timespec { // // Ideally this code could be rearranged such that it more // directly expresses the lower-cost behavior we want from it. - let (secs, nsec) = if self.tv_nsec >= other.tv_nsec { - ((self.tv_sec - other.tv_sec) as u64, (self.tv_nsec - other.tv_nsec) as u32) + let (secs, nsec) = if self.tv_nsec.0 >= other.tv_nsec.0 { + ((self.tv_sec - other.tv_sec) as u64, self.tv_nsec.0 - other.tv_nsec.0) } else { ( (self.tv_sec - other.tv_sec - 1) as u64, - self.tv_nsec as u32 + (NSEC_PER_SEC as u32) - other.tv_nsec as u32, + self.tv_nsec.0 + (NSEC_PER_SEC as u32) - other.tv_nsec.0, ) }; @@ -102,7 +110,7 @@ impl Timespec { // Nano calculations can't overflow because nanos are <1B which fit // in a u32. - let mut nsec = other.subsec_nanos() + self.tv_nsec as u32; + let mut nsec = other.subsec_nanos() + self.tv_nsec.0; if nsec >= NSEC_PER_SEC as u32 { nsec -= NSEC_PER_SEC as u32; secs = secs.checked_add(1)?; @@ -118,7 +126,7 @@ impl Timespec { .and_then(|secs| self.tv_sec.checked_sub(secs))?; // Similar to above, nanos can't overflow. - let mut nsec = self.tv_nsec as i32 - other.subsec_nanos() as i32; + let mut nsec = self.tv_nsec.0 as i32 - other.subsec_nanos() as i32; if nsec < 0 { nsec += NSEC_PER_SEC as i32; secs = secs.checked_sub(1)?; @@ -130,7 +138,7 @@ impl Timespec { pub fn to_timespec(&self) -> Option { Some(libc::timespec { tv_sec: self.tv_sec.try_into().ok()?, - tv_nsec: self.tv_nsec.try_into().ok()?, + tv_nsec: self.tv_nsec.0.try_into().ok()?, }) } } @@ -293,7 +301,7 @@ mod inner { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("Instant") .field("tv_sec", &self.t.tv_sec) - .field("tv_nsec", &self.t.tv_nsec) + .field("tv_nsec", &self.t.tv_nsec.0) .finish() } } @@ -334,7 +342,7 @@ mod inner { let mut t = MaybeUninit::uninit(); cvt(unsafe { clock_gettime64(clock, t.as_mut_ptr()) }).unwrap(); let t = unsafe { t.assume_init() }; - return Timespec { tv_sec: t.tv_sec, tv_nsec: t.tv_nsec as i64 }; + return Timespec::new(t.tv_sec, t.tv_nsec as i64); } } diff --git a/src/etc/natvis/libcore.natvis b/src/etc/natvis/libcore.natvis index a4e8a57e4b16d..624d8cc5cc55a 100644 --- a/src/etc/natvis/libcore.natvis +++ b/src/etc/natvis/libcore.natvis @@ -154,10 +154,10 @@ - {secs,d}s {nanos,d}ns + {secs,d}s {nanos.__0,d}ns secs,d - nanos,d + nanos.__0,d From 3c3bf76ce0cc9e569e04a242dfdc447131e21db9 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Wed, 28 Sep 2022 10:42:30 -0700 Subject: [PATCH 371/586] Declare `main` as visibility hidden on targets that default to hidden. On targets with `default_hidden_visibility` set, which is currrently just WebAssembly, declare the generated `main` function with visibility hidden. This makes it consistent with clang's WebAssembly target, where `main` is just a user function that gets the same visibility as any other user function, which is hidden on WebAssembly unless explicitly overridden. This will help simplify use cases which in the future may want to automatically wasm-export all visibility-"default" symbols. `main` isn't intended to be wasm-exported, and marking it hidden prevents it from being wasm-exported in that scenario. --- compiler/rustc_codegen_llvm/src/builder.rs | 7 ++++++- compiler/rustc_codegen_llvm/src/context.rs | 17 ++++++++++++++--- compiler/rustc_codegen_llvm/src/declare.rs | 6 +++++- compiler/rustc_codegen_llvm/src/intrinsic.rs | 19 +++++++++++++++---- compiler/rustc_codegen_llvm/src/llvm/mod.rs | 6 ++++++ 5 files changed, 46 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs index 59b1c7fb5dbd0..a6cd1059dc723 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs @@ -1458,7 +1458,12 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> { } else { format!("llvm.{}.sat.i{}.f{}", instr, int_width, float_width) }; - let f = self.declare_cfn(&name, llvm::UnnamedAddr::No, self.type_func(&[src_ty], dest_ty)); + let f = self.declare_cfn( + &name, + llvm::UnnamedAddr::No, + llvm::Visibility::Default, + self.type_func(&[src_ty], dest_ty), + ); self.call(self.type_func(&[src_ty], dest_ty), f, &[val], None) } diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index 67ffc7cb9511f..6aeb56eb5ade0 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -528,7 +528,12 @@ impl<'ll, 'tcx> MiscMethods<'tcx> for CodegenCx<'ll, 'tcx> { llfn } else { let fty = self.type_variadic_func(&[], self.type_i32()); - let llfn = self.declare_cfn(name, llvm::UnnamedAddr::Global, fty); + let llfn = self.declare_cfn( + name, + llvm::UnnamedAddr::Global, + llvm::Visibility::Default, + fty, + ); let target_cpu = attributes::target_cpu_attr(self); attributes::apply_to_llfn(llfn, llvm::AttributePlace::Function, &[target_cpu]); llfn @@ -585,7 +590,13 @@ impl<'ll, 'tcx> MiscMethods<'tcx> for CodegenCx<'ll, 'tcx> { fn declare_c_main(&self, fn_type: Self::Type) -> Option { if self.get_declared_value("main").is_none() { - Some(self.declare_cfn("main", llvm::UnnamedAddr::Global, fn_type)) + let visibility = if self.sess().target.default_hidden_visibility { + llvm::Visibility::Hidden + } else { + llvm::Visibility::Default + }; + + Some(self.declare_cfn("main", llvm::UnnamedAddr::Global, visibility, fn_type)) } else { // If the symbol already exists, it is an error: for example, the user wrote // #[no_mangle] extern "C" fn main(..) {..} @@ -615,7 +626,7 @@ impl<'ll> CodegenCx<'ll, '_> { } else { self.type_variadic_func(&[], ret) }; - let f = self.declare_cfn(name, llvm::UnnamedAddr::No, fn_ty); + let f = self.declare_cfn(name, llvm::UnnamedAddr::No, llvm::Visibility::Default, fn_ty); self.intrinsics.borrow_mut().insert(name, (fn_ty, f)); (fn_ty, f) } diff --git a/compiler/rustc_codegen_llvm/src/declare.rs b/compiler/rustc_codegen_llvm/src/declare.rs index 0f663a26732bb..21c466ddc244f 100644 --- a/compiler/rustc_codegen_llvm/src/declare.rs +++ b/compiler/rustc_codegen_llvm/src/declare.rs @@ -32,6 +32,7 @@ fn declare_raw_fn<'ll>( name: &str, callconv: llvm::CallConv, unnamed: llvm::UnnamedAddr, + visibility: llvm::Visibility, ty: &'ll Type, ) -> &'ll Value { debug!("declare_raw_fn(name={:?}, ty={:?})", name, ty); @@ -41,6 +42,7 @@ fn declare_raw_fn<'ll>( llvm::SetFunctionCallConv(llfn, callconv); llvm::SetUnnamedAddress(llfn, unnamed); + llvm::SetVisibility(llfn, visibility); let mut attrs = SmallVec::<[_; 4]>::new(); @@ -76,9 +78,10 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { &self, name: &str, unnamed: llvm::UnnamedAddr, + visibility: llvm::Visibility, fn_type: &'ll Type, ) -> &'ll Value { - declare_raw_fn(self, name, llvm::CCallConv, unnamed, fn_type) + declare_raw_fn(self, name, llvm::CCallConv, unnamed, visibility, fn_type) } /// Declare a Rust function. @@ -95,6 +98,7 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { name, fn_abi.llvm_cconv(), llvm::UnnamedAddr::Global, + llvm::Visibility::Default, fn_abi.llvm_type(self), ); fn_abi.apply_attrs_llfn(self, llfn); diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index a640de42a6a86..4e1e6371ad481 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -1216,7 +1216,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>( _ => return_error!("unrecognized intrinsic `{}`", name), }; let llvm_name = &format!("llvm.{0}.v{1}{2}", intr_name, in_len, elem_ty_str); - let f = bx.declare_cfn(llvm_name, llvm::UnnamedAddr::No, fn_ty); + let f = bx.declare_cfn(llvm_name, llvm::UnnamedAddr::No, llvm::Visibility::Default, fn_ty); let c = bx.call(fn_ty, f, &args.iter().map(|arg| arg.immediate()).collect::>(), None); Ok(c) @@ -1416,7 +1416,12 @@ fn generic_simd_intrinsic<'ll, 'tcx>( &[llvm_pointer_vec_ty, alignment_ty, mask_ty, llvm_elem_vec_ty], llvm_elem_vec_ty, ); - let f = bx.declare_cfn(&llvm_intrinsic, llvm::UnnamedAddr::No, fn_ty); + let f = bx.declare_cfn( + &llvm_intrinsic, + llvm::UnnamedAddr::No, + llvm::Visibility::Default, + fn_ty, + ); let v = bx.call(fn_ty, f, &[args[1].immediate(), alignment, mask, args[0].immediate()], None); return Ok(v); @@ -1542,7 +1547,12 @@ fn generic_simd_intrinsic<'ll, 'tcx>( format!("llvm.masked.scatter.{}.{}", llvm_elem_vec_str, llvm_pointer_vec_str); let fn_ty = bx.type_func(&[llvm_elem_vec_ty, llvm_pointer_vec_ty, alignment_ty, mask_ty], ret_t); - let f = bx.declare_cfn(&llvm_intrinsic, llvm::UnnamedAddr::No, fn_ty); + let f = bx.declare_cfn( + &llvm_intrinsic, + llvm::UnnamedAddr::No, + llvm::Visibility::Default, + fn_ty, + ); let v = bx.call(fn_ty, f, &[args[0].immediate(), args[1].immediate(), alignment, mask], None); return Ok(v); @@ -1991,7 +2001,8 @@ unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#, let vec_ty = bx.cx.type_vector(elem_ty, in_len as u64); let fn_ty = bx.type_func(&[vec_ty, vec_ty], vec_ty); - let f = bx.declare_cfn(llvm_intrinsic, llvm::UnnamedAddr::No, fn_ty); + let f = + bx.declare_cfn(llvm_intrinsic, llvm::UnnamedAddr::No, llvm::Visibility::Default, fn_ty); let v = bx.call(fn_ty, f, &[lhs, rhs], None); return Ok(v); } diff --git a/compiler/rustc_codegen_llvm/src/llvm/mod.rs b/compiler/rustc_codegen_llvm/src/llvm/mod.rs index 6602a4ab8636c..942e7e0427c11 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/mod.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/mod.rs @@ -172,6 +172,12 @@ pub fn SetUnnamedAddress(global: &Value, unnamed: UnnamedAddr) { } } +pub fn SetVisibility(global: &Value, visibility: Visibility) { + unsafe { + LLVMRustSetVisibility(global, visibility); + } +} + pub fn set_thread_local_mode(global: &Value, mode: ThreadLocalMode) { unsafe { LLVMSetThreadLocalMode(global, mode); From 284c94257fbf32e62bbe3a8f9e71ecb644763df9 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Wed, 28 Sep 2022 11:13:51 -0700 Subject: [PATCH 372/586] Don't export `__wasm_init_memory` on WebAssembly. Since #72889, the Rust wasm target doesn't use --passive-segments, so remove the `--export=__wasm_init_memory`. As documented in the [tool-conventions Linking convention], `__wasm_init_memory` is not intended to be exported. [tool-conventions Linking convention]: https://github.com/WebAssembly/tool-conventions/blob/7c064f304858f67ebf22964a84b7e9658e29557a/Linking.md#shared-memory-and-passive-segments --- compiler/rustc_codegen_ssa/src/back/linker.rs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs index e0bd7a33f7373..8dd08467c0893 100644 --- a/compiler/rustc_codegen_ssa/src/back/linker.rs +++ b/compiler/rustc_codegen_ssa/src/back/linker.rs @@ -1180,18 +1180,12 @@ impl<'a> WasmLd<'a> { // sharing memory and instantiating the module multiple times. As a // result if it were exported then we'd just have no sharing. // - // * `--export=__wasm_init_memory` - when using `--passive-segments` the - // linker will synthesize this function, and so we need to make sure - // that our usage of `--export` below won't accidentally cause this - // function to get deleted. - // // * `--export=*tls*` - when `#[thread_local]` symbols are used these // symbols are how the TLS segments are initialized and configured. if sess.target_features.contains(&sym::atomics) { cmd.arg("--shared-memory"); cmd.arg("--max-memory=1073741824"); cmd.arg("--import-memory"); - cmd.arg("--export=__wasm_init_memory"); cmd.arg("--export=__wasm_init_tls"); cmd.arg("--export=__tls_size"); cmd.arg("--export=__tls_align"); From 5baceaf796936b96769a979f0b475af36dfe9e47 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 28 Sep 2022 21:51:09 +0200 Subject: [PATCH 373/586] env::temp_dir: fix a typo --- library/std/src/env.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/src/env.rs b/library/std/src/env.rs index 463f714064c61..6eb7cbea6269d 100644 --- a/library/std/src/env.rs +++ b/library/std/src/env.rs @@ -603,7 +603,7 @@ pub fn home_dir() -> Option { /// # Platform-specific behavior /// /// On Unix, returns the value of the `TMPDIR` environment variable if it is -/// set, otherwise for non-Android it returns `/tmp`. If Android, since there +/// set, otherwise for non-Android it returns `/tmp`. On Android, since there /// is no global temporary folder (it is usually allocated per-app), it returns /// `/data/local/tmp`. /// On Windows, the behavior is equivalent to that of [`GetTempPath2`][GetTempPath2] / From e5096d4cba080f94448a4e766243f0f0e8083583 Mon Sep 17 00:00:00 2001 From: Cassaundra Smith Date: Fri, 23 Sep 2022 16:26:17 -0700 Subject: [PATCH 374/586] Fix span of byte-escaped left format args brace Fix #102057. --- compiler/rustc_parse_format/src/lib.rs | 2 +- .../fmt/format-args-capture-issue-102057.rs | 19 ++++++++ .../format-args-capture-issue-102057.stderr | 45 +++++++++++++++++++ 3 files changed, 65 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/fmt/format-args-capture-issue-102057.rs create mode 100644 src/test/ui/fmt/format-args-capture-issue-102057.stderr diff --git a/compiler/rustc_parse_format/src/lib.rs b/compiler/rustc_parse_format/src/lib.rs index a9e502016aa8d..df22d79f82e85 100644 --- a/compiler/rustc_parse_format/src/lib.rs +++ b/compiler/rustc_parse_format/src/lib.rs @@ -224,7 +224,7 @@ impl<'a> Iterator for Parser<'a> { '{' => { let curr_last_brace = self.last_opening_brace; let byte_pos = self.to_span_index(pos); - let lbrace_end = InnerOffset(byte_pos.0 + 1); + let lbrace_end = self.to_span_index(pos + 1); self.last_opening_brace = Some(byte_pos.to(lbrace_end)); self.cur.next(); if self.consume('{') { diff --git a/src/test/ui/fmt/format-args-capture-issue-102057.rs b/src/test/ui/fmt/format-args-capture-issue-102057.rs new file mode 100644 index 0000000000000..b8089d49bcb3b --- /dev/null +++ b/src/test/ui/fmt/format-args-capture-issue-102057.rs @@ -0,0 +1,19 @@ +fn main() { + format!("\x7Ba}"); + //~^ ERROR cannot find value `a` in this scope + format!("\x7Ba\x7D"); + //~^ ERROR cannot find value `a` in this scope + + let a = 0; + + format!("\x7Ba} {b}"); + //~^ ERROR cannot find value `b` in this scope + format!("\x7Ba\x7D {b}"); + //~^ ERROR cannot find value `b` in this scope + format!("\x7Ba} \x7Bb}"); + //~^ ERROR cannot find value `b` in this scope + format!("\x7Ba\x7D \x7Bb}"); + //~^ ERROR cannot find value `b` in this scope + format!("\x7Ba\x7D \x7Bb\x7D"); + //~^ ERROR cannot find value `b` in this scope +} diff --git a/src/test/ui/fmt/format-args-capture-issue-102057.stderr b/src/test/ui/fmt/format-args-capture-issue-102057.stderr new file mode 100644 index 0000000000000..f2d625e7f8dc8 --- /dev/null +++ b/src/test/ui/fmt/format-args-capture-issue-102057.stderr @@ -0,0 +1,45 @@ +error[E0425]: cannot find value `a` in this scope + --> $DIR/format-args-capture-issue-102057.rs:2:18 + | +LL | format!("\x7Ba}"); + | ^ not found in this scope + +error[E0425]: cannot find value `a` in this scope + --> $DIR/format-args-capture-issue-102057.rs:4:18 + | +LL | format!("\x7Ba\x7D"); + | ^ not found in this scope + +error[E0425]: cannot find value `b` in this scope + --> $DIR/format-args-capture-issue-102057.rs:9:22 + | +LL | format!("\x7Ba} {b}"); + | ^ help: a local variable with a similar name exists: `a` + +error[E0425]: cannot find value `b` in this scope + --> $DIR/format-args-capture-issue-102057.rs:11:25 + | +LL | format!("\x7Ba\x7D {b}"); + | ^ help: a local variable with a similar name exists: `a` + +error[E0425]: cannot find value `b` in this scope + --> $DIR/format-args-capture-issue-102057.rs:13:25 + | +LL | format!("\x7Ba} \x7Bb}"); + | ^ help: a local variable with a similar name exists: `a` + +error[E0425]: cannot find value `b` in this scope + --> $DIR/format-args-capture-issue-102057.rs:15:28 + | +LL | format!("\x7Ba\x7D \x7Bb}"); + | ^ help: a local variable with a similar name exists: `a` + +error[E0425]: cannot find value `b` in this scope + --> $DIR/format-args-capture-issue-102057.rs:17:28 + | +LL | format!("\x7Ba\x7D \x7Bb\x7D"); + | ^ help: a local variable with a similar name exists: `a` + +error: aborting due to 7 previous errors + +For more information about this error, try `rustc --explain E0425`. From 5f29a13a5b985229fce5fbb75f9af838734ad264 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 14 Sep 2022 17:14:30 +1000 Subject: [PATCH 375/586] Change the "dummy self type". Because this is the only occurrence of a `Res::SelfTy` with `None` and `None` fields, and the next commit will rely on those not being present. --- compiler/rustc_resolve/src/late.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 558db003867d2..bc1c2ba7fe718 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -19,7 +19,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap}; use rustc_errors::DiagnosticId; use rustc_hir::def::Namespace::{self, *}; use rustc_hir::def::{self, CtorKind, DefKind, LifetimeRes, PartialRes, PerNS}; -use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID}; +use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID, LOCAL_CRATE}; use rustc_hir::{BindingAnnotation, PrimTy, TraitCandidate}; use rustc_middle::middle::resolve_lifetime::Set1; use rustc_middle::ty::DefIdTree; @@ -2576,7 +2576,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { }, |this| { // Dummy self type for better errors if `Self` is used in the trait path. - this.with_self_rib(Res::SelfTy { trait_: None, alias_to: None }, |this| { + this.with_self_rib(Res::SelfTy { trait_: Some(LOCAL_CRATE.as_def_id()), alias_to: None }, |this| { this.with_lifetime_rib( LifetimeRibKind::AnonymousCreateParameter { binder: item_id, From 2aa028d30d1e59c3c4bf9c5bf31e9d9f8ec80273 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 28 Sep 2022 13:55:00 +1000 Subject: [PATCH 376/586] Inline `>::eq`. --- compiler/rustc_ast/src/token.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs index fa6162c51847a..96089d36b6f92 100644 --- a/compiler/rustc_ast/src/token.rs +++ b/compiler/rustc_ast/src/token.rs @@ -728,6 +728,7 @@ impl Token { } impl PartialEq for Token { + #[inline] fn eq(&self, rhs: &TokenKind) -> bool { self.kind == *rhs } From a8d5c00d4667b3765ba5fd9670a3343072529a5d Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 28 Sep 2022 14:45:31 +1000 Subject: [PATCH 377/586] Inline two `Ident` methods. --- compiler/rustc_span/src/symbol.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 07f3656d086b8..b8c0275ea576d 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1703,6 +1703,7 @@ impl Ident { /// macro (e.g., `macro` or `macro_rules!` items) and stay different if they came from different /// non-transparent macros. /// Technically, this operation strips all transparent marks from ident's syntactic context. + #[inline] pub fn normalize_to_macro_rules(self) -> Ident { Ident::new(self.name, self.span.normalize_to_macro_rules()) } @@ -1718,6 +1719,7 @@ impl Ident { } impl PartialEq for Ident { + #[inline] fn eq(&self, rhs: &Self) -> bool { self.name == rhs.name && self.span.eq_ctxt(rhs.span) } From 2f172b4f0b024990a0fd3df2fedd0fe18b48a303 Mon Sep 17 00:00:00 2001 From: Andrew Pollack Date: Wed, 28 Sep 2022 21:32:02 +0000 Subject: [PATCH 378/586] Adding target_rustcflags to TargetCfg --- src/tools/compiletest/src/common.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index 4994fb9bbf941..b9ac6c9f36418 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -385,7 +385,8 @@ impl Config { } fn target_cfg(&self) -> &TargetCfg { - self.target_cfg.borrow_with(|| TargetCfg::new(&self.rustc_path, &self.target)) + self.target_cfg + .borrow_with(|| TargetCfg::new(&self.rustc_path, &self.target, &self.target_rustcflags)) } pub fn matches_arch(&self, arch: &str) -> bool { @@ -456,11 +457,12 @@ pub enum Endian { } impl TargetCfg { - fn new(rustc_path: &Path, target: &str) -> TargetCfg { + fn new(rustc_path: &Path, target: &str, target_rustcflags: &Option) -> TargetCfg { let output = match Command::new(rustc_path) .arg("--print=cfg") .arg("--target") .arg(target) + .args(target_rustcflags.into_iter().map(|s| s.split_whitespace()).flatten()) .output() { Ok(output) => output, From b707eff5cc8780b535b0d2f170fe886f927c5082 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Wed, 28 Sep 2022 14:33:56 -0700 Subject: [PATCH 379/586] rustdoc: cut margin-top from first header in docblock Fixes a regression caused by 8846c0853d8687fda0e5f23f6687b03b243980ee, where a header's top margin used to be collapsed, but isn't any more. --- src/librustdoc/html/static/css/rustdoc.css | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index 0ea6d9c38b69f..6e0fe9fb48e56 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -138,6 +138,13 @@ h1, h2, h3, h4 { .docblock h3, .docblock h4, h5, h6 { margin: 15px 0 5px 0; } +.docblock > h2:first-child, +.docblock > h3:first-child, +.docblock > h4:first-child, +.docblock > h5:first-child, +.docblock > h6:first-child { + margin-top: 0; +} h1.fqn { margin: 0; padding: 0; From bc5443a603efd83c0eacaac0bf5383280c81a6eb Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Wed, 28 Sep 2022 14:43:58 -0700 Subject: [PATCH 380/586] Use the existing `set_visibility` function. --- compiler/rustc_codegen_llvm/src/declare.rs | 2 +- compiler/rustc_codegen_llvm/src/llvm/mod.rs | 6 ------ 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/declare.rs b/compiler/rustc_codegen_llvm/src/declare.rs index 21c466ddc244f..3fbc803d5c32f 100644 --- a/compiler/rustc_codegen_llvm/src/declare.rs +++ b/compiler/rustc_codegen_llvm/src/declare.rs @@ -42,7 +42,7 @@ fn declare_raw_fn<'ll>( llvm::SetFunctionCallConv(llfn, callconv); llvm::SetUnnamedAddress(llfn, unnamed); - llvm::SetVisibility(llfn, visibility); + llvm::set_visibility(llfn, visibility); let mut attrs = SmallVec::<[_; 4]>::new(); diff --git a/compiler/rustc_codegen_llvm/src/llvm/mod.rs b/compiler/rustc_codegen_llvm/src/llvm/mod.rs index 942e7e0427c11..6602a4ab8636c 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/mod.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/mod.rs @@ -172,12 +172,6 @@ pub fn SetUnnamedAddress(global: &Value, unnamed: UnnamedAddr) { } } -pub fn SetVisibility(global: &Value, visibility: Visibility) { - unsafe { - LLVMRustSetVisibility(global, visibility); - } -} - pub fn set_thread_local_mode(global: &Value, mode: ThreadLocalMode) { unsafe { LLVMSetThreadLocalMode(global, mode); From 297c908fee73206bc00276df80326582dad0168f Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Wed, 28 Sep 2022 14:50:58 -0700 Subject: [PATCH 381/586] Change `declare_cfn` to use the C visibility for all C ABI functions. --- compiler/rustc_codegen_llvm/src/builder.rs | 7 +------ compiler/rustc_codegen_llvm/src/context.rs | 17 +++-------------- compiler/rustc_codegen_llvm/src/declare.rs | 8 +++++++- compiler/rustc_codegen_llvm/src/intrinsic.rs | 19 ++++--------------- 4 files changed, 15 insertions(+), 36 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs index a6cd1059dc723..59b1c7fb5dbd0 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs @@ -1458,12 +1458,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> { } else { format!("llvm.{}.sat.i{}.f{}", instr, int_width, float_width) }; - let f = self.declare_cfn( - &name, - llvm::UnnamedAddr::No, - llvm::Visibility::Default, - self.type_func(&[src_ty], dest_ty), - ); + let f = self.declare_cfn(&name, llvm::UnnamedAddr::No, self.type_func(&[src_ty], dest_ty)); self.call(self.type_func(&[src_ty], dest_ty), f, &[val], None) } diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index 6aeb56eb5ade0..67ffc7cb9511f 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -528,12 +528,7 @@ impl<'ll, 'tcx> MiscMethods<'tcx> for CodegenCx<'ll, 'tcx> { llfn } else { let fty = self.type_variadic_func(&[], self.type_i32()); - let llfn = self.declare_cfn( - name, - llvm::UnnamedAddr::Global, - llvm::Visibility::Default, - fty, - ); + let llfn = self.declare_cfn(name, llvm::UnnamedAddr::Global, fty); let target_cpu = attributes::target_cpu_attr(self); attributes::apply_to_llfn(llfn, llvm::AttributePlace::Function, &[target_cpu]); llfn @@ -590,13 +585,7 @@ impl<'ll, 'tcx> MiscMethods<'tcx> for CodegenCx<'ll, 'tcx> { fn declare_c_main(&self, fn_type: Self::Type) -> Option { if self.get_declared_value("main").is_none() { - let visibility = if self.sess().target.default_hidden_visibility { - llvm::Visibility::Hidden - } else { - llvm::Visibility::Default - }; - - Some(self.declare_cfn("main", llvm::UnnamedAddr::Global, visibility, fn_type)) + Some(self.declare_cfn("main", llvm::UnnamedAddr::Global, fn_type)) } else { // If the symbol already exists, it is an error: for example, the user wrote // #[no_mangle] extern "C" fn main(..) {..} @@ -626,7 +615,7 @@ impl<'ll> CodegenCx<'ll, '_> { } else { self.type_variadic_func(&[], ret) }; - let f = self.declare_cfn(name, llvm::UnnamedAddr::No, llvm::Visibility::Default, fn_ty); + let f = self.declare_cfn(name, llvm::UnnamedAddr::No, fn_ty); self.intrinsics.borrow_mut().insert(name, (fn_ty, f)); (fn_ty, f) } diff --git a/compiler/rustc_codegen_llvm/src/declare.rs b/compiler/rustc_codegen_llvm/src/declare.rs index 3fbc803d5c32f..f79ef11720df9 100644 --- a/compiler/rustc_codegen_llvm/src/declare.rs +++ b/compiler/rustc_codegen_llvm/src/declare.rs @@ -78,9 +78,15 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { &self, name: &str, unnamed: llvm::UnnamedAddr, - visibility: llvm::Visibility, fn_type: &'ll Type, ) -> &'ll Value { + // Declare C ABI functions with the visibility used by C by default. + let visibility = if self.tcx.sess.target.default_hidden_visibility { + llvm::Visibility::Hidden + } else { + llvm::Visibility::Default + }; + declare_raw_fn(self, name, llvm::CCallConv, unnamed, visibility, fn_type) } diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index 4e1e6371ad481..a640de42a6a86 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -1216,7 +1216,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>( _ => return_error!("unrecognized intrinsic `{}`", name), }; let llvm_name = &format!("llvm.{0}.v{1}{2}", intr_name, in_len, elem_ty_str); - let f = bx.declare_cfn(llvm_name, llvm::UnnamedAddr::No, llvm::Visibility::Default, fn_ty); + let f = bx.declare_cfn(llvm_name, llvm::UnnamedAddr::No, fn_ty); let c = bx.call(fn_ty, f, &args.iter().map(|arg| arg.immediate()).collect::>(), None); Ok(c) @@ -1416,12 +1416,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>( &[llvm_pointer_vec_ty, alignment_ty, mask_ty, llvm_elem_vec_ty], llvm_elem_vec_ty, ); - let f = bx.declare_cfn( - &llvm_intrinsic, - llvm::UnnamedAddr::No, - llvm::Visibility::Default, - fn_ty, - ); + let f = bx.declare_cfn(&llvm_intrinsic, llvm::UnnamedAddr::No, fn_ty); let v = bx.call(fn_ty, f, &[args[1].immediate(), alignment, mask, args[0].immediate()], None); return Ok(v); @@ -1547,12 +1542,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>( format!("llvm.masked.scatter.{}.{}", llvm_elem_vec_str, llvm_pointer_vec_str); let fn_ty = bx.type_func(&[llvm_elem_vec_ty, llvm_pointer_vec_ty, alignment_ty, mask_ty], ret_t); - let f = bx.declare_cfn( - &llvm_intrinsic, - llvm::UnnamedAddr::No, - llvm::Visibility::Default, - fn_ty, - ); + let f = bx.declare_cfn(&llvm_intrinsic, llvm::UnnamedAddr::No, fn_ty); let v = bx.call(fn_ty, f, &[args[0].immediate(), args[1].immediate(), alignment, mask], None); return Ok(v); @@ -2001,8 +1991,7 @@ unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#, let vec_ty = bx.cx.type_vector(elem_ty, in_len as u64); let fn_ty = bx.type_func(&[vec_ty, vec_ty], vec_ty); - let f = - bx.declare_cfn(llvm_intrinsic, llvm::UnnamedAddr::No, llvm::Visibility::Default, fn_ty); + let f = bx.declare_cfn(llvm_intrinsic, llvm::UnnamedAddr::No, fn_ty); let v = bx.call(fn_ty, f, &[lhs, rhs], None); return Ok(v); } From cdae82c5fc7b04fec84062e82feb0f119d526b81 Mon Sep 17 00:00:00 2001 From: John Millikin Date: Thu, 29 Sep 2022 07:32:15 +0900 Subject: [PATCH 382/586] nonzero_negation_ops: Set `issue = "102443"`. --- library/core/src/num/nonzero.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index d8e3c95cc8702..1e6e1a155ef5d 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -743,7 +743,7 @@ macro_rules! nonzero_signed_operations { /// ``` #[must_use] #[inline(always)] - #[unstable(feature = "nonzero_negation_ops", issue = "none")] + #[unstable(feature = "nonzero_negation_ops", issue = "102443")] pub const fn is_negative(self) -> bool { self.get().is_negative() } @@ -769,7 +769,7 @@ macro_rules! nonzero_signed_operations { /// # } /// ``` #[inline] - #[unstable(feature = "nonzero_negation_ops", issue = "none")] + #[unstable(feature = "nonzero_negation_ops", issue = "102443")] pub const fn checked_neg(self) -> Option<$Ty> { if let Some(result) = self.get().checked_neg() { // SAFETY: negation of nonzero cannot yield zero values. @@ -802,7 +802,7 @@ macro_rules! nonzero_signed_operations { /// # } /// ``` #[inline] - #[unstable(feature = "nonzero_negation_ops", issue = "none")] + #[unstable(feature = "nonzero_negation_ops", issue = "102443")] pub const fn overflowing_neg(self) -> ($Ty, bool) { let (result, overflow) = self.get().overflowing_neg(); // SAFETY: negation of nonzero cannot yield zero values. @@ -836,7 +836,7 @@ macro_rules! nonzero_signed_operations { /// # } /// ``` #[inline] - #[unstable(feature = "nonzero_negation_ops", issue = "none")] + #[unstable(feature = "nonzero_negation_ops", issue = "102443")] pub const fn saturating_neg(self) -> $Ty { if let Some(result) = self.checked_neg() { return result; @@ -869,7 +869,7 @@ macro_rules! nonzero_signed_operations { /// # } /// ``` #[inline] - #[unstable(feature = "nonzero_negation_ops", issue = "none")] + #[unstable(feature = "nonzero_negation_ops", issue = "102443")] pub const fn wrapping_neg(self) -> $Ty { let result = self.get().wrapping_neg(); // SAFETY: negation of nonzero cannot yield zero values. From ceb53a3c4fa9f0c3da7b7e6d24011dee1d15ad09 Mon Sep 17 00:00:00 2001 From: John Millikin Date: Thu, 29 Sep 2022 07:33:05 +0900 Subject: [PATCH 383/586] nonzero_negation_ops: `inline(always)` -> `inline`. --- library/core/src/num/nonzero.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index 1e6e1a155ef5d..da402d66502a6 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -742,7 +742,7 @@ macro_rules! nonzero_signed_operations { /// # } /// ``` #[must_use] - #[inline(always)] + #[inline] #[unstable(feature = "nonzero_negation_ops", issue = "102443")] pub const fn is_negative(self) -> bool { self.get().is_negative() From f55ea418c3a85061ae681f7b8a589f41b582be7f Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Wed, 28 Sep 2022 13:52:13 -0700 Subject: [PATCH 384/586] rustdoc: clean up "normalize.css 8" input override CSS These rules were copied from normalize.css 3, and are mostly redundant. * `optgroup` isn't used in rustdoc at all * `textarea` is only used for the "copy" button, so it's not visible * The remaining buttons and inputs mostly have styles set anyway. * We should never be setting `color` without also setting the background to something. Otherwise, you get white-on-gray text. That seems to be [the reason] why `normalize.css` changed this. [the reason]: https://github.com/necolas/normalize.css/pull/502 --- src/librustdoc/html/static/css/rustdoc.css | 21 +++++++++------------ src/librustdoc/html/static/css/settings.css | 3 ++- 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index 0ea6d9c38b69f..7bc8fbb1ea7e4 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -191,6 +191,7 @@ h4.code-header { position: relative; } +#crate-search, h1, h2, h3, h4, h5, h6, .sidebar, .mobile-topbar, @@ -304,16 +305,6 @@ summary { /* Fix some style changes due to normalize.css 8 */ -button, -input, -optgroup, -select, -textarea { - color: inherit; - font: inherit; - margin: 0; -} - button { /* Buttons on Safari have different default padding than other platforms. Make them the same. */ padding: 1px 6px; @@ -887,6 +878,9 @@ table, /* Removes default arrow from firefox */ text-indent: 0.01px; background-color: var(--main-background-color); + color: inherit; + line-height: 1.5; + font-weight: 500; } /* cancel stylistic differences in padding in firefox for "appearance: none"-style (or equivalent)