From f9770e742ad3853d2a472e422b00cdbe8578faae Mon Sep 17 00:00:00 2001
From: Mads Marquart <mads@marquart.dk>
Date: Mon, 24 Mar 2025 21:55:14 +0100
Subject: [PATCH 01/16] Test linking and running no_std binaries

---
 tests/ui/no_std/simple-runs.rs | 41 ++++++++++++++++++++++++++++++++++
 1 file changed, 41 insertions(+)
 create mode 100644 tests/ui/no_std/simple-runs.rs

diff --git a/tests/ui/no_std/simple-runs.rs b/tests/ui/no_std/simple-runs.rs
new file mode 100644
index 00000000000..8931ac7ed11
--- /dev/null
+++ b/tests/ui/no_std/simple-runs.rs
@@ -0,0 +1,41 @@
+//! Check that `no_std` binaries can link and run without depending on `libstd`.
+
+//@ run-pass
+//@ compile-flags: -Cpanic=abort
+//@ ignore-wasm different `main` convention
+
+#![no_std]
+#![no_main]
+
+use core::ffi::{c_char, c_int};
+use core::panic::PanicInfo;
+
+// # Linux
+//
+// Linking `libc` is required by crt1.o, otherwise the linker fails with:
+// > /usr/bin/ld: in function `_start': undefined reference to `__libc_start_main'
+//
+// # Apple
+//
+// Linking `libSystem` is required, otherwise the linker fails with:
+// > ld: dynamic executables or dylibs must link with libSystem.dylib
+//
+// With the new linker introduced in Xcode 15, the error is instead:
+// > Undefined symbols: "dyld_stub_binder", referenced from: <initial-undefines>
+//
+// This _can_ be worked around by raising the deployment target with
+// MACOSX_DEPLOYMENT_TARGET=13.0, though it's a bit hard to test that while
+// still allowing the test suite to support running with older Xcode versions.
+#[cfg_attr(all(not(target_vendor = "apple"), unix), link(name = "c"))]
+#[cfg_attr(target_vendor = "apple", link(name = "System"))]
+extern "C" {}
+
+#[panic_handler]
+fn panic_handler(_info: &PanicInfo<'_>) -> ! {
+    loop {}
+}
+
+#[no_mangle]
+extern "C" fn main(_argc: c_int, _argv: *const *const c_char) -> c_int {
+    0
+}

From f21d18063ca8beb847121e367140395348399082 Mon Sep 17 00:00:00 2001
From: izarma <phuckuhh@gmail.com>
Date: Sun, 6 Apr 2025 15:09:59 +0530
Subject: [PATCH 02/16] doc changes

---
 library/core/src/iter/adapters/enumerate.rs |  2 +-
 library/core/src/iter/traits/iterator.rs    | 10 +++++-----
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/library/core/src/iter/adapters/enumerate.rs b/library/core/src/iter/adapters/enumerate.rs
index f9c388e8564..bd093e279c3 100644
--- a/library/core/src/iter/adapters/enumerate.rs
+++ b/library/core/src/iter/adapters/enumerate.rs
@@ -36,7 +36,7 @@ where
     ///
     /// The method does no guarding against overflows, so enumerating more than
     /// `usize::MAX` elements either produces the wrong result or panics. If
-    /// debug assertions are enabled, a panic is guaranteed.
+    /// overflow checks are enabled, a panic is guaranteed.
     ///
     /// # Panics
     ///
diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs
index 3bbb52fdbcb..d9534a44598 100644
--- a/library/core/src/iter/traits/iterator.rs
+++ b/library/core/src/iter/traits/iterator.rs
@@ -199,7 +199,7 @@ pub trait Iterator {
     ///
     /// The method does no guarding against overflows, so counting elements of
     /// an iterator with more than [`usize::MAX`] elements either produces the
-    /// wrong result or panics. If debug assertions are enabled, a panic is
+    /// wrong result or panics. If overflow checks are enabled, a panic is
     /// guaranteed.
     ///
     /// # Panics
@@ -931,7 +931,7 @@ pub trait Iterator {
     ///
     /// The method does no guarding against overflows, so enumerating more than
     /// [`usize::MAX`] elements either produces the wrong result or panics. If
-    /// debug assertions are enabled, a panic is guaranteed.
+    /// overflow checks are enabled, a panic is guaranteed.
     ///
     /// # Panics
     ///
@@ -2964,7 +2964,7 @@ pub trait Iterator {
     ///
     /// The method does no guarding against overflows, so if there are more
     /// than [`usize::MAX`] non-matching elements, it either produces the wrong
-    /// result or panics. If debug assertions are enabled, a panic is
+    /// result or panics. If overflow checks are enabled, a panic is
     /// guaranteed.
     ///
     /// # Panics
@@ -3516,7 +3516,7 @@ pub trait Iterator {
     /// # Panics
     ///
     /// When calling `sum()` and a primitive integer type is being returned, this
-    /// method will panic if the computation overflows and debug assertions are
+    /// method will panic if the computation overflows and overflow checks are
     /// enabled.
     ///
     /// # Examples
@@ -3550,7 +3550,7 @@ pub trait Iterator {
     /// # Panics
     ///
     /// When calling `product()` and a primitive integer type is being returned,
-    /// method will panic if the computation overflows and debug assertions are
+    /// method will panic if the computation overflows and overflow checks are
     /// enabled.
     ///
     /// # Examples

From 8b6ff4a378e2df03db108bcd918a77f8a759334f Mon Sep 17 00:00:00 2001
From: Romain Perier <romain.perier@gmail.com>
Date: Wed, 26 Mar 2025 15:49:42 +0100
Subject: [PATCH 03/16] Suggest the use of `impl Trait` in function parameter
 only

Currently in case of a Trait object in closure parameter, the compiler
suggests either to use a reference, which is correct or to use an
`impl Trait` which is not. Do not emit this suggestion when the parameter
is part of a closure.
---
 .../src/error_reporting/traits/suggestions.rs | 23 ++++++++++++++-----
 .../dont-suggest-impl-as-closure-arg.rs       |  5 ++++
 .../dont-suggest-impl-as-closure-arg.stderr   | 16 +++++++++++++
 3 files changed, 38 insertions(+), 6 deletions(-)
 create mode 100644 tests/ui/traits/dont-suggest-impl-as-closure-arg.rs
 create mode 100644 tests/ui/traits/dont-suggest-impl-as-closure-arg.stderr

diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
index 38fcba4ea62..cfe9120a4a4 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
@@ -3018,12 +3018,23 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                                 [] => span_bug!(ty.span, "trait object with no traits: {ty:?}"),
                             };
                             let needs_parens = traits.len() != 1;
-                            err.span_suggestion_verbose(
-                                span,
-                                "you can use `impl Trait` as the argument type",
-                                "impl ",
-                                Applicability::MaybeIncorrect,
-                            );
+                            // Don't recommend impl Trait as a closure argument
+                            if let Some(hir_id) = hir_id
+                                && matches!(
+                                    self.tcx.parent_hir_node(hir_id),
+                                    hir::Node::Item(hir::Item {
+                                        kind: hir::ItemKind::Fn { .. },
+                                        ..
+                                    })
+                                )
+                            {
+                                err.span_suggestion_verbose(
+                                    span,
+                                    "you can use `impl Trait` as the argument type",
+                                    "impl ",
+                                    Applicability::MaybeIncorrect,
+                                );
+                            }
                             let sugg = if !needs_parens {
                                 vec![(span.shrink_to_lo(), format!("&{kw}"))]
                             } else {
diff --git a/tests/ui/traits/dont-suggest-impl-as-closure-arg.rs b/tests/ui/traits/dont-suggest-impl-as-closure-arg.rs
new file mode 100644
index 00000000000..68e234b0f20
--- /dev/null
+++ b/tests/ui/traits/dont-suggest-impl-as-closure-arg.rs
@@ -0,0 +1,5 @@
+// Suggestion to use impl trait in closure parameter is invalid, see issue 138932
+fn main() {
+    let c = |f: dyn Fn()| f();
+    //~^ ERROR: the size for values of type `(dyn Fn() + 'static)` cannot be known at compilation time
+}
diff --git a/tests/ui/traits/dont-suggest-impl-as-closure-arg.stderr b/tests/ui/traits/dont-suggest-impl-as-closure-arg.stderr
new file mode 100644
index 00000000000..8218990503c
--- /dev/null
+++ b/tests/ui/traits/dont-suggest-impl-as-closure-arg.stderr
@@ -0,0 +1,16 @@
+error[E0277]: the size for values of type `(dyn Fn() + 'static)` cannot be known at compilation time
+  --> $DIR/dont-suggest-impl-as-closure-arg.rs:3:17
+   |
+LL |     let c = |f: dyn Fn()| f();
+   |                 ^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `Sized` is not implemented for `(dyn Fn() + 'static)`
+   = help: unsized fn params are gated as an unstable feature
+help: function arguments must have a statically known size, borrowed types always have a known size
+   |
+LL |     let c = |f: &dyn Fn()| f();
+   |                 +
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0277`.

From 9847c738930b329f70e34d97048a35cd795654b8 Mon Sep 17 00:00:00 2001
From: onur-ozkan <work@onurozkan.dev>
Date: Wed, 9 Apr 2025 09:54:45 +0300
Subject: [PATCH 04/16] set `rust.channel` to "auto-detect" for `dist` profile

Signed-off-by: onur-ozkan <work@onurozkan.dev>
---
 src/bootstrap/defaults/bootstrap.dist.toml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/bootstrap/defaults/bootstrap.dist.toml b/src/bootstrap/defaults/bootstrap.dist.toml
index 7b381b416ca..6221e2e01e4 100644
--- a/src/bootstrap/defaults/bootstrap.dist.toml
+++ b/src/bootstrap/defaults/bootstrap.dist.toml
@@ -15,7 +15,7 @@ download-ci-llvm = false
 [rust]
 # We have several defaults in bootstrap that depend on whether the channel is `dev` (e.g. `omit-git-hash` and `download-ci-llvm`).
 # Make sure they don't get set when installing from source.
-channel = "nightly"
+channel = "auto-detect"
 # Never download a rustc, distributions must build a fresh compiler.
 download-rustc = false
 lld = true

From 57135c427386b875cb2d84eae49e3f9ba045342c Mon Sep 17 00:00:00 2001
From: Jieyou Xu <jieyouxu@outlook.com>
Date: Mon, 7 Apr 2025 09:49:53 +0800
Subject: [PATCH 05/16] compiletest: add `needs-crate-type` directive

The `//@ needs-crate-type: $crate_types...` directive takes a
comma-separated list of crate types that the target platform must
support in order for the test to be run.
---
 src/tools/compiletest/src/common.rs         | 31 +++++++++++++
 src/tools/compiletest/src/directive-list.rs |  1 +
 src/tools/compiletest/src/header/needs.rs   | 48 ++++++++++++++++++++-
 src/tools/compiletest/src/header/tests.rs   | 38 ++++++++++++++++
 src/tools/compiletest/src/lib.rs            |  1 +
 5 files changed, 117 insertions(+), 2 deletions(-)

diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs
index 36218b2f904..6750b5288f4 100644
--- a/src/tools/compiletest/src/common.rs
+++ b/src/tools/compiletest/src/common.rs
@@ -395,6 +395,7 @@ pub struct Config {
 
     pub target_cfgs: OnceLock<TargetCfgs>,
     pub builtin_cfg_names: OnceLock<HashSet<String>>,
+    pub supported_crate_types: OnceLock<HashSet<String>>,
 
     pub nocapture: bool,
 
@@ -472,6 +473,11 @@ impl Config {
         self.builtin_cfg_names.get_or_init(|| builtin_cfg_names(self))
     }
 
+    /// Get the list of crate types that the target platform supports.
+    pub fn supported_crate_types(&self) -> &HashSet<String> {
+        self.supported_crate_types.get_or_init(|| supported_crate_types(self))
+    }
+
     pub fn has_threads(&self) -> bool {
         // Wasm targets don't have threads unless `-threads` is in the target
         // name, such as `wasm32-wasip1-threads`.
@@ -745,6 +751,31 @@ fn builtin_cfg_names(config: &Config) -> HashSet<String> {
     .collect()
 }
 
+pub const KNOWN_CRATE_TYPES: &[&str] =
+    &["bin", "cdylib", "dylib", "lib", "proc-macro", "rlib", "staticlib"];
+
+fn supported_crate_types(config: &Config) -> HashSet<String> {
+    let crate_types: HashSet<_> = rustc_output(
+        config,
+        &["--target", &config.target, "--print=supported-crate-types", "-Zunstable-options"],
+        Default::default(),
+    )
+    .lines()
+    .map(|l| l.to_string())
+    .collect();
+
+    for crate_type in crate_types.iter() {
+        assert!(
+            KNOWN_CRATE_TYPES.contains(&crate_type.as_str()),
+            "unexpected crate type `{}`: known crate types are {:?}",
+            crate_type,
+            KNOWN_CRATE_TYPES
+        );
+    }
+
+    crate_types
+}
+
 fn rustc_output(config: &Config, args: &[&str], envs: HashMap<String, String>) -> String {
     let mut command = Command::new(&config.rustc_path);
     add_dylib_path(&mut command, iter::once(&config.compile_lib_path));
diff --git a/src/tools/compiletest/src/directive-list.rs b/src/tools/compiletest/src/directive-list.rs
index 44d9c0330f7..086a8a67456 100644
--- a/src/tools/compiletest/src/directive-list.rs
+++ b/src/tools/compiletest/src/directive-list.rs
@@ -133,6 +133,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[
     "min-llvm-version",
     "min-system-llvm-version",
     "needs-asm-support",
+    "needs-crate-type",
     "needs-deterministic-layouts",
     "needs-dlltool",
     "needs-dynamic-linking",
diff --git a/src/tools/compiletest/src/header/needs.rs b/src/tools/compiletest/src/header/needs.rs
index 12f0790fb10..2ace40c490b 100644
--- a/src/tools/compiletest/src/header/needs.rs
+++ b/src/tools/compiletest/src/header/needs.rs
@@ -1,4 +1,4 @@
-use crate::common::{Config, KNOWN_TARGET_HAS_ATOMIC_WIDTHS, Sanitizer};
+use crate::common::{Config, KNOWN_CRATE_TYPES, KNOWN_TARGET_HAS_ATOMIC_WIDTHS, Sanitizer};
 use crate::header::{IgnoreDecision, llvm_has_libzstd};
 
 pub(super) fn handle_needs(
@@ -6,7 +6,7 @@ pub(super) fn handle_needs(
     config: &Config,
     ln: &str,
 ) -> IgnoreDecision {
-    // Note thet we intentionally still put the needs- prefix here to make the file show up when
+    // Note that we intentionally still put the needs- prefix here to make the file show up when
     // grepping for a directive name, even though we could technically strip that.
     let needs = &[
         Need {
@@ -224,6 +224,50 @@ pub(super) fn handle_needs(
         }
     }
 
+    // FIXME(jieyouxu): share multi-value directive logic with `needs-target-has-atomic` above.
+    if name == "needs-crate-type" {
+        let Some(rest) = rest else {
+            return IgnoreDecision::Error {
+                message:
+                    "expected `needs-crate-type` to have a comma-separated list of crate types"
+                        .to_string(),
+            };
+        };
+
+        // Expect directive value to be a list of comma-separated crate-types.
+        let specified_crate_types = rest
+            .split(',')
+            .map(|crate_type| crate_type.trim())
+            .map(ToString::to_string)
+            .collect::<Vec<String>>();
+
+        for crate_type in &specified_crate_types {
+            if !KNOWN_CRATE_TYPES.contains(&crate_type.as_str()) {
+                return IgnoreDecision::Error {
+                    message: format!(
+                        "unknown crate type specified in `needs-crate-type`: `{crate_type}` is not \
+                        a known crate type, known values are `{:?}`",
+                        KNOWN_CRATE_TYPES
+                    ),
+                };
+            }
+        }
+
+        let satisfies_all_crate_types = specified_crate_types
+            .iter()
+            .all(|specified| config.supported_crate_types().contains(specified));
+        if satisfies_all_crate_types {
+            return IgnoreDecision::Continue;
+        } else {
+            return IgnoreDecision::Ignore {
+                reason: format!(
+                    "skipping test as target does not support all of the crate types `{:?}`",
+                    specified_crate_types
+                ),
+            };
+        }
+    }
+
     if !name.starts_with("needs-") {
         return IgnoreDecision::Continue;
     }
diff --git a/src/tools/compiletest/src/header/tests.rs b/src/tools/compiletest/src/header/tests.rs
index 1a796cdd7cd..f3461f3c244 100644
--- a/src/tools/compiletest/src/header/tests.rs
+++ b/src/tools/compiletest/src/header/tests.rs
@@ -902,3 +902,41 @@ fn test_rustc_abi() {
     assert!(!check_ignore(&config, "//@ ignore-rustc_abi-x86-sse2"));
     assert!(check_ignore(&config, "//@ only-rustc_abi-x86-sse2"));
 }
+
+#[test]
+fn test_supported_crate_types() {
+    // Basic assumptions check on under-test compiler's `--print=supported-crate-types` output based
+    // on knowledge about the cherry-picked `x86_64-unknown-linux-gnu` and `wasm32-unknown-unknown`
+    // targets. Also smoke tests the `needs-crate-type` directive itself.
+
+    use std::collections::HashSet;
+
+    let config = cfg().target("x86_64-unknown-linux-gnu").build();
+    assert_eq!(
+        config.supported_crate_types().iter().map(String::as_str).collect::<HashSet<_>>(),
+        HashSet::from(["bin", "cdylib", "dylib", "lib", "proc-macro", "rlib", "staticlib"]),
+    );
+    assert!(!check_ignore(&config, "//@ needs-crate-type: rlib"));
+    assert!(!check_ignore(&config, "//@ needs-crate-type: dylib"));
+    assert!(!check_ignore(
+        &config,
+        "//@ needs-crate-type: bin, cdylib, dylib, lib, proc-macro, rlib, staticlib"
+    ));
+
+    let config = cfg().target("wasm32-unknown-unknown").build();
+    assert_eq!(
+        config.supported_crate_types().iter().map(String::as_str).collect::<HashSet<_>>(),
+        HashSet::from(["bin", "cdylib", "lib", "rlib", "staticlib"]),
+    );
+
+    // rlib is supported
+    assert!(!check_ignore(&config, "//@ needs-crate-type: rlib"));
+    // dylib is not
+    assert!(check_ignore(&config, "//@ needs-crate-type: dylib"));
+    // If multiple crate types are specified, then all specified crate types need to be supported.
+    assert!(check_ignore(&config, "//@ needs-crate-type: cdylib, dylib"));
+    assert!(check_ignore(
+        &config,
+        "//@ needs-crate-type: bin, cdylib, dylib, lib, proc-macro, rlib, staticlib"
+    ));
+}
diff --git a/src/tools/compiletest/src/lib.rs b/src/tools/compiletest/src/lib.rs
index 782f6e0f2d8..8fa11c81c6a 100644
--- a/src/tools/compiletest/src/lib.rs
+++ b/src/tools/compiletest/src/lib.rs
@@ -431,6 +431,7 @@ pub fn parse_config(args: Vec<String>) -> Config {
 
         target_cfgs: OnceLock::new(),
         builtin_cfg_names: OnceLock::new(),
+        supported_crate_types: OnceLock::new(),
 
         nocapture: matches.opt_present("no-capture"),
 

From 5fe7712a109941b205899e9bb929d15b040d9720 Mon Sep 17 00:00:00 2001
From: Jieyou Xu <jieyouxu@outlook.com>
Date: Mon, 7 Apr 2025 13:18:03 +0800
Subject: [PATCH 06/16] rustc-dev-guide: document `needs-crate-type`

---
 src/doc/rustc-dev-guide/src/tests/directives.md | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/src/doc/rustc-dev-guide/src/tests/directives.md b/src/doc/rustc-dev-guide/src/tests/directives.md
index 8e4a710178e..7ed583c1007 100644
--- a/src/doc/rustc-dev-guide/src/tests/directives.md
+++ b/src/doc/rustc-dev-guide/src/tests/directives.md
@@ -191,8 +191,13 @@ settings:
   specified atomic widths, e.g. the test with `//@ needs-target-has-atomic: 8,
   16, ptr` will only run if it supports the comma-separated list of atomic
   widths.
-- `needs-dynamic-linking` - ignores if target does not support dynamic linking
+- `needs-dynamic-linking` — ignores if target does not support dynamic linking
   (which is orthogonal to it being unable to create `dylib` and `cdylib` crate types)
+- `needs-crate-type` — ignores if target platform does not support one or more
+  of the comma-delimited list of specified crate types. For example,
+  `//@ needs-crate-type: cdylib, proc-macro` will cause the test to be ignored
+  on `wasm32-unknown-unknown` target because the target does not support the
+  `proc-macro` crate type.
 
 The following directives will check LLVM support:
 

From c615d1074300f450c435abbf718969bf4f416f98 Mon Sep 17 00:00:00 2001
From: Jieyou Xu <jieyouxu@outlook.com>
Date: Mon, 7 Apr 2025 13:29:13 +0800
Subject: [PATCH 07/16] tests: use specific-purpose `needs-crate-type` over
 `ignore-$target` directives

Not all existing tests are converted, I only updated ones that I can
easily find via directive comments.
---
 .../invalid-compile-flags/crate-type-flag.rs  |  9 ++---
 tests/ui/linkage-attr/issue-12133-3.rs        |  3 +-
 .../lint-non-snake-case-crate.cdylib_.stderr  |  4 +--
 .../lint-non-snake-case-crate.dylib_.stderr   |  4 +--
 .../lint-non-snake-case-crate.lib_.stderr     |  4 +--
 ...nt-non-snake-case-crate.proc_macro_.stderr |  4 +--
 .../lint-non-snake-case-crate.rlib_.stderr    |  4 +--
 .../lint-non-snake-case-crate.rs              | 33 +++++++++----------
 ...int-non-snake-case-crate.staticlib_.stderr |  4 +--
 .../abort-link-to-unwind-dylib.rs             |  4 +--
 10 files changed, 33 insertions(+), 40 deletions(-)

diff --git a/tests/ui/invalid-compile-flags/crate-type-flag.rs b/tests/ui/invalid-compile-flags/crate-type-flag.rs
index 8ccce97f7bf..61b35cf8c64 100644
--- a/tests/ui/invalid-compile-flags/crate-type-flag.rs
+++ b/tests/ui/invalid-compile-flags/crate-type-flag.rs
@@ -3,8 +3,6 @@
 //!
 //! This test does not try to check if the output artifacts are valid.
 
-// FIXME(#132309): add a proper `supports-crate-type` directive.
-
 // Single valid crate types should pass
 //@ revisions: lib rlib staticlib dylib cdylib bin proc_dash_macro
 
@@ -17,19 +15,18 @@
 //@[staticlib] compile-flags: --crate-type=staticlib
 //@[staticlib] check-pass
 
-//@[dylib] ignore-musl (dylib is supported, but musl libc is statically linked by default)
-//@[dylib] ignore-wasm (dylib is not supported)
+//@[dylib] needs-crate-type: dylib
 //@[dylib] compile-flags: --crate-type=dylib
 //@[dylib] check-pass
 
-//@[cdylib] ignore-musl (cdylib is supported, but musl libc is statically linked by default)
+//@[cdylib] needs-crate-type: cdylib
 //@[cdylib] compile-flags: --crate-type=cdylib
 //@[cdylib] check-pass
 
 //@[bin] compile-flags: --crate-type=bin
 //@[bin] check-pass
 
-//@[proc_dash_macro] ignore-wasm (proc-macro is not supported)
+//@[proc_dash_macro] needs-crate-type: proc-macro
 //@[proc_dash_macro] needs-unwind (panic=abort causes warning to be emitted)
 //@[proc_dash_macro] compile-flags: --crate-type=proc-macro
 //@[proc_dash_macro] check-pass
diff --git a/tests/ui/linkage-attr/issue-12133-3.rs b/tests/ui/linkage-attr/issue-12133-3.rs
index 473d5774c16..df1b0b2f728 100644
--- a/tests/ui/linkage-attr/issue-12133-3.rs
+++ b/tests/ui/linkage-attr/issue-12133-3.rs
@@ -2,8 +2,7 @@
 //@ aux-build:issue-12133-rlib.rs
 //@ aux-build:issue-12133-dylib.rs
 //@ aux-build:issue-12133-dylib2.rs
-//@ ignore-wasm32 no dylib support
-//@ ignore-musl
+//@ needs-crate-type: dylib
 //@ needs-dynamic-linking
 
 
diff --git a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.cdylib_.stderr b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.cdylib_.stderr
index 1192b690e29..a9c01886744 100644
--- a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.cdylib_.stderr
+++ b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.cdylib_.stderr
@@ -1,11 +1,11 @@
 error: crate `NonSnakeCase` should have a snake case name
-  --> $DIR/lint-non-snake-case-crate.rs:36:18
+  --> $DIR/lint-non-snake-case-crate.rs:35:18
    |
 LL | #![crate_name = "NonSnakeCase"]
    |                  ^^^^^^^^^^^^ help: convert the identifier to snake case: `non_snake_case`
    |
 note: the lint level is defined here
-  --> $DIR/lint-non-snake-case-crate.rs:38:9
+  --> $DIR/lint-non-snake-case-crate.rs:37:9
    |
 LL | #![deny(non_snake_case)]
    |         ^^^^^^^^^^^^^^
diff --git a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.dylib_.stderr b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.dylib_.stderr
index 1192b690e29..a9c01886744 100644
--- a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.dylib_.stderr
+++ b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.dylib_.stderr
@@ -1,11 +1,11 @@
 error: crate `NonSnakeCase` should have a snake case name
-  --> $DIR/lint-non-snake-case-crate.rs:36:18
+  --> $DIR/lint-non-snake-case-crate.rs:35:18
    |
 LL | #![crate_name = "NonSnakeCase"]
    |                  ^^^^^^^^^^^^ help: convert the identifier to snake case: `non_snake_case`
    |
 note: the lint level is defined here
-  --> $DIR/lint-non-snake-case-crate.rs:38:9
+  --> $DIR/lint-non-snake-case-crate.rs:37:9
    |
 LL | #![deny(non_snake_case)]
    |         ^^^^^^^^^^^^^^
diff --git a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.lib_.stderr b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.lib_.stderr
index 1192b690e29..a9c01886744 100644
--- a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.lib_.stderr
+++ b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.lib_.stderr
@@ -1,11 +1,11 @@
 error: crate `NonSnakeCase` should have a snake case name
-  --> $DIR/lint-non-snake-case-crate.rs:36:18
+  --> $DIR/lint-non-snake-case-crate.rs:35:18
    |
 LL | #![crate_name = "NonSnakeCase"]
    |                  ^^^^^^^^^^^^ help: convert the identifier to snake case: `non_snake_case`
    |
 note: the lint level is defined here
-  --> $DIR/lint-non-snake-case-crate.rs:38:9
+  --> $DIR/lint-non-snake-case-crate.rs:37:9
    |
 LL | #![deny(non_snake_case)]
    |         ^^^^^^^^^^^^^^
diff --git a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.proc_macro_.stderr b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.proc_macro_.stderr
index 1192b690e29..a9c01886744 100644
--- a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.proc_macro_.stderr
+++ b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.proc_macro_.stderr
@@ -1,11 +1,11 @@
 error: crate `NonSnakeCase` should have a snake case name
-  --> $DIR/lint-non-snake-case-crate.rs:36:18
+  --> $DIR/lint-non-snake-case-crate.rs:35:18
    |
 LL | #![crate_name = "NonSnakeCase"]
    |                  ^^^^^^^^^^^^ help: convert the identifier to snake case: `non_snake_case`
    |
 note: the lint level is defined here
-  --> $DIR/lint-non-snake-case-crate.rs:38:9
+  --> $DIR/lint-non-snake-case-crate.rs:37:9
    |
 LL | #![deny(non_snake_case)]
    |         ^^^^^^^^^^^^^^
diff --git a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.rlib_.stderr b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.rlib_.stderr
index 1192b690e29..a9c01886744 100644
--- a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.rlib_.stderr
+++ b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.rlib_.stderr
@@ -1,11 +1,11 @@
 error: crate `NonSnakeCase` should have a snake case name
-  --> $DIR/lint-non-snake-case-crate.rs:36:18
+  --> $DIR/lint-non-snake-case-crate.rs:35:18
    |
 LL | #![crate_name = "NonSnakeCase"]
    |                  ^^^^^^^^^^^^ help: convert the identifier to snake case: `non_snake_case`
    |
 note: the lint level is defined here
-  --> $DIR/lint-non-snake-case-crate.rs:38:9
+  --> $DIR/lint-non-snake-case-crate.rs:37:9
    |
 LL | #![deny(non_snake_case)]
    |         ^^^^^^^^^^^^^^
diff --git a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.rs b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.rs
index 6f701cd27c6..a63e9c5ddf2 100644
--- a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.rs
+++ b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.rs
@@ -10,28 +10,27 @@
 
 // But should fire on non-binary crates.
 
-// FIXME(#132309): dylib crate type is not supported on wasm; we need a proper
-// supports-crate-type directive. Also, needs-dynamic-linking should rule out
-// musl since it supports neither dylibs nor cdylibs.
-//@[dylib_] ignore-wasm
-//@[dylib_] ignore-musl
-//@[cdylib_] ignore-musl
-
-//@[dylib_] needs-dynamic-linking
+//@[cdylib_] compile-flags: --crate-type=cdylib
 //@[cdylib_] needs-dynamic-linking
+//@[cdylib_] needs-crate-type: cdylib
+
+//@[dylib_] compile-flags: --crate-type=dylib
+//@[dylib_] needs-dynamic-linking
+//@[dylib_] needs-crate-type: dylib
+
+//@[lib_] compile-flags: --crate-type=lib
+
 //@[proc_macro_] force-host
 //@[proc_macro_] no-prefer-dynamic
-
-//@[cdylib_] compile-flags: --crate-type=cdylib
-//@[dylib_] compile-flags: --crate-type=dylib
-//@[lib_] compile-flags: --crate-type=lib
 //@[proc_macro_] compile-flags: --crate-type=proc-macro
-//@[rlib_] compile-flags: --crate-type=rlib
-//@[staticlib_] compile-flags: --crate-type=staticlib
-
-// The compiler may emit a warning that causes stderr output
-// that contains a warning this test does not wish to check.
+// The compiler may emit a warning that causes stderr output that contains a warning this test does
+// not wish to check.
 //@[proc_macro_] needs-unwind
+//@[proc_macro_] needs-crate-type: proc-macro
+
+//@[rlib_] compile-flags: --crate-type=rlib
+
+//@[staticlib_] compile-flags: --crate-type=staticlib
 
 #![crate_name = "NonSnakeCase"]
 //[cdylib_,dylib_,lib_,proc_macro_,rlib_,staticlib_]~^ ERROR crate `NonSnakeCase` should have a snake case name
diff --git a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.staticlib_.stderr b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.staticlib_.stderr
index 1192b690e29..a9c01886744 100644
--- a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.staticlib_.stderr
+++ b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.staticlib_.stderr
@@ -1,11 +1,11 @@
 error: crate `NonSnakeCase` should have a snake case name
-  --> $DIR/lint-non-snake-case-crate.rs:36:18
+  --> $DIR/lint-non-snake-case-crate.rs:35:18
    |
 LL | #![crate_name = "NonSnakeCase"]
    |                  ^^^^^^^^^^^^ help: convert the identifier to snake case: `non_snake_case`
    |
 note: the lint level is defined here
-  --> $DIR/lint-non-snake-case-crate.rs:38:9
+  --> $DIR/lint-non-snake-case-crate.rs:37:9
    |
 LL | #![deny(non_snake_case)]
    |         ^^^^^^^^^^^^^^
diff --git a/tests/ui/panic-runtime/abort-link-to-unwind-dylib.rs b/tests/ui/panic-runtime/abort-link-to-unwind-dylib.rs
index 8b782413f6a..a691ceb566b 100644
--- a/tests/ui/panic-runtime/abort-link-to-unwind-dylib.rs
+++ b/tests/ui/panic-runtime/abort-link-to-unwind-dylib.rs
@@ -1,9 +1,7 @@
 //@ build-fail
 //@ compile-flags:-C panic=abort -C prefer-dynamic
 //@ needs-unwind
-//@ ignore-musl - no dylibs here
-//@ ignore-emscripten
-//@ ignore-sgx no dynamic lib support
+//@ needs-crate-type: dylib
 
 // This is a test where the local crate, compiled with `panic=abort`, links to
 // the standard library **dynamically** which is already linked against

From b1053fdb76cca8b2006558207b3b1c939c3df333 Mon Sep 17 00:00:00 2001
From: onur-ozkan <work@onurozkan.dev>
Date: Wed, 9 Apr 2025 09:45:56 +0300
Subject: [PATCH 08/16] handle `config.channel` default for tarballs

Signed-off-by: onur-ozkan <work@onurozkan.dev>
---
 src/bootstrap/src/core/config/config.rs | 33 ++++++++++++++-----------
 1 file changed, 18 insertions(+), 15 deletions(-)

diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs
index 1712be7f947..9532cfa711f 100644
--- a/src/bootstrap/src/core/config/config.rs
+++ b/src/bootstrap/src/core/config/config.rs
@@ -1540,9 +1540,6 @@ impl Config {
             }
         }
 
-        let file_content = t!(fs::read_to_string(config.src.join("src/ci/channel")));
-        let ci_channel = file_content.trim_end();
-
         // Give a hard error if `--config` or `RUST_BOOTSTRAP_CONFIG` are set to a missing path,
         // but not if `bootstrap.toml` hasn't been created.
         let mut toml = if !using_default_path || toml_path.exists() {
@@ -1847,17 +1844,21 @@ impl Config {
         let mut lld_enabled = None;
         let mut std_features = None;
 
-        let is_user_configured_rust_channel =
-            if let Some(channel) = toml.rust.as_ref().and_then(|r| r.channel.clone()) {
-                if channel == "auto-detect" {
-                    config.channel = ci_channel.into();
-                } else {
-                    config.channel = channel;
-                }
+        let file_content = t!(fs::read_to_string(config.src.join("src/ci/channel")));
+        let ci_channel = file_content.trim_end();
+
+        let toml_channel = toml.rust.as_ref().and_then(|r| r.channel.clone());
+        let is_user_configured_rust_channel = match toml_channel {
+            Some(channel) if channel == "auto-detect" => {
+                config.channel = ci_channel.into();
                 true
-            } else {
-                false
-            };
+            }
+            Some(channel) => {
+                config.channel = channel;
+                true
+            }
+            None => false,
+        };
 
         let default = config.channel == "dev";
         config.omit_git_hash = toml.rust.as_ref().and_then(|r| r.omit_git_hash).unwrap_or(default);
@@ -1882,6 +1883,10 @@ impl Config {
                 && config.src.join(".cargo/config.toml").exists(),
         );
 
+        if !is_user_configured_rust_channel && config.rust_info.is_from_tarball() {
+            config.channel = ci_channel.into();
+        }
+
         if let Some(rust) = toml.rust {
             let Rust {
                 optimize: optimize_toml,
@@ -2085,8 +2090,6 @@ impl Config {
 
                 config.channel = channel;
             }
-        } else if config.rust_info.is_from_tarball() && !is_user_configured_rust_channel {
-            ci_channel.clone_into(&mut config.channel);
         }
 
         if let Some(llvm) = toml.llvm {

From f74032621621d32cf59739b00ecc8f7f9510fc28 Mon Sep 17 00:00:00 2001
From: Alex Macleod <alex@macleod.io>
Date: Wed, 19 Mar 2025 02:19:33 +0000
Subject: [PATCH 09/16] Allow drivers to supply a list of extra symbols to
 intern

---
 compiler/rustc_driver_impl/src/lib.rs         |  1 +
 compiler/rustc_hir/src/tests.rs               |  2 +-
 compiler/rustc_interface/src/interface.rs     |  5 ++++
 compiler/rustc_interface/src/tests.rs         |  2 +-
 compiler/rustc_interface/src/util.rs          | 29 +++++++++++++------
 compiler/rustc_macros/src/symbols.rs          | 25 ++++++++++------
 compiler/rustc_metadata/src/rmeta/decoder.rs  |  4 +--
 compiler/rustc_metadata/src/rmeta/encoder.rs  |  6 ++--
 compiler/rustc_metadata/src/rmeta/mod.rs      |  2 +-
 .../rustc_middle/src/query/on_disk_cache.rs   | 12 ++++----
 compiler/rustc_span/src/lib.rs                | 15 ++++++----
 compiler/rustc_span/src/symbol.rs             | 26 ++++++++---------
 compiler/rustc_span/src/symbol/tests.rs       |  2 +-
 src/librustdoc/core.rs                        |  1 +
 src/librustdoc/doctest.rs                     |  1 +
 src/tools/clippy/Cargo.toml                   |  1 +
 .../src/attrs/deprecated_cfg_attr.rs          |  4 +--
 .../src/attrs/useless_attribute.rs            |  4 +--
 .../src/doc/needless_doctest_main.rs          |  2 +-
 src/tools/clippy/clippy_utils/src/lib.rs      |  4 ++-
 src/tools/clippy/clippy_utils/src/sym.rs      | 23 +++++++++++++++
 src/tools/clippy/src/driver.rs                |  1 +
 tests/ui-fulldeps/run-compiler-twice.rs       |  1 +
 23 files changed, 115 insertions(+), 58 deletions(-)
 create mode 100644 src/tools/clippy/clippy_utils/src/sym.rs

diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs
index 8ede6e41336..3aa9a75d893 100644
--- a/compiler/rustc_driver_impl/src/lib.rs
+++ b/compiler/rustc_driver_impl/src/lib.rs
@@ -259,6 +259,7 @@ pub fn run_compiler(at_args: &[String], callbacks: &mut (dyn Callbacks + Send))
         hash_untracked_state: None,
         register_lints: None,
         override_queries: None,
+        extra_symbols: Vec::new(),
         make_codegen_backend: None,
         registry: diagnostics_registry(),
         using_internal_features: &USING_INTERNAL_FEATURES,
diff --git a/compiler/rustc_hir/src/tests.rs b/compiler/rustc_hir/src/tests.rs
index 0837444ffdb..18c2bfdac8c 100644
--- a/compiler/rustc_hir/src/tests.rs
+++ b/compiler/rustc_hir/src/tests.rs
@@ -17,7 +17,7 @@ fn def_path_hash_depends_on_crate_id() {
     // the crate by changing the crate disambiguator (e.g. via bumping the
     // crate's version number).
 
-    create_session_globals_then(Edition::Edition2024, None, || {
+    create_session_globals_then(Edition::Edition2024, &[], None, || {
         let id0 = StableCrateId::new(Symbol::intern("foo"), false, vec!["1".to_string()], "");
         let id1 = StableCrateId::new(Symbol::intern("foo"), false, vec!["2".to_string()], "");
 
diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs
index 3f87b1a547b..5717a2b8743 100644
--- a/compiler/rustc_interface/src/interface.rs
+++ b/compiler/rustc_interface/src/interface.rs
@@ -340,6 +340,10 @@ pub struct Config {
     /// the list of queries.
     pub override_queries: Option<fn(&Session, &mut Providers)>,
 
+    /// An extra set of symbols to add to the symbol interner, the symbol indices
+    /// will start at [`PREDEFINED_SYMBOLS_COUNT`](rustc_span::symbol::PREDEFINED_SYMBOLS_COUNT)
+    pub extra_symbols: Vec<&'static str>,
+
     /// This is a callback from the driver that is called to create a codegen backend.
     ///
     /// Has no uses within this repository, but is used by bjorn3 for "the
@@ -401,6 +405,7 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se
         &early_dcx,
         config.opts.edition,
         config.opts.unstable_opts.threads,
+        &config.extra_symbols,
         SourceMapInputs { file_loader, path_mapping, hash_kind, checksum_hash_kind },
         |current_gcx| {
             // The previous `early_dcx` can't be reused here because it doesn't
diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs
index b44be1710ed..903cda3cb5b 100644
--- a/compiler/rustc_interface/src/tests.rs
+++ b/compiler/rustc_interface/src/tests.rs
@@ -53,7 +53,7 @@ where
         checksum_hash_kind,
     });
 
-    rustc_span::create_session_globals_then(DEFAULT_EDITION, sm_inputs, || {
+    rustc_span::create_session_globals_then(DEFAULT_EDITION, &[], sm_inputs, || {
         let temps_dir = sessopts.unstable_opts.temps_dir.as_deref().map(PathBuf::from);
         let io = CompilerIO {
             input: Input::Str { name: FileName::Custom(String::new()), input: String::new() },
diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs
index 5cccab893bb..fceaa6577ab 100644
--- a/compiler/rustc_interface/src/util.rs
+++ b/compiler/rustc_interface/src/util.rs
@@ -117,6 +117,7 @@ fn run_in_thread_with_globals<F: FnOnce(CurrentGcx) -> R + Send, R: Send>(
     thread_stack_size: usize,
     edition: Edition,
     sm_inputs: SourceMapInputs,
+    extra_symbols: &[&'static str],
     f: F,
 ) -> R {
     // The "thread pool" is a single spawned thread in the non-parallel
@@ -134,9 +135,12 @@ fn run_in_thread_with_globals<F: FnOnce(CurrentGcx) -> R + Send, R: Send>(
         // name contains null bytes.
         let r = builder
             .spawn_scoped(s, move || {
-                rustc_span::create_session_globals_then(edition, Some(sm_inputs), || {
-                    f(CurrentGcx::new())
-                })
+                rustc_span::create_session_globals_then(
+                    edition,
+                    extra_symbols,
+                    Some(sm_inputs),
+                    || f(CurrentGcx::new()),
+                )
             })
             .unwrap()
             .join();
@@ -152,6 +156,7 @@ pub(crate) fn run_in_thread_pool_with_globals<F: FnOnce(CurrentGcx) -> R + Send,
     thread_builder_diag: &EarlyDiagCtxt,
     edition: Edition,
     threads: usize,
+    extra_symbols: &[&'static str],
     sm_inputs: SourceMapInputs,
     f: F,
 ) -> R {
@@ -168,12 +173,18 @@ pub(crate) fn run_in_thread_pool_with_globals<F: FnOnce(CurrentGcx) -> R + Send,
     let registry = sync::Registry::new(std::num::NonZero::new(threads).unwrap());
 
     if !sync::is_dyn_thread_safe() {
-        return run_in_thread_with_globals(thread_stack_size, edition, sm_inputs, |current_gcx| {
-            // Register the thread for use with the `WorkerLocal` type.
-            registry.register();
+        return run_in_thread_with_globals(
+            thread_stack_size,
+            edition,
+            sm_inputs,
+            extra_symbols,
+            |current_gcx| {
+                // Register the thread for use with the `WorkerLocal` type.
+                registry.register();
 
-            f(current_gcx)
-        });
+                f(current_gcx)
+            },
+        );
     }
 
     let current_gcx = FromDyn::from(CurrentGcx::new());
@@ -217,7 +228,7 @@ pub(crate) fn run_in_thread_pool_with_globals<F: FnOnce(CurrentGcx) -> R + Send,
     // pool. Upon creation, each worker thread created gets a copy of the
     // session globals in TLS. This is possible because `SessionGlobals` impls
     // `Send` in the parallel compiler.
-    rustc_span::create_session_globals_then(edition, Some(sm_inputs), || {
+    rustc_span::create_session_globals_then(edition, extra_symbols, Some(sm_inputs), || {
         rustc_span::with_session_globals(|session_globals| {
             let session_globals = FromDyn::from(session_globals);
             builder
diff --git a/compiler/rustc_macros/src/symbols.rs b/compiler/rustc_macros/src/symbols.rs
index 37200f62eb5..0400de62274 100644
--- a/compiler/rustc_macros/src/symbols.rs
+++ b/compiler/rustc_macros/src/symbols.rs
@@ -142,13 +142,13 @@ pub(super) fn symbols(input: TokenStream) -> TokenStream {
     output
 }
 
-struct Preinterned {
+struct Predefined {
     idx: u32,
     span_of_name: Span,
 }
 
 struct Entries {
-    map: HashMap<String, Preinterned>,
+    map: HashMap<String, Predefined>,
 }
 
 impl Entries {
@@ -163,7 +163,7 @@ impl Entries {
             prev.idx
         } else {
             let idx = self.len();
-            self.map.insert(s.to_string(), Preinterned { idx, span_of_name: span });
+            self.map.insert(s.to_string(), Predefined { idx, span_of_name: span });
             idx
         }
     }
@@ -295,10 +295,14 @@ fn symbols_with_errors(input: TokenStream) -> (TokenStream, Vec<syn::Error>) {
     }
 
     let symbol_digits_base = entries.map["0"].idx;
-    let preinterned_symbols_count = entries.len();
+    let predefined_symbols_count = entries.len();
     let output = quote! {
         const SYMBOL_DIGITS_BASE: u32 = #symbol_digits_base;
-        const PREINTERNED_SYMBOLS_COUNT: u32 = #preinterned_symbols_count;
+
+        /// The number of predefined symbols; this is the the first index for
+        /// extra pre-interned symbols in an Interner created via
+        /// [`Interner::with_extra_symbols`].
+        pub const PREDEFINED_SYMBOLS_COUNT: u32 = #predefined_symbols_count;
 
         #[doc(hidden)]
         #[allow(non_upper_case_globals)]
@@ -315,10 +319,13 @@ fn symbols_with_errors(input: TokenStream) -> (TokenStream, Vec<syn::Error>) {
         }
 
         impl Interner {
-            pub(crate) fn fresh() -> Self {
-                Interner::prefill(&[
-                    #prefill_stream
-                ])
+            /// Creates an `Interner` with the predefined symbols from the `symbols!` macro and
+            /// any extra symbols provided by external drivers such as Clippy
+            pub(crate) fn with_extra_symbols(extra_symbols: &[&'static str]) -> Self {
+                Interner::prefill(
+                    &[#prefill_stream],
+                    extra_symbols,
+                )
             }
         }
     };
diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs
index f6cf218db9d..151cc064a96 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder.rs
@@ -562,9 +562,9 @@ impl<'a, 'tcx> SpanDecoder for DecodeContext<'a, 'tcx> {
                     Symbol::intern(s)
                 })
             }
-            SYMBOL_PREINTERNED => {
+            SYMBOL_PREDEFINED => {
                 let symbol_index = self.read_u32();
-                Symbol::new_from_decoded(symbol_index)
+                Symbol::new(symbol_index)
             }
             _ => unreachable!(),
         }
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index 7ab3d432bdf..8b7b3bba887 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -201,9 +201,9 @@ impl<'a, 'tcx> SpanEncoder for EncodeContext<'a, 'tcx> {
     }
 
     fn encode_symbol(&mut self, symbol: Symbol) {
-        // if symbol preinterned, emit tag and symbol index
-        if symbol.is_preinterned() {
-            self.opaque.emit_u8(SYMBOL_PREINTERNED);
+        // if symbol predefined, emit tag and symbol index
+        if symbol.is_predefined() {
+            self.opaque.emit_u8(SYMBOL_PREDEFINED);
             self.opaque.emit_u32(symbol.as_u32());
         } else {
             // otherwise write it as string or as offset to it
diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs
index 5536c93f84a..3eff5dfd5af 100644
--- a/compiler/rustc_metadata/src/rmeta/mod.rs
+++ b/compiler/rustc_metadata/src/rmeta/mod.rs
@@ -576,7 +576,7 @@ impl SpanTag {
 // Tags for encoding Symbol's
 const SYMBOL_STR: u8 = 0;
 const SYMBOL_OFFSET: u8 = 1;
-const SYMBOL_PREINTERNED: u8 = 2;
+const SYMBOL_PREDEFINED: u8 = 2;
 
 pub fn provide(providers: &mut Providers) {
     encoder::provide(providers);
diff --git a/compiler/rustc_middle/src/query/on_disk_cache.rs b/compiler/rustc_middle/src/query/on_disk_cache.rs
index 14e3ce8bef6..3b935842af4 100644
--- a/compiler/rustc_middle/src/query/on_disk_cache.rs
+++ b/compiler/rustc_middle/src/query/on_disk_cache.rs
@@ -45,7 +45,7 @@ const TAG_EXPN_DATA: u8 = 1;
 // Tags for encoding Symbol's
 const SYMBOL_STR: u8 = 0;
 const SYMBOL_OFFSET: u8 = 1;
-const SYMBOL_PREINTERNED: u8 = 2;
+const SYMBOL_PREDEFINED: u8 = 2;
 
 /// Provides an interface to incremental compilation data cached from the
 /// previous compilation session. This data will eventually include the results
@@ -673,9 +673,9 @@ impl<'a, 'tcx> SpanDecoder for CacheDecoder<'a, 'tcx> {
                     Symbol::intern(s)
                 })
             }
-            SYMBOL_PREINTERNED => {
+            SYMBOL_PREDEFINED => {
                 let symbol_index = self.read_u32();
-                Symbol::new_from_decoded(symbol_index)
+                Symbol::new(symbol_index)
             }
             _ => unreachable!(),
         }
@@ -891,9 +891,9 @@ impl<'a, 'tcx> SpanEncoder for CacheEncoder<'a, 'tcx> {
 
     // copy&paste impl from rustc_metadata
     fn encode_symbol(&mut self, symbol: Symbol) {
-        // if symbol preinterned, emit tag and symbol index
-        if symbol.is_preinterned() {
-            self.encoder.emit_u8(SYMBOL_PREINTERNED);
+        // if symbol predefined, emit tag and symbol index
+        if symbol.is_predefined() {
+            self.encoder.emit_u8(SYMBOL_PREDEFINED);
             self.encoder.emit_u32(symbol.as_u32());
         } else {
             // otherwise write it as string or as offset to it
diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs
index f19d4d9f362..432b1b86142 100644
--- a/compiler/rustc_span/src/lib.rs
+++ b/compiler/rustc_span/src/lib.rs
@@ -116,9 +116,13 @@ pub struct SessionGlobals {
 }
 
 impl SessionGlobals {
-    pub fn new(edition: Edition, sm_inputs: Option<SourceMapInputs>) -> SessionGlobals {
+    pub fn new(
+        edition: Edition,
+        extra_symbols: &[&'static str],
+        sm_inputs: Option<SourceMapInputs>,
+    ) -> SessionGlobals {
         SessionGlobals {
-            symbol_interner: symbol::Interner::fresh(),
+            symbol_interner: symbol::Interner::with_extra_symbols(extra_symbols),
             span_interner: Lock::new(span_encoding::SpanInterner::default()),
             metavar_spans: Default::default(),
             hygiene_data: Lock::new(hygiene::HygieneData::new(edition)),
@@ -129,6 +133,7 @@ impl SessionGlobals {
 
 pub fn create_session_globals_then<R>(
     edition: Edition,
+    extra_symbols: &[&'static str],
     sm_inputs: Option<SourceMapInputs>,
     f: impl FnOnce() -> R,
 ) -> R {
@@ -137,7 +142,7 @@ pub fn create_session_globals_then<R>(
         "SESSION_GLOBALS should never be overwritten! \
          Use another thread if you need another SessionGlobals"
     );
-    let session_globals = SessionGlobals::new(edition, sm_inputs);
+    let session_globals = SessionGlobals::new(edition, extra_symbols, sm_inputs);
     SESSION_GLOBALS.set(&session_globals, f)
 }
 
@@ -156,7 +161,7 @@ where
     F: FnOnce(&SessionGlobals) -> R,
 {
     if !SESSION_GLOBALS.is_set() {
-        let session_globals = SessionGlobals::new(edition, None);
+        let session_globals = SessionGlobals::new(edition, &[], None);
         SESSION_GLOBALS.set(&session_globals, || SESSION_GLOBALS.with(f))
     } else {
         SESSION_GLOBALS.with(f)
@@ -172,7 +177,7 @@ where
 
 /// Default edition, no source map.
 pub fn create_default_session_globals_then<R>(f: impl FnOnce() -> R) -> R {
-    create_session_globals_then(edition::DEFAULT_EDITION, None, f)
+    create_session_globals_then(edition::DEFAULT_EDITION, &[], None, f)
 }
 
 // If this ever becomes non thread-local, `decode_syntax_context`
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 8a8bec35d81..616e9390ffe 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -2506,15 +2506,10 @@ rustc_index::newtype_index! {
 }
 
 impl Symbol {
-    const fn new(n: u32) -> Self {
+    pub const fn new(n: u32) -> Self {
         Symbol(SymbolIndex::from_u32(n))
     }
 
-    /// for use in Decoder only
-    pub fn new_from_decoded(n: u32) -> Self {
-        Self::new(n)
-    }
-
     /// Maps a string to its interned representation.
     #[rustc_diagnostic_item = "SymbolIntern"]
     pub fn intern(string: &str) -> Self {
@@ -2600,11 +2595,14 @@ struct InternerInner {
 }
 
 impl Interner {
-    fn prefill(init: &[&'static str]) -> Self {
-        Interner(Lock::new(InternerInner {
-            arena: Default::default(),
-            strings: init.iter().copied().collect(),
-        }))
+    fn prefill(init: &[&'static str], extra: &[&'static str]) -> Self {
+        let strings = FxIndexSet::from_iter(init.iter().copied().chain(extra.iter().copied()));
+        assert_eq!(
+            strings.len(),
+            init.len() + extra.len(),
+            "`init` or `extra` contain duplicate symbols",
+        );
+        Interner(Lock::new(InternerInner { arena: Default::default(), strings }))
     }
 
     #[inline]
@@ -2729,9 +2727,9 @@ impl Symbol {
         self != kw::Empty && self != kw::Underscore && !self.is_path_segment_keyword()
     }
 
-    /// Is this symbol was interned in compiler's `symbols!` macro
-    pub fn is_preinterned(self) -> bool {
-        self.as_u32() < PREINTERNED_SYMBOLS_COUNT
+    /// Was this symbol predefined in the compiler's `symbols!` macro
+    pub fn is_predefined(self) -> bool {
+        self.as_u32() < PREDEFINED_SYMBOLS_COUNT
     }
 }
 
diff --git a/compiler/rustc_span/src/symbol/tests.rs b/compiler/rustc_span/src/symbol/tests.rs
index c6aa7627b2b..660d0d7179a 100644
--- a/compiler/rustc_span/src/symbol/tests.rs
+++ b/compiler/rustc_span/src/symbol/tests.rs
@@ -3,7 +3,7 @@ use crate::create_default_session_globals_then;
 
 #[test]
 fn interner_tests() {
-    let i = Interner::prefill(&[]);
+    let i = Interner::prefill(&[], &[]);
     // first one is zero:
     assert_eq!(i.intern("dog"), Symbol::new(0));
     // re-use gets the same entry:
diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs
index c47e42670c9..c4dea79370d 100644
--- a/src/librustdoc/core.rs
+++ b/src/librustdoc/core.rs
@@ -321,6 +321,7 @@ pub(crate) fn create_config(
                 (rustc_interface::DEFAULT_QUERY_PROVIDERS.typeck)(tcx, def_id)
             };
         }),
+        extra_symbols: Vec::new(),
         make_codegen_backend: None,
         registry: rustc_driver::diagnostics_registry(),
         ice_file: None,
diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs
index a2808bddb3a..88eaa52c6de 100644
--- a/src/librustdoc/doctest.rs
+++ b/src/librustdoc/doctest.rs
@@ -191,6 +191,7 @@ pub(crate) fn run(dcx: DiagCtxtHandle<'_>, input: Input, options: RustdocOptions
         hash_untracked_state: None,
         register_lints: Some(Box::new(crate::lint::register_lints)),
         override_queries: None,
+        extra_symbols: Vec::new(),
         make_codegen_backend: None,
         registry: rustc_driver::diagnostics_registry(),
         ice_file: None,
diff --git a/src/tools/clippy/Cargo.toml b/src/tools/clippy/Cargo.toml
index c4588002dc9..6c0b3af573d 100644
--- a/src/tools/clippy/Cargo.toml
+++ b/src/tools/clippy/Cargo.toml
@@ -25,6 +25,7 @@ path = "src/driver.rs"
 [dependencies]
 clippy_config = { path = "clippy_config" }
 clippy_lints = { path = "clippy_lints" }
+clippy_utils = { path = "clippy_utils" }
 rustc_tools_util = { path = "rustc_tools_util", version = "0.4.2" }
 tempfile = { version = "3.3", optional = true }
 termize = "0.1"
diff --git a/src/tools/clippy/clippy_lints/src/attrs/deprecated_cfg_attr.rs b/src/tools/clippy/clippy_lints/src/attrs/deprecated_cfg_attr.rs
index cd38aed26a3..7fab97d3ea1 100644
--- a/src/tools/clippy/clippy_lints/src/attrs/deprecated_cfg_attr.rs
+++ b/src/tools/clippy/clippy_lints/src/attrs/deprecated_cfg_attr.rs
@@ -1,10 +1,10 @@
 use super::{Attribute, DEPRECATED_CFG_ATTR, DEPRECATED_CLIPPY_CFG_ATTR, unnecessary_clippy_cfg};
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::msrvs::{self, MsrvStack};
+use clippy_utils::sym;
 use rustc_ast::AttrStyle;
 use rustc_errors::Applicability;
 use rustc_lint::EarlyContext;
-use rustc_span::sym;
 
 pub(super) fn check(cx: &EarlyContext<'_>, attr: &Attribute, msrv: &MsrvStack) {
     // check cfg_attr
@@ -18,7 +18,7 @@ pub(super) fn check(cx: &EarlyContext<'_>, attr: &Attribute, msrv: &MsrvStack) {
             && msrv.meets(msrvs::TOOL_ATTRIBUTES)
             // check for `rustfmt_skip` and `rustfmt::skip`
             && let Some(skip_item) = &items[1].meta_item()
-            && (skip_item.has_name(sym!(rustfmt_skip))
+            && (skip_item.has_name(sym::rustfmt_skip)
                 || skip_item
                     .path
                     .segments
diff --git a/src/tools/clippy/clippy_lints/src/attrs/useless_attribute.rs b/src/tools/clippy/clippy_lints/src/attrs/useless_attribute.rs
index e3e081ce08e..1cb43ab02a3 100644
--- a/src/tools/clippy/clippy_lints/src/attrs/useless_attribute.rs
+++ b/src/tools/clippy/clippy_lints/src/attrs/useless_attribute.rs
@@ -2,10 +2,10 @@ use super::USELESS_ATTRIBUTE;
 use super::utils::{is_lint_level, is_word, namespace_and_lint};
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::source::{SpanRangeExt, first_line_of_span};
+use clippy_utils::sym;
 use rustc_ast::{Attribute, Item, ItemKind};
 use rustc_errors::Applicability;
 use rustc_lint::{EarlyContext, LintContext};
-use rustc_span::sym;
 
 pub(super) fn check(cx: &EarlyContext<'_>, item: &Item, attrs: &[Attribute]) {
     let skip_unused_imports = attrs.iter().any(|attr| attr.has_name(sym::macro_use));
@@ -61,7 +61,7 @@ pub(super) fn check(cx: &EarlyContext<'_>, item: &Item, attrs: &[Attribute]) {
                             if is_word(lint, sym::unused_imports) && skip_unused_imports {
                                 return;
                             }
-                            if is_word(lint, sym!(unused_extern_crates)) {
+                            if is_word(lint, sym::unused_extern_crates) {
                                 return;
                             }
                         },
diff --git a/src/tools/clippy/clippy_lints/src/doc/needless_doctest_main.rs b/src/tools/clippy/clippy_lints/src/doc/needless_doctest_main.rs
index 3008082c232..bf98b1337bc 100644
--- a/src/tools/clippy/clippy_lints/src/doc/needless_doctest_main.rs
+++ b/src/tools/clippy/clippy_lints/src/doc/needless_doctest_main.rs
@@ -38,7 +38,7 @@ pub fn check(
     // of all `#[test]` attributes in not ignored code examples
     fn check_code_sample(code: String, edition: Edition, ignore: bool) -> (bool, Vec<Range<usize>>) {
         rustc_driver::catch_fatal_errors(|| {
-            rustc_span::create_session_globals_then(edition, None, || {
+            rustc_span::create_session_globals_then(edition, &[], None, || {
                 let mut test_attr_spans = vec![];
                 let filename = FileName::anon_source_code(&code);
 
diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs
index eb4e1a7722f..12f7d6416e3 100644
--- a/src/tools/clippy/clippy_utils/src/lib.rs
+++ b/src/tools/clippy/clippy_utils/src/lib.rs
@@ -3,6 +3,7 @@
 #![feature(f128)]
 #![feature(f16)]
 #![feature(if_let_guard)]
+#![feature(macro_metavar_expr)]
 #![feature(macro_metavar_expr_concat)]
 #![feature(let_chains)]
 #![feature(never_type)]
@@ -74,6 +75,7 @@ pub mod qualify_min_const_fn;
 pub mod source;
 pub mod str_utils;
 pub mod sugg;
+pub mod sym;
 pub mod ty;
 pub mod usage;
 pub mod visitors;
@@ -125,7 +127,7 @@ use rustc_middle::ty::{
 use rustc_span::hygiene::{ExpnKind, MacroKind};
 use rustc_span::source_map::SourceMap;
 use rustc_span::symbol::{Ident, Symbol, kw};
-use rustc_span::{InnerSpan, Span, sym};
+use rustc_span::{InnerSpan, Span};
 use visitors::{Visitable, for_each_unconsumed_temporary};
 
 use crate::consts::{ConstEvalCtxt, Constant, mir_to_const};
diff --git a/src/tools/clippy/clippy_utils/src/sym.rs b/src/tools/clippy/clippy_utils/src/sym.rs
new file mode 100644
index 00000000000..9cc72a5b3aa
--- /dev/null
+++ b/src/tools/clippy/clippy_utils/src/sym.rs
@@ -0,0 +1,23 @@
+#![allow(non_upper_case_globals)]
+
+use rustc_span::symbol::{Symbol, PREDEFINED_SYMBOLS_COUNT};
+
+pub use rustc_span::sym::*;
+
+macro_rules! generate {
+    ($($sym:ident,)*) => {
+        /// To be supplied to `rustc_interface::Config`
+        pub const EXTRA_SYMBOLS: &[&str] = &[
+            $(stringify!($sym),)*
+        ];
+
+        $(
+            pub const $sym: Symbol = Symbol::new(PREDEFINED_SYMBOLS_COUNT + ${index()});
+        )*
+    };
+}
+
+generate! {
+    rustfmt_skip,
+    unused_extern_crates,
+}
diff --git a/src/tools/clippy/src/driver.rs b/src/tools/clippy/src/driver.rs
index e4092bcd105..df9c4e8e6ae 100644
--- a/src/tools/clippy/src/driver.rs
+++ b/src/tools/clippy/src/driver.rs
@@ -160,6 +160,7 @@ impl rustc_driver::Callbacks for ClippyCallbacks {
             clippy_lints::register_lints(lint_store, conf);
             clippy_lints::register_pre_expansion_lints(lint_store, conf);
         }));
+        config.extra_symbols = clippy_utils::sym::EXTRA_SYMBOLS.into();
 
         // FIXME: #4825; This is required, because Clippy lints that are based on MIR have to be
         // run on the unoptimized MIR. On the other hand this results in some false negatives. If
diff --git a/tests/ui-fulldeps/run-compiler-twice.rs b/tests/ui-fulldeps/run-compiler-twice.rs
index ffc19b138a5..fa651baa7bc 100644
--- a/tests/ui-fulldeps/run-compiler-twice.rs
+++ b/tests/ui-fulldeps/run-compiler-twice.rs
@@ -70,6 +70,7 @@ fn compile(code: String, output: PathBuf, sysroot: PathBuf, linker: Option<&Path
         hash_untracked_state: None,
         register_lints: None,
         override_queries: None,
+        extra_symbols: Vec::new(),
         make_codegen_backend: None,
         registry: rustc_driver::diagnostics_registry(),
         using_internal_features: &rustc_driver::USING_INTERNAL_FEATURES,

From b435def33c0955712d811efc41c3ec71609196ab Mon Sep 17 00:00:00 2001
From: Trevor Gross <tmgross@umich.edu>
Date: Wed, 9 Apr 2025 20:32:31 +0000
Subject: [PATCH 10/16] Update `compiler-builtins` to 0.1.153

Includes the following changes:

* Avoid OOB access in `memcpy` and `memmove` [1]
* Enable intrinsics on AVR [2]
* `libm` updates to avoid using `core::arch` vector intrinsics [3]
* Re-enable `f16` on aarch64 without Neon [4]

[1]: https://github.com/rust-lang/compiler-builtins/pull/799
[2]: https://github.com/rust-lang/compiler-builtins/pull/791
[3]: https://github.com/rust-lang/compiler-builtins/pull/814
[4]: https://github.com/rust-lang/compiler-builtins/pull/809
---
 library/Cargo.lock       | 4 ++--
 library/alloc/Cargo.toml | 2 +-
 library/std/Cargo.toml   | 2 +-
 3 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/library/Cargo.lock b/library/Cargo.lock
index ad634e9f794..d035ca6c91f 100644
--- a/library/Cargo.lock
+++ b/library/Cargo.lock
@@ -67,9 +67,9 @@ dependencies = [
 
 [[package]]
 name = "compiler_builtins"
-version = "0.1.152"
+version = "0.1.153"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2153cf213eb259361567720ce55f6446f17acd0ccca87fb6dc05360578228a58"
+checksum = "926ef6a360c15a911023352fd6969c51605d70495406f735beb1ca0257448e59"
 dependencies = [
  "cc",
  "rustc-std-workspace-core",
diff --git a/library/alloc/Cargo.toml b/library/alloc/Cargo.toml
index 1d2dd1e6081..ee8cb9d25a3 100644
--- a/library/alloc/Cargo.toml
+++ b/library/alloc/Cargo.toml
@@ -16,7 +16,7 @@ bench = false
 
 [dependencies]
 core = { path = "../core", public = true }
-compiler_builtins = { version = "=0.1.152", features = ['rustc-dep-of-std'] }
+compiler_builtins = { version = "=0.1.153", features = ['rustc-dep-of-std'] }
 
 [features]
 compiler-builtins-mem = ['compiler_builtins/mem']
diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml
index 176da603d58..6b70ff764d7 100644
--- a/library/std/Cargo.toml
+++ b/library/std/Cargo.toml
@@ -18,7 +18,7 @@ cfg-if = { version = "1.0", features = ['rustc-dep-of-std'] }
 panic_unwind = { path = "../panic_unwind", optional = true }
 panic_abort = { path = "../panic_abort" }
 core = { path = "../core", public = true }
-compiler_builtins = { version = "=0.1.152" }
+compiler_builtins = { version = "=0.1.153" }
 unwind = { path = "../unwind" }
 hashbrown = { version = "0.15", default-features = false, features = [
     'rustc-dep-of-std',

From 62d5fb85ac64f034f031423cb747cf57ee14a048 Mon Sep 17 00:00:00 2001
From: Michael Goulet <michael@errs.io>
Date: Tue, 8 Apr 2025 21:41:02 +0000
Subject: [PATCH 11/16] Simplify

---
 .../src/solve/fulfill/derive_errors.rs        | 52 ++++++++-----------
 1 file changed, 22 insertions(+), 30 deletions(-)

diff --git a/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs b/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs
index 9cbe4147fb4..73d3f81296f 100644
--- a/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs
+++ b/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs
@@ -388,7 +388,8 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> {
             (true, Ok(Certainty::Maybe(MaybeCause::Ambiguity))) | (false, Err(_)) => {}
             _ => return ControlFlow::Continue(()),
         }
-        let pred_kind = goal.goal().predicate.kind();
+
+        let pred = goal.goal().predicate;
 
         let candidates = self.non_trivial_candidates(goal);
         let candidate = match candidates.as_slice() {
@@ -410,12 +411,12 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> {
 
         // FIXME: Also, what about considering >1 layer up the stack? May be necessary
         // for normalizes-to.
-        let child_mode = match pred_kind.skip_binder() {
-            ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) => {
-                ChildMode::Trait(pred_kind.rebind(pred))
+        let child_mode = match pred.kind().skip_binder() {
+            ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_pred)) => {
+                ChildMode::Trait(pred.kind().rebind(trait_pred))
             }
-            ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(pred)) => {
-                ChildMode::Host(pred_kind.rebind(pred))
+            ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(host_pred)) => {
+                ChildMode::Host(pred.kind().rebind(host_pred))
             }
             ty::PredicateKind::NormalizesTo(normalizes_to)
                 if matches!(
@@ -423,7 +424,7 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> {
                     ty::AliasTermKind::ProjectionTy | ty::AliasTermKind::ProjectionConst
                 ) =>
             {
-                ChildMode::Trait(pred_kind.rebind(ty::TraitPredicate {
+                ChildMode::Trait(pred.kind().rebind(ty::TraitPredicate {
                     trait_ref: normalizes_to.alias.trait_ref(tcx),
                     polarity: ty::PredicatePolarity::Positive,
                 }))
@@ -457,10 +458,12 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> {
         for nested_goal in nested_goals {
             trace!(nested_goal = ?(nested_goal.goal(), nested_goal.source(), nested_goal.result()));
 
+            let nested_pred = nested_goal.goal().predicate;
+
             let make_obligation = |cause| Obligation {
                 cause,
                 param_env: nested_goal.goal().param_env,
-                predicate: nested_goal.goal().predicate,
+                predicate: nested_pred,
                 recursion_depth: self.obligation.recursion_depth + 1,
             };
 
@@ -510,28 +513,17 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> {
 
         // alias-relate may fail because the lhs or rhs can't be normalized,
         // and therefore is treated as rigid.
-        if let Some(ty::PredicateKind::AliasRelate(lhs, rhs, _)) = pred_kind.no_bound_vars() {
-            if let Some(obligation) = goal
-                .infcx()
-                .visit_proof_tree_at_depth(
-                    goal.goal().with(tcx, ty::ClauseKind::WellFormed(lhs.into())),
-                    goal.depth() + 1,
-                    self,
-                )
-                .break_value()
-            {
-                return ControlFlow::Break(obligation);
-            } else if let Some(obligation) = goal
-                .infcx()
-                .visit_proof_tree_at_depth(
-                    goal.goal().with(tcx, ty::ClauseKind::WellFormed(rhs.into())),
-                    goal.depth() + 1,
-                    self,
-                )
-                .break_value()
-            {
-                return ControlFlow::Break(obligation);
-            }
+        if let Some(ty::PredicateKind::AliasRelate(lhs, rhs, _)) = pred.kind().no_bound_vars() {
+            goal.infcx().visit_proof_tree_at_depth(
+                goal.goal().with(tcx, ty::ClauseKind::WellFormed(lhs.into())),
+                goal.depth() + 1,
+                self,
+            )?;
+            goal.infcx().visit_proof_tree_at_depth(
+                goal.goal().with(tcx, ty::ClauseKind::WellFormed(rhs.into())),
+                goal.depth() + 1,
+                self,
+            )?;
         }
 
         self.detect_error_in_higher_ranked_projection(goal)?;

From 8f00b1fdad0c60220625bace86510db125ecf31a Mon Sep 17 00:00:00 2001
From: Boxy <rust@boxyuwu.dev>
Date: Thu, 10 Apr 2025 17:48:33 +0100
Subject: [PATCH 12/16] Allow parenthesis around inferred array lengths

---
 compiler/rustc_ast_lowering/src/lib.rs        |  4 +-
 .../parend_infer.nogate.stderr                | 53 +++++++++++++++++++
 .../generic_arg_infer/parend_infer.rs         | 20 ++++++-
 3 files changed, 75 insertions(+), 2 deletions(-)
 create mode 100644 tests/ui/const-generics/generic_arg_infer/parend_infer.nogate.stderr

diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index 6aa6a18ee9a..f62d250fcbe 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -2034,7 +2034,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
     }
 
     fn lower_array_length_to_const_arg(&mut self, c: &AnonConst) -> &'hir hir::ConstArg<'hir> {
-        match c.value.kind {
+        // We cannot just match on `ExprKind::Underscore` as `(_)` is represented as
+        // `ExprKind::Paren(ExprKind::Underscore)` and should also be lowered to `GenericArg::Infer`
+        match c.value.peel_parens().kind {
             ExprKind::Underscore => {
                 if !self.tcx.features().generic_arg_infer() {
                     feature_err(
diff --git a/tests/ui/const-generics/generic_arg_infer/parend_infer.nogate.stderr b/tests/ui/const-generics/generic_arg_infer/parend_infer.nogate.stderr
new file mode 100644
index 00000000000..d0a5da9676d
--- /dev/null
+++ b/tests/ui/const-generics/generic_arg_infer/parend_infer.nogate.stderr
@@ -0,0 +1,53 @@
+error[E0658]: const arguments cannot yet be inferred with `_`
+  --> $DIR/parend_infer.rs:24:16
+   |
+LL |     let c: Foo<_> = Foo::<1>;
+   |                ^
+   |
+   = note: see issue #85077 <https://github.com/rust-lang/rust/issues/85077> for more information
+   = help: add `#![feature(generic_arg_infer)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: const arguments cannot yet be inferred with `_`
+  --> $DIR/parend_infer.rs:26:16
+   |
+LL |     let c: Foo<(_)> = Foo::<1>;
+   |                ^^^
+   |
+   = note: see issue #85077 <https://github.com/rust-lang/rust/issues/85077> for more information
+   = help: add `#![feature(generic_arg_infer)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: const arguments cannot yet be inferred with `_`
+  --> $DIR/parend_infer.rs:28:16
+   |
+LL |     let c: Foo<(((_)))> = Foo::<1>;
+   |                ^^^^^^^
+   |
+   = note: see issue #85077 <https://github.com/rust-lang/rust/issues/85077> for more information
+   = help: add `#![feature(generic_arg_infer)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: using `_` for array lengths is unstable
+  --> $DIR/parend_infer.rs:17:17
+   |
+LL |     let b: [u8; (_)] = [1; (((((_)))))];
+   |                 ^^^
+   |
+   = note: see issue #85077 <https://github.com/rust-lang/rust/issues/85077> for more information
+   = help: add `#![feature(generic_arg_infer)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: using `_` for array lengths is unstable
+  --> $DIR/parend_infer.rs:17:28
+   |
+LL |     let b: [u8; (_)] = [1; (((((_)))))];
+   |                            ^^^^^^^^^^^
+   |
+   = note: see issue #85077 <https://github.com/rust-lang/rust/issues/85077> for more information
+   = help: add `#![feature(generic_arg_infer)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/const-generics/generic_arg_infer/parend_infer.rs b/tests/ui/const-generics/generic_arg_infer/parend_infer.rs
index 81c42183b38..3dc27a702de 100644
--- a/tests/ui/const-generics/generic_arg_infer/parend_infer.rs
+++ b/tests/ui/const-generics/generic_arg_infer/parend_infer.rs
@@ -1,7 +1,9 @@
-//@ check-pass
+//@[gate] check-pass
 //@ revisions: gate nogate
 #![cfg_attr(gate, feature(generic_arg_infer))]
 
+struct Foo<const N: usize>;
+
 fn main() {
     // AST Types preserve parens for pretty printing reasons. This means
     // that this is parsed as a `TyKind::Paren(TyKind::Infer)`. Generic
@@ -9,4 +11,20 @@ fn main() {
     // but `TyKind::Infer` wrapped in arbitrarily many `TyKind::Paren`.
     let a: Vec<(_)> = vec![1_u8];
     let a: Vec<(((((_)))))> = vec![1_u8];
+
+    // AST Exprs similarly preserve parens for pretty printing reasons.
+    #[rustfmt::skip]
+    let b: [u8; (_)] = [1; (((((_)))))];
+    //[nogate]~^ error: using `_` for array lengths is unstable
+    //[nogate]~| error: using `_` for array lengths is unstable
+    let b: [u8; 2] = b;
+
+    // This is the same case as AST types as the parser doesn't distinguish between const
+    // and type args when they share syntax
+    let c: Foo<_> = Foo::<1>;
+    //[nogate]~^ error: const arguments cannot yet be inferred with `_`
+    let c: Foo<(_)> = Foo::<1>;
+    //[nogate]~^ error: const arguments cannot yet be inferred with `_`
+    let c: Foo<(((_)))> = Foo::<1>;
+    //[nogate]~^ error: const arguments cannot yet be inferred with `_`
 }

From decd7ecd1e3640c4bada4f4a3de411a8d507d40c Mon Sep 17 00:00:00 2001
From: Michael Goulet <michael@errs.io>
Date: Wed, 9 Apr 2025 17:25:46 +0000
Subject: [PATCH 13/16] Deeply normalize obligations in BestObligation

---
 .../src/solve/fulfill/derive_errors.rs        |  19 ++-
 .../src/solve/normalize.rs                    |  32 ++--
 .../as_expression.next.stderr                 |  12 +-
 .../do_not_recommend/as_expression.rs         |   3 +-
 .../unsatisfied-const-trait-bound.stderr      | 138 +++++++++++++++---
 tests/ui/traits/next-solver/async.fail.stderr |   4 +-
 tests/ui/traits/next-solver/async.rs          |   2 +-
 .../traits/next-solver/more-object-bound.rs   |   2 +-
 .../next-solver/more-object-bound.stderr      |  12 +-
 .../recursive-self-normalization-2.rs         |   2 +-
 .../recursive-self-normalization-2.stderr     |   6 +-
 11 files changed, 172 insertions(+), 60 deletions(-)

diff --git a/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs b/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs
index 73d3f81296f..d8dcd12aecb 100644
--- a/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs
+++ b/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs
@@ -13,9 +13,9 @@ use rustc_next_trait_solver::solve::{GenerateProofTree, SolverDelegateEvalExt as
 use rustc_type_ir::solve::NoSolution;
 use tracing::{instrument, trace};
 
-use crate::solve::Certainty;
 use crate::solve::delegate::SolverDelegate;
 use crate::solve::inspect::{self, ProofTreeInferCtxtExt, ProofTreeVisitor};
+use crate::solve::{Certainty, deeply_normalize_for_diagnostics};
 use crate::traits::{FulfillmentError, FulfillmentErrorCode, wf};
 
 pub(super) fn fulfillment_error_for_no_solution<'tcx>(
@@ -151,7 +151,7 @@ fn find_best_leaf_obligation<'tcx>(
     //
     // We should probably fix the visitor to not do so instead, as this also
     // means the leaf obligation may be incorrect.
-    infcx
+    let obligation = infcx
         .fudge_inference_if_ok(|| {
             infcx
                 .visit_proof_tree(
@@ -161,7 +161,8 @@ fn find_best_leaf_obligation<'tcx>(
                 .break_value()
                 .ok_or(())
         })
-        .unwrap_or(obligation)
+        .unwrap_or(obligation);
+    deeply_normalize_for_diagnostics(infcx, obligation.param_env, obligation)
 }
 
 struct BestObligation<'tcx> {
@@ -298,7 +299,7 @@ impl<'tcx> BestObligation<'tcx> {
     /// `NormalizesTo` goal, so we don't fall back to the rigid projection check
     /// that should catch when a projection goal fails due to an unsatisfied trait
     /// goal.
-    fn detect_error_in_higher_ranked_projection(
+    fn detect_trait_error_in_higher_ranked_projection(
         &mut self,
         goal: &inspect::InspectGoal<'_, 'tcx>,
     ) -> ControlFlow<PredicateObligation<'tcx>> {
@@ -307,7 +308,13 @@ impl<'tcx> BestObligation<'tcx> {
             && !projection_clause.bound_vars().is_empty()
         {
             let pred = projection_clause.map_bound(|proj| proj.projection_term.trait_ref(tcx));
-            self.with_derived_obligation(self.obligation.with(tcx, pred), |this| {
+            let obligation = Obligation::new(
+                tcx,
+                self.obligation.cause.clone(),
+                goal.goal().param_env,
+                deeply_normalize_for_diagnostics(goal.infcx(), goal.goal().param_env, pred),
+            );
+            self.with_derived_obligation(obligation, |this| {
                 goal.infcx().visit_proof_tree_at_depth(
                     goal.goal().with(tcx, pred),
                     goal.depth() + 1,
@@ -526,7 +533,7 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> {
             )?;
         }
 
-        self.detect_error_in_higher_ranked_projection(goal)?;
+        self.detect_trait_error_in_higher_ranked_projection(goal)?;
 
         ControlFlow::Break(self.obligation.clone())
     }
diff --git a/compiler/rustc_trait_selection/src/solve/normalize.rs b/compiler/rustc_trait_selection/src/solve/normalize.rs
index 232357dc71a..79fb044a67f 100644
--- a/compiler/rustc_trait_selection/src/solve/normalize.rs
+++ b/compiler/rustc_trait_selection/src/solve/normalize.rs
@@ -253,20 +253,28 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for DeeplyNormalizeForDiagnosticsFolder<'_,
     }
 
     fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
-        deeply_normalize_with_skipped_universes(
-            self.at,
-            ty,
-            vec![None; ty.outer_exclusive_binder().as_usize()],
-        )
-        .unwrap_or_else(|_: Vec<ScrubbedTraitError<'tcx>>| ty.super_fold_with(self))
+        let infcx = self.at.infcx;
+        infcx
+            .commit_if_ok(|_| {
+                deeply_normalize_with_skipped_universes(
+                    self.at,
+                    ty,
+                    vec![None; ty.outer_exclusive_binder().as_usize()],
+                )
+            })
+            .unwrap_or_else(|_: Vec<ScrubbedTraitError<'tcx>>| ty.super_fold_with(self))
     }
 
     fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
-        deeply_normalize_with_skipped_universes(
-            self.at,
-            ct,
-            vec![None; ct.outer_exclusive_binder().as_usize()],
-        )
-        .unwrap_or_else(|_: Vec<ScrubbedTraitError<'tcx>>| ct.super_fold_with(self))
+        let infcx = self.at.infcx;
+        infcx
+            .commit_if_ok(|_| {
+                deeply_normalize_with_skipped_universes(
+                    self.at,
+                    ct,
+                    vec![None; ct.outer_exclusive_binder().as_usize()],
+                )
+            })
+            .unwrap_or_else(|_: Vec<ScrubbedTraitError<'tcx>>| ct.super_fold_with(self))
     }
 }
diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.next.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.next.stderr
index 90bb715a052..6170250992c 100644
--- a/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.next.stderr
+++ b/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.next.stderr
@@ -1,12 +1,14 @@
-error[E0277]: the trait bound `&str: AsExpression<<SelectInt as Expression>::SqlType>` is not satisfied
+error[E0277]: the trait bound `&str: AsExpression<Integer>` is not satisfied
   --> $DIR/as_expression.rs:56:21
    |
 LL |     SelectInt.check("bar");
-   |               ----- ^^^^^ the trait `AsExpression<<SelectInt as Expression>::SqlType>` is not implemented for `&str`
+   |               ----- ^^^^^ the trait `AsExpression<Integer>` is not implemented for `&str`
    |               |
    |               required by a bound introduced by this call
    |
-   = help: the trait `AsExpression<Text>` is implemented for `&str`
+   = help: the trait `AsExpression<Integer>` is not implemented for `&str`
+           but trait `AsExpression<Text>` is implemented for it
+   = help: for that trait implementation, expected `Text`, found `Integer`
 note: required by a bound in `Foo::check`
   --> $DIR/as_expression.rs:47:12
    |
@@ -16,11 +18,11 @@ LL |     where
 LL |         T: AsExpression<Self::SqlType>,
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Foo::check`
 
-error[E0271]: type mismatch resolving `<SelectInt as Expression>::SqlType == Text`
+error[E0271]: type mismatch resolving `Integer == Text`
   --> $DIR/as_expression.rs:56:5
    |
 LL |     SelectInt.check("bar");
-   |     ^^^^^^^^^^^^^^^^^^^^^^ expected `Text`, found `Integer`
+   |     ^^^^^^^^^^^^^^^^^^^^^^ types differ
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.rs b/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.rs
index b5ff76809a2..673adb82870 100644
--- a/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.rs
+++ b/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.rs
@@ -54,7 +54,6 @@ impl<T> Foo for T where T: Expression {}
 
 fn main() {
     SelectInt.check("bar");
-    //[current]~^ ERROR the trait bound `&str: AsExpression<Integer>` is not satisfied
-    //[next]~^^ ERROR the trait bound `&str: AsExpression<<SelectInt as Expression>::SqlType>` is not satisfied
+    //~^ ERROR the trait bound `&str: AsExpression<Integer>` is not satisfied
     //[next]~| ERROR type mismatch
 }
diff --git a/tests/ui/traits/const-traits/unsatisfied-const-trait-bound.stderr b/tests/ui/traits/const-traits/unsatisfied-const-trait-bound.stderr
index be761e49ba0..03e26615d7e 100644
--- a/tests/ui/traits/const-traits/unsatisfied-const-trait-bound.stderr
+++ b/tests/ui/traits/const-traits/unsatisfied-const-trait-bound.stderr
@@ -6,30 +6,134 @@ LL | #![feature(const_trait_impl, generic_const_exprs)]
    |
    = help: remove one of these features
 
-error[E0277]: the trait bound `T: const Trait` is not satisfied
-  --> $DIR/unsatisfied-const-trait-bound.rs:29:37
+error[E0391]: cycle detected when evaluating type-level constant
+  --> $DIR/unsatisfied-const-trait-bound.rs:29:35
    |
 LL | fn accept0<T: Trait>(_: Container<{ T::make() }>) {}
-   |                                     ^
+   |                                   ^^^^^^^^^^^^^
+   |
+note: ...which requires const-evaluating + checking `accept0::{constant#0}`...
+  --> $DIR/unsatisfied-const-trait-bound.rs:29:35
+   |
+LL | fn accept0<T: Trait>(_: Container<{ T::make() }>) {}
+   |                                   ^^^^^^^^^^^^^
+note: ...which requires caching mir of `accept0::{constant#0}` for CTFE...
+  --> $DIR/unsatisfied-const-trait-bound.rs:29:35
+   |
+LL | fn accept0<T: Trait>(_: Container<{ T::make() }>) {}
+   |                                   ^^^^^^^^^^^^^
+note: ...which requires elaborating drops for `accept0::{constant#0}`...
+  --> $DIR/unsatisfied-const-trait-bound.rs:29:35
+   |
+LL | fn accept0<T: Trait>(_: Container<{ T::make() }>) {}
+   |                                   ^^^^^^^^^^^^^
+note: ...which requires borrow-checking `accept0::{constant#0}`...
+  --> $DIR/unsatisfied-const-trait-bound.rs:29:35
+   |
+LL | fn accept0<T: Trait>(_: Container<{ T::make() }>) {}
+   |                                   ^^^^^^^^^^^^^
+note: ...which requires promoting constants in MIR for `accept0::{constant#0}`...
+  --> $DIR/unsatisfied-const-trait-bound.rs:29:35
+   |
+LL | fn accept0<T: Trait>(_: Container<{ T::make() }>) {}
+   |                                   ^^^^^^^^^^^^^
+note: ...which requires const checking `accept0::{constant#0}`...
+  --> $DIR/unsatisfied-const-trait-bound.rs:29:35
+   |
+LL | fn accept0<T: Trait>(_: Container<{ T::make() }>) {}
+   |                                   ^^^^^^^^^^^^^
+note: ...which requires building MIR for `accept0::{constant#0}`...
+  --> $DIR/unsatisfied-const-trait-bound.rs:29:35
+   |
+LL | fn accept0<T: Trait>(_: Container<{ T::make() }>) {}
+   |                                   ^^^^^^^^^^^^^
+note: ...which requires building an abstract representation for `accept0::{constant#0}`...
+  --> $DIR/unsatisfied-const-trait-bound.rs:29:35
+   |
+LL | fn accept0<T: Trait>(_: Container<{ T::make() }>) {}
+   |                                   ^^^^^^^^^^^^^
+note: ...which requires building THIR for `accept0::{constant#0}`...
+  --> $DIR/unsatisfied-const-trait-bound.rs:29:35
+   |
+LL | fn accept0<T: Trait>(_: Container<{ T::make() }>) {}
+   |                                   ^^^^^^^^^^^^^
+note: ...which requires type-checking `accept0::{constant#0}`...
+  --> $DIR/unsatisfied-const-trait-bound.rs:29:35
+   |
+LL | fn accept0<T: Trait>(_: Container<{ T::make() }>) {}
+   |                                   ^^^^^^^^^^^^^
+   = note: ...which again requires evaluating type-level constant, completing the cycle
+note: cycle used when checking that `accept0` is well-formed
+  --> $DIR/unsatisfied-const-trait-bound.rs:29:1
+   |
+LL | fn accept0<T: Trait>(_: Container<{ T::make() }>) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = 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[E0277]: the trait bound `T: const Trait` is not satisfied
-  --> $DIR/unsatisfied-const-trait-bound.rs:33:50
+error[E0391]: cycle detected when caching mir of `accept1::{constant#0}` for CTFE
+  --> $DIR/unsatisfied-const-trait-bound.rs:33:48
    |
 LL | const fn accept1<T: ~const Trait>(_: Container<{ T::make() }>) {}
-   |                                                  ^
-
-error[E0277]: the trait bound `Ty: const Trait` is not satisfied
-  --> $DIR/unsatisfied-const-trait-bound.rs:22:15
+   |                                                ^^^^^^^^^^^^^
    |
-LL |     require::<Ty>();
-   |               ^^
+note: ...which requires elaborating drops for `accept1::{constant#0}`...
+  --> $DIR/unsatisfied-const-trait-bound.rs:33:48
    |
-note: required by a bound in `require`
-  --> $DIR/unsatisfied-const-trait-bound.rs:8:15
+LL | const fn accept1<T: ~const Trait>(_: Container<{ T::make() }>) {}
+   |                                                ^^^^^^^^^^^^^
+note: ...which requires borrow-checking `accept1::{constant#0}`...
+  --> $DIR/unsatisfied-const-trait-bound.rs:33:48
    |
-LL | fn require<T: const Trait>() {}
-   |               ^^^^^^^^^^^ required by this bound in `require`
+LL | const fn accept1<T: ~const Trait>(_: Container<{ T::make() }>) {}
+   |                                                ^^^^^^^^^^^^^
+note: ...which requires promoting constants in MIR for `accept1::{constant#0}`...
+  --> $DIR/unsatisfied-const-trait-bound.rs:33:48
+   |
+LL | const fn accept1<T: ~const Trait>(_: Container<{ T::make() }>) {}
+   |                                                ^^^^^^^^^^^^^
+note: ...which requires const checking `accept1::{constant#0}`...
+  --> $DIR/unsatisfied-const-trait-bound.rs:33:48
+   |
+LL | const fn accept1<T: ~const Trait>(_: Container<{ T::make() }>) {}
+   |                                                ^^^^^^^^^^^^^
+note: ...which requires building MIR for `accept1::{constant#0}`...
+  --> $DIR/unsatisfied-const-trait-bound.rs:33:48
+   |
+LL | const fn accept1<T: ~const Trait>(_: Container<{ T::make() }>) {}
+   |                                                ^^^^^^^^^^^^^
+note: ...which requires building an abstract representation for `accept1::{constant#0}`...
+  --> $DIR/unsatisfied-const-trait-bound.rs:33:48
+   |
+LL | const fn accept1<T: ~const Trait>(_: Container<{ T::make() }>) {}
+   |                                                ^^^^^^^^^^^^^
+note: ...which requires building THIR for `accept1::{constant#0}`...
+  --> $DIR/unsatisfied-const-trait-bound.rs:33:48
+   |
+LL | const fn accept1<T: ~const Trait>(_: Container<{ T::make() }>) {}
+   |                                                ^^^^^^^^^^^^^
+note: ...which requires type-checking `accept1::{constant#0}`...
+  --> $DIR/unsatisfied-const-trait-bound.rs:33:48
+   |
+LL | const fn accept1<T: ~const Trait>(_: Container<{ T::make() }>) {}
+   |                                                ^^^^^^^^^^^^^
+note: ...which requires evaluating type-level constant...
+  --> $DIR/unsatisfied-const-trait-bound.rs:33:48
+   |
+LL | const fn accept1<T: ~const Trait>(_: Container<{ T::make() }>) {}
+   |                                                ^^^^^^^^^^^^^
+note: ...which requires const-evaluating + checking `accept1::{constant#0}`...
+  --> $DIR/unsatisfied-const-trait-bound.rs:33:48
+   |
+LL | const fn accept1<T: ~const Trait>(_: Container<{ T::make() }>) {}
+   |                                                ^^^^^^^^^^^^^
+   = note: ...which again requires caching mir of `accept1::{constant#0}` for CTFE, completing the cycle
+note: cycle used when const-evaluating + checking `accept1::{constant#0}`
+  --> $DIR/unsatisfied-const-trait-bound.rs:33:48
+   |
+LL | const fn accept1<T: ~const Trait>(_: Container<{ T::make() }>) {}
+   |                                                ^^^^^^^^^^^^^
+   = 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: aborting due to 4 previous errors
+error: aborting due to 3 previous errors
 
-For more information about this error, try `rustc --explain E0277`.
+For more information about this error, try `rustc --explain E0391`.
diff --git a/tests/ui/traits/next-solver/async.fail.stderr b/tests/ui/traits/next-solver/async.fail.stderr
index bc89842d16a..a76a10d20ee 100644
--- a/tests/ui/traits/next-solver/async.fail.stderr
+++ b/tests/ui/traits/next-solver/async.fail.stderr
@@ -1,8 +1,8 @@
-error[E0271]: expected `{async block@$DIR/async.rs:12:17: 12:22}` to be a future that resolves to `i32`, but it resolves to `()`
+error[E0271]: type mismatch resolving `() == i32`
   --> $DIR/async.rs:12:17
    |
 LL |     needs_async(async {});
-   |     ----------- ^^^^^^^^ expected `i32`, found `()`
+   |     ----------- ^^^^^^^^ types differ
    |     |
    |     required by a bound introduced by this call
    |
diff --git a/tests/ui/traits/next-solver/async.rs b/tests/ui/traits/next-solver/async.rs
index fded7743547..34c0ed02eeb 100644
--- a/tests/ui/traits/next-solver/async.rs
+++ b/tests/ui/traits/next-solver/async.rs
@@ -10,7 +10,7 @@ fn needs_async(_: impl Future<Output = i32>) {}
 #[cfg(fail)]
 fn main() {
     needs_async(async {});
-    //[fail]~^ ERROR expected `{async block@$DIR/async.rs:12:17: 12:22}` to be a future that resolves to `i32`, but it resolves to `()`
+    //[fail]~^ ERROR type mismatch resolving `() == i32`
 }
 
 #[cfg(pass)]
diff --git a/tests/ui/traits/next-solver/more-object-bound.rs b/tests/ui/traits/next-solver/more-object-bound.rs
index 3d3fdc926f6..1dad1903a64 100644
--- a/tests/ui/traits/next-solver/more-object-bound.rs
+++ b/tests/ui/traits/next-solver/more-object-bound.rs
@@ -10,7 +10,7 @@ trait Trait: SuperTrait<A = <Self as SuperTrait>::B> {}
 
 fn transmute<A, B>(x: A) -> B {
     foo::<A, B, dyn Trait<A = A, B = B>>(x)
-    //~^ ERROR type mismatch resolving `<dyn Trait<A = A, B = B> as SuperTrait>::A == B`
+    //~^ ERROR type mismatch resolving `A == B`
 }
 
 fn foo<A, B, T: ?Sized>(x: T::A) -> B
diff --git a/tests/ui/traits/next-solver/more-object-bound.stderr b/tests/ui/traits/next-solver/more-object-bound.stderr
index 39849d4c865..d04376cc9c6 100644
--- a/tests/ui/traits/next-solver/more-object-bound.stderr
+++ b/tests/ui/traits/next-solver/more-object-bound.stderr
@@ -1,17 +1,9 @@
-error[E0271]: type mismatch resolving `<dyn Trait<A = A, B = B> as SuperTrait>::A == B`
+error[E0271]: type mismatch resolving `A == B`
   --> $DIR/more-object-bound.rs:12:5
    |
-LL | fn transmute<A, B>(x: A) -> B {
-   |              -  - expected type parameter
-   |              |
-   |              found type parameter
 LL |     foo::<A, B, dyn Trait<A = A, B = B>>(x)
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected type parameter `B`, found type parameter `A`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ
    |
-   = note: expected type parameter `B`
-              found type parameter `A`
-   = note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound
-   = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters
    = note: required because it appears within the type `dyn Trait<A = A, B = B>`
 note: required by a bound in `foo`
   --> $DIR/more-object-bound.rs:18:8
diff --git a/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.rs b/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.rs
index 94a9484ecdc..b2a8c8cb4ae 100644
--- a/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.rs
+++ b/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.rs
@@ -13,7 +13,7 @@ fn needs_bar<S: Bar>() {}
 
 fn test<T: Foo1<Assoc1 = <T as Foo2>::Assoc2> + Foo2<Assoc2 = <T as Foo1>::Assoc1>>() {
     needs_bar::<T::Assoc1>();
-    //~^ ERROR the trait bound `<T as Foo1>::Assoc1: Bar` is not satisfied
+    //~^ ERROR the trait bound `<T as Foo2>::Assoc2: Bar` is not satisfied
 }
 
 fn main() {}
diff --git a/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.stderr b/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.stderr
index 6f5111a6193..c4be47e3520 100644
--- a/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.stderr
+++ b/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.stderr
@@ -1,8 +1,8 @@
-error[E0277]: the trait bound `<T as Foo1>::Assoc1: Bar` is not satisfied
+error[E0277]: the trait bound `<T as Foo2>::Assoc2: Bar` is not satisfied
   --> $DIR/recursive-self-normalization-2.rs:15:17
    |
 LL |     needs_bar::<T::Assoc1>();
-   |                 ^^^^^^^^^ the trait `Bar` is not implemented for `<T as Foo1>::Assoc1`
+   |                 ^^^^^^^^^ the trait `Bar` is not implemented for `<T as Foo2>::Assoc2`
    |
 note: required by a bound in `needs_bar`
   --> $DIR/recursive-self-normalization-2.rs:12:17
@@ -11,7 +11,7 @@ LL | fn needs_bar<S: Bar>() {}
    |                 ^^^ required by this bound in `needs_bar`
 help: consider further restricting the associated type
    |
-LL | fn test<T: Foo1<Assoc1 = <T as Foo2>::Assoc2> + Foo2<Assoc2 = <T as Foo1>::Assoc1>>() where <T as Foo1>::Assoc1: Bar {
+LL | fn test<T: Foo1<Assoc1 = <T as Foo2>::Assoc2> + Foo2<Assoc2 = <T as Foo1>::Assoc1>>() where <T as Foo2>::Assoc2: Bar {
    |                                                                                       ++++++++++++++++++++++++++++++
 
 error: aborting due to 1 previous error

From 59c55339af73b5345ec28d7d830c7bd3feee45b3 Mon Sep 17 00:00:00 2001
From: Folkert de Vries <folkert@folkertdev.nl>
Date: Sat, 22 Feb 2025 22:01:18 +0100
Subject: [PATCH 14/16] add `simd_insert_dyn` and `simd_extract_dyn`

---
 compiler/rustc_codegen_llvm/src/intrinsic.rs  | 69 +++++++++--------
 .../rustc_hir_analysis/src/check/intrinsic.rs |  8 +-
 compiler/rustc_span/src/symbol.rs             |  2 +
 library/core/src/intrinsics/simd.rs           | 39 +++++++++-
 tests/codegen/simd/extract-insert-dyn.rs      | 75 +++++++++++++++++++
 .../simd/intrinsic/generic-elements-pass.rs   | 41 +++++++++-
 6 files changed, 197 insertions(+), 37 deletions(-)
 create mode 100644 tests/codegen/simd/extract-insert-dyn.rs

diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs
index 660fc7ec4c4..a14600f925f 100644
--- a/compiler/rustc_codegen_llvm/src/intrinsic.rs
+++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs
@@ -1417,7 +1417,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
         return Ok(bx.shuffle_vector(args[0].immediate(), args[1].immediate(), indices));
     }
 
-    if name == sym::simd_insert {
+    if name == sym::simd_insert || name == sym::simd_insert_dyn {
         require!(
             in_elem == arg_tys[2],
             InvalidMonomorphization::InsertedType {
@@ -1428,40 +1428,49 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
                 out_ty: arg_tys[2]
             }
         );
-        let idx = bx
-            .const_to_opt_u128(args[1].immediate(), false)
-            .expect("typeck should have ensure that this is a const");
-        if idx >= in_len.into() {
-            return_error!(InvalidMonomorphization::SimdIndexOutOfBounds {
-                span,
-                name,
-                arg_idx: 1,
-                total_len: in_len.into(),
-            });
-        }
-        return Ok(bx.insert_element(
-            args[0].immediate(),
-            args[2].immediate(),
-            bx.const_i32(idx as i32),
-        ));
+
+        let index_imm = if name == sym::simd_insert {
+            let idx = bx
+                .const_to_opt_u128(args[1].immediate(), false)
+                .expect("typeck should have ensure that this is a const");
+            if idx >= in_len.into() {
+                return_error!(InvalidMonomorphization::SimdIndexOutOfBounds {
+                    span,
+                    name,
+                    arg_idx: 1,
+                    total_len: in_len.into(),
+                });
+            }
+            bx.const_i32(idx as i32)
+        } else {
+            args[1].immediate()
+        };
+
+        return Ok(bx.insert_element(args[0].immediate(), args[2].immediate(), index_imm));
     }
-    if name == sym::simd_extract {
+    if name == sym::simd_extract || name == sym::simd_extract_dyn {
         require!(
             ret_ty == in_elem,
             InvalidMonomorphization::ReturnType { span, name, in_elem, in_ty, ret_ty }
         );
-        let idx = bx
-            .const_to_opt_u128(args[1].immediate(), false)
-            .expect("typeck should have ensure that this is a const");
-        if idx >= in_len.into() {
-            return_error!(InvalidMonomorphization::SimdIndexOutOfBounds {
-                span,
-                name,
-                arg_idx: 1,
-                total_len: in_len.into(),
-            });
-        }
-        return Ok(bx.extract_element(args[0].immediate(), bx.const_i32(idx as i32)));
+        let index_imm = if name == sym::simd_extract {
+            let idx = bx
+                .const_to_opt_u128(args[1].immediate(), false)
+                .expect("typeck should have ensure that this is a const");
+            if idx >= in_len.into() {
+                return_error!(InvalidMonomorphization::SimdIndexOutOfBounds {
+                    span,
+                    name,
+                    arg_idx: 1,
+                    total_len: in_len.into(),
+                });
+            }
+            bx.const_i32(idx as i32)
+        } else {
+            args[1].immediate()
+        };
+
+        return Ok(bx.extract_element(args[0].immediate(), index_imm));
     }
 
     if name == sym::simd_select {
diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
index 42d785c8dd0..21d40b01e9a 100644
--- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs
+++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
@@ -674,8 +674,12 @@ pub fn check_intrinsic_type(
             sym::simd_masked_load => (3, 0, vec![param(0), param(1), param(2)], param(2)),
             sym::simd_masked_store => (3, 0, vec![param(0), param(1), param(2)], tcx.types.unit),
             sym::simd_scatter => (3, 0, vec![param(0), param(1), param(2)], tcx.types.unit),
-            sym::simd_insert => (2, 0, vec![param(0), tcx.types.u32, param(1)], param(0)),
-            sym::simd_extract => (2, 0, vec![param(0), tcx.types.u32], param(1)),
+            sym::simd_insert | sym::simd_insert_dyn => {
+                (2, 0, vec![param(0), tcx.types.u32, param(1)], param(0))
+            }
+            sym::simd_extract | sym::simd_extract_dyn => {
+                (2, 0, vec![param(0), tcx.types.u32], param(1))
+            }
             sym::simd_cast
             | sym::simd_as
             | sym::simd_cast_ptr
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 8a8bec35d81..0b6e3f64ad1 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -1885,6 +1885,7 @@ symbols! {
         simd_eq,
         simd_expose_provenance,
         simd_extract,
+        simd_extract_dyn,
         simd_fabs,
         simd_fcos,
         simd_fexp,
@@ -1903,6 +1904,7 @@ symbols! {
         simd_ge,
         simd_gt,
         simd_insert,
+        simd_insert_dyn,
         simd_le,
         simd_lt,
         simd_masked_load,
diff --git a/library/core/src/intrinsics/simd.rs b/library/core/src/intrinsics/simd.rs
index ae6e1a779ed..9ac6ee85535 100644
--- a/library/core/src/intrinsics/simd.rs
+++ b/library/core/src/intrinsics/simd.rs
@@ -4,7 +4,7 @@
 
 /// Inserts an element into a vector, returning the updated vector.
 ///
-/// `T` must be a vector with element type `U`.
+/// `T` must be a vector with element type `U`, and `idx` must be `const`.
 ///
 /// # Safety
 ///
@@ -15,14 +15,47 @@ pub const unsafe fn simd_insert<T, U>(x: T, idx: u32, val: U) -> T;
 
 /// Extracts an element from a vector.
 ///
+/// `T` must be a vector with element type `U`, and `idx` must be `const`.
+///
+/// # Safety
+///
+/// `idx` must be const and in-bounds of the vector.
+#[rustc_intrinsic]
+#[rustc_nounwind]
+pub const unsafe fn simd_extract<T, U>(x: T, idx: u32) -> U;
+
+/// Inserts an element into a vector, returning the updated vector.
+///
 /// `T` must be a vector with element type `U`.
 ///
+/// If the index is `const`, [`simd_insert`] may emit better assembly.
+///
 /// # Safety
 ///
 /// `idx` must be in-bounds of the vector.
-#[rustc_intrinsic]
 #[rustc_nounwind]
-pub const unsafe fn simd_extract<T, U>(x: T, idx: u32) -> U;
+#[cfg_attr(not(bootstrap), rustc_intrinsic)]
+pub unsafe fn simd_insert_dyn<T, U>(mut x: T, idx: u32, val: U) -> T {
+    // SAFETY: `idx` must be in-bounds
+    unsafe { (&raw mut x).cast::<U>().add(idx as usize).write(val) }
+    x
+}
+
+/// Extracts an element from a vector.
+///
+/// `T` must be a vector with element type `U`.
+///
+/// If the index is `const`, [`simd_extract`] may emit better assembly.
+///
+/// # Safety
+///
+/// `idx` must be in-bounds of the vector.
+#[rustc_nounwind]
+#[cfg_attr(not(bootstrap), rustc_intrinsic)]
+pub unsafe fn simd_extract_dyn<T, U>(x: T, idx: u32) -> U {
+    // SAFETY: `idx` must be in-bounds
+    unsafe { (&raw const x).cast::<U>().add(idx as usize).read() }
+}
 
 /// Adds two simd vectors elementwise.
 ///
diff --git a/tests/codegen/simd/extract-insert-dyn.rs b/tests/codegen/simd/extract-insert-dyn.rs
new file mode 100644
index 00000000000..584e2c7887a
--- /dev/null
+++ b/tests/codegen/simd/extract-insert-dyn.rs
@@ -0,0 +1,75 @@
+//@compile-flags: -C opt-level=3 -C no-prepopulate-passes
+
+#![feature(core_intrinsics, repr_simd)]
+#![no_std]
+#![crate_type = "lib"]
+#![allow(non_camel_case_types)]
+
+// Test that `core::intrinsics::simd::{simd_extract_dyn, simd_insert_dyn}`
+// lower to an LLVM extractelement or insertelement operation.
+
+use core::intrinsics::simd::{simd_extract, simd_extract_dyn, simd_insert, simd_insert_dyn};
+
+#[repr(simd)]
+#[derive(Clone, Copy)]
+pub struct u32x16([u32; 16]);
+
+#[repr(simd)]
+#[derive(Clone, Copy)]
+pub struct i8x16([i8; 16]);
+
+// CHECK-LABEL: dyn_simd_extract
+// CHECK: extractelement <16 x i8> %x, i32 %idx
+#[no_mangle]
+unsafe extern "C" fn dyn_simd_extract(x: i8x16, idx: u32) -> i8 {
+    simd_extract_dyn(x, idx)
+}
+
+// CHECK-LABEL: literal_dyn_simd_extract
+// CHECK: extractelement <16 x i8> %x, i32 7
+#[no_mangle]
+unsafe extern "C" fn literal_dyn_simd_extract(x: i8x16) -> i8 {
+    simd_extract_dyn(x, 7)
+}
+
+// CHECK-LABEL: const_dyn_simd_extract
+// CHECK: extractelement <16 x i8> %x, i32 7
+#[no_mangle]
+unsafe extern "C" fn const_dyn_simd_extract(x: i8x16) -> i8 {
+    simd_extract_dyn(x, const { 3 + 4 })
+}
+
+// CHECK-LABEL: const_simd_extract
+// CHECK: extractelement <16 x i8> %x, i32 7
+#[no_mangle]
+unsafe extern "C" fn const_simd_extract(x: i8x16) -> i8 {
+    simd_extract(x, const { 3 + 4 })
+}
+
+// CHECK-LABEL: dyn_simd_insert
+// CHECK: insertelement <16 x i8> %x, i8 %e, i32 %idx
+#[no_mangle]
+unsafe extern "C" fn dyn_simd_insert(x: i8x16, e: i8, idx: u32) -> i8x16 {
+    simd_insert_dyn(x, idx, e)
+}
+
+// CHECK-LABEL: literal_dyn_simd_insert
+// CHECK: insertelement <16 x i8> %x, i8 %e, i32 7
+#[no_mangle]
+unsafe extern "C" fn literal_dyn_simd_insert(x: i8x16, e: i8) -> i8x16 {
+    simd_insert_dyn(x, 7, e)
+}
+
+// CHECK-LABEL: const_dyn_simd_insert
+// CHECK: insertelement <16 x i8> %x, i8 %e, i32 7
+#[no_mangle]
+unsafe extern "C" fn const_dyn_simd_insert(x: i8x16, e: i8) -> i8x16 {
+    simd_insert_dyn(x, const { 3 + 4 }, e)
+}
+
+// CHECK-LABEL: const_simd_insert
+// CHECK: insertelement <16 x i8> %x, i8 %e, i32 7
+#[no_mangle]
+unsafe extern "C" fn const_simd_insert(x: i8x16, e: i8) -> i8x16 {
+    simd_insert(x, const { 3 + 4 }, e)
+}
diff --git a/tests/ui/simd/intrinsic/generic-elements-pass.rs b/tests/ui/simd/intrinsic/generic-elements-pass.rs
index 4dc2e4d5a80..e4d47cdb381 100644
--- a/tests/ui/simd/intrinsic/generic-elements-pass.rs
+++ b/tests/ui/simd/intrinsic/generic-elements-pass.rs
@@ -1,8 +1,10 @@
 //@ run-pass
 
-#![feature(repr_simd, core_intrinsics)]
+#![feature(repr_simd, intrinsics, core_intrinsics)]
 
-use std::intrinsics::simd::{simd_extract, simd_insert, simd_shuffle};
+use std::intrinsics::simd::{
+    simd_extract, simd_extract_dyn, simd_insert, simd_insert_dyn, simd_shuffle,
+};
 
 #[repr(simd)]
 #[derive(Copy, Clone, Debug, PartialEq)]
@@ -70,6 +72,41 @@ fn main() {
         all_eq!(simd_extract(x8, 6), 86);
         all_eq!(simd_extract(x8, 7), 87);
     }
+    unsafe {
+        all_eq!(simd_insert_dyn(x2, 0, 100), i32x2([100, 21]));
+        all_eq!(simd_insert_dyn(x2, 1, 100), i32x2([20, 100]));
+
+        all_eq!(simd_insert_dyn(x4, 0, 100), i32x4([100, 41, 42, 43]));
+        all_eq!(simd_insert_dyn(x4, 1, 100), i32x4([40, 100, 42, 43]));
+        all_eq!(simd_insert_dyn(x4, 2, 100), i32x4([40, 41, 100, 43]));
+        all_eq!(simd_insert_dyn(x4, 3, 100), i32x4([40, 41, 42, 100]));
+
+        all_eq!(simd_insert_dyn(x8, 0, 100), i32x8([100, 81, 82, 83, 84, 85, 86, 87]));
+        all_eq!(simd_insert_dyn(x8, 1, 100), i32x8([80, 100, 82, 83, 84, 85, 86, 87]));
+        all_eq!(simd_insert_dyn(x8, 2, 100), i32x8([80, 81, 100, 83, 84, 85, 86, 87]));
+        all_eq!(simd_insert_dyn(x8, 3, 100), i32x8([80, 81, 82, 100, 84, 85, 86, 87]));
+        all_eq!(simd_insert_dyn(x8, 4, 100), i32x8([80, 81, 82, 83, 100, 85, 86, 87]));
+        all_eq!(simd_insert_dyn(x8, 5, 100), i32x8([80, 81, 82, 83, 84, 100, 86, 87]));
+        all_eq!(simd_insert_dyn(x8, 6, 100), i32x8([80, 81, 82, 83, 84, 85, 100, 87]));
+        all_eq!(simd_insert_dyn(x8, 7, 100), i32x8([80, 81, 82, 83, 84, 85, 86, 100]));
+
+        all_eq!(simd_extract_dyn(x2, 0), 20);
+        all_eq!(simd_extract_dyn(x2, 1), 21);
+
+        all_eq!(simd_extract_dyn(x4, 0), 40);
+        all_eq!(simd_extract_dyn(x4, 1), 41);
+        all_eq!(simd_extract_dyn(x4, 2), 42);
+        all_eq!(simd_extract_dyn(x4, 3), 43);
+
+        all_eq!(simd_extract_dyn(x8, 0), 80);
+        all_eq!(simd_extract_dyn(x8, 1), 81);
+        all_eq!(simd_extract_dyn(x8, 2), 82);
+        all_eq!(simd_extract_dyn(x8, 3), 83);
+        all_eq!(simd_extract_dyn(x8, 4), 84);
+        all_eq!(simd_extract_dyn(x8, 5), 85);
+        all_eq!(simd_extract_dyn(x8, 6), 86);
+        all_eq!(simd_extract_dyn(x8, 7), 87);
+    }
 
     let y2 = i32x2([120, 121]);
     let y4 = i32x4([140, 141, 142, 143]);

From d7e7f8b522c9c2f5d8a509947904cd31956faa27 Mon Sep 17 00:00:00 2001
From: Augie Fackler <augie@google.com>
Date: Fri, 7 Mar 2025 14:25:21 -0500
Subject: [PATCH 15/16] tests: adjust expectation for f128 abi on Windows

llvm/llvm-project@5ee1c0b7148571ed9d60e447b66fb0f35de14576 updates llvm
to match the documented calling convention to pass f128 indirectly.

@rustbot label llvm-main
---
 tests/assembly/x86_64-windows-float-abi.rs | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/tests/assembly/x86_64-windows-float-abi.rs b/tests/assembly/x86_64-windows-float-abi.rs
index e8900be1aae..cbc80910851 100644
--- a/tests/assembly/x86_64-windows-float-abi.rs
+++ b/tests/assembly/x86_64-windows-float-abi.rs
@@ -37,7 +37,8 @@ pub extern "C" fn second_f64(_: f64, x: f64) -> f64 {
 }
 
 // CHECK-LABEL: second_f128
-// CHECK: movaps %xmm1, %xmm0
+// FIXME(llvm21): this can be just %rdx instead of the regex once we don't test on LLVM 20
+// CHECK: movaps {{(%xmm1|\(%rdx\))}}, %xmm0
 // CHECK-NEXT: retq
 #[no_mangle]
 pub extern "C" fn second_f128(_: f128, x: f128) -> f128 {

From 7e8184fa2a712356f1827c8abc01bafcd359b122 Mon Sep 17 00:00:00 2001
From: Nicholas Nethercote <n.nethercote@gmail.com>
Date: Fri, 11 Apr 2025 10:10:06 +1000
Subject: [PATCH 16/16] Improve `AssocItem::descr`.

The commit adds "associated" to the description of associated types and
associated consts, to match the description of associated functions.
This increases error message precision and consistency with
`AssocKind::fmt`.

The commit also notes an imperfection in `AssocKind::fmt`; fixing this
imperfection is possible but beyond the scope of this PR.
---
 compiler/rustc_middle/src/ty/assoc.rs         |  6 +++--
 .../elided-lifetime.rs                        |  2 +-
 .../elided-lifetime.stderr                    |  6 ++---
 .../static-trait-impl.rs                      |  2 +-
 .../static-trait-impl.stderr                  |  6 ++---
 .../const_params_have_right_type.stderr       |  2 +-
 .../issue-102114.current.stderr               |  2 +-
 .../issue-102114.next.stderr                  |  2 +-
 .../parameter_number_and_kind_impl.rs         |  6 ++---
 .../parameter_number_and_kind_impl.stderr     | 24 +++++++++----------
 .../assoc-const-missing-type.rs               |  2 +-
 .../assoc-const-missing-type.stderr           |  6 ++---
 .../generic-const-items/compare-impl-item.rs  |  2 +-
 .../compare-impl-item.stderr                  | 14 +++++------
 ...bstituting-in-region-112823.current.stderr |  2 +-
 ...nsubstituting-in-region-112823.next.stderr |  2 +-
 .../in-trait/span-bug-issue-121457.rs         |  2 +-
 .../in-trait/span-bug-issue-121457.stderr     |  6 ++---
 tests/ui/lifetimes/no_lending_iterators.rs    |  2 +-
 .../ui/lifetimes/no_lending_iterators.stderr  |  6 ++---
 ...trait-in-type-alias-with-bad-substs.stderr |  2 +-
 21 files changed, 53 insertions(+), 51 deletions(-)

diff --git a/compiler/rustc_middle/src/ty/assoc.rs b/compiler/rustc_middle/src/ty/assoc.rs
index e3d332036f1..bbaf735fbdb 100644
--- a/compiler/rustc_middle/src/ty/assoc.rs
+++ b/compiler/rustc_middle/src/ty/assoc.rs
@@ -98,10 +98,10 @@ impl AssocItem {
 
     pub fn descr(&self) -> &'static str {
         match self.kind {
-            ty::AssocKind::Const => "const",
+            ty::AssocKind::Const => "associated const",
             ty::AssocKind::Fn if self.fn_has_self_parameter => "method",
             ty::AssocKind::Fn => "associated function",
-            ty::AssocKind::Type => "type",
+            ty::AssocKind::Type => "associated type",
         }
     }
 
@@ -155,6 +155,8 @@ impl AssocKind {
 impl std::fmt::Display for AssocKind {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         match self {
+            // FIXME: fails to distinguish between "associated function" and
+            // "method" because `has_self` isn't known here.
             AssocKind::Fn => write!(f, "method"),
             AssocKind::Const => write!(f, "associated const"),
             AssocKind::Type => write!(f, "associated type"),
diff --git a/tests/ui/consts/static-default-lifetime/elided-lifetime.rs b/tests/ui/consts/static-default-lifetime/elided-lifetime.rs
index ccf63f86fcf..d60fe7d409a 100644
--- a/tests/ui/consts/static-default-lifetime/elided-lifetime.rs
+++ b/tests/ui/consts/static-default-lifetime/elided-lifetime.rs
@@ -16,7 +16,7 @@ impl Bar for Foo<'_> {
     const STATIC: &str = "";
     //~^ ERROR `&` without an explicit lifetime name cannot be used here
     //~| WARN this was previously accepted by the compiler but is being phased out
-    //~| ERROR lifetime parameters or bounds on const `STATIC` do not match the trait declaration
+    //~| ERROR lifetime parameters or bounds on associated const `STATIC` do not match the trait declaration
 }
 
 fn main() {}
diff --git a/tests/ui/consts/static-default-lifetime/elided-lifetime.stderr b/tests/ui/consts/static-default-lifetime/elided-lifetime.stderr
index 33873f5c5a5..bb8365b0ae5 100644
--- a/tests/ui/consts/static-default-lifetime/elided-lifetime.stderr
+++ b/tests/ui/consts/static-default-lifetime/elided-lifetime.stderr
@@ -39,14 +39,14 @@ help: use the `'static` lifetime
 LL |     const STATIC: &'static str = "";
    |                    +++++++
 
-error[E0195]: lifetime parameters or bounds on const `STATIC` do not match the trait declaration
+error[E0195]: lifetime parameters or bounds on associated const `STATIC` do not match the trait declaration
   --> $DIR/elided-lifetime.rs:16:17
    |
 LL |     const STATIC: &str;
-   |                 - lifetimes in impl do not match this const in trait
+   |                 - lifetimes in impl do not match this associated const in trait
 ...
 LL |     const STATIC: &str = "";
-   |                 ^ lifetimes do not match const in trait
+   |                 ^ lifetimes do not match associated const in trait
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/consts/static-default-lifetime/static-trait-impl.rs b/tests/ui/consts/static-default-lifetime/static-trait-impl.rs
index 1e12259e483..85746df146f 100644
--- a/tests/ui/consts/static-default-lifetime/static-trait-impl.rs
+++ b/tests/ui/consts/static-default-lifetime/static-trait-impl.rs
@@ -9,7 +9,7 @@ impl Bar<'_> for A {
     const STATIC: &str = "";
     //~^ ERROR `&` without an explicit lifetime name cannot be used here
     //~| WARN this was previously accepted by the compiler but is being phased out
-    //~| ERROR lifetime parameters or bounds on const `STATIC` do not match the trait declaration
+    //~| ERROR lifetime parameters or bounds on associated const `STATIC` do not match the trait declaration
 }
 
 struct B;
diff --git a/tests/ui/consts/static-default-lifetime/static-trait-impl.stderr b/tests/ui/consts/static-default-lifetime/static-trait-impl.stderr
index 116f28e8484..38d24db1317 100644
--- a/tests/ui/consts/static-default-lifetime/static-trait-impl.stderr
+++ b/tests/ui/consts/static-default-lifetime/static-trait-impl.stderr
@@ -21,14 +21,14 @@ help: use the `'static` lifetime
 LL |     const STATIC: &'static str = "";
    |                    +++++++
 
-error[E0195]: lifetime parameters or bounds on const `STATIC` do not match the trait declaration
+error[E0195]: lifetime parameters or bounds on associated const `STATIC` do not match the trait declaration
   --> $DIR/static-trait-impl.rs:9:17
    |
 LL |     const STATIC: &'a str;
-   |                 - lifetimes in impl do not match this const in trait
+   |                 - lifetimes in impl do not match this associated const in trait
 ...
 LL |     const STATIC: &str = "";
-   |                 ^ lifetimes do not match const in trait
+   |                 ^ lifetimes do not match associated const in trait
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/generic-associated-types/const_params_have_right_type.stderr b/tests/ui/generic-associated-types/const_params_have_right_type.stderr
index 78992112a7c..a3d3a66a05c 100644
--- a/tests/ui/generic-associated-types/const_params_have_right_type.stderr
+++ b/tests/ui/generic-associated-types/const_params_have_right_type.stderr
@@ -1,4 +1,4 @@
-error[E0053]: type `Foo` has an incompatible generic parameter for trait `Trait`
+error[E0053]: associated type `Foo` has an incompatible generic parameter for trait `Trait`
   --> $DIR/const_params_have_right_type.rs:6:14
    |
 LL | trait Trait {
diff --git a/tests/ui/generic-associated-types/issue-102114.current.stderr b/tests/ui/generic-associated-types/issue-102114.current.stderr
index 03471d08d74..5aace1eeaa2 100644
--- a/tests/ui/generic-associated-types/issue-102114.current.stderr
+++ b/tests/ui/generic-associated-types/issue-102114.current.stderr
@@ -1,4 +1,4 @@
-error[E0049]: type `B` has 1 type parameter but its trait declaration has 0 type parameters
+error[E0049]: associated type `B` has 1 type parameter but its trait declaration has 0 type parameters
   --> $DIR/issue-102114.rs:15:12
    |
 LL |     type B<'b>;
diff --git a/tests/ui/generic-associated-types/issue-102114.next.stderr b/tests/ui/generic-associated-types/issue-102114.next.stderr
index 03471d08d74..5aace1eeaa2 100644
--- a/tests/ui/generic-associated-types/issue-102114.next.stderr
+++ b/tests/ui/generic-associated-types/issue-102114.next.stderr
@@ -1,4 +1,4 @@
-error[E0049]: type `B` has 1 type parameter but its trait declaration has 0 type parameters
+error[E0049]: associated type `B` has 1 type parameter but its trait declaration has 0 type parameters
   --> $DIR/issue-102114.rs:15:12
    |
 LL |     type B<'b>;
diff --git a/tests/ui/generic-associated-types/parameter_number_and_kind_impl.rs b/tests/ui/generic-associated-types/parameter_number_and_kind_impl.rs
index c1381025ac2..a39a7aacc7b 100644
--- a/tests/ui/generic-associated-types/parameter_number_and_kind_impl.rs
+++ b/tests/ui/generic-associated-types/parameter_number_and_kind_impl.rs
@@ -12,11 +12,11 @@ struct Fooy;
 
 impl Foo for Fooy {
     type A = u32;
-    //~^ ERROR lifetime parameters or bounds on type `A` do not match the trait declaration
+    //~^ ERROR lifetime parameters or bounds on associated type `A` do not match the trait declaration
     type B<'a, T> = Vec<T>;
     //~^ ERROR type `B` has 1 type parameter but its trait declaration has 0 type parameters
     type C<'a> = u32;
-    //~^ ERROR lifetime parameters or bounds on type `C` do not match the trait declaration
+    //~^ ERROR lifetime parameters or bounds on associated type `C` do not match the trait declaration
 }
 
 struct Fooer;
@@ -25,7 +25,7 @@ impl Foo for Fooer {
     type A<T> = u32;
     //~^ ERROR type `A` has 1 type parameter but its trait declaration has 0 type parameters
     type B<'a> = u32;
-    //~^ ERROR lifetime parameters or bounds on type `B` do not match the trait declaration
+    //~^ ERROR lifetime parameters or bounds on associated type `B` do not match the trait declaration
     type C<T> = T;
     //~^ ERROR type `C` has 1 type parameter but its trait declaration has 0 type parameters
 }
diff --git a/tests/ui/generic-associated-types/parameter_number_and_kind_impl.stderr b/tests/ui/generic-associated-types/parameter_number_and_kind_impl.stderr
index fdd6d305ab2..f7c4a07589c 100644
--- a/tests/ui/generic-associated-types/parameter_number_and_kind_impl.stderr
+++ b/tests/ui/generic-associated-types/parameter_number_and_kind_impl.stderr
@@ -1,13 +1,13 @@
-error[E0195]: lifetime parameters or bounds on type `A` do not match the trait declaration
+error[E0195]: lifetime parameters or bounds on associated type `A` do not match the trait declaration
   --> $DIR/parameter_number_and_kind_impl.rs:14:11
    |
 LL |     type A<'a>;
-   |           ---- lifetimes in impl do not match this type in trait
+   |           ---- lifetimes in impl do not match this associated type in trait
 ...
 LL |     type A = u32;
-   |           ^ lifetimes do not match type in trait
+   |           ^ lifetimes do not match associated type in trait
 
-error[E0049]: type `B` has 1 type parameter but its trait declaration has 0 type parameters
+error[E0049]: associated type `B` has 1 type parameter but its trait declaration has 0 type parameters
   --> $DIR/parameter_number_and_kind_impl.rs:16:12
    |
 LL |     type B<'a, 'b>;
@@ -20,16 +20,16 @@ LL |     type B<'a, T> = Vec<T>;
    |            |
    |            found 1 type parameter
 
-error[E0195]: lifetime parameters or bounds on type `C` do not match the trait declaration
+error[E0195]: lifetime parameters or bounds on associated type `C` do not match the trait declaration
   --> $DIR/parameter_number_and_kind_impl.rs:18:11
    |
 LL |     type C;
-   |           - lifetimes in impl do not match this type in trait
+   |           - lifetimes in impl do not match this associated type in trait
 ...
 LL |     type C<'a> = u32;
-   |           ^^^^ lifetimes do not match type in trait
+   |           ^^^^ lifetimes do not match associated type in trait
 
-error[E0049]: type `A` has 1 type parameter but its trait declaration has 0 type parameters
+error[E0049]: associated type `A` has 1 type parameter but its trait declaration has 0 type parameters
   --> $DIR/parameter_number_and_kind_impl.rs:25:12
    |
 LL |     type A<'a>;
@@ -38,16 +38,16 @@ LL |     type A<'a>;
 LL |     type A<T> = u32;
    |            ^ found 1 type parameter
 
-error[E0195]: lifetime parameters or bounds on type `B` do not match the trait declaration
+error[E0195]: lifetime parameters or bounds on associated type `B` do not match the trait declaration
   --> $DIR/parameter_number_and_kind_impl.rs:27:11
    |
 LL |     type B<'a, 'b>;
-   |           -------- lifetimes in impl do not match this type in trait
+   |           -------- lifetimes in impl do not match this associated type in trait
 ...
 LL |     type B<'a> = u32;
-   |           ^^^^ lifetimes do not match type in trait
+   |           ^^^^ lifetimes do not match associated type in trait
 
-error[E0049]: type `C` has 1 type parameter but its trait declaration has 0 type parameters
+error[E0049]: associated type `C` has 1 type parameter but its trait declaration has 0 type parameters
   --> $DIR/parameter_number_and_kind_impl.rs:29:12
    |
 LL |     type C;
diff --git a/tests/ui/generic-const-items/assoc-const-missing-type.rs b/tests/ui/generic-const-items/assoc-const-missing-type.rs
index 0c94a4262ef..dde47cf993e 100644
--- a/tests/ui/generic-const-items/assoc-const-missing-type.rs
+++ b/tests/ui/generic-const-items/assoc-const-missing-type.rs
@@ -14,7 +14,7 @@ impl Trait for () {
     //~| ERROR mismatched types
     const Q = "";
     //~^ ERROR missing type for `const` item
-    //~| ERROR lifetime parameters or bounds on const `Q` do not match the trait declaration
+    //~| ERROR lifetime parameters or bounds on associated const `Q` do not match the trait declaration
 }
 
 fn main() {}
diff --git a/tests/ui/generic-const-items/assoc-const-missing-type.stderr b/tests/ui/generic-const-items/assoc-const-missing-type.stderr
index 5af119dffa7..9f6db575ec2 100644
--- a/tests/ui/generic-const-items/assoc-const-missing-type.stderr
+++ b/tests/ui/generic-const-items/assoc-const-missing-type.stderr
@@ -15,14 +15,14 @@ error: missing type for `const` item
 LL |     const K<T> = ();
    |               ^ help: provide a type for the associated constant: `()`
 
-error[E0195]: lifetime parameters or bounds on const `Q` do not match the trait declaration
+error[E0195]: lifetime parameters or bounds on associated const `Q` do not match the trait declaration
   --> $DIR/assoc-const-missing-type.rs:15:12
    |
 LL |     const Q<'a>: &'a str;
-   |            ---- lifetimes in impl do not match this const in trait
+   |            ---- lifetimes in impl do not match this associated const in trait
 ...
 LL |     const Q = "";
-   |            ^ lifetimes do not match const in trait
+   |            ^ lifetimes do not match associated const in trait
 
 error: missing type for `const` item
   --> $DIR/assoc-const-missing-type.rs:15:12
diff --git a/tests/ui/generic-const-items/compare-impl-item.rs b/tests/ui/generic-const-items/compare-impl-item.rs
index 21c958a0abe..b301cd0dae0 100644
--- a/tests/ui/generic-const-items/compare-impl-item.rs
+++ b/tests/ui/generic-const-items/compare-impl-item.rs
@@ -22,7 +22,7 @@ impl<P> Trait<P> for () {
     const D<const N: u16>: u16 = N;
     //~^ ERROR const `D` has an incompatible generic parameter for trait `Trait`
     const E: &'static () = &();
-    //~^ ERROR lifetime parameters or bounds on const `E` do not match the trait declaration
+    //~^ ERROR lifetime parameters or bounds on associated const `E` do not match the trait declaration
 
     const F: usize = 1024
     where
diff --git a/tests/ui/generic-const-items/compare-impl-item.stderr b/tests/ui/generic-const-items/compare-impl-item.stderr
index 3bf28e9da60..f7e3ff6501b 100644
--- a/tests/ui/generic-const-items/compare-impl-item.stderr
+++ b/tests/ui/generic-const-items/compare-impl-item.stderr
@@ -1,4 +1,4 @@
-error[E0049]: const `A` has 1 type parameter but its trait declaration has 0 type parameters
+error[E0049]: associated const `A` has 1 type parameter but its trait declaration has 0 type parameters
   --> $DIR/compare-impl-item.rs:16:13
    |
 LL |     const A: ();
@@ -7,7 +7,7 @@ LL |     const A: ();
 LL |     const A<T>: () = ();
    |             ^ found 1 type parameter
 
-error[E0049]: const `B` has 1 const parameter but its trait declaration has 2 const parameters
+error[E0049]: associated const `B` has 1 const parameter but its trait declaration has 2 const parameters
   --> $DIR/compare-impl-item.rs:18:13
    |
 LL |     const B<const K: u64, const Q: u64>: u64;
@@ -18,7 +18,7 @@ LL |     const B<const K: u64, const Q: u64>: u64;
 LL |     const B<const K: u64>: u64 = 0;
    |             ^^^^^^^^^^^^ found 1 const parameter
 
-error[E0049]: const `C` has 0 type parameters but its trait declaration has 1 type parameter
+error[E0049]: associated const `C` has 0 type parameters but its trait declaration has 1 type parameter
   --> $DIR/compare-impl-item.rs:20:13
    |
 LL |     const C<T>: T;
@@ -27,7 +27,7 @@ LL |     const C<T>: T;
 LL |     const C<'a>: &'a str = "";
    |             ^^ found 0 type parameters
 
-error[E0053]: const `D` has an incompatible generic parameter for trait `Trait`
+error[E0053]: associated const `D` has an incompatible generic parameter for trait `Trait`
   --> $DIR/compare-impl-item.rs:22:13
    |
 LL | trait Trait<P> {
@@ -42,14 +42,14 @@ LL | impl<P> Trait<P> for () {
 LL |     const D<const N: u16>: u16 = N;
    |             ^^^^^^^^^^^^ found const parameter of type `u16`
 
-error[E0195]: lifetime parameters or bounds on const `E` do not match the trait declaration
+error[E0195]: lifetime parameters or bounds on associated const `E` do not match the trait declaration
   --> $DIR/compare-impl-item.rs:24:12
    |
 LL |     const E<'a>: &'a ();
-   |            ---- lifetimes in impl do not match this const in trait
+   |            ---- lifetimes in impl do not match this associated const in trait
 ...
 LL |     const E: &'static () = &();
-   |            ^ lifetimes do not match const in trait
+   |            ^ lifetimes do not match associated const in trait
 
 error[E0276]: impl has stricter requirements than trait
   --> $DIR/compare-impl-item.rs:29:12
diff --git a/tests/ui/impl-trait/ice-unexpected-param-type-whensubstituting-in-region-112823.current.stderr b/tests/ui/impl-trait/ice-unexpected-param-type-whensubstituting-in-region-112823.current.stderr
index c76415d8114..341262ac85b 100644
--- a/tests/ui/impl-trait/ice-unexpected-param-type-whensubstituting-in-region-112823.current.stderr
+++ b/tests/ui/impl-trait/ice-unexpected-param-type-whensubstituting-in-region-112823.current.stderr
@@ -4,7 +4,7 @@ error[E0407]: method `line_stream` is not a member of trait `X`
 LL |     fn line_stream<'a, Repr>(&'a self) -> Self::LineStreamFut<'a, Repr> {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not a member of trait `X`
 
-error[E0049]: type `LineStream` has 0 type parameters but its trait declaration has 1 type parameter
+error[E0049]: associated type `LineStream` has 0 type parameters but its trait declaration has 1 type parameter
   --> $DIR/ice-unexpected-param-type-whensubstituting-in-region-112823.rs:25:21
    |
 LL |     type LineStream<'a, Repr>
diff --git a/tests/ui/impl-trait/ice-unexpected-param-type-whensubstituting-in-region-112823.next.stderr b/tests/ui/impl-trait/ice-unexpected-param-type-whensubstituting-in-region-112823.next.stderr
index 4d72490ff95..9632d2ce624 100644
--- a/tests/ui/impl-trait/ice-unexpected-param-type-whensubstituting-in-region-112823.next.stderr
+++ b/tests/ui/impl-trait/ice-unexpected-param-type-whensubstituting-in-region-112823.next.stderr
@@ -4,7 +4,7 @@ error[E0407]: method `line_stream` is not a member of trait `X`
 LL |     fn line_stream<'a, Repr>(&'a self) -> Self::LineStreamFut<'a, Repr> {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not a member of trait `X`
 
-error[E0049]: type `LineStream` has 0 type parameters but its trait declaration has 1 type parameter
+error[E0049]: associated type `LineStream` has 0 type parameters but its trait declaration has 1 type parameter
   --> $DIR/ice-unexpected-param-type-whensubstituting-in-region-112823.rs:25:21
    |
 LL |     type LineStream<'a, Repr>
diff --git a/tests/ui/impl-trait/in-trait/span-bug-issue-121457.rs b/tests/ui/impl-trait/in-trait/span-bug-issue-121457.rs
index ab21dae7dc5..7dc747bffba 100644
--- a/tests/ui/impl-trait/in-trait/span-bug-issue-121457.rs
+++ b/tests/ui/impl-trait/in-trait/span-bug-issue-121457.rs
@@ -8,7 +8,7 @@ pub trait Iterable {
 
 impl<'a, I: 'a + Iterable> Iterable for &'a I {
     type Item = u32;
-    //~^ ERROR lifetime parameters or bounds on type `Item` do not match the trait declaration
+    //~^ ERROR lifetime parameters or bounds on associated type `Item` do not match the trait declaration
 
     fn iter(&self) -> impl for<'missing> Iterator<Item = Self::Item<'missing>> {}
     //~^ ERROR binding for associated type `Item` references lifetime `'missing`
diff --git a/tests/ui/impl-trait/in-trait/span-bug-issue-121457.stderr b/tests/ui/impl-trait/in-trait/span-bug-issue-121457.stderr
index d8a2eef94a1..eaa320455bb 100644
--- a/tests/ui/impl-trait/in-trait/span-bug-issue-121457.stderr
+++ b/tests/ui/impl-trait/in-trait/span-bug-issue-121457.stderr
@@ -12,17 +12,17 @@ LL |     fn iter(&self) -> impl for<'missing> Iterator<Item = Self::Item<'missin
    |
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
-error[E0195]: lifetime parameters or bounds on type `Item` do not match the trait declaration
+error[E0195]: lifetime parameters or bounds on associated type `Item` do not match the trait declaration
   --> $DIR/span-bug-issue-121457.rs:10:14
    |
 LL |     type Item<'a>
-   |              ---- lifetimes in impl do not match this type in trait
+   |              ---- lifetimes in impl do not match this associated type in trait
 LL |     where
 LL |         Self: 'a;
    |               -- this bound might be missing in the impl
 ...
 LL |     type Item = u32;
-   |              ^ lifetimes do not match type in trait
+   |              ^ lifetimes do not match associated type in trait
 
 error[E0277]: `()` is not an iterator
   --> $DIR/span-bug-issue-121457.rs:13:23
diff --git a/tests/ui/lifetimes/no_lending_iterators.rs b/tests/ui/lifetimes/no_lending_iterators.rs
index 21395475fb3..b3e8ad08ba1 100644
--- a/tests/ui/lifetimes/no_lending_iterators.rs
+++ b/tests/ui/lifetimes/no_lending_iterators.rs
@@ -25,7 +25,7 @@ impl Bar for usize {
 
 impl Bar for isize {
     type Item<'a> = &'a isize;
-    //~^ ERROR 27:14: 27:18: lifetime parameters or bounds on type `Item` do not match the trait declaration [E0195]
+    //~^ ERROR 27:14: 27:18: lifetime parameters or bounds on associated type `Item` do not match the trait declaration [E0195]
 
     fn poke(&mut self, item: Self::Item) {
         self += *item;
diff --git a/tests/ui/lifetimes/no_lending_iterators.stderr b/tests/ui/lifetimes/no_lending_iterators.stderr
index 9ceaef2f9b1..340ef935885 100644
--- a/tests/ui/lifetimes/no_lending_iterators.stderr
+++ b/tests/ui/lifetimes/no_lending_iterators.stderr
@@ -16,14 +16,14 @@ error: in the trait associated type is declared without lifetime parameters, so
 LL |     type Item = &usize;
    |                 ^ this lifetime must come from the implemented type
 
-error[E0195]: lifetime parameters or bounds on type `Item` do not match the trait declaration
+error[E0195]: lifetime parameters or bounds on associated type `Item` do not match the trait declaration
   --> $DIR/no_lending_iterators.rs:27:14
    |
 LL |     type Item;
-   |              - lifetimes in impl do not match this type in trait
+   |              - lifetimes in impl do not match this associated type in trait
 ...
 LL |     type Item<'a> = &'a isize;
-   |              ^^^^ lifetimes do not match type in trait
+   |              ^^^^ lifetimes do not match associated type in trait
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/type-alias-impl-trait/impl-trait-in-type-alias-with-bad-substs.stderr b/tests/ui/type-alias-impl-trait/impl-trait-in-type-alias-with-bad-substs.stderr
index 13f5d8b8ea6..c58d919c4b1 100644
--- a/tests/ui/type-alias-impl-trait/impl-trait-in-type-alias-with-bad-substs.stderr
+++ b/tests/ui/type-alias-impl-trait/impl-trait-in-type-alias-with-bad-substs.stderr
@@ -1,4 +1,4 @@
-error[E0049]: type `Baz` has 1 type parameter but its trait declaration has 0 type parameters
+error[E0049]: associated type `Baz` has 1 type parameter but its trait declaration has 0 type parameters
   --> $DIR/impl-trait-in-type-alias-with-bad-substs.rs:19:14
    |
 LL |     type Baz<'a>;