From 15f0149c3ea7338b829663ec76c2160ea5730087 Mon Sep 17 00:00:00 2001
From: Meysam Azad <MeysamAzad81@gmail.com>
Date: Sun, 20 Aug 2023 14:54:16 +0700
Subject: [PATCH 1/9] =?UTF-8?q?feat(docs):=20add=20cargo-pgo=20to=20PGO=20?=
 =?UTF-8?q?documentation=20=F0=9F=93=9D?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../rustc/src/profile-guided-optimization.md  | 22 +++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/src/doc/rustc/src/profile-guided-optimization.md b/src/doc/rustc/src/profile-guided-optimization.md
index d9cf7ce30f9..465a26a1301 100644
--- a/src/doc/rustc/src/profile-guided-optimization.md
+++ b/src/doc/rustc/src/profile-guided-optimization.md
@@ -145,3 +145,25 @@ in Clang's documentation is therefore an interesting read for anyone who wants
 to use PGO with Rust.
 
 [clang-pgo]: https://clang.llvm.org/docs/UsersManual.html#profile-guided-optimization
+
+## Community Maintained Tools
+
+As an alternative to directly using the compiler for Profile-Guided Optimization,
+you may choose to go with `cargo-pgo`, which has an intuitive command-line API
+and saves you the trouble of doing all the manual work. You can read more about
+it in their repository accessible from this link: https://github.com/Kobzol/cargo-pgo
+
+For the sake of completeness, here are the corresponding steps using `cargo-pgo`:
+
+```bash
+# Install the binary as usual: cargo install cargo-pgo
+cargo pgo build
+LLVM_PROFILE_FILE=./target/pgo-profiles/rustc-pgo_%m_%p.profraw ./target/x86_64-unknown-linux-gnu/release/myprogram
+cargo pgo optimize
+```
+
+These steps will do the following just as before:
+
+1. Build an instrumented binary from the source code.
+2. Use the instrumentation in the binary when running it for the first time.
+3. Use the instrumentation results from the last step to create an optimized binary.

From 29ec0ec4a6fb72dcb61e1cd1b1b4bb7aa0da9351 Mon Sep 17 00:00:00 2001
From: Meysam <MeysamAzad81@gmail.com>
Date: Wed, 25 Oct 2023 08:43:06 +0700
Subject: [PATCH 2/9] Update src/doc/rustc/src/profile-guided-optimization.md
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Co-authored-by: Jakub Beránek <berykubik@gmail.com>
---
 src/doc/rustc/src/profile-guided-optimization.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/doc/rustc/src/profile-guided-optimization.md b/src/doc/rustc/src/profile-guided-optimization.md
index 465a26a1301..951dda03e80 100644
--- a/src/doc/rustc/src/profile-guided-optimization.md
+++ b/src/doc/rustc/src/profile-guided-optimization.md
@@ -165,5 +165,5 @@ cargo pgo optimize
 These steps will do the following just as before:
 
 1. Build an instrumented binary from the source code.
-2. Use the instrumentation in the binary when running it for the first time.
+2. Run the instrumented binary to gather PGO profiles.
 3. Use the instrumentation results from the last step to create an optimized binary.

From 3ecc8c37d428979206b302e3b7e0a15a8a62c638 Mon Sep 17 00:00:00 2001
From: Meysam <MeysamAzad81@gmail.com>
Date: Wed, 25 Oct 2023 08:43:21 +0700
Subject: [PATCH 3/9] Update src/doc/rustc/src/profile-guided-optimization.md
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Co-authored-by: Jakub Beránek <berykubik@gmail.com>
---
 src/doc/rustc/src/profile-guided-optimization.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/doc/rustc/src/profile-guided-optimization.md b/src/doc/rustc/src/profile-guided-optimization.md
index 951dda03e80..781b89d7153 100644
--- a/src/doc/rustc/src/profile-guided-optimization.md
+++ b/src/doc/rustc/src/profile-guided-optimization.md
@@ -166,4 +166,4 @@ These steps will do the following just as before:
 
 1. Build an instrumented binary from the source code.
 2. Run the instrumented binary to gather PGO profiles.
-3. Use the instrumentation results from the last step to create an optimized binary.
+3. Use the gathered PGO profiles from the last step to build an optimized binary.

From 515535a657b823491b6f8b2c79788988c8b7306f Mon Sep 17 00:00:00 2001
From: Meysam <MeysamAzad81@gmail.com>
Date: Wed, 25 Oct 2023 08:44:50 +0700
Subject: [PATCH 4/9] Update profile-guided-optimization.md

---
 src/doc/rustc/src/profile-guided-optimization.md | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/src/doc/rustc/src/profile-guided-optimization.md b/src/doc/rustc/src/profile-guided-optimization.md
index 781b89d7153..38b655b7542 100644
--- a/src/doc/rustc/src/profile-guided-optimization.md
+++ b/src/doc/rustc/src/profile-guided-optimization.md
@@ -156,9 +156,10 @@ it in their repository accessible from this link: https://github.com/Kobzol/carg
 For the sake of completeness, here are the corresponding steps using `cargo-pgo`:
 
 ```bash
-# Install the binary as usual: cargo install cargo-pgo
+# Install if you haven't already
+cargo install cargo-pgo
+
 cargo pgo build
-LLVM_PROFILE_FILE=./target/pgo-profiles/rustc-pgo_%m_%p.profraw ./target/x86_64-unknown-linux-gnu/release/myprogram
 cargo pgo optimize
 ```
 

From 4392230c08f04c7168e3502e8e075bb19d709a47 Mon Sep 17 00:00:00 2001
From: NAHO <90870942+trueNAHO@users.noreply.github.com>
Date: Thu, 26 Oct 2023 19:28:48 +0200
Subject: [PATCH 5/9] Fix documentation typo in
 std::iter::Iterator::collect_into

---
 library/core/src/iter/traits/iterator.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs
index 166d04e078d..6adea444214 100644
--- a/library/core/src/iter/traits/iterator.rs
+++ b/library/core/src/iter/traits/iterator.rs
@@ -2142,7 +2142,7 @@ pub trait Iterator {
     /// passed collection. The collection is then returned, so the call chain
     /// can be continued.
     ///
-    /// This is useful when you already have a collection and wants to add
+    /// This is useful when you already have a collection and want to add
     /// the iterator items to it.
     ///
     /// This method is a convenience method to call [Extend::extend](trait.Extend.html),

From 1836c1fbbdf0d6902da9a2d2473dbc72f371eb2e Mon Sep 17 00:00:00 2001
From: Michael Goulet <michael@errs.io>
Date: Thu, 26 Oct 2023 17:30:53 +0000
Subject: [PATCH 6/9] Stash and cancel cycle errors for auto trait leakage in
 opaques

---
 compiler/rustc_errors/src/lib.rs              |  2 +
 compiler/rustc_macros/src/query.rs            |  8 ++
 compiler/rustc_middle/src/query/mod.rs        |  1 +
 compiler/rustc_query_impl/src/plumbing.rs     |  3 +
 compiler/rustc_query_system/src/error.rs      |  1 +
 .../rustc_query_system/src/query/plumbing.rs  | 13 +++-
 .../error_reporting/type_err_ctxt_ext.rs      |  7 ++
 tests/ui/impl-trait/auto-trait-leak.rs        |  2 -
 tests/ui/impl-trait/auto-trait-leak.stderr    | 68 +----------------
 .../auto-trait-leakage3.rs                    |  3 -
 .../auto-trait-leakage3.stderr                | 48 +-----------
 .../type-alias-impl-trait/inference-cycle.rs  |  7 +-
 .../inference-cycle.stderr                    | 50 ++-----------
 .../ui/type-alias-impl-trait/reveal_local.rs  |  3 -
 .../type-alias-impl-trait/reveal_local.stderr | 73 ++-----------------
 15 files changed, 55 insertions(+), 234 deletions(-)

diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs
index da74ee6391a..5e3fdf170bc 100644
--- a/compiler/rustc_errors/src/lib.rs
+++ b/compiler/rustc_errors/src/lib.rs
@@ -508,6 +508,8 @@ pub enum StashKey {
     TraitMissingMethod,
     OpaqueHiddenTypeMismatch,
     MaybeForgetReturn,
+    /// Query cycle detected, stashing in favor of a better error.
+    Cycle,
 }
 
 fn default_track_diagnostic(d: &mut Diagnostic, f: &mut dyn FnMut(&mut Diagnostic)) {
diff --git a/compiler/rustc_macros/src/query.rs b/compiler/rustc_macros/src/query.rs
index d8a695b131b..ad1980136f3 100644
--- a/compiler/rustc_macros/src/query.rs
+++ b/compiler/rustc_macros/src/query.rs
@@ -97,6 +97,9 @@ struct QueryModifiers {
     /// A cycle error results in a delay_bug call
     cycle_delay_bug: Option<Ident>,
 
+    /// A cycle error results in a stashed cycle error that can be unstashed and canceled later
+    cycle_stash: Option<Ident>,
+
     /// Don't hash the result, instead just mark a query red if it runs
     no_hash: Option<Ident>,
 
@@ -127,6 +130,7 @@ fn parse_query_modifiers(input: ParseStream<'_>) -> Result<QueryModifiers> {
     let mut desc = None;
     let mut fatal_cycle = None;
     let mut cycle_delay_bug = None;
+    let mut cycle_stash = None;
     let mut no_hash = None;
     let mut anon = None;
     let mut eval_always = None;
@@ -181,6 +185,8 @@ fn parse_query_modifiers(input: ParseStream<'_>) -> Result<QueryModifiers> {
             try_insert!(fatal_cycle = modifier);
         } else if modifier == "cycle_delay_bug" {
             try_insert!(cycle_delay_bug = modifier);
+        } else if modifier == "cycle_stash" {
+            try_insert!(cycle_stash = modifier);
         } else if modifier == "no_hash" {
             try_insert!(no_hash = modifier);
         } else if modifier == "anon" {
@@ -208,6 +214,7 @@ fn parse_query_modifiers(input: ParseStream<'_>) -> Result<QueryModifiers> {
         desc,
         fatal_cycle,
         cycle_delay_bug,
+        cycle_stash,
         no_hash,
         anon,
         eval_always,
@@ -329,6 +336,7 @@ pub fn rustc_queries(input: TokenStream) -> TokenStream {
             fatal_cycle,
             arena_cache,
             cycle_delay_bug,
+            cycle_stash,
             no_hash,
             anon,
             eval_always,
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index 0c2241f8729..062b03e71fd 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -251,6 +251,7 @@ rustc_queries! {
             "computing type of opaque `{path}`",
             path = tcx.def_path_str(key),
         }
+        cycle_stash
     }
 
     query type_alias_is_lazy(key: DefId) -> bool {
diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs
index 4516708ce17..536c0a20e2a 100644
--- a/compiler/rustc_query_impl/src/plumbing.rs
+++ b/compiler/rustc_query_impl/src/plumbing.rs
@@ -197,6 +197,9 @@ macro_rules! handle_cycle_error {
     ([(fatal_cycle) $($rest:tt)*]) => {{
         rustc_query_system::HandleCycleError::Fatal
     }};
+    ([(cycle_stash) $($rest:tt)*]) => {{
+        rustc_query_system::HandleCycleError::Stash
+    }};
     ([(cycle_delay_bug) $($rest:tt)*]) => {{
         rustc_query_system::HandleCycleError::DelayBug
     }};
diff --git a/compiler/rustc_query_system/src/error.rs b/compiler/rustc_query_system/src/error.rs
index e49e78cc7c4..5829e17ec16 100644
--- a/compiler/rustc_query_system/src/error.rs
+++ b/compiler/rustc_query_system/src/error.rs
@@ -15,6 +15,7 @@ pub enum HandleCycleError {
     Error,
     Fatal,
     DelayBug,
+    Stash,
 }
 
 #[derive(Subdiagnostic)]
diff --git a/compiler/rustc_query_system/src/query/plumbing.rs b/compiler/rustc_query_system/src/query/plumbing.rs
index 69a9c0eb95a..1f3403d09be 100644
--- a/compiler/rustc_query_system/src/query/plumbing.rs
+++ b/compiler/rustc_query_system/src/query/plumbing.rs
@@ -19,7 +19,7 @@ use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_data_structures::sync::Lock;
 #[cfg(parallel_compiler)]
 use rustc_data_structures::{outline, sync};
-use rustc_errors::{DiagnosticBuilder, ErrorGuaranteed, FatalError};
+use rustc_errors::{DiagnosticBuilder, ErrorGuaranteed, FatalError, StashKey};
 use rustc_span::{Span, DUMMY_SP};
 use std::cell::Cell;
 use std::collections::hash_map::Entry;
@@ -133,6 +133,17 @@ where
             let guar = error.delay_as_bug();
             query.value_from_cycle_error(*qcx.dep_context(), &cycle_error.cycle, guar)
         }
+        Stash => {
+            let guar = if let Some(root) = cycle_error.cycle.first()
+                && let Some(span) = root.query.span
+            {
+                error.stash(span, StashKey::Cycle);
+                qcx.dep_context().sess().delay_span_bug(span, "delayed cycle error")
+            } else {
+                error.emit()
+            };
+            query.value_from_cycle_error(*qcx.dep_context(), &cycle_error.cycle, guar)
+        }
     }
 }
 
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs
index 1245b4a7756..5fe7ed22f27 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs
@@ -3071,6 +3071,13 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                 );
             }
         };
+
+        if let Some(diag) =
+            self.tcx.sess.diagnostic().steal_diagnostic(self.tcx.def_span(def_id), StashKey::Cycle)
+        {
+            diag.cancel();
+        }
+
         err
     }
 
diff --git a/tests/ui/impl-trait/auto-trait-leak.rs b/tests/ui/impl-trait/auto-trait-leak.rs
index 1f90292f457..de4f523c23a 100644
--- a/tests/ui/impl-trait/auto-trait-leak.rs
+++ b/tests/ui/impl-trait/auto-trait-leak.rs
@@ -9,8 +9,6 @@ fn main() {}
 // independently resolved and only require the concrete
 // return type, which can't depend on the obligation.
 fn cycle1() -> impl Clone {
-    //~^ ERROR cycle detected
-    //~| ERROR cycle detected
     send(cycle2().clone());
 
     Rc::new(Cell::new(5))
diff --git a/tests/ui/impl-trait/auto-trait-leak.stderr b/tests/ui/impl-trait/auto-trait-leak.stderr
index 62341f6de0c..28643ec03e1 100644
--- a/tests/ui/impl-trait/auto-trait-leak.stderr
+++ b/tests/ui/impl-trait/auto-trait-leak.stderr
@@ -1,66 +1,5 @@
-error[E0391]: cycle detected when computing type of opaque `cycle1::{opaque#0}`
-  --> $DIR/auto-trait-leak.rs:11:16
-   |
-LL | fn cycle1() -> impl Clone {
-   |                ^^^^^^^^^^
-   |
-note: ...which requires type-checking `cycle1`...
-  --> $DIR/auto-trait-leak.rs:14:5
-   |
-LL |     send(cycle2().clone());
-   |     ^^^^
-   = note: ...which requires evaluating trait selection obligation `cycle2::{opaque#0}: core::marker::Send`...
-note: ...which requires computing type of opaque `cycle2::{opaque#0}`...
-  --> $DIR/auto-trait-leak.rs:19:16
-   |
-LL | fn cycle2() -> impl Clone {
-   |                ^^^^^^^^^^
-note: ...which requires type-checking `cycle2`...
-  --> $DIR/auto-trait-leak.rs:20:5
-   |
-LL |     send(cycle1().clone());
-   |     ^^^^
-   = note: ...which requires evaluating trait selection obligation `cycle1::{opaque#0}: core::marker::Send`...
-   = note: ...which again requires computing type of opaque `cycle1::{opaque#0}`, completing the cycle
-note: cycle used when computing type of `cycle1::{opaque#0}`
-  --> $DIR/auto-trait-leak.rs:11:16
-   |
-LL | fn cycle1() -> impl Clone {
-   |                ^^^^^^^^^^
-   = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
-
-error[E0391]: cycle detected when computing type of opaque `cycle1::{opaque#0}`
-  --> $DIR/auto-trait-leak.rs:11:16
-   |
-LL | fn cycle1() -> impl Clone {
-   |                ^^^^^^^^^^
-   |
-note: ...which requires type-checking `cycle1`...
-  --> $DIR/auto-trait-leak.rs:14:5
-   |
-LL |     send(cycle2().clone());
-   |     ^^^^
-   = note: ...which requires evaluating trait selection obligation `cycle2::{opaque#0}: core::marker::Send`...
-note: ...which requires computing type of opaque `cycle2::{opaque#0}`...
-  --> $DIR/auto-trait-leak.rs:19:16
-   |
-LL | fn cycle2() -> impl Clone {
-   |                ^^^^^^^^^^
-note: ...which requires type-checking `cycle2`...
-  --> $DIR/auto-trait-leak.rs:19:1
-   |
-LL | fn cycle2() -> impl Clone {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
-   = note: ...which again requires computing type of opaque `cycle1::{opaque#0}`, completing the cycle
-note: cycle used when computing type of `cycle1::{opaque#0}`
-  --> $DIR/auto-trait-leak.rs:11:16
-   |
-LL | fn cycle1() -> impl Clone {
-   |                ^^^^^^^^^^
-   = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
-
 error: cannot check whether the hidden type of opaque type satisfies auto traits
-  --> $DIR/auto-trait-leak.rs:20:10
+  --> $DIR/auto-trait-leak.rs:18:10
    |
 LL |     send(cycle1().clone());
    |     ---- ^^^^^^^^^^^^^^^^
@@ -73,7 +12,7 @@ note: opaque type is declared here
 LL | fn cycle1() -> impl Clone {
    |                ^^^^^^^^^^
 note: this item depends on auto traits of the hidden type, but may also be registering the hidden type. This is not supported right now. You can try moving the opaque type and the item that actually registers a hidden type into a new submodule
-  --> $DIR/auto-trait-leak.rs:19:4
+  --> $DIR/auto-trait-leak.rs:17:4
    |
 LL | fn cycle2() -> impl Clone {
    |    ^^^^^^
@@ -83,6 +22,5 @@ note: required by a bound in `send`
 LL | fn send<T: Send>(_: T) {}
    |            ^^^^ required by this bound in `send`
 
-error: aborting due to 3 previous errors
+error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0391`.
diff --git a/tests/ui/type-alias-impl-trait/auto-trait-leakage3.rs b/tests/ui/type-alias-impl-trait/auto-trait-leakage3.rs
index 660950d5906..cad75cffe05 100644
--- a/tests/ui/type-alias-impl-trait/auto-trait-leakage3.rs
+++ b/tests/ui/type-alias-impl-trait/auto-trait-leakage3.rs
@@ -5,9 +5,6 @@
 
 mod m {
     pub type Foo = impl std::fmt::Debug;
-    //~^ ERROR: cycle detected when computing type of opaque `m::Foo::{opaque#0}` [E0391]
-    //~| ERROR: cycle detected when computing type of opaque `m::Foo::{opaque#0}` [E0391]
-
     pub fn foo() -> Foo {
         22_u32
     }
diff --git a/tests/ui/type-alias-impl-trait/auto-trait-leakage3.stderr b/tests/ui/type-alias-impl-trait/auto-trait-leakage3.stderr
index d8698826660..d47b1fe3678 100644
--- a/tests/ui/type-alias-impl-trait/auto-trait-leakage3.stderr
+++ b/tests/ui/type-alias-impl-trait/auto-trait-leakage3.stderr
@@ -1,44 +1,5 @@
-error[E0391]: cycle detected when computing type of opaque `m::Foo::{opaque#0}`
-  --> $DIR/auto-trait-leakage3.rs:7:20
-   |
-LL |     pub type Foo = impl std::fmt::Debug;
-   |                    ^^^^^^^^^^^^^^^^^^^^
-   |
-note: ...which requires type-checking `m::bar`...
-  --> $DIR/auto-trait-leakage3.rs:16:9
-   |
-LL |         is_send(foo());
-   |         ^^^^^^^
-   = note: ...which requires evaluating trait selection obligation `m::Foo: core::marker::Send`...
-   = note: ...which again requires computing type of opaque `m::Foo::{opaque#0}`, completing the cycle
-note: cycle used when computing type of `m::Foo::{opaque#0}`
-  --> $DIR/auto-trait-leakage3.rs:7:20
-   |
-LL |     pub type Foo = impl std::fmt::Debug;
-   |                    ^^^^^^^^^^^^^^^^^^^^
-   = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
-
-error[E0391]: cycle detected when computing type of opaque `m::Foo::{opaque#0}`
-  --> $DIR/auto-trait-leakage3.rs:7:20
-   |
-LL |     pub type Foo = impl std::fmt::Debug;
-   |                    ^^^^^^^^^^^^^^^^^^^^
-   |
-note: ...which requires type-checking `m::bar`...
-  --> $DIR/auto-trait-leakage3.rs:15:5
-   |
-LL |     pub fn bar() {
-   |     ^^^^^^^^^^^^
-   = note: ...which again requires computing type of opaque `m::Foo::{opaque#0}`, completing the cycle
-note: cycle used when computing type of `m::Foo::{opaque#0}`
-  --> $DIR/auto-trait-leakage3.rs:7:20
-   |
-LL |     pub type Foo = impl std::fmt::Debug;
-   |                    ^^^^^^^^^^^^^^^^^^^^
-   = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
-
 error: cannot check whether the hidden type of `auto_trait_leakage3[211d]::m::Foo::{opaque#0}` satisfies auto traits
-  --> $DIR/auto-trait-leakage3.rs:16:17
+  --> $DIR/auto-trait-leakage3.rs:13:17
    |
 LL |         is_send(foo());
    |         ------- ^^^^^
@@ -51,16 +12,15 @@ note: opaque type is declared here
 LL |     pub type Foo = impl std::fmt::Debug;
    |                    ^^^^^^^^^^^^^^^^^^^^
 note: this item depends on auto traits of the hidden type, but may also be registering the hidden type. This is not supported right now. You can try moving the opaque type and the item that actually registers a hidden type into a new submodule
-  --> $DIR/auto-trait-leakage3.rs:15:12
+  --> $DIR/auto-trait-leakage3.rs:12:12
    |
 LL |     pub fn bar() {
    |            ^^^
 note: required by a bound in `is_send`
-  --> $DIR/auto-trait-leakage3.rs:20:19
+  --> $DIR/auto-trait-leakage3.rs:17:19
    |
 LL |     fn is_send<T: Send>(_: T) {}
    |                   ^^^^ required by this bound in `is_send`
 
-error: aborting due to 3 previous errors
+error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0391`.
diff --git a/tests/ui/type-alias-impl-trait/inference-cycle.rs b/tests/ui/type-alias-impl-trait/inference-cycle.rs
index 20175a4feca..6e4507ed460 100644
--- a/tests/ui/type-alias-impl-trait/inference-cycle.rs
+++ b/tests/ui/type-alias-impl-trait/inference-cycle.rs
@@ -3,17 +3,14 @@
 
 mod m {
     pub type Foo = impl std::fmt::Debug;
-    //~^ ERROR cycle detected
-    //~| ERROR cycle detected
-
-    // Cycle: error today, but it'd be nice if it eventually worked
 
     pub fn foo() -> Foo {
         is_send(bar())
     }
 
     pub fn bar() {
-        is_send(foo()); // Today: error
+        // Cycle: error today, but it'd be nice if it eventually worked
+        is_send(foo());
         //~^ ERROR: cannot check whether the hidden type of `inference_cycle[4ecc]::m::Foo::{opaque#0}` satisfies auto traits
     }
 
diff --git a/tests/ui/type-alias-impl-trait/inference-cycle.stderr b/tests/ui/type-alias-impl-trait/inference-cycle.stderr
index 4ab059d054b..ef7abe58864 100644
--- a/tests/ui/type-alias-impl-trait/inference-cycle.stderr
+++ b/tests/ui/type-alias-impl-trait/inference-cycle.stderr
@@ -1,46 +1,7 @@
-error[E0391]: cycle detected when computing type of opaque `m::Foo::{opaque#0}`
-  --> $DIR/inference-cycle.rs:5:20
-   |
-LL |     pub type Foo = impl std::fmt::Debug;
-   |                    ^^^^^^^^^^^^^^^^^^^^
-   |
-note: ...which requires type-checking `m::bar`...
-  --> $DIR/inference-cycle.rs:16:9
-   |
-LL |         is_send(foo()); // Today: error
-   |         ^^^^^^^
-   = note: ...which requires evaluating trait selection obligation `m::Foo: core::marker::Send`...
-   = note: ...which again requires computing type of opaque `m::Foo::{opaque#0}`, completing the cycle
-note: cycle used when computing type of `m::Foo::{opaque#0}`
-  --> $DIR/inference-cycle.rs:5:20
-   |
-LL |     pub type Foo = impl std::fmt::Debug;
-   |                    ^^^^^^^^^^^^^^^^^^^^
-   = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
-
-error[E0391]: cycle detected when computing type of opaque `m::Foo::{opaque#0}`
-  --> $DIR/inference-cycle.rs:5:20
-   |
-LL |     pub type Foo = impl std::fmt::Debug;
-   |                    ^^^^^^^^^^^^^^^^^^^^
-   |
-note: ...which requires type-checking `m::bar`...
-  --> $DIR/inference-cycle.rs:15:5
-   |
-LL |     pub fn bar() {
-   |     ^^^^^^^^^^^^
-   = note: ...which again requires computing type of opaque `m::Foo::{opaque#0}`, completing the cycle
-note: cycle used when computing type of `m::Foo::{opaque#0}`
-  --> $DIR/inference-cycle.rs:5:20
-   |
-LL |     pub type Foo = impl std::fmt::Debug;
-   |                    ^^^^^^^^^^^^^^^^^^^^
-   = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
-
 error: cannot check whether the hidden type of `inference_cycle[4ecc]::m::Foo::{opaque#0}` satisfies auto traits
-  --> $DIR/inference-cycle.rs:16:17
+  --> $DIR/inference-cycle.rs:13:17
    |
-LL |         is_send(foo()); // Today: error
+LL |         is_send(foo());
    |         ------- ^^^^^
    |         |
    |         required by a bound introduced by this call
@@ -51,16 +12,15 @@ note: opaque type is declared here
 LL |     pub type Foo = impl std::fmt::Debug;
    |                    ^^^^^^^^^^^^^^^^^^^^
 note: this item depends on auto traits of the hidden type, but may also be registering the hidden type. This is not supported right now. You can try moving the opaque type and the item that actually registers a hidden type into a new submodule
-  --> $DIR/inference-cycle.rs:15:12
+  --> $DIR/inference-cycle.rs:11:12
    |
 LL |     pub fn bar() {
    |            ^^^
 note: required by a bound in `is_send`
-  --> $DIR/inference-cycle.rs:24:19
+  --> $DIR/inference-cycle.rs:21:19
    |
 LL |     fn is_send<T: Send>(_: T) {}
    |                   ^^^^ required by this bound in `is_send`
 
-error: aborting due to 3 previous errors
+error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0391`.
diff --git a/tests/ui/type-alias-impl-trait/reveal_local.rs b/tests/ui/type-alias-impl-trait/reveal_local.rs
index 7943bb240f1..07fd989b0fa 100644
--- a/tests/ui/type-alias-impl-trait/reveal_local.rs
+++ b/tests/ui/type-alias-impl-trait/reveal_local.rs
@@ -3,9 +3,6 @@
 use std::fmt::Debug;
 
 type Foo = impl Debug;
-//~^ ERROR cycle detected
-//~| ERROR cycle detected
-//~| ERROR cycle detected
 
 fn is_send<T: Send>() {}
 
diff --git a/tests/ui/type-alias-impl-trait/reveal_local.stderr b/tests/ui/type-alias-impl-trait/reveal_local.stderr
index c62fd88f4e2..796e2d011dc 100644
--- a/tests/ui/type-alias-impl-trait/reveal_local.stderr
+++ b/tests/ui/type-alias-impl-trait/reveal_local.stderr
@@ -1,44 +1,5 @@
-error[E0391]: cycle detected when computing type of opaque `Foo::{opaque#0}`
-  --> $DIR/reveal_local.rs:5:12
-   |
-LL | type Foo = impl Debug;
-   |            ^^^^^^^^^^
-   |
-note: ...which requires type-checking `not_good`...
-  --> $DIR/reveal_local.rs:15:5
-   |
-LL |     is_send::<Foo>();
-   |     ^^^^^^^^^^^^^^
-   = note: ...which requires evaluating trait selection obligation `Foo: core::marker::Send`...
-   = note: ...which again requires computing type of opaque `Foo::{opaque#0}`, completing the cycle
-note: cycle used when computing type of `Foo::{opaque#0}`
-  --> $DIR/reveal_local.rs:5:12
-   |
-LL | type Foo = impl Debug;
-   |            ^^^^^^^^^^
-   = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
-
-error[E0391]: cycle detected when computing type of opaque `Foo::{opaque#0}`
-  --> $DIR/reveal_local.rs:5:12
-   |
-LL | type Foo = impl Debug;
-   |            ^^^^^^^^^^
-   |
-note: ...which requires type-checking `not_good`...
-  --> $DIR/reveal_local.rs:12:1
-   |
-LL | fn not_good() {
-   | ^^^^^^^^^^^^^
-   = note: ...which again requires computing type of opaque `Foo::{opaque#0}`, completing the cycle
-note: cycle used when computing type of `Foo::{opaque#0}`
-  --> $DIR/reveal_local.rs:5:12
-   |
-LL | type Foo = impl Debug;
-   |            ^^^^^^^^^^
-   = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
-
 error: cannot check whether the hidden type of `reveal_local[9507]::Foo::{opaque#0}` satisfies auto traits
-  --> $DIR/reveal_local.rs:15:15
+  --> $DIR/reveal_local.rs:12:15
    |
 LL |     is_send::<Foo>();
    |               ^^^
@@ -49,37 +10,18 @@ note: opaque type is declared here
 LL | type Foo = impl Debug;
    |            ^^^^^^^^^^
 note: this item depends on auto traits of the hidden type, but may also be registering the hidden type. This is not supported right now. You can try moving the opaque type and the item that actually registers a hidden type into a new submodule
-  --> $DIR/reveal_local.rs:12:4
+  --> $DIR/reveal_local.rs:9:4
    |
 LL | fn not_good() {
    |    ^^^^^^^^
 note: required by a bound in `is_send`
-  --> $DIR/reveal_local.rs:10:15
+  --> $DIR/reveal_local.rs:7:15
    |
 LL | fn is_send<T: Send>() {}
    |               ^^^^ required by this bound in `is_send`
 
-error[E0391]: cycle detected when computing type of opaque `Foo::{opaque#0}`
-  --> $DIR/reveal_local.rs:5:12
-   |
-LL | type Foo = impl Debug;
-   |            ^^^^^^^^^^
-   |
-note: ...which requires type-checking `not_gooder`...
-  --> $DIR/reveal_local.rs:19:1
-   |
-LL | fn not_gooder() -> Foo {
-   | ^^^^^^^^^^^^^^^^^^^^^^
-   = note: ...which again requires computing type of opaque `Foo::{opaque#0}`, completing the cycle
-note: cycle used when computing type of `Foo::{opaque#0}`
-  --> $DIR/reveal_local.rs:5:12
-   |
-LL | type Foo = impl Debug;
-   |            ^^^^^^^^^^
-   = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
-
 error: cannot check whether the hidden type of `reveal_local[9507]::Foo::{opaque#0}` satisfies auto traits
-  --> $DIR/reveal_local.rs:25:15
+  --> $DIR/reveal_local.rs:22:15
    |
 LL |     is_send::<Foo>();
    |               ^^^
@@ -90,16 +32,15 @@ note: opaque type is declared here
 LL | type Foo = impl Debug;
    |            ^^^^^^^^^^
 note: this item depends on auto traits of the hidden type, but may also be registering the hidden type. This is not supported right now. You can try moving the opaque type and the item that actually registers a hidden type into a new submodule
-  --> $DIR/reveal_local.rs:19:4
+  --> $DIR/reveal_local.rs:16:4
    |
 LL | fn not_gooder() -> Foo {
    |    ^^^^^^^^^^
 note: required by a bound in `is_send`
-  --> $DIR/reveal_local.rs:10:15
+  --> $DIR/reveal_local.rs:7:15
    |
 LL | fn is_send<T: Send>() {}
    |               ^^^^ required by this bound in `is_send`
 
-error: aborting due to 5 previous errors
+error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0391`.

From 27919ceba717cd5be7f7ebcb2f5e5f5afa955035 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Esteban=20K=C3=BCber?= <esteban@kuber.com.ar>
Date: Wed, 18 Oct 2023 00:24:21 +0000
Subject: [PATCH 7/9] Tweak suggestion spans for invalid crate-level inner
 attribute

CC #89566.
---
 compiler/rustc_passes/messages.ftl            |  3 +
 compiler/rustc_passes/src/check_attr.rs       | 22 ++++-
 compiler/rustc_passes/src/errors.rs           | 20 +++-
 .../unix_sigpipe/unix_sigpipe-crate.stderr    |  8 +-
 tests/ui/derives/issue-36617.stderr           | 40 ++++++--
 .../issue-43106-gating-of-bench.stderr        |  6 +-
 ...sue-43106-gating-of-builtin-attrs-error.rs |  6 ++
 ...43106-gating-of-builtin-attrs-error.stderr | 96 ++++++++++++-------
 .../issue-43106-gating-of-test.stderr         |  6 +-
 tests/ui/imports/issue-28134.stderr           |  5 +-
 .../ui/span/issue-43927-non-ADT-derive.stderr |  8 +-
 11 files changed, 160 insertions(+), 60 deletions(-)

diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl
index 84d3b84e13f..026186cbe6c 100644
--- a/compiler/rustc_passes/messages.ftl
+++ b/compiler/rustc_passes/messages.ftl
@@ -393,6 +393,9 @@ passes_invalid_attr_at_crate_level =
     `{$name}` attribute cannot be used at crate level
     .suggestion = perhaps you meant to use an outer attribute
 
+passes_invalid_attr_at_crate_level_item =
+    the inner attribute doesn't annotate this {$kind}
+
 passes_invalid_deprecation_version =
     invalid deprecation version found
     .label = invalid deprecation version
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index dfe75ea5e8e..a8a27e761cb 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -2534,10 +2534,30 @@ fn check_invalid_crate_level_attr(tcx: TyCtxt<'_>, attrs: &[Attribute]) {
         if attr.style == AttrStyle::Inner {
             for attr_to_check in ATTRS_TO_CHECK {
                 if attr.has_name(*attr_to_check) {
+                    let item = tcx
+                        .hir()
+                        .items()
+                        .map(|id| tcx.hir().item(id))
+                        .find(|item| !item.span.is_dummy()) // Skip prelude `use`s
+                        .map(|item| errors::ItemFollowingInnerAttr {
+                            span: item.ident.span,
+                            kind: item.kind.descr(),
+                        });
                     tcx.sess.emit_err(errors::InvalidAttrAtCrateLevel {
                         span: attr.span,
-                        snippet: tcx.sess.source_map().span_to_snippet(attr.span).ok(),
+                        sugg_span: tcx
+                            .sess
+                            .source_map()
+                            .span_to_snippet(attr.span)
+                            .ok()
+                            .filter(|src| src.starts_with("#!["))
+                            .map(|_| {
+                                attr.span
+                                    .with_lo(attr.span.lo() + BytePos(1))
+                                    .with_hi(attr.span.lo() + BytePos(2))
+                            }),
                         name: *attr_to_check,
+                        item,
                     });
                 }
             }
diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs
index 6e840f24c69..eca0fb7748b 100644
--- a/compiler/rustc_passes/src/errors.rs
+++ b/compiler/rustc_passes/src/errors.rs
@@ -856,8 +856,15 @@ pub struct UnknownLangItem {
 
 pub struct InvalidAttrAtCrateLevel {
     pub span: Span,
-    pub snippet: Option<String>,
+    pub sugg_span: Option<Span>,
     pub name: Symbol,
+    pub item: Option<ItemFollowingInnerAttr>,
+}
+
+#[derive(Clone, Copy)]
+pub struct ItemFollowingInnerAttr {
+    pub span: Span,
+    pub kind: &'static str,
 }
 
 impl IntoDiagnostic<'_> for InvalidAttrAtCrateLevel {
@@ -871,15 +878,18 @@ impl IntoDiagnostic<'_> for InvalidAttrAtCrateLevel {
         diag.set_arg("name", self.name);
         // Only emit an error with a suggestion if we can create a string out
         // of the attribute span
-        if let Some(src) = self.snippet {
-            let replacement = src.replace("#!", "#");
+        if let Some(span) = self.sugg_span {
             diag.span_suggestion_verbose(
-                self.span,
+                span,
                 fluent::passes_suggestion,
-                replacement,
+                String::new(),
                 rustc_errors::Applicability::MachineApplicable,
             );
         }
+        if let Some(item) = self.item {
+            diag.set_arg("kind", item.kind);
+            diag.span_label(item.span, fluent::passes_invalid_attr_at_crate_level_item);
+        }
         diag
     }
 }
diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-crate.stderr b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-crate.stderr
index a1fb4d6787c..225b8e8f32f 100644
--- a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-crate.stderr
+++ b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-crate.stderr
@@ -3,11 +3,15 @@ error: `unix_sigpipe` attribute cannot be used at crate level
    |
 LL | #![unix_sigpipe = "inherit"]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |
+LL | fn main() {}
+   |    ---- the inner attribute doesn't annotate this function
    |
 help: perhaps you meant to use an outer attribute
    |
-LL | #[unix_sigpipe = "inherit"]
-   | ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+LL - #![unix_sigpipe = "inherit"]
+LL + #[unix_sigpipe = "inherit"]
+   |
 
 error: aborting due to previous error
 
diff --git a/tests/ui/derives/issue-36617.stderr b/tests/ui/derives/issue-36617.stderr
index 9cc0a29b065..98be7963e5e 100644
--- a/tests/ui/derives/issue-36617.stderr
+++ b/tests/ui/derives/issue-36617.stderr
@@ -43,55 +43,75 @@ error: `derive` attribute cannot be used at crate level
    |
 LL | #![derive(Copy)]
    | ^^^^^^^^^^^^^^^^
+...
+LL | fn main() {}
+   |    ---- the inner attribute doesn't annotate this function
    |
 help: perhaps you meant to use an outer attribute
    |
-LL | #[derive(Copy)]
-   | ~~~~~~~~~~~~~~~
+LL - #![derive(Copy)]
+LL + #[derive(Copy)]
+   |
 
 error: `test` attribute cannot be used at crate level
   --> $DIR/issue-36617.rs:4:1
    |
 LL | #![test]
    | ^^^^^^^^
+...
+LL | fn main() {}
+   |    ---- the inner attribute doesn't annotate this function
    |
 help: perhaps you meant to use an outer attribute
    |
-LL | #[test]
-   | ~~~~~~~
+LL - #![test]
+LL + #[test]
+   |
 
 error: `test_case` attribute cannot be used at crate level
   --> $DIR/issue-36617.rs:7:1
    |
 LL | #![test_case]
    | ^^^^^^^^^^^^^
+...
+LL | fn main() {}
+   |    ---- the inner attribute doesn't annotate this function
    |
 help: perhaps you meant to use an outer attribute
    |
-LL | #[test_case]
-   | ~~~~~~~~~~~~
+LL - #![test_case]
+LL + #[test_case]
+   |
 
 error: `bench` attribute cannot be used at crate level
   --> $DIR/issue-36617.rs:10:1
    |
 LL | #![bench]
    | ^^^^^^^^^
+...
+LL | fn main() {}
+   |    ---- the inner attribute doesn't annotate this function
    |
 help: perhaps you meant to use an outer attribute
    |
-LL | #[bench]
-   | ~~~~~~~~
+LL - #![bench]
+LL + #[bench]
+   |
 
 error: `global_allocator` attribute cannot be used at crate level
   --> $DIR/issue-36617.rs:13:1
    |
 LL | #![global_allocator]
    | ^^^^^^^^^^^^^^^^^^^^
+...
+LL | fn main() {}
+   |    ---- the inner attribute doesn't annotate this function
    |
 help: perhaps you meant to use an outer attribute
    |
-LL | #[global_allocator]
-   | ~~~~~~~~~~~~~~~~~~~
+LL - #![global_allocator]
+LL + #[global_allocator]
+   |
 
 error: aborting due to 10 previous errors
 
diff --git a/tests/ui/feature-gates/issue-43106-gating-of-bench.stderr b/tests/ui/feature-gates/issue-43106-gating-of-bench.stderr
index 6b332211942..8270d46d492 100644
--- a/tests/ui/feature-gates/issue-43106-gating-of-bench.stderr
+++ b/tests/ui/feature-gates/issue-43106-gating-of-bench.stderr
@@ -11,10 +11,14 @@ error: `bench` attribute cannot be used at crate level
    |
 LL | #![bench                   = "4100"]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | fn main() {}
+   |    ---- the inner attribute doesn't annotate this function
    |
 help: perhaps you meant to use an outer attribute
    |
-LL | #[bench                   = "4100"]
+LL - #![bench                   = "4100"]
+LL + #[bench                   = "4100"]
    |
 
 error: aborting due to 2 previous errors
diff --git a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.rs b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.rs
index 1fe133ac2bc..0f833f793bd 100644
--- a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.rs
+++ b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.rs
@@ -32,6 +32,12 @@
 //~^ ERROR attribute should be applied to function or closure
 mod inline {
     //~^ NOTE not a function or closure
+    //~| NOTE the inner attribute doesn't annotate this module
+    //~| NOTE the inner attribute doesn't annotate this module
+    //~| NOTE the inner attribute doesn't annotate this module
+    //~| NOTE the inner attribute doesn't annotate this module
+    //~| NOTE the inner attribute doesn't annotate this module
+    //~| NOTE the inner attribute doesn't annotate this module
 
     mod inner { #![inline] }
     //~^ ERROR attribute should be applied to function or closure
diff --git a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr
index 78767040421..f01153dcb96 100644
--- a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr
+++ b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr
@@ -7,7 +7,7 @@ LL | #![rustc_main]
    = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable
 
 error: attribute must be of the form `#[inline]` or `#[inline(always|never)]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:40:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:46:5
    |
 LL |     #[inline = "2100"] fn f() { }
    |     ^^^^^^^^^^^^^^^^^^
@@ -17,31 +17,31 @@ LL |     #[inline = "2100"] fn f() { }
    = note: `#[deny(ill_formed_attribute_input)]` on by default
 
 error: `start` attribute can only be used on functions
-  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:119:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:125:1
    |
 LL | #[start]
    | ^^^^^^^^
 
 error: `start` attribute can only be used on functions
-  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:122:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:128:17
    |
 LL |     mod inner { #![start] }
    |                 ^^^^^^^^^
 
 error: `start` attribute can only be used on functions
-  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:127:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:133:5
    |
 LL |     #[start] struct S;
    |     ^^^^^^^^
 
 error: `start` attribute can only be used on functions
-  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:130:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:136:5
    |
 LL |     #[start] type T = S;
    |     ^^^^^^^^
 
 error: `start` attribute can only be used on functions
-  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:133:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:139:5
    |
 LL |     #[start] impl S { }
    |     ^^^^^^^^
@@ -55,14 +55,14 @@ LL |
 LL | / mod inline {
 LL | |
 LL | |
-LL | |     mod inner { #![inline] }
+LL | |
 ...  |
 LL | |
 LL | | }
    | |_- not a function or closure
 
 error: attribute should be applied to an `extern crate` item
-  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:59:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:65:1
    |
 LL |   #[no_link]
    |   ^^^^^^^^^^
@@ -77,7 +77,7 @@ LL | | }
    | |_- not an `extern crate` item
 
 error: attribute should be applied to a free function, impl method or static
-  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:85:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:91:1
    |
 LL |   #[export_name = "2200"]
    |   ^^^^^^^^^^^^^^^^^^^^^^^
@@ -92,7 +92,7 @@ LL | | }
    | |_- not a free function, impl method or static
 
 error[E0517]: attribute should be applied to a struct, enum, or union
-  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:137:8
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:143:8
    |
 LL |   #[repr(C)]
    |          ^
@@ -129,10 +129,14 @@ error: `macro_export` attribute cannot be used at crate level
    |
 LL | #![macro_export]
    | ^^^^^^^^^^^^^^^^
+...
+LL | mod inline {
+   |     ------ the inner attribute doesn't annotate this module
    |
 help: perhaps you meant to use an outer attribute
    |
-LL | #[macro_export]
+LL - #![macro_export]
+LL + #[macro_export]
    |
 
 error: `rustc_main` attribute cannot be used at crate level
@@ -140,21 +144,29 @@ error: `rustc_main` attribute cannot be used at crate level
    |
 LL | #![rustc_main]
    | ^^^^^^^^^^^^^^
+...
+LL | mod inline {
+   |     ------ the inner attribute doesn't annotate this module
    |
 help: perhaps you meant to use an outer attribute
    |
-LL | #[rustc_main]
-   | ~~~~~~~~~~~~~
+LL - #![rustc_main]
+LL + #[rustc_main]
+   |
 
 error: `start` attribute cannot be used at crate level
   --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:16:1
    |
 LL | #![start]
    | ^^^^^^^^^
+...
+LL | mod inline {
+   |     ------ the inner attribute doesn't annotate this module
    |
 help: perhaps you meant to use an outer attribute
    |
-LL | #[start]
+LL - #![start]
+LL + #[start]
    |
 
 error: `repr` attribute cannot be used at crate level
@@ -162,10 +174,14 @@ error: `repr` attribute cannot be used at crate level
    |
 LL | #![repr()]
    | ^^^^^^^^^^
+...
+LL | mod inline {
+   |     ------ the inner attribute doesn't annotate this module
    |
 help: perhaps you meant to use an outer attribute
    |
-LL | #[repr()]
+LL - #![repr()]
+LL + #[repr()]
    |
 
 error: `path` attribute cannot be used at crate level
@@ -173,10 +189,14 @@ error: `path` attribute cannot be used at crate level
    |
 LL | #![path = "3800"]
    | ^^^^^^^^^^^^^^^^^
+...
+LL | mod inline {
+   |     ------ the inner attribute doesn't annotate this module
    |
 help: perhaps you meant to use an outer attribute
    |
-LL | #[path = "3800"]
+LL - #![path = "3800"]
+LL + #[path = "3800"]
    |
 
 error: `automatically_derived` attribute cannot be used at crate level
@@ -184,122 +204,126 @@ error: `automatically_derived` attribute cannot be used at crate level
    |
 LL | #![automatically_derived]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | mod inline {
+   |     ------ the inner attribute doesn't annotate this module
    |
 help: perhaps you meant to use an outer attribute
    |
-LL | #[automatically_derived]
+LL - #![automatically_derived]
+LL + #[automatically_derived]
    |
 
 error[E0518]: attribute should be applied to function or closure
-  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:36:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:42:17
    |
 LL |     mod inner { #![inline] }
    |     ------------^^^^^^^^^^-- not a function or closure
 
 error[E0518]: attribute should be applied to function or closure
-  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:46:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:52:5
    |
 LL |     #[inline] struct S;
    |     ^^^^^^^^^ --------- not a function or closure
 
 error[E0518]: attribute should be applied to function or closure
-  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:50:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:56:5
    |
 LL |     #[inline] type T = S;
    |     ^^^^^^^^^ ----------- not a function or closure
 
 error[E0518]: attribute should be applied to function or closure
-  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:54:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:60:5
    |
 LL |     #[inline] impl S { }
    |     ^^^^^^^^^ ---------- not a function or closure
 
 error: attribute should be applied to an `extern crate` item
-  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:64:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:70:17
    |
 LL |     mod inner { #![no_link] }
    |     ------------^^^^^^^^^^^-- not an `extern crate` item
 
 error: attribute should be applied to an `extern crate` item
-  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:68:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:74:5
    |
 LL |     #[no_link] fn f() { }
    |     ^^^^^^^^^^ ---------- not an `extern crate` item
 
 error: attribute should be applied to an `extern crate` item
-  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:72:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:78:5
    |
 LL |     #[no_link] struct S;
    |     ^^^^^^^^^^ --------- not an `extern crate` item
 
 error: attribute should be applied to an `extern crate` item
-  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:76:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:82:5
    |
 LL |     #[no_link]type T = S;
    |     ^^^^^^^^^^----------- not an `extern crate` item
 
 error: attribute should be applied to an `extern crate` item
-  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:80:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:86:5
    |
 LL |     #[no_link] impl S { }
    |     ^^^^^^^^^^ ---------- not an `extern crate` item
 
 error: attribute should be applied to a free function, impl method or static
-  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:90:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:96:17
    |
 LL |     mod inner { #![export_name="2200"] }
    |     ------------^^^^^^^^^^^^^^^^^^^^^^-- not a free function, impl method or static
 
 error: attribute should be applied to a free function, impl method or static
-  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:96:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:102:5
    |
 LL |     #[export_name = "2200"] struct S;
    |     ^^^^^^^^^^^^^^^^^^^^^^^ --------- not a free function, impl method or static
 
 error: attribute should be applied to a free function, impl method or static
-  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:100:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:106:5
    |
 LL |     #[export_name = "2200"] type T = S;
    |     ^^^^^^^^^^^^^^^^^^^^^^^ ----------- not a free function, impl method or static
 
 error: attribute should be applied to a free function, impl method or static
-  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:104:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:110:5
    |
 LL |     #[export_name = "2200"] impl S { }
    |     ^^^^^^^^^^^^^^^^^^^^^^^ ---------- not a free function, impl method or static
 
 error: attribute should be applied to a free function, impl method or static
-  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:109:9
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:115:9
    |
 LL |         #[export_name = "2200"] fn foo();
    |         ^^^^^^^^^^^^^^^^^^^^^^^ --------- not a free function, impl method or static
 
 error: attribute should be applied to a free function, impl method or static
-  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:113:9
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:119:9
    |
 LL |         #[export_name = "2200"] fn bar() {}
    |         ^^^^^^^^^^^^^^^^^^^^^^^ ----------- not a free function, impl method or static
 
 error[E0517]: attribute should be applied to a struct, enum, or union
-  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:141:25
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:147:25
    |
 LL |     mod inner { #![repr(C)] }
    |     --------------------^---- not a struct, enum, or union
 
 error[E0517]: attribute should be applied to a struct, enum, or union
-  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:145:12
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:151:12
    |
 LL |     #[repr(C)] fn f() { }
    |            ^   ---------- not a struct, enum, or union
 
 error[E0517]: attribute should be applied to a struct, enum, or union
-  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:151:12
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:157:12
    |
 LL |     #[repr(C)] type T = S;
    |            ^   ----------- not a struct, enum, or union
 
 error[E0517]: attribute should be applied to a struct, enum, or union
-  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:155:12
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:161:12
    |
 LL |     #[repr(C)] impl S { }
    |            ^   ---------- not a struct, enum, or union
diff --git a/tests/ui/feature-gates/issue-43106-gating-of-test.stderr b/tests/ui/feature-gates/issue-43106-gating-of-test.stderr
index 300a9966dd8..922c9861aa3 100644
--- a/tests/ui/feature-gates/issue-43106-gating-of-test.stderr
+++ b/tests/ui/feature-gates/issue-43106-gating-of-test.stderr
@@ -11,10 +11,14 @@ error: `test` attribute cannot be used at crate level
    |
 LL | #![test                    = "4200"]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | fn main() {}
+   |    ---- the inner attribute doesn't annotate this function
    |
 help: perhaps you meant to use an outer attribute
    |
-LL | #[test                    = "4200"]
+LL - #![test                    = "4200"]
+LL + #[test                    = "4200"]
    |
 
 error: aborting due to 2 previous errors
diff --git a/tests/ui/imports/issue-28134.stderr b/tests/ui/imports/issue-28134.stderr
index 33cb53f202a..5315c2e9fee 100644
--- a/tests/ui/imports/issue-28134.stderr
+++ b/tests/ui/imports/issue-28134.stderr
@@ -14,8 +14,9 @@ LL | #![test]
    |
 help: perhaps you meant to use an outer attribute
    |
-LL | #[test]
-   | ~~~~~~~
+LL - #![test]
+LL + #[test]
+   |
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/span/issue-43927-non-ADT-derive.stderr b/tests/ui/span/issue-43927-non-ADT-derive.stderr
index e3ae37e3689..a22a4d2b40a 100644
--- a/tests/ui/span/issue-43927-non-ADT-derive.stderr
+++ b/tests/ui/span/issue-43927-non-ADT-derive.stderr
@@ -11,11 +11,15 @@ error: `derive` attribute cannot be used at crate level
    |
 LL | #![derive(Debug, PartialEq, Eq)] // should be an outer attribute!
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | struct DerivedOn;
+   |        --------- the inner attribute doesn't annotate this struct
    |
 help: perhaps you meant to use an outer attribute
    |
-LL | #[derive(Debug, PartialEq, Eq)] // should be an outer attribute!
-   | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+LL - #![derive(Debug, PartialEq, Eq)] // should be an outer attribute!
+LL + #[derive(Debug, PartialEq, Eq)] // should be an outer attribute!
+   |
 
 error: aborting due to 2 previous errors
 

From 613e6181a66e572abd7b980931d08c74c480967d Mon Sep 17 00:00:00 2001
From: "Celina G. Val" <celinval@amazon.com>
Date: Thu, 26 Oct 2023 20:10:54 -0700
Subject: [PATCH 8/9] Specialize ZeroSized constants

ZeroSized constants can be represented as `mir::Const::Val` even if
their layout is not yet known. In those cases, CrateItem::body() was
crashing when trying to convert a `ConstValue::ZeroSized` into its
stable counterpart `ConstantKind::Allocated`.

Instead, we now map `ConstValue::ZeroSized` into a new variant:
`ConstantKind::ZeroSized`.
---
 compiler/rustc_smir/src/rustc_smir/mod.rs | 19 ++++++++++++++-----
 compiler/stable_mir/src/ty.rs             |  3 +++
 compiler/stable_mir/src/visitor.rs        |  2 +-
 3 files changed, 18 insertions(+), 6 deletions(-)

diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs
index e772ae942fa..5411a12cf04 100644
--- a/compiler/rustc_smir/src/rustc_smir/mod.rs
+++ b/compiler/rustc_smir/src/rustc_smir/mod.rs
@@ -1284,11 +1284,15 @@ impl<'tcx> Stable<'tcx> for ty::Const<'tcx> {
         let kind = match self.kind() {
             ty::Value(val) => {
                 let const_val = tables.tcx.valtree_to_const_val((self.ty(), val));
-                stable_mir::ty::ConstantKind::Allocated(alloc::new_allocation(
-                    self.ty(),
-                    const_val,
-                    tables,
-                ))
+                if matches!(const_val, mir::ConstValue::ZeroSized) {
+                    ConstantKind::ZeroSized
+                } else {
+                    stable_mir::ty::ConstantKind::Allocated(alloc::new_allocation(
+                        self.ty(),
+                        const_val,
+                        tables,
+                    ))
+                }
             }
             ty::ParamCt(param) => stable_mir::ty::ConstantKind::Param(param.stable(tables)),
             ty::ErrorCt(_) => unreachable!(),
@@ -1402,6 +1406,11 @@ impl<'tcx> Stable<'tcx> for rustc_middle::mir::Const<'tcx> {
                 let id = tables.intern_const(*self);
                 Const::new(kind, ty, id)
             }
+            mir::Const::Val(val, ty) if matches!(val, mir::ConstValue::ZeroSized) => {
+                let ty = ty.stable(tables);
+                let id = tables.intern_const(*self);
+                Const::new(ConstantKind::ZeroSized, ty, id)
+            }
             mir::Const::Val(val, ty) => {
                 let kind = ConstantKind::Allocated(alloc::new_allocation(ty, val, tables));
                 let ty = ty.stable(tables);
diff --git a/compiler/stable_mir/src/ty.rs b/compiler/stable_mir/src/ty.rs
index 0dbf6fe23aa..e7440cc439b 100644
--- a/compiler/stable_mir/src/ty.rs
+++ b/compiler/stable_mir/src/ty.rs
@@ -444,6 +444,9 @@ pub enum ConstantKind {
     Allocated(Allocation),
     Unevaluated(UnevaluatedConst),
     Param(ParamConst),
+    /// Store ZST constants.
+    /// We have to special handle these constants since its type might be generic.
+    ZeroSized,
 }
 
 #[derive(Clone, Debug)]
diff --git a/compiler/stable_mir/src/visitor.rs b/compiler/stable_mir/src/visitor.rs
index c337f5b68d3..05e0b9b4d78 100644
--- a/compiler/stable_mir/src/visitor.rs
+++ b/compiler/stable_mir/src/visitor.rs
@@ -50,7 +50,7 @@ impl Visitable for Const {
         match &self.kind() {
             super::ty::ConstantKind::Allocated(alloc) => alloc.visit(visitor)?,
             super::ty::ConstantKind::Unevaluated(uv) => uv.visit(visitor)?,
-            super::ty::ConstantKind::Param(_) => {}
+            super::ty::ConstantKind::Param(_) | super::ty::ConstantKind::ZeroSized => {}
         }
         self.ty().visit(visitor)
     }

From b3f7f4dff75e3beaa7b6e60f9e5484f82fff8065 Mon Sep 17 00:00:00 2001
From: Ralf Jung <post@ralfj.de>
Date: Fri, 27 Oct 2023 07:51:38 +0200
Subject: [PATCH 9/9] replace transmute by raw pointer cast

---
 library/std/src/thread/mod.rs | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs
index 7b26068c294..68ea486933a 100644
--- a/library/std/src/thread/mod.rs
+++ b/library/std/src/thread/mod.rs
@@ -545,6 +545,13 @@ impl Builder {
             scope_data.increment_num_running_threads();
         }
 
+        let main = Box::new(main);
+        #[cfg(bootstrap)]
+        let main =
+            unsafe { mem::transmute::<Box<dyn FnOnce() + 'a>, Box<dyn FnOnce() + 'static>>(main) };
+        #[cfg(not(bootstrap))]
+        let main = unsafe { Box::from_raw(Box::into_raw(main) as *mut (dyn FnOnce() + 'static)) };
+
         Ok(JoinInner {
             // SAFETY:
             //
@@ -559,14 +566,7 @@ impl Builder {
             // Similarly, the `sys` implementation must guarantee that no references to the closure
             // exist after the thread has terminated, which is signaled by `Thread::join`
             // returning.
-            native: unsafe {
-                imp::Thread::new(
-                    stack_size,
-                    mem::transmute::<Box<dyn FnOnce() + 'a>, Box<dyn FnOnce() + 'static>>(
-                        Box::new(main),
-                    ),
-                )?
-            },
+            native: unsafe { imp::Thread::new(stack_size, main)? },
             thread: my_thread,
             packet: my_packet,
         })