about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2025-07-10 19:56:08 +0000
committerbors <bors@rust-lang.org>2025-07-10 19:56:08 +0000
commit2a023bf80a6fbd6a06d5460a34eb247b986286ed (patch)
treed5ca6e0ecb9a1b89ddd3fc5cb328f67a51a181fe
parenta9f2aad0454ef1a06de6588d012517b534540765 (diff)
parentb5d1b92a8c7241cc6989e3b5d0246654c4065679 (diff)
downloadrust-2a023bf80a6fbd6a06d5460a34eb247b986286ed.tar.gz
rust-2a023bf80a6fbd6a06d5460a34eb247b986286ed.zip
Auto merge of #143746 - matthiaskrgr:rollup-yaojj7t, r=matthiaskrgr
Rollup of 9 pull requests

Successful merges:

 - rust-lang/rust#143446 (use `--dynamic-list` for exporting executable symbols)
 - rust-lang/rust#143590 (Fix weird rustdoc output when single and glob reexport conflict on a name)
 - rust-lang/rust#143599 (emit `.att_syntax` when global/naked asm use that option)
 - rust-lang/rust#143615 (Fix handling of no_std targets in `doc::Std` step)
 - rust-lang/rust#143632 (fix: correct parameter names in LLVMRustBuildMinNum and LLVMRustBuildMaxNum FFI declarations)
 - rust-lang/rust#143640 (Constify `Fn*` traits)
 - rust-lang/rust#143651 (Win: Use exceptions with empty data for SEH panic exception copies instead of a new panic)
 - rust-lang/rust#143660 (Disable docs for `compiler-builtins` and `sysroot`)
 - rust-lang/rust#143665 ([rustdoc-json] Add tests for `#[doc(hidden)]` handling of items.)

r? `@ghost`
`@rustbot` modify labels: rollup
-rw-r--r--compiler/rustc_codegen_llvm/src/asm.rs22
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm/ffi.rs4
-rw-r--r--compiler/rustc_codegen_ssa/src/back/linker.rs41
-rw-r--r--compiler/rustc_hir_typeck/messages.ftl7
-rw-r--r--compiler/rustc_hir_typeck/src/callee.rs23
-rw-r--r--compiler/rustc_hir_typeck/src/errors.rs18
-rw-r--r--compiler/rustc_hir_typeck/src/upvar.rs6
-rw-r--r--compiler/rustc_trait_selection/src/traits/effects.rs51
-rw-r--r--library/compiler-builtins/compiler-builtins/Cargo.toml2
-rw-r--r--library/core/src/intrinsics/mod.rs2
-rw-r--r--library/core/src/ops/function.rs34
-rw-r--r--library/panic_unwind/src/seh.rs18
-rw-r--r--library/sysroot/Cargo.toml4
-rw-r--r--src/bootstrap/src/core/build_steps/compile.rs30
-rw-r--r--src/bootstrap/src/core/build_steps/doc.rs10
-rw-r--r--src/bootstrap/src/core/builder/mod.rs9
-rw-r--r--src/bootstrap/src/core/builder/tests.rs169
-rw-r--r--src/bootstrap/src/utils/tests/mod.rs28
-rw-r--r--src/librustdoc/clean/inline.rs10
-rw-r--r--src/librustdoc/clean/mod.rs50
-rw-r--r--src/librustdoc/visit_ast.rs64
-rw-r--r--tests/assembly/emit-intel-att-syntax.rs75
-rw-r--r--tests/rustdoc-json/visibility/doc_hidden_default.rs19
-rw-r--r--tests/rustdoc-json/visibility/doc_hidden_documented.rs17
-rw-r--r--tests/rustdoc/reexport/merge-glob-and-non-glob.rs41
-rw-r--r--tests/ui/consts/fn_trait_refs.stderr175
-rw-r--r--tests/ui/consts/unstable-const-fn-in-libcore.stderr32
-rw-r--r--tests/ui/impl-trait/normalize-tait-in-const.stderr32
-rw-r--r--tests/ui/intrinsics/const-eval-select-bad.rs7
-rw-r--r--tests/ui/intrinsics/const-eval-select-bad.stderr58
-rw-r--r--tests/ui/linking/export-executable-symbols.rs30
-rw-r--r--tests/ui/traits/const-traits/call.rs2
-rw-r--r--tests/ui/traits/const-traits/call.stderr7
-rw-r--r--tests/ui/traits/const-traits/const-closure-parse-not-item.stderr32
-rw-r--r--tests/ui/traits/const-traits/const-closure-trait-method-fail.stderr33
-rw-r--r--tests/ui/traits/const-traits/const-closure-trait-method.rs5
-rw-r--r--tests/ui/traits/const-traits/const-closure-trait-method.stderr30
-rw-r--r--tests/ui/traits/const-traits/const-closures.rs5
-rw-r--r--tests/ui/traits/const-traits/const-closures.stderr103
-rw-r--r--tests/ui/traits/const-traits/const_closure-const_trait_impl-ice-113381.rs5
-rw-r--r--tests/ui/traits/const-traits/const_closure-const_trait_impl-ice-113381.stderr12
-rw-r--r--tests/ui/traits/const-traits/ice-112822-expected-type-for-param.rs6
-rw-r--r--tests/ui/traits/const-traits/ice-112822-expected-type-for-param.stderr46
-rw-r--r--tests/ui/traits/const-traits/ice-123664-unexpected-bound-var.rs8
-rw-r--r--tests/ui/traits/const-traits/ice-123664-unexpected-bound-var.stderr21
-rw-r--r--tests/ui/traits/const-traits/non-const-op-const-closure-non-const-outer.rs2
-rw-r--r--tests/ui/traits/const-traits/non-const-op-const-closure-non-const-outer.stderr10
47 files changed, 648 insertions, 767 deletions
diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs
index 9ddadcf16aa..a643a91141e 100644
--- a/compiler/rustc_codegen_llvm/src/asm.rs
+++ b/compiler/rustc_codegen_llvm/src/asm.rs
@@ -384,15 +384,19 @@ impl<'tcx> AsmCodegenMethods<'tcx> for CodegenCx<'_, 'tcx> {
     ) {
         let asm_arch = self.tcx.sess.asm_arch.unwrap();
 
-        // Default to Intel syntax on x86
-        let intel_syntax = matches!(asm_arch, InlineAsmArch::X86 | InlineAsmArch::X86_64)
-            && !options.contains(InlineAsmOptions::ATT_SYNTAX);
-
         // Build the template string
         let mut template_str = String::new();
-        if intel_syntax {
-            template_str.push_str(".intel_syntax\n");
+
+        // On X86 platforms there are two assembly syntaxes. Rust uses intel by default,
+        // but AT&T can be specified explicitly.
+        if matches!(asm_arch, InlineAsmArch::X86 | InlineAsmArch::X86_64) {
+            if options.contains(InlineAsmOptions::ATT_SYNTAX) {
+                template_str.push_str(".att_syntax\n")
+            } else {
+                template_str.push_str(".intel_syntax\n")
+            }
         }
+
         for piece in template {
             match *piece {
                 InlineAsmTemplatePiece::String(ref s) => template_str.push_str(s),
@@ -431,7 +435,11 @@ impl<'tcx> AsmCodegenMethods<'tcx> for CodegenCx<'_, 'tcx> {
                 }
             }
         }
-        if intel_syntax {
+
+        // Just to play it safe, if intel was used, reset the assembly syntax to att.
+        if matches!(asm_arch, InlineAsmArch::X86 | InlineAsmArch::X86_64)
+            && !options.contains(InlineAsmOptions::ATT_SYNTAX)
+        {
             template_str.push_str("\n.att_syntax\n");
         }
 
diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
index 91ada856d59..b9dd10ff014 100644
--- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
@@ -1980,12 +1980,12 @@ unsafe extern "C" {
     pub(crate) fn LLVMRustBuildMinNum<'a>(
         B: &Builder<'a>,
         LHS: &'a Value,
-        LHS: &'a Value,
+        RHS: &'a Value,
     ) -> &'a Value;
     pub(crate) fn LLVMRustBuildMaxNum<'a>(
         B: &Builder<'a>,
         LHS: &'a Value,
-        LHS: &'a Value,
+        RHS: &'a Value,
     ) -> &'a Value;
 
     // Atomic Operations
diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs
index 1896f63bd2d..e0a3ad55be0 100644
--- a/compiler/rustc_codegen_ssa/src/back/linker.rs
+++ b/compiler/rustc_codegen_ssa/src/back/linker.rs
@@ -800,9 +800,7 @@ impl<'a> Linker for GccLinker<'a> {
             return;
         }
 
-        let is_windows = self.sess.target.is_like_windows;
-        let path = tmpdir.join(if is_windows { "list.def" } else { "list" });
-
+        let path = tmpdir.join(if self.sess.target.is_like_windows { "list.def" } else { "list" });
         debug!("EXPORTED SYMBOLS:");
 
         if self.sess.target.is_like_darwin {
@@ -817,7 +815,8 @@ impl<'a> Linker for GccLinker<'a> {
             if let Err(error) = res {
                 self.sess.dcx().emit_fatal(errors::LibDefWriteFailure { error });
             }
-        } else if is_windows {
+            self.link_arg("-exported_symbols_list").link_arg(path);
+        } else if self.sess.target.is_like_windows {
             let res: io::Result<()> = try {
                 let mut f = File::create_buffered(&path)?;
 
@@ -835,6 +834,21 @@ impl<'a> Linker for GccLinker<'a> {
             if let Err(error) = res {
                 self.sess.dcx().emit_fatal(errors::LibDefWriteFailure { error });
             }
+            self.link_arg(path);
+        } else if crate_type == CrateType::Executable && !self.sess.target.is_like_solaris {
+            let res: io::Result<()> = try {
+                let mut f = File::create_buffered(&path)?;
+                writeln!(f, "{{")?;
+                for (sym, _) in symbols {
+                    debug!(sym);
+                    writeln!(f, "  {sym};")?;
+                }
+                writeln!(f, "}};")?;
+            };
+            if let Err(error) = res {
+                self.sess.dcx().emit_fatal(errors::VersionScriptWriteFailure { error });
+            }
+            self.link_arg("--dynamic-list").link_arg(path);
         } else {
             // Write an LD version script
             let res: io::Result<()> = try {
@@ -852,18 +866,13 @@ impl<'a> Linker for GccLinker<'a> {
             if let Err(error) = res {
                 self.sess.dcx().emit_fatal(errors::VersionScriptWriteFailure { error });
             }
-        }
-
-        if self.sess.target.is_like_darwin {
-            self.link_arg("-exported_symbols_list").link_arg(path);
-        } else if self.sess.target.is_like_solaris {
-            self.link_arg("-M").link_arg(path);
-        } else if is_windows {
-            self.link_arg(path);
-        } else {
-            let mut arg = OsString::from("--version-script=");
-            arg.push(path);
-            self.link_arg(arg).link_arg("--no-undefined-version");
+            if self.sess.target.is_like_solaris {
+                self.link_arg("-M").link_arg(path);
+            } else {
+                let mut arg = OsString::from("--version-script=");
+                arg.push(path);
+                self.link_arg(arg).link_arg("--no-undefined-version");
+            }
         }
     }
 
diff --git a/compiler/rustc_hir_typeck/messages.ftl b/compiler/rustc_hir_typeck/messages.ftl
index c21b16c9f9f..bac4d70103c 100644
--- a/compiler/rustc_hir_typeck/messages.ftl
+++ b/compiler/rustc_hir_typeck/messages.ftl
@@ -82,13 +82,6 @@ hir_typeck_cast_unknown_pointer = cannot cast {$to ->
 hir_typeck_const_continue_bad_label =
     `#[const_continue]` must break to a labeled block that participates in a `#[loop_match]`
 
-hir_typeck_const_select_must_be_const = this argument must be a `const fn`
-    .help = consult the documentation on `const_eval_select` for more information
-
-hir_typeck_const_select_must_be_fn = this argument must be a function item
-    .note = expected a function item, found {$ty}
-    .help = consult the documentation on `const_eval_select` for more information
-
 hir_typeck_continue_labeled_block =
     `continue` pointing to a labeled block
     .label = labeled blocks cannot be `continue`'d
diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs
index 7611f8ac3e1..48bb45de53e 100644
--- a/compiler/rustc_hir_typeck/src/callee.rs
+++ b/compiler/rustc_hir_typeck/src/callee.rs
@@ -578,29 +578,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             }
         }
 
-        if let Some(def_id) = def_id
-            && self.tcx.def_kind(def_id) == hir::def::DefKind::Fn
-            && self.tcx.is_intrinsic(def_id, sym::const_eval_select)
-        {
-            let fn_sig = self.resolve_vars_if_possible(fn_sig);
-            for idx in 0..=1 {
-                let arg_ty = fn_sig.inputs()[idx + 1];
-                let span = arg_exprs.get(idx + 1).map_or(call_expr.span, |arg| arg.span);
-                // Check that second and third argument of `const_eval_select` must be `FnDef`, and additionally that
-                // the second argument must be `const fn`. The first argument must be a tuple, but this is already expressed
-                // in the function signature (`F: FnOnce<ARG>`), so I did not bother to add another check here.
-                //
-                // This check is here because there is currently no way to express a trait bound for `FnDef` types only.
-                if let ty::FnDef(def_id, _args) = *arg_ty.kind() {
-                    if idx == 0 && !self.tcx.is_const_fn(def_id) {
-                        self.dcx().emit_err(errors::ConstSelectMustBeConst { span });
-                    }
-                } else {
-                    self.dcx().emit_err(errors::ConstSelectMustBeFn { span, ty: arg_ty });
-                }
-            }
-        }
-
         fn_sig.output()
     }
 
diff --git a/compiler/rustc_hir_typeck/src/errors.rs b/compiler/rustc_hir_typeck/src/errors.rs
index 3606c778fc4..a8bb6956f10 100644
--- a/compiler/rustc_hir_typeck/src/errors.rs
+++ b/compiler/rustc_hir_typeck/src/errors.rs
@@ -606,24 +606,6 @@ impl Subdiagnostic for RemoveSemiForCoerce {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_typeck_const_select_must_be_const)]
-#[help]
-pub(crate) struct ConstSelectMustBeConst {
-    #[primary_span]
-    pub span: Span,
-}
-
-#[derive(Diagnostic)]
-#[diag(hir_typeck_const_select_must_be_fn)]
-#[note]
-#[help]
-pub(crate) struct ConstSelectMustBeFn<'a> {
-    #[primary_span]
-    pub span: Span,
-    pub ty: Ty<'a>,
-}
-
-#[derive(Diagnostic)]
 #[diag(hir_typeck_union_pat_multiple_fields)]
 pub(crate) struct UnionPatMultipleFields {
     #[primary_span]
diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs
index 982cfa2e42b..be774106abf 100644
--- a/compiler/rustc_hir_typeck/src/upvar.rs
+++ b/compiler/rustc_hir_typeck/src/upvar.rs
@@ -529,7 +529,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         // process any deferred resolutions.
         let deferred_call_resolutions = self.remove_deferred_call_resolutions(closure_def_id);
         for deferred_call_resolution in deferred_call_resolutions {
-            deferred_call_resolution.resolve(self);
+            deferred_call_resolution.resolve(&mut FnCtxt::new(
+                self,
+                self.param_env,
+                closure_def_id,
+            ));
         }
     }
 
diff --git a/compiler/rustc_trait_selection/src/traits/effects.rs b/compiler/rustc_trait_selection/src/traits/effects.rs
index 176d308de91..d694a092853 100644
--- a/compiler/rustc_trait_selection/src/traits/effects.rs
+++ b/compiler/rustc_trait_selection/src/traits/effects.rs
@@ -1,7 +1,8 @@
 use rustc_hir::{self as hir, LangItem};
 use rustc_infer::infer::{BoundRegionConversionTime, DefineOpaqueTypes};
 use rustc_infer::traits::{
-    ImplDerivedHostCause, ImplSource, Obligation, ObligationCauseCode, PredicateObligation,
+    ImplDerivedHostCause, ImplSource, Obligation, ObligationCause, ObligationCauseCode,
+    PredicateObligation,
 };
 use rustc_middle::span_bug;
 use rustc_middle::traits::query::NoSolution;
@@ -303,6 +304,9 @@ fn evaluate_host_effect_from_builtin_impls<'tcx>(
 ) -> Result<ThinVec<PredicateObligation<'tcx>>, EvaluationFailure> {
     match selcx.tcx().as_lang_item(obligation.predicate.def_id()) {
         Some(LangItem::Destruct) => evaluate_host_effect_for_destruct_goal(selcx, obligation),
+        Some(LangItem::Fn | LangItem::FnMut | LangItem::FnOnce) => {
+            evaluate_host_effect_for_fn_goal(selcx, obligation)
+        }
         _ => Err(EvaluationFailure::NoSolution),
     }
 }
@@ -398,6 +402,51 @@ fn evaluate_host_effect_for_destruct_goal<'tcx>(
         .collect())
 }
 
+// NOTE: Keep this in sync with `extract_fn_def_from_const_callable` in the new solver.
+fn evaluate_host_effect_for_fn_goal<'tcx>(
+    selcx: &mut SelectionContext<'_, 'tcx>,
+    obligation: &HostEffectObligation<'tcx>,
+) -> Result<ThinVec<PredicateObligation<'tcx>>, EvaluationFailure> {
+    let tcx = selcx.tcx();
+    let self_ty = obligation.predicate.self_ty();
+
+    let (def, args) = match *self_ty.kind() {
+        ty::FnDef(def, args) => (def, args),
+
+        // We may support function pointers at some point in the future
+        ty::FnPtr(..) => return Err(EvaluationFailure::NoSolution),
+
+        // Closures could implement `[const] Fn`,
+        // but they don't really need to right now.
+        ty::Closure(..) | ty::CoroutineClosure(_, _) => {
+            return Err(EvaluationFailure::NoSolution);
+        }
+
+        // Everything else needs explicit impls or cannot have an impl
+        _ => return Err(EvaluationFailure::NoSolution),
+    };
+
+    match tcx.constness(def) {
+        hir::Constness::Const => Ok(tcx
+            .const_conditions(def)
+            .instantiate(tcx, args)
+            .into_iter()
+            .map(|(c, span)| {
+                let code = ObligationCauseCode::WhereClause(def, span);
+                let cause =
+                    ObligationCause::new(obligation.cause.span, obligation.cause.body_id, code);
+                Obligation::new(
+                    tcx,
+                    cause,
+                    obligation.param_env,
+                    c.to_host_effect_clause(tcx, obligation.predicate.constness),
+                )
+            })
+            .collect()),
+        hir::Constness::NotConst => Err(EvaluationFailure::NoSolution),
+    }
+}
+
 fn evaluate_host_effect_from_selection_candidate<'tcx>(
     selcx: &mut SelectionContext<'_, 'tcx>,
     obligation: &HostEffectObligation<'tcx>,
diff --git a/library/compiler-builtins/compiler-builtins/Cargo.toml b/library/compiler-builtins/compiler-builtins/Cargo.toml
index c5446cd76e3..3ccb05f73fb 100644
--- a/library/compiler-builtins/compiler-builtins/Cargo.toml
+++ b/library/compiler-builtins/compiler-builtins/Cargo.toml
@@ -19,6 +19,8 @@ links = "compiler-rt"
 bench = false
 doctest = false
 test = false
+# make sure this crate isn't included in public standard library docs
+doc = false
 
 [dependencies]
 core = { path = "../../core", optional = true }
diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs
index f5dcfeebed8..c2e4b751c65 100644
--- a/library/core/src/intrinsics/mod.rs
+++ b/library/core/src/intrinsics/mod.rs
@@ -2279,7 +2279,7 @@ pub const fn const_eval_select<ARG: Tuple, F, G, RET>(
 ) -> RET
 where
     G: FnOnce<ARG, Output = RET>,
-    F: FnOnce<ARG, Output = RET>;
+    F: const FnOnce<ARG, Output = RET>;
 
 /// A macro to make it easier to invoke const_eval_select. Use as follows:
 /// ```rust,ignore (just a macro example)
diff --git a/library/core/src/ops/function.rs b/library/core/src/ops/function.rs
index df48c104410..763b60d88e5 100644
--- a/library/core/src/ops/function.rs
+++ b/library/core/src/ops/function.rs
@@ -72,7 +72,8 @@ use crate::marker::Tuple;
 )]
 #[fundamental] // so that regex can rely that `&str: !FnMut`
 #[must_use = "closures are lazy and do nothing unless called"]
-// FIXME(const_trait_impl) #[const_trait]
+#[const_trait]
+#[rustc_const_unstable(feature = "const_trait_impl", issue = "67792")]
 pub trait Fn<Args: Tuple>: FnMut<Args> {
     /// Performs the call operation.
     #[unstable(feature = "fn_traits", issue = "29625")]
@@ -159,7 +160,8 @@ pub trait Fn<Args: Tuple>: FnMut<Args> {
 )]
 #[fundamental] // so that regex can rely that `&str: !FnMut`
 #[must_use = "closures are lazy and do nothing unless called"]
-// FIXME(const_trait_impl) #[const_trait]
+#[const_trait]
+#[rustc_const_unstable(feature = "const_trait_impl", issue = "67792")]
 pub trait FnMut<Args: Tuple>: FnOnce<Args> {
     /// Performs the call operation.
     #[unstable(feature = "fn_traits", issue = "29625")]
@@ -238,7 +240,8 @@ pub trait FnMut<Args: Tuple>: FnOnce<Args> {
 )]
 #[fundamental] // so that regex can rely that `&str: !FnMut`
 #[must_use = "closures are lazy and do nothing unless called"]
-// FIXME(const_trait_impl) #[const_trait]
+#[const_trait]
+#[rustc_const_unstable(feature = "const_trait_impl", issue = "67792")]
 pub trait FnOnce<Args: Tuple> {
     /// The returned type after the call operator is used.
     #[lang = "fn_once_output"]
@@ -254,9 +257,10 @@ mod impls {
     use crate::marker::Tuple;
 
     #[stable(feature = "rust1", since = "1.0.0")]
-    impl<A: Tuple, F: ?Sized> Fn<A> for &F
+    #[rustc_const_unstable(feature = "const_trait_impl", issue = "67792")]
+    impl<A: Tuple, F: ?Sized> const Fn<A> for &F
     where
-        F: Fn<A>,
+        F: ~const Fn<A>,
     {
         extern "rust-call" fn call(&self, args: A) -> F::Output {
             (**self).call(args)
@@ -264,9 +268,10 @@ mod impls {
     }
 
     #[stable(feature = "rust1", since = "1.0.0")]
-    impl<A: Tuple, F: ?Sized> FnMut<A> for &F
+    #[rustc_const_unstable(feature = "const_trait_impl", issue = "67792")]
+    impl<A: Tuple, F: ?Sized> const FnMut<A> for &F
     where
-        F: Fn<A>,
+        F: ~const Fn<A>,
     {
         extern "rust-call" fn call_mut(&mut self, args: A) -> F::Output {
             (**self).call(args)
@@ -274,9 +279,10 @@ mod impls {
     }
 
     #[stable(feature = "rust1", since = "1.0.0")]
-    impl<A: Tuple, F: ?Sized> FnOnce<A> for &F
+    #[rustc_const_unstable(feature = "const_trait_impl", issue = "67792")]
+    impl<A: Tuple, F: ?Sized> const FnOnce<A> for &F
     where
-        F: Fn<A>,
+        F: ~const Fn<A>,
     {
         type Output = F::Output;
 
@@ -286,9 +292,10 @@ mod impls {
     }
 
     #[stable(feature = "rust1", since = "1.0.0")]
-    impl<A: Tuple, F: ?Sized> FnMut<A> for &mut F
+    #[rustc_const_unstable(feature = "const_trait_impl", issue = "67792")]
+    impl<A: Tuple, F: ?Sized> const FnMut<A> for &mut F
     where
-        F: FnMut<A>,
+        F: ~const FnMut<A>,
     {
         extern "rust-call" fn call_mut(&mut self, args: A) -> F::Output {
             (*self).call_mut(args)
@@ -296,9 +303,10 @@ mod impls {
     }
 
     #[stable(feature = "rust1", since = "1.0.0")]
-    impl<A: Tuple, F: ?Sized> FnOnce<A> for &mut F
+    #[rustc_const_unstable(feature = "const_trait_impl", issue = "67792")]
+    impl<A: Tuple, F: ?Sized> const FnOnce<A> for &mut F
     where
-        F: FnMut<A>,
+        F: ~const FnMut<A>,
     {
         type Output = F::Output;
         extern "rust-call" fn call_once(self, args: A) -> F::Output {
diff --git a/library/panic_unwind/src/seh.rs b/library/panic_unwind/src/seh.rs
index 003ac4f0cd3..668e988abff 100644
--- a/library/panic_unwind/src/seh.rs
+++ b/library/panic_unwind/src/seh.rs
@@ -61,6 +61,7 @@ struct Exception {
     // and its destructor is executed by the C++ runtime. When we take the Box
     // out of the exception, we need to leave the exception in a valid state
     // for its destructor to run without double-dropping the Box.
+    // We also construct this as None for copies of the exception.
     data: Option<Box<dyn Any + Send>>,
 }
 
@@ -264,7 +265,11 @@ static mut TYPE_DESCRIPTOR: _TypeDescriptor = _TypeDescriptor {
 // runtime under a try/catch block and the panic that we generate here will be
 // used as the result of the exception copy. This is used by the C++ runtime to
 // support capturing exceptions with std::exception_ptr, which we can't support
-// because Box<dyn Any> isn't clonable.
+// because Box<dyn Any> isn't clonable. Thus we throw an exception without data,
+// which the C++ runtime will attempt to copy, which will once again fail, and
+// a std::bad_exception instance ends up in the std::exception_ptr instance.
+// The lack of data doesn't matter because the exception will never be rethrown
+// - it is purely used to signal to the C++ runtime that copying failed.
 macro_rules! define_cleanup {
     ($abi:tt $abi2:tt) => {
         unsafe extern $abi fn exception_cleanup(e: *mut Exception) {
@@ -278,7 +283,9 @@ macro_rules! define_cleanup {
         unsafe extern $abi2 fn exception_copy(
             _dest: *mut Exception, _src: *mut Exception
         ) -> *mut Exception {
-            panic!("Rust panics cannot be copied");
+            unsafe {
+                throw_exception(None);
+            }
         }
     }
 }
@@ -291,6 +298,10 @@ cfg_if::cfg_if! {
 }
 
 pub(crate) unsafe fn panic(data: Box<dyn Any + Send>) -> u32 {
+    unsafe { throw_exception(Some(data)) }
+}
+
+unsafe fn throw_exception(data: Option<Box<dyn Any + Send>>) -> ! {
     use core::intrinsics::{AtomicOrdering, atomic_store};
 
     // _CxxThrowException executes entirely on this stack frame, so there's no
@@ -300,8 +311,7 @@ pub(crate) unsafe fn panic(data: Box<dyn Any + Send>) -> u32 {
     // The ManuallyDrop is needed here since we don't want Exception to be
     // dropped when unwinding. Instead it will be dropped by exception_cleanup
     // which is invoked by the C++ runtime.
-    let mut exception =
-        ManuallyDrop::new(Exception { canary: (&raw const TYPE_DESCRIPTOR), data: Some(data) });
+    let mut exception = ManuallyDrop::new(Exception { canary: (&raw const TYPE_DESCRIPTOR), data });
     let throw_ptr = (&raw mut exception) as *mut _;
 
     // This... may seems surprising, and justifiably so. On 32-bit MSVC the
diff --git a/library/sysroot/Cargo.toml b/library/sysroot/Cargo.toml
index c4937c36d4c..290c2eeed44 100644
--- a/library/sysroot/Cargo.toml
+++ b/library/sysroot/Cargo.toml
@@ -5,6 +5,10 @@ name = "sysroot"
 version = "0.0.0"
 edition = "2024"
 
+[lib]
+# make sure this crate isn't included in public standard library docs
+doc = false
+
 # this is a dummy crate to ensure that all required crates appear in the sysroot
 [dependencies]
 proc_macro = { path = "../proc_macro", public = true }
diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs
index 05965ecc170..1282a89a5e4 100644
--- a/src/bootstrap/src/core/build_steps/compile.rs
+++ b/src/bootstrap/src/core/build_steps/compile.rs
@@ -449,26 +449,24 @@ fn copy_self_contained_objects(
     target_deps
 }
 
-/// Resolves standard library crates for `Std::run_make` for any build kind (like check, build, clippy, etc.).
+/// Resolves standard library crates for `Std::run_make` for any build kind (like check, doc,
+/// build, clippy, etc.).
 pub fn std_crates_for_run_make(run: &RunConfig<'_>) -> Vec<String> {
-    // FIXME: Extend builder tests to cover the `crates` field of `Std` instances.
-    if cfg!(test) {
-        return vec![];
-    }
-
-    let has_alias = run.paths.iter().any(|set| set.assert_single_path().path.ends_with("library"));
+    let mut crates = run.make_run_crates(builder::Alias::Library);
+
+    // For no_std targets, we only want to check core and alloc
+    // Regardless of core/alloc being selected explicitly or via the "library" default alias,
+    // we only want to keep these two crates.
+    // The set of no_std crates should be kept in sync with what `Builder::std_cargo` does.
+    // Note: an alternative design would be to return an enum from this function (Default vs Subset)
+    // of crates. However, several steps currently pass `-p <package>` even if all crates are
+    // selected, because Cargo behaves differently in that case. To keep that behavior without
+    // making further changes, we pre-filter the no-std crates here.
     let target_is_no_std = run.builder.no_std(run.target).unwrap_or(false);
-
-    // For no_std targets, do not add any additional crates to the compilation other than what `compile::std_cargo` already adds for no_std targets.
     if target_is_no_std {
-        vec![]
-    }
-    // If the paths include "library", build the entire standard library.
-    else if has_alias {
-        run.make_run_crates(builder::Alias::Library)
-    } else {
-        run.cargo_crates_in_set()
+        crates.retain(|c| c == "core" || c == "alloc");
     }
+    crates
 }
 
 /// Tries to find LLVM's `compiler-rt` source directory, for building `library/profiler_builtins`.
diff --git a/src/bootstrap/src/core/build_steps/doc.rs b/src/bootstrap/src/core/build_steps/doc.rs
index f7c4c5ad0bb..37418f640ac 100644
--- a/src/bootstrap/src/core/build_steps/doc.rs
+++ b/src/bootstrap/src/core/build_steps/doc.rs
@@ -665,7 +665,11 @@ impl Step for Std {
     }
 
     fn metadata(&self) -> Option<StepMetadata> {
-        Some(StepMetadata::doc("std", self.target).stage(self.stage))
+        Some(
+            StepMetadata::doc("std", self.target)
+                .stage(self.stage)
+                .with_metadata(format!("crates=[{}]", self.crates.join(","))),
+        )
     }
 }
 
@@ -739,10 +743,6 @@ fn doc_std(
     }
 
     for krate in requested_crates {
-        if krate == "sysroot" {
-            // The sysroot crate is an implementation detail, don't include it in public docs.
-            continue;
-        }
         cargo.arg("-p").arg(krate);
     }
 
diff --git a/src/bootstrap/src/core/builder/mod.rs b/src/bootstrap/src/core/builder/mod.rs
index 7464327fde9..4d606953d99 100644
--- a/src/bootstrap/src/core/builder/mod.rs
+++ b/src/bootstrap/src/core/builder/mod.rs
@@ -146,6 +146,8 @@ pub struct StepMetadata {
     target: TargetSelection,
     built_by: Option<Compiler>,
     stage: Option<u32>,
+    /// Additional opaque string printed in the metadata
+    metadata: Option<String>,
 }
 
 impl StepMetadata {
@@ -170,7 +172,7 @@ impl StepMetadata {
     }
 
     fn new(name: &'static str, target: TargetSelection, kind: Kind) -> Self {
-        Self { name, kind, target, built_by: None, stage: None }
+        Self { name, kind, target, built_by: None, stage: None, metadata: None }
     }
 
     pub fn built_by(mut self, compiler: Compiler) -> Self {
@@ -183,6 +185,11 @@ impl StepMetadata {
         self
     }
 
+    pub fn with_metadata(mut self, metadata: String) -> Self {
+        self.metadata = Some(metadata);
+        self
+    }
+
     pub fn get_stage(&self) -> Option<u32> {
         self.stage.or(self
             .built_by
diff --git a/src/bootstrap/src/core/builder/tests.rs b/src/bootstrap/src/core/builder/tests.rs
index bbcb58fca14..68d1885b0a7 100644
--- a/src/bootstrap/src/core/builder/tests.rs
+++ b/src/bootstrap/src/core/builder/tests.rs
@@ -637,8 +637,8 @@ mod snapshot {
 
     use crate::core::build_steps::{compile, dist, doc, test, tool};
     use crate::core::builder::tests::{
-        TEST_TRIPLE_1, TEST_TRIPLE_2, TEST_TRIPLE_3, configure, configure_with_args, first,
-        host_target, render_steps, run_build,
+        RenderConfig, TEST_TRIPLE_1, TEST_TRIPLE_2, TEST_TRIPLE_3, configure, configure_with_args,
+        first, host_target, render_steps, run_build,
     };
     use crate::core::builder::{Builder, Kind, StepDescription, StepMetadata};
     use crate::core::config::TargetSelection;
@@ -994,7 +994,7 @@ mod snapshot {
         [build] llvm <host>
         [build] rustc 0 <host> -> rustc 1 <host>
         [build] rustdoc 0 <host>
-        [doc] std 1 <host>
+        [doc] std 1 <host> crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,std,sysroot,test,unwind]
         ");
     }
 
@@ -1043,12 +1043,12 @@ mod snapshot {
         [build] rustc 1 <host> -> std 1 <host>
         [build] rustc 1 <host> -> rustc 2 <host>
         [build] rustdoc 1 <host>
-        [doc] std 2 <host>
+        [doc] std 2 <host> crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,std,sysroot,test,unwind]
         [build] rustc 2 <host> -> std 2 <host>
         [build] rustc 0 <host> -> LintDocs 1 <host>
         [build] rustc 0 <host> -> RustInstaller 1 <host>
         [dist] docs <host>
-        [doc] std 2 <host>
+        [doc] std 2 <host> crates=[]
         [dist] mingw <host>
         [build] rustc 0 <host> -> GenerateCopyright 1 <host>
         [dist] rustc <host>
@@ -1075,12 +1075,12 @@ mod snapshot {
         [build] rustc 1 <host> -> rustc 2 <host>
         [build] rustc 1 <host> -> WasmComponentLd 2 <host>
         [build] rustdoc 1 <host>
-        [doc] std 2 <host>
+        [doc] std 2 <host> crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,std,sysroot,test,unwind]
         [build] rustc 2 <host> -> std 2 <host>
         [build] rustc 0 <host> -> LintDocs 1 <host>
         [build] rustc 0 <host> -> RustInstaller 1 <host>
         [dist] docs <host>
-        [doc] std 2 <host>
+        [doc] std 2 <host> crates=[]
         [dist] mingw <host>
         [build] rustc 0 <host> -> GenerateCopyright 1 <host>
         [dist] rustc <host>
@@ -1112,15 +1112,15 @@ mod snapshot {
         [build] rustc 1 <host> -> std 1 <host>
         [build] rustc 1 <host> -> rustc 2 <host>
         [build] rustdoc 1 <host>
-        [doc] std 2 <host>
-        [doc] std 2 <target1>
+        [doc] std 2 <host> crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,std,sysroot,test,unwind]
+        [doc] std 2 <target1> crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,std,sysroot,test,unwind]
         [build] rustc 2 <host> -> std 2 <host>
         [build] rustc 0 <host> -> LintDocs 1 <host>
         [build] rustc 0 <host> -> RustInstaller 1 <host>
         [dist] docs <host>
         [dist] docs <target1>
-        [doc] std 2 <host>
-        [doc] std 2 <target1>
+        [doc] std 2 <host> crates=[]
+        [doc] std 2 <target1> crates=[]
         [dist] mingw <host>
         [dist] mingw <target1>
         [build] rustc 0 <host> -> GenerateCopyright 1 <host>
@@ -1149,14 +1149,14 @@ mod snapshot {
         [build] rustc 1 <host> -> std 1 <host>
         [build] rustc 1 <host> -> rustc 2 <host>
         [build] rustdoc 1 <host>
-        [doc] std 2 <host>
+        [doc] std 2 <host> crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,std,sysroot,test,unwind]
         [build] rustc 2 <host> -> std 2 <host>
         [build] rustc 0 <host> -> LintDocs 1 <host>
         [build] rustc 1 <host> -> std 1 <target1>
         [build] rustc 2 <host> -> std 2 <target1>
         [build] rustc 0 <host> -> RustInstaller 1 <host>
         [dist] docs <host>
-        [doc] std 2 <host>
+        [doc] std 2 <host> crates=[]
         [dist] mingw <host>
         [build] rustc 0 <host> -> GenerateCopyright 1 <host>
         [dist] rustc <host>
@@ -1186,8 +1186,8 @@ mod snapshot {
         [build] rustc 1 <host> -> std 1 <host>
         [build] rustc 1 <host> -> rustc 2 <host>
         [build] rustdoc 1 <host>
-        [doc] std 2 <host>
-        [doc] std 2 <target1>
+        [doc] std 2 <host> crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,std,sysroot,test,unwind]
+        [doc] std 2 <target1> crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,std,sysroot,test,unwind]
         [build] rustc 2 <host> -> std 2 <host>
         [build] rustc 0 <host> -> LintDocs 1 <host>
         [build] rustc 1 <host> -> std 1 <target1>
@@ -1195,8 +1195,8 @@ mod snapshot {
         [build] rustc 0 <host> -> RustInstaller 1 <host>
         [dist] docs <host>
         [dist] docs <target1>
-        [doc] std 2 <host>
-        [doc] std 2 <target1>
+        [doc] std 2 <host> crates=[]
+        [doc] std 2 <target1> crates=[]
         [dist] mingw <host>
         [dist] mingw <target1>
         [build] rustc 0 <host> -> GenerateCopyright 1 <host>
@@ -1228,11 +1228,11 @@ mod snapshot {
         [build] rustc 1 <host> -> std 1 <host>
         [build] rustc 1 <host> -> rustc 2 <host>
         [build] rustdoc 1 <host>
-        [doc] std 2 <target1>
+        [doc] std 2 <target1> crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,std,sysroot,test,unwind]
         [build] rustc 2 <host> -> std 2 <host>
         [build] rustc 0 <host> -> RustInstaller 1 <host>
         [dist] docs <target1>
-        [doc] std 2 <target1>
+        [doc] std 2 <target1> crates=[]
         [dist] mingw <target1>
         [build] rustc 2 <host> -> std 2 <target1>
         [dist] rustc 2 <host> -> std 2 <target1>
@@ -1260,14 +1260,14 @@ mod snapshot {
         [build] rustc 1 <host> -> rustc 2 <host>
         [build] rustc 1 <host> -> WasmComponentLd 2 <host>
         [build] rustdoc 1 <host>
-        [doc] std 2 <target1>
+        [doc] std 2 <target1> crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,std,sysroot,test,unwind]
         [build] rustc 2 <host> -> std 2 <host>
         [build] rustc 1 <host> -> std 1 <target1>
         [build] rustc 2 <host> -> std 2 <target1>
         [build] rustc 0 <host> -> LintDocs 1 <host>
         [build] rustc 0 <host> -> RustInstaller 1 <host>
         [dist] docs <target1>
-        [doc] std 2 <target1>
+        [doc] std 2 <target1> crates=[]
         [dist] mingw <target1>
         [build] llvm <target1>
         [build] rustc 1 <host> -> rustc 2 <target1>
@@ -1575,6 +1575,80 @@ mod snapshot {
         steps.assert_contains(StepMetadata::test("CrateLibrustc", host));
         steps.assert_contains_fuzzy(StepMetadata::build("rustc", host));
     }
+
+    #[test]
+    fn doc_library() {
+        let ctx = TestCtx::new();
+        insta::assert_snapshot!(
+            ctx.config("doc")
+                .path("library")
+                .render_steps(), @r"
+        [build] llvm <host>
+        [build] rustc 0 <host> -> rustc 1 <host>
+        [build] rustdoc 0 <host>
+        [doc] std 1 <host> crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,std,sysroot,test,unwind]
+        ");
+    }
+
+    #[test]
+    fn doc_core() {
+        let ctx = TestCtx::new();
+        insta::assert_snapshot!(
+            ctx.config("doc")
+                .path("core")
+                .render_steps(), @r"
+        [build] llvm <host>
+        [build] rustc 0 <host> -> rustc 1 <host>
+        [build] rustdoc 0 <host>
+        [doc] std 1 <host> crates=[core]
+        ");
+    }
+
+    #[test]
+    fn doc_core_no_std_target() {
+        let ctx = TestCtx::new();
+        insta::assert_snapshot!(
+            ctx.config("doc")
+                .path("core")
+                .override_target_no_std(&host_target())
+                .render_steps(), @r"
+        [build] llvm <host>
+        [build] rustc 0 <host> -> rustc 1 <host>
+        [build] rustdoc 0 <host>
+        [doc] std 1 <host> crates=[core]
+        ");
+    }
+
+    #[test]
+    fn doc_library_no_std_target() {
+        let ctx = TestCtx::new();
+        insta::assert_snapshot!(
+            ctx.config("doc")
+                .path("library")
+                .override_target_no_std(&host_target())
+                .render_steps(), @r"
+        [build] llvm <host>
+        [build] rustc 0 <host> -> rustc 1 <host>
+        [build] rustdoc 0 <host>
+        [doc] std 1 <host> crates=[alloc,core]
+        ");
+    }
+
+    #[test]
+    fn doc_library_no_std_target_cross_compile() {
+        let ctx = TestCtx::new();
+        insta::assert_snapshot!(
+            ctx.config("doc")
+                .path("library")
+                .targets(&[TEST_TRIPLE_1])
+                .override_target_no_std(TEST_TRIPLE_1)
+                .render_steps(), @r"
+        [build] llvm <host>
+        [build] rustc 0 <host> -> rustc 1 <host>
+        [build] rustdoc 0 <host>
+        [doc] std 1 <target1> crates=[alloc,core]
+        ");
+    }
 }
 
 struct ExecutedSteps {
@@ -1583,7 +1657,11 @@ struct ExecutedSteps {
 
 impl ExecutedSteps {
     fn render(&self) -> String {
-        render_steps(&self.steps)
+        self.render_with(RenderConfig::default())
+    }
+
+    fn render_with(&self, config: RenderConfig) -> String {
+        render_steps(&self.steps, config)
     }
 
     #[track_caller]
@@ -1592,7 +1670,7 @@ impl ExecutedSteps {
         if !self.contains(&metadata) {
             panic!(
                 "Metadata `{}` ({metadata:?}) not found in executed steps:\n{}",
-                render_metadata(&metadata),
+                render_metadata(&metadata, &RenderConfig::default()),
                 self.render()
             );
         }
@@ -1607,7 +1685,7 @@ impl ExecutedSteps {
         if !self.contains_fuzzy(&metadata) {
             panic!(
                 "Metadata `{}` ({metadata:?}) not found in executed steps:\n{}",
-                render_metadata(&metadata),
+                render_metadata(&metadata, &RenderConfig::default()),
                 self.render()
             );
         }
@@ -1619,7 +1697,7 @@ impl ExecutedSteps {
         if self.contains(&metadata) {
             panic!(
                 "Metadata `{}` ({metadata:?}) found in executed steps (it should not be there):\n{}",
-                render_metadata(&metadata),
+                render_metadata(&metadata, &RenderConfig::default()),
                 self.render()
             );
         }
@@ -1641,7 +1719,7 @@ impl ExecutedSteps {
 }
 
 fn fuzzy_metadata_eq(executed: &StepMetadata, to_match: &StepMetadata) -> bool {
-    let StepMetadata { name, kind, target, built_by: _, stage: _ } = executed;
+    let StepMetadata { name, kind, target, built_by: _, stage: _, metadata } = executed;
     *name == to_match.name && *kind == to_match.kind && *target == to_match.target
 }
 
@@ -1672,6 +1750,16 @@ impl ConfigBuilder {
     }
 }
 
+struct RenderConfig {
+    normalize_host: bool,
+}
+
+impl Default for RenderConfig {
+    fn default() -> Self {
+        Self { normalize_host: true }
+    }
+}
+
 /// Renders the executed bootstrap steps for usage in snapshot tests with insta.
 /// Only renders certain important steps.
 /// Each value in `steps` should be a tuple of (Step, step output).
@@ -1679,7 +1767,7 @@ impl ConfigBuilder {
 /// The arrow in the rendered output (`X -> Y`) means `X builds Y`.
 /// This is similar to the output printed by bootstrap to stdout, but here it is
 /// generated purely for the purpose of tests.
-fn render_steps(steps: &[ExecutedStep]) -> String {
+fn render_steps(steps: &[ExecutedStep], config: RenderConfig) -> String {
     steps
         .iter()
         .filter_map(|step| {
@@ -1689,32 +1777,35 @@ fn render_steps(steps: &[ExecutedStep]) -> String {
                 return None;
             };
 
-            Some(render_metadata(&metadata))
+            Some(render_metadata(&metadata, &config))
         })
         .collect::<Vec<_>>()
         .join("\n")
 }
 
-fn render_metadata(metadata: &StepMetadata) -> String {
+fn render_metadata(metadata: &StepMetadata, config: &RenderConfig) -> String {
     let mut record = format!("[{}] ", metadata.kind.as_str());
     if let Some(compiler) = metadata.built_by {
-        write!(record, "{} -> ", render_compiler(compiler));
+        write!(record, "{} -> ", render_compiler(compiler, config));
     }
     let stage = metadata.get_stage().map(|stage| format!("{stage} ")).unwrap_or_default();
-    write!(record, "{} {stage}<{}>", metadata.name, normalize_target(metadata.target));
+    write!(record, "{} {stage}<{}>", metadata.name, normalize_target(metadata.target, config));
+    if let Some(metadata) = &metadata.metadata {
+        write!(record, " {metadata}");
+    }
     record
 }
 
-fn normalize_target(target: TargetSelection) -> String {
-    target
-        .to_string()
-        .replace(&host_target(), "host")
-        .replace(TEST_TRIPLE_1, "target1")
-        .replace(TEST_TRIPLE_2, "target2")
+fn normalize_target(target: TargetSelection, config: &RenderConfig) -> String {
+    let mut target = target.to_string();
+    if config.normalize_host {
+        target = target.replace(&host_target(), "host");
+    }
+    target.replace(TEST_TRIPLE_1, "target1").replace(TEST_TRIPLE_2, "target2")
 }
 
-fn render_compiler(compiler: Compiler) -> String {
-    format!("rustc {} <{}>", compiler.stage, normalize_target(compiler.host))
+fn render_compiler(compiler: Compiler, config: &RenderConfig) -> String {
+    format!("rustc {} <{}>", compiler.stage, normalize_target(compiler.host, config))
 }
 
 fn host_target() -> String {
diff --git a/src/bootstrap/src/utils/tests/mod.rs b/src/bootstrap/src/utils/tests/mod.rs
index 5b568c1df5b..ec87e71e0b6 100644
--- a/src/bootstrap/src/utils/tests/mod.rs
+++ b/src/bootstrap/src/utils/tests/mod.rs
@@ -48,17 +48,30 @@ impl ConfigBuilder {
     }
 
     pub fn path(mut self, path: &str) -> Self {
-        self.args.push(path.to_string());
-        self
+        self.arg(path)
     }
 
     pub fn paths(mut self, paths: &[&str]) -> Self {
-        for path in paths {
-            self = self.path(path);
+        self.args(paths)
+    }
+
+    pub fn arg(mut self, arg: &str) -> Self {
+        self.args.push(arg.to_string());
+        self
+    }
+
+    pub fn args(mut self, args: &[&str]) -> Self {
+        for arg in args {
+            self = self.arg(arg);
         }
         self
     }
 
+    /// Set the specified target to be treated as a no_std target.
+    pub fn override_target_no_std(mut self, target: &str) -> Self {
+        self.args(&["--set", &format!("target.{target}.no-std=true")])
+    }
+
     pub fn hosts(mut self, targets: &[&str]) -> Self {
         self.args.push("--host".to_string());
         self.args.push(targets.join(","));
@@ -77,13 +90,6 @@ impl ConfigBuilder {
         self
     }
 
-    pub fn args(mut self, args: &[&str]) -> Self {
-        for arg in args {
-            self.args.push(arg.to_string());
-        }
-        self
-    }
-
     pub fn create_config(mut self) -> Config {
         // Run in dry-check, otherwise the test would be too slow
         self.args.push("--dry-run".to_string());
diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs
index 96199cb972a..37b012d6d0d 100644
--- a/src/librustdoc/clean/inline.rs
+++ b/src/librustdoc/clean/inline.rs
@@ -152,8 +152,14 @@ pub(crate) fn try_inline(
     };
 
     cx.inlined.insert(did.into());
-    let mut item =
-        crate::clean::generate_item_with_correct_attrs(cx, kind, did, name, import_def_id, None);
+    let mut item = crate::clean::generate_item_with_correct_attrs(
+        cx,
+        kind,
+        did,
+        name,
+        import_def_id.as_slice(),
+        None,
+    );
     // The visibility needs to reflect the one from the reexport and not from the "source" DefId.
     item.inner.inline_stmt_id = import_def_id;
     ret.push(item);
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index c2f3da18cd3..e6f7aef02c0 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -94,12 +94,12 @@ pub(crate) fn clean_doc_module<'tcx>(doc: &DocModule<'tcx>, cx: &mut DocContext<
     // This covers the case where somebody does an import which should pull in an item,
     // but there's already an item with the same namespace and same name. Rust gives
     // priority to the not-imported one, so we should, too.
-    items.extend(doc.items.values().flat_map(|(item, renamed, import_id)| {
+    items.extend(doc.items.values().flat_map(|(item, renamed, import_ids)| {
         // First, lower everything other than glob imports.
         if matches!(item.kind, hir::ItemKind::Use(_, hir::UseKind::Glob)) {
             return Vec::new();
         }
-        let v = clean_maybe_renamed_item(cx, item, *renamed, *import_id);
+        let v = clean_maybe_renamed_item(cx, item, *renamed, import_ids);
         for item in &v {
             if let Some(name) = item.name
                 && (cx.render_options.document_hidden || !item.is_doc_hidden())
@@ -162,7 +162,7 @@ pub(crate) fn clean_doc_module<'tcx>(doc: &DocModule<'tcx>, cx: &mut DocContext<
         kind,
         doc.def_id.to_def_id(),
         doc.name,
-        doc.import_id,
+        doc.import_id.as_slice(),
         doc.renamed,
     )
 }
@@ -182,22 +182,29 @@ fn generate_item_with_correct_attrs(
     kind: ItemKind,
     def_id: DefId,
     name: Symbol,
-    import_id: Option<LocalDefId>,
+    import_ids: &[LocalDefId],
     renamed: Option<Symbol>,
 ) -> Item {
     let target_attrs = inline::load_attrs(cx, def_id);
-    let attrs = if let Some(import_id) = import_id {
-        // glob reexports are treated the same as `#[doc(inline)]` items.
-        //
-        // For glob re-exports the item may or may not exist to be re-exported (potentially the cfgs
-        // on the path up until the glob can be removed, and only cfgs on the globbed item itself
-        // matter), for non-inlined re-exports see #85043.
-        let is_inline = hir_attr_lists(inline::load_attrs(cx, import_id.to_def_id()), sym::doc)
-            .get_word_attr(sym::inline)
-            .is_some()
-            || (is_glob_import(cx.tcx, import_id)
-                && (cx.render_options.document_hidden || !cx.tcx.is_doc_hidden(def_id)));
-        let mut attrs = get_all_import_attributes(cx, import_id, def_id, is_inline);
+    let attrs = if !import_ids.is_empty() {
+        let mut attrs = Vec::with_capacity(import_ids.len());
+        let mut is_inline = false;
+
+        for import_id in import_ids.iter().copied() {
+            // glob reexports are treated the same as `#[doc(inline)]` items.
+            //
+            // For glob re-exports the item may or may not exist to be re-exported (potentially the
+            // cfgs on the path up until the glob can be removed, and only cfgs on the globbed item
+            // itself matter), for non-inlined re-exports see #85043.
+            let import_is_inline =
+                hir_attr_lists(inline::load_attrs(cx, import_id.to_def_id()), sym::doc)
+                    .get_word_attr(sym::inline)
+                    .is_some()
+                    || (is_glob_import(cx.tcx, import_id)
+                        && (cx.render_options.document_hidden || !cx.tcx.is_doc_hidden(def_id)));
+            attrs.extend(get_all_import_attributes(cx, import_id, def_id, is_inline));
+            is_inline = is_inline || import_is_inline;
+        }
         add_without_unwanted_attributes(&mut attrs, target_attrs, is_inline, None);
         attrs
     } else {
@@ -216,7 +223,8 @@ fn generate_item_with_correct_attrs(
 
     let name = renamed.or(Some(name));
     let mut item = Item::from_def_id_and_attrs_and_parts(def_id, name, kind, attrs, cfg);
-    item.inner.inline_stmt_id = import_id;
+    // FIXME (GuillaumeGomez): Should we also make `inline_stmt_id` a `Vec` instead of an `Option`?
+    item.inner.inline_stmt_id = import_ids.first().copied();
     item
 }
 
@@ -2754,7 +2762,7 @@ fn clean_maybe_renamed_item<'tcx>(
     cx: &mut DocContext<'tcx>,
     item: &hir::Item<'tcx>,
     renamed: Option<Symbol>,
-    import_id: Option<LocalDefId>,
+    import_ids: &[LocalDefId],
 ) -> Vec<Item> {
     use hir::ItemKind;
     fn get_name(
@@ -2825,7 +2833,7 @@ fn clean_maybe_renamed_item<'tcx>(
                     })),
                     item.owner_id.def_id.to_def_id(),
                     name,
-                    import_id,
+                    import_ids,
                     renamed,
                 ));
                 return ret;
@@ -2880,7 +2888,7 @@ fn clean_maybe_renamed_item<'tcx>(
             kind,
             item.owner_id.def_id.to_def_id(),
             name,
-            import_id,
+            import_ids,
             renamed,
         )]
     })
@@ -3151,7 +3159,7 @@ fn clean_maybe_renamed_foreign_item<'tcx>(
             kind,
             item.owner_id.def_id.to_def_id(),
             item.ident.name,
-            import_id,
+            import_id.as_slice(),
             renamed,
         )
     })
diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs
index 2889bfae7b0..2784d7c761a 100644
--- a/src/librustdoc/visit_ast.rs
+++ b/src/librustdoc/visit_ast.rs
@@ -32,11 +32,29 @@ pub(crate) struct Module<'hir> {
     pub(crate) def_id: LocalDefId,
     pub(crate) renamed: Option<Symbol>,
     pub(crate) import_id: Option<LocalDefId>,
-    /// The key is the item `ItemId` and the value is: (item, renamed, import_id).
+    /// The key is the item `ItemId` and the value is: (item, renamed, Vec<import_id>).
     /// We use `FxIndexMap` to keep the insert order.
+    ///
+    /// `import_id` needs to be a `Vec` because we live in a dark world where you can have code
+    /// like:
+    ///
+    /// ```
+    /// mod raw {
+    ///     pub fn foo() {}
+    /// }
+    ///
+    /// /// Foobar
+    /// pub use raw::foo;
+    ///
+    /// pub use raw::*;
+    /// ```
+    ///
+    /// So in this case, we don't want to have two items but just one with attributes from all
+    /// non-glob imports to be merged. Glob imports attributes are always ignored, whether they're
+    /// shadowed or not.
     pub(crate) items: FxIndexMap<
         (LocalDefId, Option<Symbol>),
-        (&'hir hir::Item<'hir>, Option<Symbol>, Option<LocalDefId>),
+        (&'hir hir::Item<'hir>, Option<Symbol>, Vec<LocalDefId>),
     >,
 
     /// (def_id, renamed) -> (res, local_import_id)
@@ -154,7 +172,9 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
             {
                 let item = self.cx.tcx.hir_expect_item(local_def_id);
                 let (ident, _, _) = item.expect_macro();
-                top_level_module.items.insert((local_def_id, Some(ident.name)), (item, None, None));
+                top_level_module
+                    .items
+                    .insert((local_def_id, Some(ident.name)), (item, None, Vec::new()));
             }
         }
 
@@ -236,7 +256,6 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
     ) -> bool {
         debug!("maybe_inline_local (renamed: {renamed:?}) res: {res:?}");
 
-        let glob = renamed.is_none();
         if renamed == Some(kw::Underscore) {
             // We never inline `_` reexports.
             return false;
@@ -261,6 +280,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
             return false;
         }
 
+        let is_glob = renamed.is_none();
         let is_hidden = !document_hidden && tcx.is_doc_hidden(ori_res_did);
         let Some(res_did) = ori_res_did.as_local() else {
             // For cross-crate impl inlining we need to know whether items are
@@ -268,7 +288,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
             // made reachable by cross-crate inlining which we're checking here.
             // (this is done here because we need to know this upfront).
             crate::visit_lib::lib_embargo_visit_item(self.cx, ori_res_did);
-            if is_hidden || glob {
+            if is_hidden || is_glob {
                 return false;
             }
             // We store inlined foreign items otherwise, it'd mean that the `use` item would be kept
@@ -316,10 +336,10 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
             // Bang macros are handled a bit on their because of how they are handled by the
             // compiler. If they have `#[doc(hidden)]` and the re-export doesn't have
             // `#[doc(inline)]`, then we don't inline it.
-            Node::Item(_) if is_bang_macro && !please_inline && renamed.is_some() && is_hidden => {
+            Node::Item(_) if is_bang_macro && !please_inline && !is_glob && is_hidden => {
                 return false;
             }
-            Node::Item(&hir::Item { kind: hir::ItemKind::Mod(_, m), .. }) if glob => {
+            Node::Item(&hir::Item { kind: hir::ItemKind::Mod(_, m), .. }) if is_glob => {
                 let prev = mem::replace(&mut self.inlining, true);
                 for &i in m.item_ids {
                     let i = tcx.hir_item(i);
@@ -328,13 +348,13 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
                 self.inlining = prev;
                 true
             }
-            Node::Item(it) if !glob => {
+            Node::Item(it) if !is_glob => {
                 let prev = mem::replace(&mut self.inlining, true);
                 self.visit_item_inner(it, renamed, Some(def_id));
                 self.inlining = prev;
                 true
             }
-            Node::ForeignItem(it) if !glob => {
+            Node::ForeignItem(it) if !is_glob => {
                 let prev = mem::replace(&mut self.inlining, true);
                 self.visit_foreign_item_inner(it, renamed, Some(def_id));
                 self.inlining = prev;
@@ -378,8 +398,8 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
     fn add_to_current_mod(
         &mut self,
         item: &'tcx hir::Item<'_>,
-        renamed: Option<Symbol>,
-        parent_id: Option<LocalDefId>,
+        mut renamed: Option<Symbol>,
+        import_id: Option<LocalDefId>,
     ) {
         if self.is_importable_from_parent
             // If we're inside an item, only impl blocks and `macro_rules!` with the `macro_export`
@@ -392,11 +412,21 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
                 _ => false,
             }
         {
-            self.modules
-                .last_mut()
-                .unwrap()
-                .items
-                .insert((item.owner_id.def_id, renamed), (item, renamed, parent_id));
+            if renamed == item.kind.ident().map(|ident| ident.name) {
+                renamed = None;
+            }
+            let key = (item.owner_id.def_id, renamed);
+            if let Some(import_id) = import_id {
+                self.modules
+                    .last_mut()
+                    .unwrap()
+                    .items
+                    .entry(key)
+                    .and_modify(|v| v.2.push(import_id))
+                    .or_insert_with(|| (item, renamed, vec![import_id]));
+            } else {
+                self.modules.last_mut().unwrap().items.insert(key, (item, renamed, Vec::new()));
+            }
         }
     }
 
@@ -468,7 +498,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
                             _ => false,
                         });
                         let ident = match kind {
-                            hir::UseKind::Single(ident) => Some(renamed.unwrap_or(ident.name)),
+                            hir::UseKind::Single(ident) => Some(ident.name),
                             hir::UseKind::Glob => None,
                             hir::UseKind::ListStem => unreachable!(),
                         };
diff --git a/tests/assembly/emit-intel-att-syntax.rs b/tests/assembly/emit-intel-att-syntax.rs
new file mode 100644
index 00000000000..7b479a0f79e
--- /dev/null
+++ b/tests/assembly/emit-intel-att-syntax.rs
@@ -0,0 +1,75 @@
+//@ assembly-output: emit-asm
+//@ revisions: att intel
+//@ [att] compile-flags: -Cllvm-args=-x86-asm-syntax=att
+//@ [intel] compile-flags: -Cllvm-args=-x86-asm-syntax=intel
+//@ only-x86_64
+
+#![crate_type = "lib"]
+
+// CHECK-LABEL: naked_att:
+// intel-CHECK: mov rax, qword ptr [rdi]
+// intel-CHECK: ret
+// att-CHECK: movq (%rdi), %rax
+// att-CHECK: retq
+
+#[unsafe(naked)]
+#[unsafe(no_mangle)]
+extern "sysv64" fn naked_att() {
+    std::arch::naked_asm!(
+        "
+        movq (%rdi), %rax
+        retq
+        ",
+        options(att_syntax),
+    );
+}
+
+// CHECK-LABEL: naked_intel:
+// intel-CHECK: mov rax, rdi
+// intel-CHECK: ret
+// att-CHECK: movq (%rdi), %rax
+// att-CHECK: retq
+
+#[unsafe(naked)]
+#[unsafe(no_mangle)]
+extern "sysv64" fn naked_intel() {
+    std::arch::naked_asm!(
+        "
+        mov rax, rdi
+        ret
+        ",
+        options(),
+    );
+}
+
+// CHECK-LABEL: global_att:
+// intel-CHECK: mov rax, rdi
+// intel-CHECK: ret
+// att-CHECK: movq (%rdi), %rax
+// att-CHECK: retq
+
+core::arch::global_asm!(
+    "
+    .globl global_att
+    global_att:
+        movq (%rdi), %rax
+        retq
+    ",
+    options(att_syntax),
+);
+
+// CHECK-LABEL: global_intel:
+// intel-CHECK: mov rax, rdi
+// intel-CHECK: ret
+// att-CHECK: movq (%rdi), %rax
+// att-CHECK: retq
+
+core::arch::global_asm!(
+    "
+    .globl global_intel
+    global_intel:
+        mov rax, rdi
+        ret
+    ",
+    options(),
+);
diff --git a/tests/rustdoc-json/visibility/doc_hidden_default.rs b/tests/rustdoc-json/visibility/doc_hidden_default.rs
new file mode 100644
index 00000000000..3fa91b3c4ad
--- /dev/null
+++ b/tests/rustdoc-json/visibility/doc_hidden_default.rs
@@ -0,0 +1,19 @@
+#![no_std]
+
+// Without `--document-hidden-items`,
+// none of these items are present in rustdoc JSON.
+
+//@ !has "$.index[?(@.name=='func')]"
+#[doc(hidden)]
+pub fn func() {}
+
+//@ !has "$.index[?(@.name=='Unit')]"
+#[doc(hidden)]
+pub struct Unit;
+
+//@ !has "$.index[?(@.name=='hidden')]"
+#[doc(hidden)]
+pub mod hidden {
+    //@ !has "$.index[?(@.name=='Inner')]"
+    pub struct Inner;
+}
diff --git a/tests/rustdoc-json/visibility/doc_hidden_documented.rs b/tests/rustdoc-json/visibility/doc_hidden_documented.rs
new file mode 100644
index 00000000000..6e9ef48680b
--- /dev/null
+++ b/tests/rustdoc-json/visibility/doc_hidden_documented.rs
@@ -0,0 +1,17 @@
+//@ compile-flags: --document-hidden-items
+#![no_std]
+
+//@ is "$.index[?(@.name=='func')].attrs" '["#[doc(hidden)]"]'
+#[doc(hidden)]
+pub fn func() {}
+
+//@ is "$.index[?(@.name=='Unit')].attrs" '["#[doc(hidden)]"]'
+#[doc(hidden)]
+pub struct Unit;
+
+//@ is "$.index[?(@.name=='hidden')].attrs" '["#[doc(hidden)]"]'
+#[doc(hidden)]
+pub mod hidden {
+    //@ is "$.index[?(@.name=='Inner')].attrs" '[]'
+    pub struct Inner;
+}
diff --git a/tests/rustdoc/reexport/merge-glob-and-non-glob.rs b/tests/rustdoc/reexport/merge-glob-and-non-glob.rs
new file mode 100644
index 00000000000..ff67859cb39
--- /dev/null
+++ b/tests/rustdoc/reexport/merge-glob-and-non-glob.rs
@@ -0,0 +1,41 @@
+// This test ensures that if an item is inlined from two different `use`,
+// then it will use attributes from both of them.
+// This is a regression test for <https://github.com/rust-lang/rust/issues/143107>.
+
+#![feature(no_core)]
+#![no_core]
+#![no_std]
+#![crate_name = "foo"]
+
+// First we ensure we only have two items.
+//@ has 'foo/index.html'
+//@ count - '//dl[@class="item-table"]/dt' 2
+// We should also only have one section (Structs).
+//@ count - '//h2[@class="section-header"]' 1
+// We now check the short docs.
+//@ has - '//dl[@class="item-table"]/dd' 'Foobar Blob'
+//@ has - '//dl[@class="item-table"]/dd' 'Tarte Tatin'
+
+//@ has 'foo/struct.Foo.html'
+//@ has - '//*[@class="docblock"]' 'Foobar Blob'
+
+//@ has 'foo/struct.Another.html'
+//@ has - '//*[@class="docblock"]' 'Tarte Tatin'
+
+mod raw {
+    /// Blob
+    pub struct Foo;
+
+    /// Tatin
+    pub struct Another;
+}
+
+/// Foobar
+pub use raw::Foo;
+
+// Glob reexport attributes are ignored.
+/// Baz
+pub use raw::*;
+
+/// Tarte
+pub use raw::Another as Another;
diff --git a/tests/ui/consts/fn_trait_refs.stderr b/tests/ui/consts/fn_trait_refs.stderr
index 445dd75f824..bbe0714801c 100644
--- a/tests/ui/consts/fn_trait_refs.stderr
+++ b/tests/ui/consts/fn_trait_refs.stderr
@@ -4,151 +4,6 @@ error[E0635]: unknown feature `const_fn_trait_ref_impls`
 LL | #![feature(const_fn_trait_ref_impls)]
    |            ^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: `[const]` can only be applied to `#[const_trait]` traits
-  --> $DIR/fn_trait_refs.rs:14:8
-   |
-LL |     T: [const] Fn<()> + [const] Destruct,
-   |        ^^^^^^^ can't be applied to `Fn`
-   |
-note: `Fn` can't be used with `[const]` because it isn't annotated with `#[const_trait]`
-  --> $SRC_DIR/core/src/ops/function.rs:LL:COL
-
-error: `[const]` can only be applied to `#[const_trait]` traits
-  --> $DIR/fn_trait_refs.rs:14:8
-   |
-LL |     T: [const] Fn<()> + [const] Destruct,
-   |        ^^^^^^^ can't be applied to `Fn`
-   |
-note: `Fn` can't be used with `[const]` because it isn't annotated with `#[const_trait]`
-  --> $SRC_DIR/core/src/ops/function.rs:LL:COL
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
-error: `[const]` can only be applied to `#[const_trait]` traits
-  --> $DIR/fn_trait_refs.rs:14:8
-   |
-LL |     T: [const] Fn<()> + [const] Destruct,
-   |        ^^^^^^^ can't be applied to `Fn`
-   |
-note: `Fn` can't be used with `[const]` because it isn't annotated with `#[const_trait]`
-  --> $SRC_DIR/core/src/ops/function.rs:LL:COL
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
-error: `[const]` can only be applied to `#[const_trait]` traits
-  --> $DIR/fn_trait_refs.rs:21:8
-   |
-LL |     T: [const] FnMut<()> + [const] Destruct,
-   |        ^^^^^^^ can't be applied to `FnMut`
-   |
-note: `FnMut` can't be used with `[const]` because it isn't annotated with `#[const_trait]`
-  --> $SRC_DIR/core/src/ops/function.rs:LL:COL
-
-error: `[const]` can only be applied to `#[const_trait]` traits
-  --> $DIR/fn_trait_refs.rs:21:8
-   |
-LL |     T: [const] FnMut<()> + [const] Destruct,
-   |        ^^^^^^^ can't be applied to `FnMut`
-   |
-note: `FnMut` can't be used with `[const]` because it isn't annotated with `#[const_trait]`
-  --> $SRC_DIR/core/src/ops/function.rs:LL:COL
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
-error: `[const]` can only be applied to `#[const_trait]` traits
-  --> $DIR/fn_trait_refs.rs:21:8
-   |
-LL |     T: [const] FnMut<()> + [const] Destruct,
-   |        ^^^^^^^ can't be applied to `FnMut`
-   |
-note: `FnMut` can't be used with `[const]` because it isn't annotated with `#[const_trait]`
-  --> $SRC_DIR/core/src/ops/function.rs:LL:COL
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
-error: `[const]` can only be applied to `#[const_trait]` traits
-  --> $DIR/fn_trait_refs.rs:28:8
-   |
-LL |     T: [const] FnOnce<()>,
-   |        ^^^^^^^ can't be applied to `FnOnce`
-   |
-note: `FnOnce` can't be used with `[const]` because it isn't annotated with `#[const_trait]`
-  --> $SRC_DIR/core/src/ops/function.rs:LL:COL
-
-error: `[const]` can only be applied to `#[const_trait]` traits
-  --> $DIR/fn_trait_refs.rs:28:8
-   |
-LL |     T: [const] FnOnce<()>,
-   |        ^^^^^^^ can't be applied to `FnOnce`
-   |
-note: `FnOnce` can't be used with `[const]` because it isn't annotated with `#[const_trait]`
-  --> $SRC_DIR/core/src/ops/function.rs:LL:COL
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
-error: `[const]` can only be applied to `#[const_trait]` traits
-  --> $DIR/fn_trait_refs.rs:28:8
-   |
-LL |     T: [const] FnOnce<()>,
-   |        ^^^^^^^ can't be applied to `FnOnce`
-   |
-note: `FnOnce` can't be used with `[const]` because it isn't annotated with `#[const_trait]`
-  --> $SRC_DIR/core/src/ops/function.rs:LL:COL
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
-error: `[const]` can only be applied to `#[const_trait]` traits
-  --> $DIR/fn_trait_refs.rs:35:8
-   |
-LL |     T: [const] Fn<()> + [const] Destruct,
-   |        ^^^^^^^ can't be applied to `Fn`
-   |
-note: `Fn` can't be used with `[const]` because it isn't annotated with `#[const_trait]`
-  --> $SRC_DIR/core/src/ops/function.rs:LL:COL
-
-error: `[const]` can only be applied to `#[const_trait]` traits
-  --> $DIR/fn_trait_refs.rs:35:8
-   |
-LL |     T: [const] Fn<()> + [const] Destruct,
-   |        ^^^^^^^ can't be applied to `Fn`
-   |
-note: `Fn` can't be used with `[const]` because it isn't annotated with `#[const_trait]`
-  --> $SRC_DIR/core/src/ops/function.rs:LL:COL
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
-error: `[const]` can only be applied to `#[const_trait]` traits
-  --> $DIR/fn_trait_refs.rs:35:8
-   |
-LL |     T: [const] Fn<()> + [const] Destruct,
-   |        ^^^^^^^ can't be applied to `Fn`
-   |
-note: `Fn` can't be used with `[const]` because it isn't annotated with `#[const_trait]`
-  --> $SRC_DIR/core/src/ops/function.rs:LL:COL
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
-error: `[const]` can only be applied to `#[const_trait]` traits
-  --> $DIR/fn_trait_refs.rs:49:8
-   |
-LL |     T: [const] FnMut<()> + [const] Destruct,
-   |        ^^^^^^^ can't be applied to `FnMut`
-   |
-note: `FnMut` can't be used with `[const]` because it isn't annotated with `#[const_trait]`
-  --> $SRC_DIR/core/src/ops/function.rs:LL:COL
-
-error: `[const]` can only be applied to `#[const_trait]` traits
-  --> $DIR/fn_trait_refs.rs:49:8
-   |
-LL |     T: [const] FnMut<()> + [const] Destruct,
-   |        ^^^^^^^ can't be applied to `FnMut`
-   |
-note: `FnMut` can't be used with `[const]` because it isn't annotated with `#[const_trait]`
-  --> $SRC_DIR/core/src/ops/function.rs:LL:COL
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
-error: `[const]` can only be applied to `#[const_trait]` traits
-  --> $DIR/fn_trait_refs.rs:49:8
-   |
-LL |     T: [const] FnMut<()> + [const] Destruct,
-   |        ^^^^^^^ can't be applied to `FnMut`
-   |
-note: `FnMut` can't be used with `[const]` because it isn't annotated with `#[const_trait]`
-  --> $SRC_DIR/core/src/ops/function.rs:LL:COL
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
 error[E0277]: the trait bound `(i32, i32, i32): const PartialEq` is not satisfied
   --> $DIR/fn_trait_refs.rs:71:17
    |
@@ -161,31 +16,7 @@ error[E0277]: the trait bound `(i32, i32): const PartialEq` is not satisfied
 LL |         assert!(test_two == (2, 2));
    |                 ^^^^^^^^^^^^^^^^^^
 
-error[E0015]: cannot call non-const closure in constant functions
-  --> $DIR/fn_trait_refs.rs:16:5
-   |
-LL |     f()
-   |     ^^^
-   |
-   = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
-
-error[E0015]: cannot call non-const closure in constant functions
-  --> $DIR/fn_trait_refs.rs:23:5
-   |
-LL |     f()
-   |     ^^^
-   |
-   = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
-
-error[E0015]: cannot call non-const closure in constant functions
-  --> $DIR/fn_trait_refs.rs:30:5
-   |
-LL |     f()
-   |     ^^^
-   |
-   = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
-
-error: aborting due to 21 previous errors
+error: aborting due to 3 previous errors
 
-Some errors have detailed explanations: E0015, E0277, E0635.
-For more information about an error, try `rustc --explain E0015`.
+Some errors have detailed explanations: E0277, E0635.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/tests/ui/consts/unstable-const-fn-in-libcore.stderr b/tests/ui/consts/unstable-const-fn-in-libcore.stderr
index 95e48b7b7c8..16db7791cd8 100644
--- a/tests/ui/consts/unstable-const-fn-in-libcore.stderr
+++ b/tests/ui/consts/unstable-const-fn-in-libcore.stderr
@@ -1,30 +1,3 @@
-error: `[const]` can only be applied to `#[const_trait]` traits
-  --> $DIR/unstable-const-fn-in-libcore.rs:19:32
-   |
-LL |     const fn unwrap_or_else<F: [const] FnOnce() -> T>(self, f: F) -> T {
-   |                                ^^^^^^^ can't be applied to `FnOnce`
-   |
-note: `FnOnce` can't be used with `[const]` because it isn't annotated with `#[const_trait]`
-  --> $SRC_DIR/core/src/ops/function.rs:LL:COL
-
-error: `[const]` can only be applied to `#[const_trait]` traits
-  --> $DIR/unstable-const-fn-in-libcore.rs:19:32
-   |
-LL |     const fn unwrap_or_else<F: [const] FnOnce() -> T>(self, f: F) -> T {
-   |                                ^^^^^^^ can't be applied to `FnOnce`
-   |
-note: `FnOnce` can't be used with `[const]` because it isn't annotated with `#[const_trait]`
-  --> $SRC_DIR/core/src/ops/function.rs:LL:COL
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
-error[E0015]: cannot call non-const closure in constant functions
-  --> $DIR/unstable-const-fn-in-libcore.rs:24:26
-   |
-LL |             Opt::None => f(),
-   |                          ^^^
-   |
-   = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
-
 error[E0493]: destructor of `F` cannot be evaluated at compile-time
   --> $DIR/unstable-const-fn-in-libcore.rs:19:61
    |
@@ -43,7 +16,6 @@ LL |     const fn unwrap_or_else<F: [const] FnOnce() -> T>(self, f: F) -> T {
 LL |     }
    |     - value is dropped here
 
-error: aborting due to 5 previous errors
+error: aborting due to 2 previous errors
 
-Some errors have detailed explanations: E0015, E0493.
-For more information about an error, try `rustc --explain E0015`.
+For more information about this error, try `rustc --explain E0493`.
diff --git a/tests/ui/impl-trait/normalize-tait-in-const.stderr b/tests/ui/impl-trait/normalize-tait-in-const.stderr
index e17737d1860..051eb62d9cb 100644
--- a/tests/ui/impl-trait/normalize-tait-in-const.stderr
+++ b/tests/ui/impl-trait/normalize-tait-in-const.stderr
@@ -1,22 +1,3 @@
-error: `[const]` can only be applied to `#[const_trait]` traits
-  --> $DIR/normalize-tait-in-const.rs:27:35
-   |
-LL | const fn with_positive<F: for<'a> [const] Fn(&'a Alias<'a>) + [const] Destruct>(fun: F) {
-   |                                   ^^^^^^^ can't be applied to `Fn`
-   |
-note: `Fn` can't be used with `[const]` because it isn't annotated with `#[const_trait]`
-  --> $SRC_DIR/core/src/ops/function.rs:LL:COL
-
-error: `[const]` can only be applied to `#[const_trait]` traits
-  --> $DIR/normalize-tait-in-const.rs:27:35
-   |
-LL | const fn with_positive<F: for<'a> [const] Fn(&'a Alias<'a>) + [const] Destruct>(fun: F) {
-   |                                   ^^^^^^^ can't be applied to `Fn`
-   |
-note: `Fn` can't be used with `[const]` because it isn't annotated with `#[const_trait]`
-  --> $SRC_DIR/core/src/ops/function.rs:LL:COL
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
 error: unconstrained opaque type
   --> $DIR/normalize-tait-in-const.rs:14:26
    |
@@ -44,15 +25,6 @@ note: this item must have a `#[define_opaque(foo::Alias)]` attribute to be able
 LL |     pub const fn filter_positive<'a>() -> &'a Alias<'a> {
    |                  ^^^^^^^^^^^^^^^
 
-error[E0015]: cannot call non-const closure in constant functions
-  --> $DIR/normalize-tait-in-const.rs:28:5
-   |
-LL |     fun(filter_positive());
-   |     ^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
-
-error: aborting due to 5 previous errors
+error: aborting due to 2 previous errors
 
-Some errors have detailed explanations: E0015, E0308.
-For more information about an error, try `rustc --explain E0015`.
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/intrinsics/const-eval-select-bad.rs b/tests/ui/intrinsics/const-eval-select-bad.rs
index 3365d57af7c..f4071251299 100644
--- a/tests/ui/intrinsics/const-eval-select-bad.rs
+++ b/tests/ui/intrinsics/const-eval-select-bad.rs
@@ -5,13 +5,10 @@ use std::intrinsics::const_eval_select;
 
 const fn not_fn_items() {
     const_eval_select((), || {}, || {});
-    //~^ ERROR this argument must be a function item
-    //~| ERROR this argument must be a function item
+    //~^ ERROR const FnOnce()` is not satisfied
     const_eval_select((), 42, 0xDEADBEEF);
     //~^ ERROR expected a `FnOnce()` closure
     //~| ERROR expected a `FnOnce()` closure
-    //~| ERROR this argument must be a function item
-    //~| ERROR this argument must be a function item
 }
 
 const fn foo(n: i32) -> i32 {
@@ -40,7 +37,7 @@ const fn args_ty_mismatch() {
 
 const fn non_const_fn() {
     const_eval_select((1,), bar, bar);
-    //~^ ERROR this argument must be a `const fn`
+    //~^ ERROR the trait bound `fn(i32) -> bool {bar}: const FnOnce(i32)` is not satisfied
 }
 
 fn main() {}
diff --git a/tests/ui/intrinsics/const-eval-select-bad.stderr b/tests/ui/intrinsics/const-eval-select-bad.stderr
index bb159bed282..d701f5ea909 100644
--- a/tests/ui/intrinsics/const-eval-select-bad.stderr
+++ b/tests/ui/intrinsics/const-eval-select-bad.stderr
@@ -1,23 +1,16 @@
-error: this argument must be a function item
+error[E0277]: the trait bound `{closure@$DIR/const-eval-select-bad.rs:7:27: 7:29}: const FnOnce()` is not satisfied
   --> $DIR/const-eval-select-bad.rs:7:27
    |
 LL |     const_eval_select((), || {}, || {});
-   |                           ^^^^^
-   |
-   = note: expected a function item, found {closure@$DIR/const-eval-select-bad.rs:7:27: 7:29}
-   = help: consult the documentation on `const_eval_select` for more information
-
-error: this argument must be a function item
-  --> $DIR/const-eval-select-bad.rs:7:34
-   |
-LL |     const_eval_select((), || {}, || {});
-   |                                  ^^^^^
+   |     -----------------     ^^^^^
+   |     |
+   |     required by a bound introduced by this call
    |
-   = note: expected a function item, found {closure@$DIR/const-eval-select-bad.rs:7:34: 7:36}
-   = help: consult the documentation on `const_eval_select` for more information
+note: required by a bound in `const_eval_select`
+  --> $SRC_DIR/core/src/intrinsics/mod.rs:LL:COL
 
 error[E0277]: expected a `FnOnce()` closure, found `{integer}`
-  --> $DIR/const-eval-select-bad.rs:10:27
+  --> $DIR/const-eval-select-bad.rs:9:27
    |
 LL |     const_eval_select((), 42, 0xDEADBEEF);
    |     -----------------     ^^ expected an `FnOnce()` closure, found `{integer}`
@@ -30,7 +23,7 @@ note: required by a bound in `const_eval_select`
   --> $SRC_DIR/core/src/intrinsics/mod.rs:LL:COL
 
 error[E0277]: expected a `FnOnce()` closure, found `{integer}`
-  --> $DIR/const-eval-select-bad.rs:10:31
+  --> $DIR/const-eval-select-bad.rs:9:31
    |
 LL |     const_eval_select((), 42, 0xDEADBEEF);
    |     -----------------         ^^^^^^^^^^ expected an `FnOnce()` closure, found `{integer}`
@@ -42,26 +35,8 @@ LL |     const_eval_select((), 42, 0xDEADBEEF);
 note: required by a bound in `const_eval_select`
   --> $SRC_DIR/core/src/intrinsics/mod.rs:LL:COL
 
-error: this argument must be a function item
-  --> $DIR/const-eval-select-bad.rs:10:27
-   |
-LL |     const_eval_select((), 42, 0xDEADBEEF);
-   |                           ^^
-   |
-   = note: expected a function item, found {integer}
-   = help: consult the documentation on `const_eval_select` for more information
-
-error: this argument must be a function item
-  --> $DIR/const-eval-select-bad.rs:10:31
-   |
-LL |     const_eval_select((), 42, 0xDEADBEEF);
-   |                               ^^^^^^^^^^
-   |
-   = note: expected a function item, found {integer}
-   = help: consult the documentation on `const_eval_select` for more information
-
 error[E0271]: expected `bar` to return `i32`, but it returns `bool`
-  --> $DIR/const-eval-select-bad.rs:32:34
+  --> $DIR/const-eval-select-bad.rs:29:34
    |
 LL |     const_eval_select((1,), foo, bar);
    |     -----------------            ^^^ expected `i32`, found `bool`
@@ -72,7 +47,7 @@ note: required by a bound in `const_eval_select`
   --> $SRC_DIR/core/src/intrinsics/mod.rs:LL:COL
 
 error[E0631]: type mismatch in function arguments
-  --> $DIR/const-eval-select-bad.rs:37:32
+  --> $DIR/const-eval-select-bad.rs:34:32
    |
 LL | const fn foo(n: i32) -> i32 {
    | --------------------------- found signature defined here
@@ -91,15 +66,18 @@ help: consider wrapping the function in a closure
 LL |     const_eval_select((true,), |arg0: bool| foo(/* i32 */), baz);
    |                                ++++++++++++    +++++++++++
 
-error: this argument must be a `const fn`
-  --> $DIR/const-eval-select-bad.rs:42:29
+error[E0277]: the trait bound `fn(i32) -> bool {bar}: const FnOnce(i32)` is not satisfied
+  --> $DIR/const-eval-select-bad.rs:39:29
    |
 LL |     const_eval_select((1,), bar, bar);
-   |                             ^^^
+   |     -----------------       ^^^
+   |     |
+   |     required by a bound introduced by this call
    |
-   = help: consult the documentation on `const_eval_select` for more information
+note: required by a bound in `const_eval_select`
+  --> $SRC_DIR/core/src/intrinsics/mod.rs:LL:COL
 
-error: aborting due to 9 previous errors
+error: aborting due to 6 previous errors
 
 Some errors have detailed explanations: E0271, E0277, E0631.
 For more information about an error, try `rustc --explain E0271`.
diff --git a/tests/ui/linking/export-executable-symbols.rs b/tests/ui/linking/export-executable-symbols.rs
new file mode 100644
index 00000000000..aea5527b6a1
--- /dev/null
+++ b/tests/ui/linking/export-executable-symbols.rs
@@ -0,0 +1,30 @@
+//@ run-pass
+//@ only-linux
+//@ only-gnu
+//@ compile-flags: -Zexport-executable-symbols
+//@ edition: 2024
+
+// Regression test for <https://github.com/rust-lang/rust/issues/101610>.
+
+#![feature(rustc_private)]
+
+extern crate libc;
+
+#[unsafe(no_mangle)]
+fn hack() -> u64 {
+    998244353
+}
+
+fn main() {
+    unsafe {
+        let handle = libc::dlopen(std::ptr::null(), libc::RTLD_NOW);
+        let ptr = libc::dlsym(handle, c"hack".as_ptr());
+        let ptr: Option<unsafe fn() -> u64> = std::mem::transmute(ptr);
+        if let Some(f) = ptr {
+            assert!(f() == 998244353);
+            println!("symbol `hack` is found successfully");
+        } else {
+            panic!("symbol `hack` is not found");
+        }
+    }
+}
diff --git a/tests/ui/traits/const-traits/call.rs b/tests/ui/traits/const-traits/call.rs
index b985e3da345..b1080fe78bb 100644
--- a/tests/ui/traits/const-traits/call.rs
+++ b/tests/ui/traits/const-traits/call.rs
@@ -5,7 +5,7 @@
 
 pub const _: () = {
     assert!((const || true)());
-    //~^ ERROR cannot call non-const closure in constants
+    //~^ ERROR }: [const] Fn()` is not satisfied
 };
 
 fn main() {}
diff --git a/tests/ui/traits/const-traits/call.stderr b/tests/ui/traits/const-traits/call.stderr
index e9bf64092f3..8e32cab6dfc 100644
--- a/tests/ui/traits/const-traits/call.stderr
+++ b/tests/ui/traits/const-traits/call.stderr
@@ -1,12 +1,9 @@
-error[E0015]: cannot call non-const closure in constants
+error[E0277]: the trait bound `{closure@$DIR/call.rs:7:14: 7:22}: [const] Fn()` is not satisfied
   --> $DIR/call.rs:7:13
    |
 LL |     assert!((const || true)());
    |             ^^^^^^^^^^^^^^^^^
-   |
-   = note: closures need an RFC before allowed to be called in constants
-   = note: calls in constants are limited to constant functions, tuple structs and tuple variants
 
 error: aborting due to 1 previous error
 
-For more information about this error, try `rustc --explain E0015`.
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/const-traits/const-closure-parse-not-item.stderr b/tests/ui/traits/const-traits/const-closure-parse-not-item.stderr
index fdfe3b95d55..1d8d5ff1b4f 100644
--- a/tests/ui/traits/const-traits/const-closure-parse-not-item.stderr
+++ b/tests/ui/traits/const-traits/const-closure-parse-not-item.stderr
@@ -1,31 +1,9 @@
-error: `[const]` can only be applied to `#[const_trait]` traits
-  --> $DIR/const-closure-parse-not-item.rs:7:25
+error[E0277]: the trait bound `{closure@$DIR/const-closure-parse-not-item.rs:8:5: 8:18}: [const] Fn()` is not satisfied
+  --> $DIR/const-closure-parse-not-item.rs:7:20
    |
 LL | const fn test() -> impl [const] Fn() {
-   |                         ^^^^^^^ can't be applied to `Fn`
-   |
-note: `Fn` can't be used with `[const]` because it isn't annotated with `#[const_trait]`
-  --> $SRC_DIR/core/src/ops/function.rs:LL:COL
-
-error: `[const]` can only be applied to `#[const_trait]` traits
-  --> $DIR/const-closure-parse-not-item.rs:7:25
-   |
-LL | const fn test() -> impl [const] Fn() {
-   |                         ^^^^^^^ can't be applied to `Fn`
-   |
-note: `Fn` can't be used with `[const]` because it isn't annotated with `#[const_trait]`
-  --> $SRC_DIR/core/src/ops/function.rs:LL:COL
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
-error: `[const]` can only be applied to `#[const_trait]` traits
-  --> $DIR/const-closure-parse-not-item.rs:7:25
-   |
-LL | const fn test() -> impl [const] Fn() {
-   |                         ^^^^^^^ can't be applied to `Fn`
-   |
-note: `Fn` can't be used with `[const]` because it isn't annotated with `#[const_trait]`
-  --> $SRC_DIR/core/src/ops/function.rs:LL:COL
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+   |                    ^^^^^^^^^^^^^^^^^
 
-error: aborting due to 3 previous errors
+error: aborting due to 1 previous error
 
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/const-traits/const-closure-trait-method-fail.stderr b/tests/ui/traits/const-traits/const-closure-trait-method-fail.stderr
index 89b202b3438..fddd8d10bcc 100644
--- a/tests/ui/traits/const-traits/const-closure-trait-method-fail.stderr
+++ b/tests/ui/traits/const-traits/const-closure-trait-method-fail.stderr
@@ -1,30 +1,9 @@
-error: `[const]` can only be applied to `#[const_trait]` traits
-  --> $DIR/const-closure-trait-method-fail.rs:14:32
+error[E0277]: the trait bound `(): const Tr` is not satisfied
+  --> $DIR/const-closure-trait-method-fail.rs:18:23
    |
-LL | const fn need_const_closure<T: [const] FnOnce(()) -> i32>(x: T) -> i32 {
-   |                                ^^^^^^^ can't be applied to `FnOnce`
-   |
-note: `FnOnce` can't be used with `[const]` because it isn't annotated with `#[const_trait]`
-  --> $SRC_DIR/core/src/ops/function.rs:LL:COL
-
-error: `[const]` can only be applied to `#[const_trait]` traits
-  --> $DIR/const-closure-trait-method-fail.rs:14:32
-   |
-LL | const fn need_const_closure<T: [const] FnOnce(()) -> i32>(x: T) -> i32 {
-   |                                ^^^^^^^ can't be applied to `FnOnce`
-   |
-note: `FnOnce` can't be used with `[const]` because it isn't annotated with `#[const_trait]`
-  --> $SRC_DIR/core/src/ops/function.rs:LL:COL
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
-error[E0015]: cannot call non-const closure in constant functions
-  --> $DIR/const-closure-trait-method-fail.rs:15:5
-   |
-LL |     x(())
-   |     ^^^^^
-   |
-   = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
+LL | const _: () = assert!(need_const_closure(Tr::a) == 42);
+   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 3 previous errors
+error: aborting due to 1 previous error
 
-For more information about this error, try `rustc --explain E0015`.
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/const-traits/const-closure-trait-method.rs b/tests/ui/traits/const-traits/const-closure-trait-method.rs
index 831d6e27946..6477aa63c68 100644
--- a/tests/ui/traits/const-traits/const-closure-trait-method.rs
+++ b/tests/ui/traits/const-traits/const-closure-trait-method.rs
@@ -1,5 +1,6 @@
-//@ known-bug: #110395
-// FIXME check-pass
+//@ check-pass
+//@ revisions: next old
+//@[next] compile-flags: -Znext-solver
 #![feature(const_trait_impl)]
 
 #[const_trait]
diff --git a/tests/ui/traits/const-traits/const-closure-trait-method.stderr b/tests/ui/traits/const-traits/const-closure-trait-method.stderr
deleted file mode 100644
index 6de25dc11ef..00000000000
--- a/tests/ui/traits/const-traits/const-closure-trait-method.stderr
+++ /dev/null
@@ -1,30 +0,0 @@
-error: `[const]` can only be applied to `#[const_trait]` traits
-  --> $DIR/const-closure-trait-method.rs:14:32
-   |
-LL | const fn need_const_closure<T: [const] FnOnce(()) -> i32>(x: T) -> i32 {
-   |                                ^^^^^^^ can't be applied to `FnOnce`
-   |
-note: `FnOnce` can't be used with `[const]` because it isn't annotated with `#[const_trait]`
-  --> $SRC_DIR/core/src/ops/function.rs:LL:COL
-
-error: `[const]` can only be applied to `#[const_trait]` traits
-  --> $DIR/const-closure-trait-method.rs:14:32
-   |
-LL | const fn need_const_closure<T: [const] FnOnce(()) -> i32>(x: T) -> i32 {
-   |                                ^^^^^^^ can't be applied to `FnOnce`
-   |
-note: `FnOnce` can't be used with `[const]` because it isn't annotated with `#[const_trait]`
-  --> $SRC_DIR/core/src/ops/function.rs:LL:COL
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
-error[E0015]: cannot call non-const closure in constant functions
-  --> $DIR/const-closure-trait-method.rs:15:5
-   |
-LL |     x(())
-   |     ^^^^^
-   |
-   = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
-
-error: aborting due to 3 previous errors
-
-For more information about this error, try `rustc --explain E0015`.
diff --git a/tests/ui/traits/const-traits/const-closures.rs b/tests/ui/traits/const-traits/const-closures.rs
index 2f6f4dc4ba3..8f1c018ca5d 100644
--- a/tests/ui/traits/const-traits/const-closures.rs
+++ b/tests/ui/traits/const-traits/const-closures.rs
@@ -1,5 +1,6 @@
-//@ known-bug: #110395
-// FIXME check-pass
+//@ check-pass
+//@ revisions: next old
+//@[next] compile-flags: -Znext-solver
 
 #![feature(const_trait_impl)]
 
diff --git a/tests/ui/traits/const-traits/const-closures.stderr b/tests/ui/traits/const-traits/const-closures.stderr
deleted file mode 100644
index 19869b47085..00000000000
--- a/tests/ui/traits/const-traits/const-closures.stderr
+++ /dev/null
@@ -1,103 +0,0 @@
-error: `[const]` can only be applied to `#[const_trait]` traits
-  --> $DIR/const-closures.rs:8:12
-   |
-LL |         F: [const] FnOnce() -> u8,
-   |            ^^^^^^^ can't be applied to `FnOnce`
-   |
-note: `FnOnce` can't be used with `[const]` because it isn't annotated with `#[const_trait]`
-  --> $SRC_DIR/core/src/ops/function.rs:LL:COL
-
-error: `[const]` can only be applied to `#[const_trait]` traits
-  --> $DIR/const-closures.rs:9:12
-   |
-LL |         F: [const] FnMut() -> u8,
-   |            ^^^^^^^ can't be applied to `FnMut`
-   |
-note: `FnMut` can't be used with `[const]` because it isn't annotated with `#[const_trait]`
-  --> $SRC_DIR/core/src/ops/function.rs:LL:COL
-
-error: `[const]` can only be applied to `#[const_trait]` traits
-  --> $DIR/const-closures.rs:10:12
-   |
-LL |         F: [const] Fn() -> u8,
-   |            ^^^^^^^ can't be applied to `Fn`
-   |
-note: `Fn` can't be used with `[const]` because it isn't annotated with `#[const_trait]`
-  --> $SRC_DIR/core/src/ops/function.rs:LL:COL
-
-error: `[const]` can only be applied to `#[const_trait]` traits
-  --> $DIR/const-closures.rs:8:12
-   |
-LL |         F: [const] FnOnce() -> u8,
-   |            ^^^^^^^ can't be applied to `FnOnce`
-   |
-note: `FnOnce` can't be used with `[const]` because it isn't annotated with `#[const_trait]`
-  --> $SRC_DIR/core/src/ops/function.rs:LL:COL
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
-error: `[const]` can only be applied to `#[const_trait]` traits
-  --> $DIR/const-closures.rs:9:12
-   |
-LL |         F: [const] FnMut() -> u8,
-   |            ^^^^^^^ can't be applied to `FnMut`
-   |
-note: `FnMut` can't be used with `[const]` because it isn't annotated with `#[const_trait]`
-  --> $SRC_DIR/core/src/ops/function.rs:LL:COL
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
-error: `[const]` can only be applied to `#[const_trait]` traits
-  --> $DIR/const-closures.rs:10:12
-   |
-LL |         F: [const] Fn() -> u8,
-   |            ^^^^^^^ can't be applied to `Fn`
-   |
-note: `Fn` can't be used with `[const]` because it isn't annotated with `#[const_trait]`
-  --> $SRC_DIR/core/src/ops/function.rs:LL:COL
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
-error: `[const]` can only be applied to `#[const_trait]` traits
-  --> $DIR/const-closures.rs:23:20
-   |
-LL | const fn answer<F: [const] Fn() -> u8>(f: &F) -> u8 {
-   |                    ^^^^^^^ can't be applied to `Fn`
-   |
-note: `Fn` can't be used with `[const]` because it isn't annotated with `#[const_trait]`
-  --> $SRC_DIR/core/src/ops/function.rs:LL:COL
-
-error: `[const]` can only be applied to `#[const_trait]` traits
-  --> $DIR/const-closures.rs:23:20
-   |
-LL | const fn answer<F: [const] Fn() -> u8>(f: &F) -> u8 {
-   |                    ^^^^^^^ can't be applied to `Fn`
-   |
-note: `Fn` can't be used with `[const]` because it isn't annotated with `#[const_trait]`
-  --> $SRC_DIR/core/src/ops/function.rs:LL:COL
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
-error[E0015]: cannot call non-const closure in constant functions
-  --> $DIR/const-closures.rs:24:5
-   |
-LL |     f() + f()
-   |     ^^^
-   |
-   = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
-
-error[E0015]: cannot call non-const closure in constant functions
-  --> $DIR/const-closures.rs:24:11
-   |
-LL |     f() + f()
-   |           ^^^
-   |
-   = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
-
-error[E0015]: cannot call non-const closure in constant functions
-  --> $DIR/const-closures.rs:12:5
-   |
-LL |     f() * 7
-   |     ^^^
-   |
-   = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
-
-error: aborting due to 11 previous errors
-
-For more information about this error, try `rustc --explain E0015`.
diff --git a/tests/ui/traits/const-traits/const_closure-const_trait_impl-ice-113381.rs b/tests/ui/traits/const-traits/const_closure-const_trait_impl-ice-113381.rs
index 92427039b43..30002038f68 100644
--- a/tests/ui/traits/const-traits/const_closure-const_trait_impl-ice-113381.rs
+++ b/tests/ui/traits/const-traits/const_closure-const_trait_impl-ice-113381.rs
@@ -1,3 +1,4 @@
+//@ known-bug: #110395
 //@ compile-flags: -Znext-solver
 #![feature(const_closures, const_trait_impl)]
 #![allow(incomplete_features)]
@@ -11,7 +12,7 @@ impl Foo for () {
 }
 
 fn main() {
-    (const || { (()).foo() })();
-    //~^ ERROR: cannot call non-const method `<() as Foo>::foo` in constant functions
+    (const || (()).foo())();
+    // ^ ERROR: cannot call non-const method `<() as Foo>::foo` in constant functions
     // FIXME(const_trait_impl) this should probably say constant closures
 }
diff --git a/tests/ui/traits/const-traits/const_closure-const_trait_impl-ice-113381.stderr b/tests/ui/traits/const-traits/const_closure-const_trait_impl-ice-113381.stderr
index c08642ba5a3..dab3f14161f 100644
--- a/tests/ui/traits/const-traits/const_closure-const_trait_impl-ice-113381.stderr
+++ b/tests/ui/traits/const-traits/const_closure-const_trait_impl-ice-113381.stderr
@@ -1,11 +1,9 @@
-error[E0015]: cannot call non-const method `<() as Foo>::foo` in constant functions
-  --> $DIR/const_closure-const_trait_impl-ice-113381.rs:14:22
+error[E0277]: the trait bound `{closure@$DIR/const_closure-const_trait_impl-ice-113381.rs:15:6: 15:14}: [const] Fn()` is not satisfied
+  --> $DIR/const_closure-const_trait_impl-ice-113381.rs:15:5
    |
-LL |     (const || { (()).foo() })();
-   |                      ^^^^^
-   |
-   = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
+LL |     (const || (()).foo())();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 1 previous error
 
-For more information about this error, try `rustc --explain E0015`.
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/const-traits/ice-112822-expected-type-for-param.rs b/tests/ui/traits/const-traits/ice-112822-expected-type-for-param.rs
index 026f2c0d603..8ee3db445d0 100644
--- a/tests/ui/traits/const-traits/ice-112822-expected-type-for-param.rs
+++ b/tests/ui/traits/const-traits/ice-112822-expected-type-for-param.rs
@@ -1,16 +1,14 @@
 #![feature(const_trait_impl)]
 
 const fn test() -> impl [const] Fn() {
-    //~^ ERROR `[const]` can only be applied to `#[const_trait]` traits
-    //~| ERROR `[const]` can only be applied to `#[const_trait]` traits
-    //~| ERROR `[const]` can only be applied to `#[const_trait]` traits
+    //~^ ERROR: }: [const] Fn()` is not satisfied
     const move || { //~ ERROR const closures are experimental
         let sl: &[u8] = b"foo";
 
         match sl {
             [first, remainder @ ..] => {
                 assert_eq!(first, &b'f');
-                //~^ ERROR cannot call non-const function
+                // FIXME(const_closures) ^ ERROR cannot call non-const function
             }
             [] => panic!(),
         }
diff --git a/tests/ui/traits/const-traits/ice-112822-expected-type-for-param.stderr b/tests/ui/traits/const-traits/ice-112822-expected-type-for-param.stderr
index 78d7b962cc4..abbe0a0070a 100644
--- a/tests/ui/traits/const-traits/ice-112822-expected-type-for-param.stderr
+++ b/tests/ui/traits/const-traits/ice-112822-expected-type-for-param.stderr
@@ -1,5 +1,5 @@
 error[E0658]: const closures are experimental
-  --> $DIR/ice-112822-expected-type-for-param.rs:7:5
+  --> $DIR/ice-112822-expected-type-for-param.rs:5:5
    |
 LL |     const move || {
    |     ^^^^^
@@ -8,45 +8,13 @@ LL |     const move || {
    = help: add `#![feature(const_closures)]` 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: `[const]` can only be applied to `#[const_trait]` traits
-  --> $DIR/ice-112822-expected-type-for-param.rs:3:25
+error[E0277]: the trait bound `{closure@$DIR/ice-112822-expected-type-for-param.rs:5:5: 5:18}: [const] Fn()` is not satisfied
+  --> $DIR/ice-112822-expected-type-for-param.rs:3:20
    |
 LL | const fn test() -> impl [const] Fn() {
-   |                         ^^^^^^^ can't be applied to `Fn`
-   |
-note: `Fn` can't be used with `[const]` because it isn't annotated with `#[const_trait]`
-  --> $SRC_DIR/core/src/ops/function.rs:LL:COL
-
-error: `[const]` can only be applied to `#[const_trait]` traits
-  --> $DIR/ice-112822-expected-type-for-param.rs:3:25
-   |
-LL | const fn test() -> impl [const] Fn() {
-   |                         ^^^^^^^ can't be applied to `Fn`
-   |
-note: `Fn` can't be used with `[const]` because it isn't annotated with `#[const_trait]`
-  --> $SRC_DIR/core/src/ops/function.rs:LL:COL
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
-error: `[const]` can only be applied to `#[const_trait]` traits
-  --> $DIR/ice-112822-expected-type-for-param.rs:3:25
-   |
-LL | const fn test() -> impl [const] Fn() {
-   |                         ^^^^^^^ can't be applied to `Fn`
-   |
-note: `Fn` can't be used with `[const]` because it isn't annotated with `#[const_trait]`
-  --> $SRC_DIR/core/src/ops/function.rs:LL:COL
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
-error[E0015]: cannot call non-const function `core::panicking::assert_failed::<&u8, &u8>` in constant functions
-  --> $DIR/ice-112822-expected-type-for-param.rs:12:17
-   |
-LL |                 assert_eq!(first, &b'f');
-   |                 ^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
-   = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
+   |                    ^^^^^^^^^^^^^^^^^
 
-error: aborting due to 5 previous errors
+error: aborting due to 2 previous errors
 
-Some errors have detailed explanations: E0015, E0658.
-For more information about an error, try `rustc --explain E0015`.
+Some errors have detailed explanations: E0277, E0658.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/const-traits/ice-123664-unexpected-bound-var.rs b/tests/ui/traits/const-traits/ice-123664-unexpected-bound-var.rs
deleted file mode 100644
index f1dbd947161..00000000000
--- a/tests/ui/traits/const-traits/ice-123664-unexpected-bound-var.rs
+++ /dev/null
@@ -1,8 +0,0 @@
-#![allow(incomplete_features)]
-#![feature(generic_const_exprs, const_trait_impl)]
-
-const fn with_positive<F: [const] Fn()>() {}
-//~^ ERROR `[const]` can only be applied to `#[const_trait]` traits
-//~| ERROR `[const]` can only be applied to `#[const_trait]` traits
-
-pub fn main() {}
diff --git a/tests/ui/traits/const-traits/ice-123664-unexpected-bound-var.stderr b/tests/ui/traits/const-traits/ice-123664-unexpected-bound-var.stderr
deleted file mode 100644
index 1eccb16b46e..00000000000
--- a/tests/ui/traits/const-traits/ice-123664-unexpected-bound-var.stderr
+++ /dev/null
@@ -1,21 +0,0 @@
-error: `[const]` can only be applied to `#[const_trait]` traits
-  --> $DIR/ice-123664-unexpected-bound-var.rs:4:27
-   |
-LL | const fn with_positive<F: [const] Fn()>() {}
-   |                           ^^^^^^^ can't be applied to `Fn`
-   |
-note: `Fn` can't be used with `[const]` because it isn't annotated with `#[const_trait]`
-  --> $SRC_DIR/core/src/ops/function.rs:LL:COL
-
-error: `[const]` can only be applied to `#[const_trait]` traits
-  --> $DIR/ice-123664-unexpected-bound-var.rs:4:27
-   |
-LL | const fn with_positive<F: [const] Fn()>() {}
-   |                           ^^^^^^^ can't be applied to `Fn`
-   |
-note: `Fn` can't be used with `[const]` because it isn't annotated with `#[const_trait]`
-  --> $SRC_DIR/core/src/ops/function.rs:LL:COL
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
-error: aborting due to 2 previous errors
-
diff --git a/tests/ui/traits/const-traits/non-const-op-const-closure-non-const-outer.rs b/tests/ui/traits/const-traits/non-const-op-const-closure-non-const-outer.rs
index fa0f7869644..d0470fa3458 100644
--- a/tests/ui/traits/const-traits/non-const-op-const-closure-non-const-outer.rs
+++ b/tests/ui/traits/const-traits/non-const-op-const-closure-non-const-outer.rs
@@ -11,5 +11,5 @@ impl Foo for () {
 
 fn main() {
     (const || { (()).foo() })();
-    //~^ ERROR: cannot call non-const method
+    //~^ ERROR: }: [const] Fn()` is not satisfied
 }
diff --git a/tests/ui/traits/const-traits/non-const-op-const-closure-non-const-outer.stderr b/tests/ui/traits/const-traits/non-const-op-const-closure-non-const-outer.stderr
index 2d33406c222..dcf65ab6940 100644
--- a/tests/ui/traits/const-traits/non-const-op-const-closure-non-const-outer.stderr
+++ b/tests/ui/traits/const-traits/non-const-op-const-closure-non-const-outer.stderr
@@ -1,11 +1,9 @@
-error[E0015]: cannot call non-const method `<() as Foo>::foo` in constant functions
-  --> $DIR/non-const-op-const-closure-non-const-outer.rs:13:22
+error[E0277]: the trait bound `{closure@$DIR/non-const-op-const-closure-non-const-outer.rs:13:6: 13:14}: [const] Fn()` is not satisfied
+  --> $DIR/non-const-op-const-closure-non-const-outer.rs:13:5
    |
 LL |     (const || { (()).foo() })();
-   |                      ^^^^^
-   |
-   = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 1 previous error
 
-For more information about this error, try `rustc --explain E0015`.
+For more information about this error, try `rustc --explain E0277`.