about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2025-08-14 09:56:07 +0000
committerbors <bors@rust-lang.org>2025-08-14 09:56:07 +0000
commit30017c36d6b5e3382ee7cf018d330a6a4a937d39 (patch)
tree1f82b0946b33be1024b6d2fa1e460cacdfc17574
parent2c1ac85679678dfe5cce7ea8037735b0349ceaf3 (diff)
parent762b7ecdb0085feb8ee4f5be38aefaee9f719fac (diff)
downloadrust-30017c36d6b5e3382ee7cf018d330a6a4a937d39.tar.gz
rust-30017c36d6b5e3382ee7cf018d330a6a4a937d39.zip
Auto merge of #145388 - GuillaumeGomez:rollup-hnlt5ov, r=GuillaumeGomez
Rollup of 13 pull requests

Successful merges:

 - rust-lang/rust#140434 (rustdoc: Allow multiple references to a single footnote)
 - rust-lang/rust#142372 (Improve `--remap-path-prefix` documentation)
 - rust-lang/rust#142741 (Fix unsoundness in some tests)
 - rust-lang/rust#144515 (Implement `ptr_cast_array`)
 - rust-lang/rust#144727 (Add tracing to resolve-related functions)
 - rust-lang/rust#144959 (fix(unicode-table-generator): fix duplicated unique indices)
 - rust-lang/rust#145179 (Avoid abbreviating "numerator" as "numer", to allow catching typo "numer" elsewhere)
 - rust-lang/rust#145250 (Add regression test for a former ICE involving helper attributes containing interpolated tokens)
 - rust-lang/rust#145266 (Reduce some queries around associated items)
 - rust-lang/rust#145299 (doc test: fix mpsc.rs try_send doc test)
 - rust-lang/rust#145323 (Port the `#[linkage]` attribute to the new attribute system)
 - rust-lang/rust#145361 (Suppress wrapper suggestion when expected and actual ty are the same adt and the variant is unresolved)
 - rust-lang/rust#145372 (resolve: Miscellaneous cleanups)

r? `@ghost`
`@rustbot` modify labels: rollup
-rw-r--r--compiler/rustc_attr_parsing/src/attributes/link_attrs.rs76
-rw-r--r--compiler/rustc_attr_parsing/src/context.rs3
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs3
-rw-r--r--compiler/rustc_borrowck/src/type_check/mod.rs5
-rw-r--r--compiler/rustc_codegen_cranelift/src/constant.rs8
-rw-r--r--compiler/rustc_codegen_cranelift/src/driver/aot.rs5
-rw-r--r--compiler/rustc_codegen_cranelift/src/linkage.rs3
-rw-r--r--compiler/rustc_codegen_gcc/src/base.rs2
-rw-r--r--compiler/rustc_codegen_gcc/src/consts.rs2
-rw-r--r--compiler/rustc_codegen_gcc/src/mono_item.rs3
-rw-r--r--compiler/rustc_codegen_llvm/src/base.rs3
-rw-r--r--compiler/rustc_codegen_llvm/src/consts.rs3
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/mod.rs43
-rw-r--r--compiler/rustc_codegen_llvm/src/mono_item.rs3
-rw-r--r--compiler/rustc_codegen_ssa/src/back/symbol_export.rs3
-rw-r--r--compiler/rustc_codegen_ssa/src/codegen_attrs.rs77
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/naked_asm.rs4
-rw-r--r--compiler/rustc_codegen_ssa/src/mono_item.rs3
-rw-r--r--compiler/rustc_codegen_ssa/src/traits/declare.rs3
-rw-r--r--compiler/rustc_const_eval/src/interpret/call.rs25
-rw-r--r--compiler/rustc_const_eval/src/interpret/cast.rs34
-rw-r--r--compiler/rustc_const_eval/src/interpret/eval_context.rs1
-rw-r--r--compiler/rustc_const_eval/src/interpret/step.rs6
-rw-r--r--compiler/rustc_hir/src/attrs/data_structures.rs21
-rw-r--r--compiler/rustc_hir/src/attrs/encode_cross_crate.rs1
-rw-r--r--compiler/rustc_hir/src/hir.rs1
-rw-r--r--compiler/rustc_hir_analysis/src/check/compare_impl_item.rs6
-rw-r--r--compiler/rustc_hir_analysis/src/check/wfcheck.rs3
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs9
-rw-r--r--compiler/rustc_lint/src/pass_by_value.rs6
-rw-r--r--compiler/rustc_lint/src/types.rs5
-rw-r--r--compiler/rustc_middle/src/middle/codegen_fn_attrs.rs3
-rw-r--r--compiler/rustc_middle/src/middle/privacy.rs6
-rw-r--r--compiler/rustc_middle/src/mir/mono.rs18
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs39
-rw-r--r--compiler/rustc_mir_transform/src/check_call_recursion.rs4
-rw-r--r--compiler/rustc_mir_transform/src/check_packed_ref.rs2
-rw-r--r--compiler/rustc_mir_transform/src/shim.rs2
-rw-r--r--compiler/rustc_monomorphize/src/partitioning.rs17
-rw-r--r--compiler/rustc_passes/src/check_attr.rs8
-rw-r--r--compiler/rustc_passes/src/dead.rs2
-rw-r--r--compiler/rustc_resolve/src/diagnostics.rs48
-rw-r--r--compiler/rustc_resolve/src/ident.rs7
-rw-r--r--compiler/rustc_resolve/src/late.rs22
-rw-r--r--compiler/rustc_resolve/src/late/diagnostics.rs51
-rw-r--r--compiler/rustc_resolve/src/macros.rs15
-rw-r--r--compiler/rustc_span/src/symbol.rs8
-rw-r--r--compiler/rustc_trait_selection/src/traits/project.rs2
-rw-r--r--library/core/src/ptr/const_ptr.rs9
-rw-r--r--library/core/src/ptr/mut_ptr.rs9
-rw-r--r--library/core/src/ptr/non_null.rs7
-rw-r--r--library/core/src/slice/mod.rs20
-rw-r--r--library/coretests/tests/io/borrowed_buf.rs4
-rw-r--r--library/std/src/sync/mpsc.rs8
-rw-r--r--library/std/src/sys_common/mod.rs13
-rw-r--r--src/doc/rustc/src/SUMMARY.md1
-rw-r--r--src/doc/rustc/src/command-line-arguments.md21
-rw-r--r--src/doc/rustc/src/remap-source-paths.md53
-rw-r--r--src/librustdoc/html/markdown/footnotes.rs33
-rw-r--r--src/tools/miri/src/helpers.rs2
-rw-r--r--src/tools/miri/src/shims/time.rs4
-rw-r--r--src/tools/unicode-table-generator/src/raw_emitter.rs2
-rw-r--r--tests/rustdoc/footnote-reference-ids.rs23
-rw-r--r--tests/rustdoc/footnote-reference-in-footnote-def.rs2
-rw-r--r--tests/ui/attributes/auxiliary/derive_macro_with_helper.rs8
-rw-r--r--tests/ui/attributes/helper-attr-interpolated-non-lit-arg.rs20
-rw-r--r--tests/ui/attributes/malformed-attrs.stderr37
-rw-r--r--tests/ui/hygiene/arguments.stderr3
-rw-r--r--tests/ui/hygiene/cross-crate-name-hiding-2.stderr5
-rw-r--r--tests/ui/hygiene/globs.stderr14
-rw-r--r--tests/ui/linkage-attr/linkage3.rs2
-rw-r--r--tests/ui/linkage-attr/linkage3.stderr27
-rw-r--r--tests/ui/proc-macro/proc-macro-attributes.stderr8
-rw-r--r--tests/ui/typeck/suggestions/suggest-add-wrapper-issue-145294.rs26
-rw-r--r--tests/ui/typeck/suggestions/suggest-add-wrapper-issue-145294.stderr21
-rw-r--r--typos.toml1
76 files changed, 646 insertions, 361 deletions
diff --git a/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs
index d406c30b83e..e4ced2e37c5 100644
--- a/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs
@@ -1,6 +1,6 @@
 use rustc_feature::{AttributeTemplate, template};
-use rustc_hir::attrs::AttributeKind;
 use rustc_hir::attrs::AttributeKind::{LinkName, LinkOrdinal, LinkSection};
+use rustc_hir::attrs::{AttributeKind, Linkage};
 use rustc_span::{Span, Symbol, sym};
 
 use crate::attributes::{
@@ -129,3 +129,77 @@ impl<S: Stage> SingleAttributeParser<S> for LinkOrdinalParser {
         Some(LinkOrdinal { ordinal, span: cx.attr_span })
     }
 }
+
+pub(crate) struct LinkageParser;
+
+impl<S: Stage> SingleAttributeParser<S> for LinkageParser {
+    const PATH: &[Symbol] = &[sym::linkage];
+
+    const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
+
+    const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
+
+    const TEMPLATE: AttributeTemplate = template!(NameValueStr: [
+        "available_externally",
+        "common",
+        "extern_weak",
+        "external",
+        "internal",
+        "linkonce",
+        "linkonce_odr",
+        "weak",
+        "weak_odr",
+    ]);
+
+    fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
+        let Some(name_value) = args.name_value() else {
+            cx.expected_name_value(cx.attr_span, Some(sym::linkage));
+            return None;
+        };
+
+        let Some(value) = name_value.value_as_str() else {
+            cx.expected_string_literal(name_value.value_span, Some(name_value.value_as_lit()));
+            return None;
+        };
+
+        // Use the names from src/llvm/docs/LangRef.rst here. Most types are only
+        // applicable to variable declarations and may not really make sense for
+        // Rust code in the first place but allow them anyway and trust that the
+        // user knows what they're doing. Who knows, unanticipated use cases may pop
+        // up in the future.
+        //
+        // ghost, dllimport, dllexport and linkonce_odr_autohide are not supported
+        // and don't have to be, LLVM treats them as no-ops.
+        let linkage = match value {
+            sym::available_externally => Linkage::AvailableExternally,
+            sym::common => Linkage::Common,
+            sym::extern_weak => Linkage::ExternalWeak,
+            sym::external => Linkage::External,
+            sym::internal => Linkage::Internal,
+            sym::linkonce => Linkage::LinkOnceAny,
+            sym::linkonce_odr => Linkage::LinkOnceODR,
+            sym::weak => Linkage::WeakAny,
+            sym::weak_odr => Linkage::WeakODR,
+
+            _ => {
+                cx.expected_specific_argument(
+                    name_value.value_span,
+                    vec![
+                        "available_externally",
+                        "common",
+                        "extern_weak",
+                        "external",
+                        "internal",
+                        "linkonce",
+                        "linkonce_odr",
+                        "weak",
+                        "weak_odr",
+                    ],
+                );
+                return None;
+            }
+        };
+
+        Some(AttributeKind::Linkage(linkage, cx.attr_span))
+    }
+}
diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs
index 1420753a44e..6045a8b28a2 100644
--- a/compiler/rustc_attr_parsing/src/context.rs
+++ b/compiler/rustc_attr_parsing/src/context.rs
@@ -27,7 +27,7 @@ use crate::attributes::dummy::DummyParser;
 use crate::attributes::inline::{InlineParser, RustcForceInlineParser};
 use crate::attributes::link_attrs::{
     ExportStableParser, FfiConstParser, FfiPureParser, LinkNameParser, LinkOrdinalParser,
-    LinkSectionParser, StdInternalSymbolParser,
+    LinkSectionParser, LinkageParser, StdInternalSymbolParser,
 };
 use crate::attributes::lint_helpers::{
     AsPtrParser, AutomaticallyDerivedParser, PassByValueParser, PubTransparentParser,
@@ -167,6 +167,7 @@ attribute_parsers!(
         Single<LinkNameParser>,
         Single<LinkOrdinalParser>,
         Single<LinkSectionParser>,
+        Single<LinkageParser>,
         Single<MustUseParser>,
         Single<OptimizeParser>,
         Single<PathAttributeParser>,
diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
index 5d9416b59fc..c0ca35f9ff8 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
@@ -677,12 +677,13 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
     ///  - is the trait from the local crate? If not, we can't suggest changing signatures
     ///  - `Span` of the argument in the trait definition
     fn is_error_in_trait(&self, local: Local) -> (bool, bool, Option<Span>) {
+        let tcx = self.infcx.tcx;
         if self.body.local_kind(local) != LocalKind::Arg {
             return (false, false, None);
         }
         let my_def = self.body.source.def_id();
         let Some(td) =
-            self.infcx.tcx.impl_of_assoc(my_def).and_then(|x| self.infcx.tcx.trait_id_of_impl(x))
+            tcx.trait_impl_of_assoc(my_def).and_then(|id| self.infcx.tcx.trait_id_of_impl(id))
         else {
             return (false, false, None);
         };
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index c3aa205d5aa..a960b96b91c 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -1773,10 +1773,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
                     locations,
                 );
 
-                assert!(!matches!(
-                    tcx.impl_of_assoc(def_id).map(|imp| tcx.def_kind(imp)),
-                    Some(DefKind::Impl { of_trait: true })
-                ));
+                assert_eq!(tcx.trait_impl_of_assoc(def_id), None);
                 self.prove_predicates(
                     args.types().map(|ty| ty::ClauseKind::WellFormed(ty.into())),
                     locations,
diff --git a/compiler/rustc_codegen_cranelift/src/constant.rs b/compiler/rustc_codegen_cranelift/src/constant.rs
index bec546badc9..a56466750e7 100644
--- a/compiler/rustc_codegen_cranelift/src/constant.rs
+++ b/compiler/rustc_codegen_cranelift/src/constant.rs
@@ -281,8 +281,8 @@ fn data_id_for_static(
             .abi
             .bytes();
 
-        let linkage = if import_linkage == rustc_middle::mir::mono::Linkage::ExternalWeak
-            || import_linkage == rustc_middle::mir::mono::Linkage::WeakAny
+        let linkage = if import_linkage == rustc_hir::attrs::Linkage::ExternalWeak
+            || import_linkage == rustc_hir::attrs::Linkage::WeakAny
         {
             Linkage::Preemptible
         } else {
@@ -332,8 +332,8 @@ fn data_id_for_static(
 
     let linkage = if definition {
         crate::linkage::get_static_linkage(tcx, def_id)
-    } else if attrs.linkage == Some(rustc_middle::mir::mono::Linkage::ExternalWeak)
-        || attrs.linkage == Some(rustc_middle::mir::mono::Linkage::WeakAny)
+    } else if attrs.linkage == Some(rustc_hir::attrs::Linkage::ExternalWeak)
+        || attrs.linkage == Some(rustc_hir::attrs::Linkage::WeakAny)
     {
         Linkage::Preemptible
     } else {
diff --git a/compiler/rustc_codegen_cranelift/src/driver/aot.rs b/compiler/rustc_codegen_cranelift/src/driver/aot.rs
index 8ec3599b63d..7e77781dc2f 100644
--- a/compiler/rustc_codegen_cranelift/src/driver/aot.rs
+++ b/compiler/rustc_codegen_cranelift/src/driver/aot.rs
@@ -18,12 +18,11 @@ use rustc_codegen_ssa::{
 use rustc_data_structures::profiling::SelfProfilerRef;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_data_structures::sync::{IntoDynSyncSend, par_map};
+use rustc_hir::attrs::Linkage as RLinkage;
 use rustc_metadata::fs::copy_to_stdout;
 use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
 use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
-use rustc_middle::mir::mono::{
-    CodegenUnit, Linkage as RLinkage, MonoItem, MonoItemData, Visibility,
-};
+use rustc_middle::mir::mono::{CodegenUnit, MonoItem, MonoItemData, Visibility};
 use rustc_session::Session;
 use rustc_session::config::{DebugInfo, OutFileName, OutputFilenames, OutputType};
 
diff --git a/compiler/rustc_codegen_cranelift/src/linkage.rs b/compiler/rustc_codegen_cranelift/src/linkage.rs
index ca853aac158..d76ab9d0109 100644
--- a/compiler/rustc_codegen_cranelift/src/linkage.rs
+++ b/compiler/rustc_codegen_cranelift/src/linkage.rs
@@ -1,4 +1,5 @@
-use rustc_middle::mir::mono::{Linkage as RLinkage, MonoItem, Visibility};
+use rustc_hir::attrs::Linkage as RLinkage;
+use rustc_middle::mir::mono::{MonoItem, Visibility};
 
 use crate::prelude::*;
 
diff --git a/compiler/rustc_codegen_gcc/src/base.rs b/compiler/rustc_codegen_gcc/src/base.rs
index c105916bbb2..e9d72e457a0 100644
--- a/compiler/rustc_codegen_gcc/src/base.rs
+++ b/compiler/rustc_codegen_gcc/src/base.rs
@@ -8,8 +8,8 @@ use rustc_codegen_ssa::ModuleCodegen;
 use rustc_codegen_ssa::base::maybe_create_entry_wrapper;
 use rustc_codegen_ssa::mono_item::MonoItemExt;
 use rustc_codegen_ssa::traits::DebugInfoCodegenMethods;
+use rustc_hir::attrs::Linkage;
 use rustc_middle::dep_graph;
-use rustc_middle::mir::mono::Linkage;
 #[cfg(feature = "master")]
 use rustc_middle::mir::mono::Visibility;
 use rustc_middle::ty::TyCtxt;
diff --git a/compiler/rustc_codegen_gcc/src/consts.rs b/compiler/rustc_codegen_gcc/src/consts.rs
index 873f1f1951c..619277eba8b 100644
--- a/compiler/rustc_codegen_gcc/src/consts.rs
+++ b/compiler/rustc_codegen_gcc/src/consts.rs
@@ -5,13 +5,13 @@ use rustc_abi::{self as abi, Align, HasDataLayout, Primitive, Size, WrappingRang
 use rustc_codegen_ssa::traits::{
     BaseTypeCodegenMethods, ConstCodegenMethods, StaticCodegenMethods,
 };
+use rustc_hir::attrs::Linkage;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::LOCAL_CRATE;
 use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
 use rustc_middle::mir::interpret::{
     self, ConstAllocation, ErrorHandled, Scalar as InterpScalar, read_target_uint,
 };
-use rustc_middle::mir::mono::Linkage;
 use rustc_middle::ty::layout::LayoutOf;
 use rustc_middle::ty::{self, Instance};
 use rustc_middle::{bug, span_bug};
diff --git a/compiler/rustc_codegen_gcc/src/mono_item.rs b/compiler/rustc_codegen_gcc/src/mono_item.rs
index ff188c437da..35d44d21bcb 100644
--- a/compiler/rustc_codegen_gcc/src/mono_item.rs
+++ b/compiler/rustc_codegen_gcc/src/mono_item.rs
@@ -1,11 +1,12 @@
 #[cfg(feature = "master")]
 use gccjit::{FnAttribute, VarAttribute};
 use rustc_codegen_ssa::traits::PreDefineCodegenMethods;
+use rustc_hir::attrs::Linkage;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{DefId, LOCAL_CRATE};
 use rustc_middle::bug;
 use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
-use rustc_middle::mir::mono::{Linkage, Visibility};
+use rustc_middle::mir::mono::Visibility;
 use rustc_middle::ty::layout::{FnAbiOf, HasTypingEnv, LayoutOf};
 use rustc_middle::ty::{self, Instance, TypeVisitableExt};
 
diff --git a/compiler/rustc_codegen_llvm/src/base.rs b/compiler/rustc_codegen_llvm/src/base.rs
index 5dda836988c..9cc5d8dbc21 100644
--- a/compiler/rustc_codegen_llvm/src/base.rs
+++ b/compiler/rustc_codegen_llvm/src/base.rs
@@ -18,9 +18,10 @@ use rustc_codegen_ssa::base::maybe_create_entry_wrapper;
 use rustc_codegen_ssa::mono_item::MonoItemExt;
 use rustc_codegen_ssa::traits::*;
 use rustc_data_structures::small_c_str::SmallCStr;
+use rustc_hir::attrs::Linkage;
 use rustc_middle::dep_graph;
 use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs;
-use rustc_middle::mir::mono::{Linkage, Visibility};
+use rustc_middle::mir::mono::Visibility;
 use rustc_middle::ty::TyCtxt;
 use rustc_session::config::DebugInfo;
 use rustc_span::Symbol;
diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs
index 6b06daf3477..9ec7b0f80ae 100644
--- a/compiler/rustc_codegen_llvm/src/consts.rs
+++ b/compiler/rustc_codegen_llvm/src/consts.rs
@@ -4,6 +4,7 @@ use rustc_abi::{Align, HasDataLayout, Primitive, Scalar, Size, WrappingRange};
 use rustc_codegen_ssa::common;
 use rustc_codegen_ssa::traits::*;
 use rustc_hir::LangItem;
+use rustc_hir::attrs::Linkage;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{DefId, LOCAL_CRATE};
 use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
@@ -11,7 +12,7 @@ use rustc_middle::mir::interpret::{
     Allocation, ConstAllocation, ErrorHandled, InitChunk, Pointer, Scalar as InterpScalar,
     read_target_uint,
 };
-use rustc_middle::mir::mono::{Linkage, MonoItem};
+use rustc_middle::mir::mono::MonoItem;
 use rustc_middle::ty::layout::{HasTypingEnv, LayoutOf};
 use rustc_middle::ty::{self, Instance};
 use rustc_middle::{bug, span_bug};
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
index 6cbf2dbf7d3..2c3a84499ac 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
@@ -533,31 +533,26 @@ impl<'ll, 'tcx> DebugInfoCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> {
             // First, let's see if this is a method within an inherent impl. Because
             // if yes, we want to make the result subroutine DIE a child of the
             // subroutine's self-type.
-            if let Some(impl_def_id) = cx.tcx.impl_of_assoc(instance.def_id()) {
-                // If the method does *not* belong to a trait, proceed
-                if cx.tcx.trait_id_of_impl(impl_def_id).is_none() {
-                    let impl_self_ty = cx.tcx.instantiate_and_normalize_erasing_regions(
-                        instance.args,
-                        cx.typing_env(),
-                        cx.tcx.type_of(impl_def_id),
-                    );
-
-                    // Only "class" methods are generally understood by LLVM,
-                    // so avoid methods on other types (e.g., `<*mut T>::null`).
-                    if let ty::Adt(def, ..) = impl_self_ty.kind()
-                        && !def.is_box()
-                    {
-                        // Again, only create type information if full debuginfo is enabled
-                        if cx.sess().opts.debuginfo == DebugInfo::Full && !impl_self_ty.has_param()
-                        {
-                            return (type_di_node(cx, impl_self_ty), true);
-                        } else {
-                            return (namespace::item_namespace(cx, def.did()), false);
-                        }
+            // For trait method impls we still use the "parallel namespace"
+            // strategy
+            if let Some(imp_def_id) = cx.tcx.inherent_impl_of_assoc(instance.def_id()) {
+                let impl_self_ty = cx.tcx.instantiate_and_normalize_erasing_regions(
+                    instance.args,
+                    cx.typing_env(),
+                    cx.tcx.type_of(imp_def_id),
+                );
+
+                // Only "class" methods are generally understood by LLVM,
+                // so avoid methods on other types (e.g., `<*mut T>::null`).
+                if let ty::Adt(def, ..) = impl_self_ty.kind()
+                    && !def.is_box()
+                {
+                    // Again, only create type information if full debuginfo is enabled
+                    if cx.sess().opts.debuginfo == DebugInfo::Full && !impl_self_ty.has_param() {
+                        return (type_di_node(cx, impl_self_ty), true);
+                    } else {
+                        return (namespace::item_namespace(cx, def.did()), false);
                     }
-                } else {
-                    // For trait method impls we still use the "parallel namespace"
-                    // strategy
                 }
             }
 
diff --git a/compiler/rustc_codegen_llvm/src/mono_item.rs b/compiler/rustc_codegen_llvm/src/mono_item.rs
index f9edaded60d..5075befae8a 100644
--- a/compiler/rustc_codegen_llvm/src/mono_item.rs
+++ b/compiler/rustc_codegen_llvm/src/mono_item.rs
@@ -1,8 +1,9 @@
 use rustc_codegen_ssa::traits::*;
+use rustc_hir::attrs::Linkage;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{DefId, LOCAL_CRATE};
 use rustc_middle::bug;
-use rustc_middle::mir::mono::{Linkage, Visibility};
+use rustc_middle::mir::mono::Visibility;
 use rustc_middle::ty::layout::{FnAbiOf, HasTypingEnv, LayoutOf};
 use rustc_middle::ty::{self, Instance, TypeVisitableExt};
 use rustc_session::config::CrateType;
diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs
index 0494666bda9..77096822fdc 100644
--- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs
+++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs
@@ -306,7 +306,8 @@ fn exported_generic_symbols_provider_local<'tcx>(
     let mut symbols: Vec<_> = vec![];
 
     if tcx.local_crate_exports_generics() {
-        use rustc_middle::mir::mono::{Linkage, MonoItem, Visibility};
+        use rustc_hir::attrs::Linkage;
+        use rustc_middle::mir::mono::{MonoItem, Visibility};
         use rustc_middle::ty::InstanceKind;
 
         // Normally, we require that shared monomorphizations are not hidden,
diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
index 287787eb3d1..a36a772bc97 100644
--- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
+++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
@@ -11,7 +11,6 @@ use rustc_hir::{self as hir, Attribute, LangItem, find_attr, lang_items};
 use rustc_middle::middle::codegen_fn_attrs::{
     CodegenFnAttrFlags, CodegenFnAttrs, PatchableFunctionEntry,
 };
-use rustc_middle::mir::mono::Linkage;
 use rustc_middle::query::Providers;
 use rustc_middle::span_bug;
 use rustc_middle::ty::{self as ty, TyCtxt};
@@ -26,31 +25,6 @@ use crate::target_features::{
     check_target_feature_trait_unsafe, check_tied_features, from_target_feature_attr,
 };
 
-fn linkage_by_name(tcx: TyCtxt<'_>, def_id: LocalDefId, name: &str) -> Linkage {
-    use rustc_middle::mir::mono::Linkage::*;
-
-    // Use the names from src/llvm/docs/LangRef.rst here. Most types are only
-    // applicable to variable declarations and may not really make sense for
-    // Rust code in the first place but allow them anyway and trust that the
-    // user knows what they're doing. Who knows, unanticipated use cases may pop
-    // up in the future.
-    //
-    // ghost, dllimport, dllexport and linkonce_odr_autohide are not supported
-    // and don't have to be, LLVM treats them as no-ops.
-    match name {
-        "available_externally" => AvailableExternally,
-        "common" => Common,
-        "extern_weak" => ExternalWeak,
-        "external" => External,
-        "internal" => Internal,
-        "linkonce" => LinkOnceAny,
-        "linkonce_odr" => LinkOnceODR,
-        "weak" => WeakAny,
-        "weak_odr" => WeakODR,
-        _ => tcx.dcx().span_fatal(tcx.def_span(def_id), "invalid linkage specified"),
-    }
-}
-
 /// In some cases, attributes are only valid on functions, but it's the `check_attr`
 /// pass that checks that they aren't used anywhere else, rather than this module.
 /// In these cases, we bail from performing further checks that are only meaningful for
@@ -103,13 +77,6 @@ fn parse_instruction_set_attr(tcx: TyCtxt<'_>, attr: &Attribute) -> Option<Instr
     }
 }
 
-// FIXME(jdonszelmann): remove when linkage becomes a parsed attr
-fn parse_linkage_attr(tcx: TyCtxt<'_>, did: LocalDefId, attr: &Attribute) -> Option<Linkage> {
-    let val = attr.value_str()?;
-    let linkage = linkage_by_name(tcx, did, val.as_str());
-    Some(linkage)
-}
-
 // FIXME(jdonszelmann): remove when no_sanitize becomes a parsed attr
 fn parse_no_sanitize_attr(tcx: TyCtxt<'_>, attr: &Attribute) -> Option<SanitizerSet> {
     let list = attr.meta_item_list()?;
@@ -332,6 +299,28 @@ fn process_builtin_attrs(
                 AttributeKind::StdInternalSymbol(_) => {
                     codegen_fn_attrs.flags |= CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL
                 }
+                AttributeKind::Linkage(linkage, _) => {
+                    let linkage = Some(*linkage);
+
+                    if tcx.is_foreign_item(did) {
+                        codegen_fn_attrs.import_linkage = linkage;
+
+                        if tcx.is_mutable_static(did.into()) {
+                            let mut diag = tcx.dcx().struct_span_err(
+                                attr.span(),
+                                "extern mutable statics are not allowed with `#[linkage]`",
+                            );
+                            diag.note(
+                                "marking the extern static mutable would allow changing which \
+                                symbol the static references rather than make the target of the \
+                                symbol mutable",
+                            );
+                            diag.emit();
+                        }
+                    } else {
+                        codegen_fn_attrs.linkage = linkage;
+                    }
+                }
                 _ => {}
             }
         }
@@ -349,28 +338,6 @@ fn process_builtin_attrs(
                 codegen_fn_attrs.flags |= CodegenFnAttrFlags::ALLOCATOR_ZEROED
             }
             sym::thread_local => codegen_fn_attrs.flags |= CodegenFnAttrFlags::THREAD_LOCAL,
-            sym::linkage => {
-                let linkage = parse_linkage_attr(tcx, did, attr);
-
-                if tcx.is_foreign_item(did) {
-                    codegen_fn_attrs.import_linkage = linkage;
-
-                    if tcx.is_mutable_static(did.into()) {
-                        let mut diag = tcx.dcx().struct_span_err(
-                            attr.span(),
-                            "extern mutable statics are not allowed with `#[linkage]`",
-                        );
-                        diag.note(
-                            "marking the extern static mutable would allow changing which \
-                            symbol the static references rather than make the target of the \
-                            symbol mutable",
-                        );
-                        diag.emit();
-                    }
-                } else {
-                    codegen_fn_attrs.linkage = linkage;
-                }
-            }
             sym::no_sanitize => {
                 interesting_spans.no_sanitize = Some(attr.span());
                 codegen_fn_attrs.no_sanitize |=
diff --git a/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs b/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs
index 2a9b5c9019b..31784cabf4a 100644
--- a/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs
@@ -1,6 +1,6 @@
 use rustc_abi::{BackendRepr, Float, Integer, Primitive, RegKind};
-use rustc_hir::attrs::InstructionSetAttr;
-use rustc_middle::mir::mono::{Linkage, MonoItemData, Visibility};
+use rustc_hir::attrs::{InstructionSetAttr, Linkage};
+use rustc_middle::mir::mono::{MonoItemData, Visibility};
 use rustc_middle::mir::{InlineAsmOperand, START_BLOCK};
 use rustc_middle::ty::layout::{FnAbiOf, LayoutOf, TyAndLayout};
 use rustc_middle::ty::{Instance, Ty, TyCtxt, TypeVisitableExt};
diff --git a/compiler/rustc_codegen_ssa/src/mono_item.rs b/compiler/rustc_codegen_ssa/src/mono_item.rs
index b9040c330fb..8f03dc1e6b5 100644
--- a/compiler/rustc_codegen_ssa/src/mono_item.rs
+++ b/compiler/rustc_codegen_ssa/src/mono_item.rs
@@ -1,5 +1,6 @@
+use rustc_hir::attrs::Linkage;
 use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
-use rustc_middle::mir::mono::{Linkage, MonoItem, MonoItemData, Visibility};
+use rustc_middle::mir::mono::{MonoItem, MonoItemData, Visibility};
 use rustc_middle::ty::layout::HasTyCtxt;
 use tracing::debug;
 
diff --git a/compiler/rustc_codegen_ssa/src/traits/declare.rs b/compiler/rustc_codegen_ssa/src/traits/declare.rs
index 9f735546558..8d5f0a5b939 100644
--- a/compiler/rustc_codegen_ssa/src/traits/declare.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/declare.rs
@@ -1,5 +1,6 @@
+use rustc_hir::attrs::Linkage;
 use rustc_hir::def_id::DefId;
-use rustc_middle::mir::mono::{Linkage, Visibility};
+use rustc_middle::mir::mono::Visibility;
 use rustc_middle::ty::Instance;
 
 pub trait PreDefineCodegenMethods<'tcx> {
diff --git a/compiler/rustc_const_eval/src/interpret/call.rs b/compiler/rustc_const_eval/src/interpret/call.rs
index b1cc0cc2878..64cb934ac8d 100644
--- a/compiler/rustc_const_eval/src/interpret/call.rs
+++ b/compiler/rustc_const_eval/src/interpret/call.rs
@@ -731,18 +731,21 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
     ) {
         let tcx = *self.tcx;
 
-        let trait_def_id = tcx.trait_of_assoc(def_id).unwrap();
+        let trait_def_id = tcx.parent(def_id);
         let virtual_trait_ref = ty::TraitRef::from_assoc(tcx, trait_def_id, virtual_instance.args);
         let existential_trait_ref = ty::ExistentialTraitRef::erase_self_ty(tcx, virtual_trait_ref);
         let concrete_trait_ref = existential_trait_ref.with_self_ty(tcx, dyn_ty);
 
-        let concrete_method = Instance::expect_resolve_for_vtable(
-            tcx,
-            self.typing_env,
-            def_id,
-            virtual_instance.args.rebase_onto(tcx, trait_def_id, concrete_trait_ref.args),
-            self.cur_span(),
-        );
+        let concrete_method = {
+            let _trace = enter_trace_span!(M, resolve::expect_resolve_for_vtable, ?def_id);
+            Instance::expect_resolve_for_vtable(
+                tcx,
+                self.typing_env,
+                def_id,
+                virtual_instance.args.rebase_onto(tcx, trait_def_id, concrete_trait_ref.args),
+                self.cur_span(),
+            )
+        };
         assert_eq!(concrete_instance, concrete_method);
     }
 
@@ -825,7 +828,11 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
                 place
             }
         };
-        let instance = ty::Instance::resolve_drop_in_place(*self.tcx, place.layout.ty);
+        let instance = {
+            let _trace =
+                enter_trace_span!(M, resolve::resolve_drop_in_place, ty = ?place.layout.ty);
+            ty::Instance::resolve_drop_in_place(*self.tcx, place.layout.ty)
+        };
         let fn_abi = self.fn_abi_of_instance(instance, ty::List::empty())?;
 
         let arg = self.mplace_to_ref(&place)?;
diff --git a/compiler/rustc_const_eval/src/interpret/cast.rs b/compiler/rustc_const_eval/src/interpret/cast.rs
index de4fbc7b475..e3afeda5b7c 100644
--- a/compiler/rustc_const_eval/src/interpret/cast.rs
+++ b/compiler/rustc_const_eval/src/interpret/cast.rs
@@ -16,8 +16,8 @@ use super::{
     FnVal, ImmTy, Immediate, InterpCx, Machine, OpTy, PlaceTy, err_inval, interp_ok, throw_ub,
     throw_ub_custom,
 };
-use crate::fluent_generated as fluent;
 use crate::interpret::Writeable;
+use crate::{enter_trace_span, fluent_generated as fluent};
 
 impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
     pub fn cast(
@@ -81,13 +81,16 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
                 // The src operand does not matter, just its type
                 match *src.layout.ty.kind() {
                     ty::FnDef(def_id, args) => {
-                        let instance = ty::Instance::resolve_for_fn_ptr(
-                            *self.tcx,
-                            self.typing_env,
-                            def_id,
-                            args,
-                        )
-                        .ok_or_else(|| err_inval!(TooGeneric))?;
+                        let instance = {
+                            let _trace = enter_trace_span!(M, resolve::resolve_for_fn_ptr, ?def_id);
+                            ty::Instance::resolve_for_fn_ptr(
+                                *self.tcx,
+                                self.typing_env,
+                                def_id,
+                                args,
+                            )
+                            .ok_or_else(|| err_inval!(TooGeneric))?
+                        };
 
                         let fn_ptr = self.fn_ptr(FnVal::Instance(instance));
                         self.write_pointer(fn_ptr, dest)?;
@@ -114,12 +117,15 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
                 // The src operand does not matter, just its type
                 match *src.layout.ty.kind() {
                     ty::Closure(def_id, args) => {
-                        let instance = ty::Instance::resolve_closure(
-                            *self.tcx,
-                            def_id,
-                            args,
-                            ty::ClosureKind::FnOnce,
-                        );
+                        let instance = {
+                            let _trace = enter_trace_span!(M, resolve::resolve_closure, ?def_id);
+                            ty::Instance::resolve_closure(
+                                *self.tcx,
+                                def_id,
+                                args,
+                                ty::ClosureKind::FnOnce,
+                            )
+                        };
                         let fn_ptr = self.fn_ptr(FnVal::Instance(instance));
                         self.write_pointer(fn_ptr, dest)?;
                     }
diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs
index d4f2bb8257d..a8a1ac1c980 100644
--- a/compiler/rustc_const_eval/src/interpret/eval_context.rs
+++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs
@@ -344,6 +344,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
         def: DefId,
         args: GenericArgsRef<'tcx>,
     ) -> InterpResult<'tcx, ty::Instance<'tcx>> {
+        let _trace = enter_trace_span!(M, resolve::try_resolve, def = ?def);
         trace!("resolve: {:?}, {:#?}", def, args);
         trace!("typing_env: {:#?}", self.typing_env);
         trace!("args: {:#?}", args);
diff --git a/compiler/rustc_const_eval/src/interpret/step.rs b/compiler/rustc_const_eval/src/interpret/step.rs
index 76e470b69dc..f1995b3f132 100644
--- a/compiler/rustc_const_eval/src/interpret/step.rs
+++ b/compiler/rustc_const_eval/src/interpret/step.rs
@@ -560,7 +560,11 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
                     "Async Drop must be expanded or reset to sync in runtime MIR"
                 );
                 let place = self.eval_place(place)?;
-                let instance = Instance::resolve_drop_in_place(*self.tcx, place.layout.ty);
+                let instance = {
+                    let _trace =
+                        enter_trace_span!(M, resolve::resolve_drop_in_place, ty = ?place.layout.ty);
+                    Instance::resolve_drop_in_place(*self.tcx, place.layout.ty)
+                };
                 if let ty::InstanceKind::DropGlue(_, None) = instance.def {
                     // This is the branch we enter if and only if the dropped type has no drop glue
                     // whatsoever. This can happen as a result of monomorphizing a drop of a
diff --git a/compiler/rustc_hir/src/attrs/data_structures.rs b/compiler/rustc_hir/src/attrs/data_structures.rs
index e02edf5fe24..510fc832978 100644
--- a/compiler/rustc_hir/src/attrs/data_structures.rs
+++ b/compiler/rustc_hir/src/attrs/data_structures.rs
@@ -187,6 +187,24 @@ pub enum CfgEntry {
     Version(Option<RustcVersion>, Span),
 }
 
+/// Possible values for the `#[linkage]` attribute, allowing to specify the
+/// linkage type for a `MonoItem`.
+///
+/// See <https://llvm.org/docs/LangRef.html#linkage-types> for more details about these variants.
+#[derive(Encodable, Decodable, Clone, Copy, Debug, PartialEq, Eq, Hash)]
+#[derive(HashStable_Generic, PrintAttribute)]
+pub enum Linkage {
+    AvailableExternally,
+    Common,
+    ExternalWeak,
+    External,
+    Internal,
+    LinkOnceAny,
+    LinkOnceODR,
+    WeakAny,
+    WeakODR,
+}
+
 /// Represents parsed *built-in* inert attributes.
 ///
 /// ## Overview
@@ -360,6 +378,9 @@ pub enum AttributeKind {
     /// Represents [`#[link_section]`](https://doc.rust-lang.org/reference/abi.html#the-link_section-attribute)
     LinkSection { name: Symbol, span: Span },
 
+    /// Represents `#[linkage]`.
+    Linkage(Linkage, Span),
+
     /// Represents `#[loop_match]`.
     LoopMatch(Span),
 
diff --git a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs
index 7ce624dcc55..84a975523f2 100644
--- a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs
+++ b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs
@@ -46,6 +46,7 @@ impl AttributeKind {
             LinkName { .. } => Yes, // Needed for rustdoc
             LinkOrdinal { .. } => No,
             LinkSection { .. } => Yes, // Needed for rustdoc
+            Linkage(..) => No,
             LoopMatch(..) => No,
             MacroEscape(..) => No,
             MacroTransparency(..) => Yes,
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index e8feb721984..0cc03ef7b5b 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -1310,6 +1310,7 @@ impl AttributeExt for Attribute {
             Attribute::Parsed(AttributeKind::ShouldPanic { span, .. }) => *span,
             Attribute::Parsed(AttributeKind::AutomaticallyDerived(span)) => *span,
             Attribute::Parsed(AttributeKind::AllowInternalUnsafe(span)) => *span,
+            Attribute::Parsed(AttributeKind::Linkage(_, span)) => *span,
             a => panic!("can't get the span of an arbitrary parsed attribute: {a:?}"),
         }
     }
diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
index 6767e5ed88d..e4827256193 100644
--- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
+++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
@@ -445,10 +445,10 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
     tcx: TyCtxt<'tcx>,
     impl_m_def_id: LocalDefId,
 ) -> Result<&'tcx DefIdMap<ty::EarlyBinder<'tcx, Ty<'tcx>>>, ErrorGuaranteed> {
-    let impl_m = tcx.opt_associated_item(impl_m_def_id.to_def_id()).unwrap();
-    let trait_m = tcx.opt_associated_item(impl_m.trait_item_def_id.unwrap()).unwrap();
+    let impl_m = tcx.associated_item(impl_m_def_id.to_def_id());
+    let trait_m = tcx.associated_item(impl_m.trait_item_def_id.unwrap());
     let impl_trait_ref =
-        tcx.impl_trait_ref(impl_m.impl_container(tcx).unwrap()).unwrap().instantiate_identity();
+        tcx.impl_trait_ref(tcx.parent(impl_m_def_id.to_def_id())).unwrap().instantiate_identity();
     // First, check a few of the same things as `compare_impl_method`,
     // just so we don't ICE during instantiation later.
     check_method_is_structurally_compatible(tcx, impl_m, trait_m, impl_trait_ref, true)?;
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
index c642435b989..e6a1f6d8d8b 100644
--- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -2287,8 +2287,7 @@ fn lint_redundant_lifetimes<'tcx>(
             // Proceed
         }
         DefKind::AssocFn | DefKind::AssocTy | DefKind::AssocConst => {
-            let parent_def_id = tcx.local_parent(owner_id);
-            if matches!(tcx.def_kind(parent_def_id), DefKind::Impl { of_trait: true }) {
+            if tcx.trait_impl_of_assoc(owner_id.to_def_id()).is_some() {
                 // Don't check for redundant lifetimes for associated items of trait
                 // implementations, since the signature is required to be compatible
                 // with the trait, even if the implementation implies some lifetimes
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
index 6013430e1ff..aca3840712e 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
@@ -2378,6 +2378,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 .filter_map(|variant| {
                     let sole_field = &variant.single_field();
 
+                    // When expected_ty and expr_ty are the same ADT, we prefer to compare their internal generic params,
+                    // When the current variant has a sole field whose type is still an unresolved inference variable,
+                    // suggestions would be often wrong. So suppress the suggestion. See #145294.
+                    if let (ty::Adt(exp_adt, _), ty::Adt(act_adt, _)) = (expected.kind(), expr_ty.kind())
+                        && exp_adt.did() == act_adt.did()
+                        && sole_field.ty(self.tcx, args).is_ty_var() {
+                            return None;
+                    }
+
                     let field_is_local = sole_field.did.is_local();
                     let field_is_accessible =
                         sole_field.vis.is_accessible_from(expr.hir_id.owner.def_id, self.tcx)
diff --git a/compiler/rustc_lint/src/pass_by_value.rs b/compiler/rustc_lint/src/pass_by_value.rs
index 4f65acd8001..29006732aad 100644
--- a/compiler/rustc_lint/src/pass_by_value.rs
+++ b/compiler/rustc_lint/src/pass_by_value.rs
@@ -24,10 +24,8 @@ impl<'tcx> LateLintPass<'tcx> for PassByValue {
     fn check_ty(&mut self, cx: &LateContext<'_>, ty: &'tcx hir::Ty<'tcx, AmbigArg>) {
         match &ty.kind {
             TyKind::Ref(_, hir::MutTy { ty: inner_ty, mutbl: hir::Mutability::Not }) => {
-                if let Some(impl_did) = cx.tcx.impl_of_assoc(ty.hir_id.owner.to_def_id()) {
-                    if cx.tcx.impl_trait_ref(impl_did).is_some() {
-                        return;
-                    }
+                if cx.tcx.trait_impl_of_assoc(ty.hir_id.owner.to_def_id()).is_some() {
+                    return;
                 }
                 if let Some(t) = path_for_pass_by_value(cx, inner_ty) {
                     cx.emit_span_lint(
diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs
index b0afc333ebe..f8a692313f0 100644
--- a/compiler/rustc_lint/src/types.rs
+++ b/compiler/rustc_lint/src/types.rs
@@ -1904,10 +1904,9 @@ impl InvalidAtomicOrdering {
         if let ExprKind::MethodCall(method_path, _, args, _) = &expr.kind
             && recognized_names.contains(&method_path.ident.name)
             && let Some(m_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id)
-            && let Some(impl_did) = cx.tcx.impl_of_assoc(m_def_id)
-            && let Some(adt) = cx.tcx.type_of(impl_did).instantiate_identity().ty_adt_def()
             // skip extension traits, only lint functions from the standard library
-            && cx.tcx.trait_id_of_impl(impl_did).is_none()
+            && let Some(impl_did) = cx.tcx.inherent_impl_of_assoc(m_def_id)
+            && let Some(adt) = cx.tcx.type_of(impl_did).instantiate_identity().ty_adt_def()
             && let parent = cx.tcx.parent(adt.did())
             && cx.tcx.is_diagnostic_item(sym::atomic_mod, parent)
             && ATOMIC_TYPES.contains(&cx.tcx.item_name(adt.did()))
diff --git a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs
index 52341df0740..2852c4cbd34 100644
--- a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs
+++ b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs
@@ -2,13 +2,12 @@ use std::borrow::Cow;
 
 use rustc_abi::Align;
 use rustc_ast::expand::autodiff_attrs::AutoDiffAttrs;
-use rustc_hir::attrs::{InlineAttr, InstructionSetAttr, OptimizeAttr};
+use rustc_hir::attrs::{InlineAttr, InstructionSetAttr, Linkage, OptimizeAttr};
 use rustc_hir::def_id::DefId;
 use rustc_macros::{HashStable, TyDecodable, TyEncodable};
 use rustc_span::Symbol;
 use rustc_target::spec::SanitizerSet;
 
-use crate::mir::mono::Linkage;
 use crate::ty::{InstanceKind, TyCtxt};
 
 impl<'tcx> TyCtxt<'tcx> {
diff --git a/compiler/rustc_middle/src/middle/privacy.rs b/compiler/rustc_middle/src/middle/privacy.rs
index 785ddd1ee29..e3e04c9d180 100644
--- a/compiler/rustc_middle/src/middle/privacy.rs
+++ b/compiler/rustc_middle/src/middle/privacy.rs
@@ -181,11 +181,7 @@ impl EffectiveVisibilities {
             // nominal visibility. For some items nominal visibility doesn't make sense so we
             // don't check this condition for them.
             let is_impl = matches!(tcx.def_kind(def_id), DefKind::Impl { .. });
-            let is_associated_item_in_trait_impl = tcx
-                .impl_of_assoc(def_id.to_def_id())
-                .and_then(|impl_id| tcx.trait_id_of_impl(impl_id))
-                .is_some();
-            if !is_impl && !is_associated_item_in_trait_impl {
+            if !is_impl && tcx.trait_impl_of_assoc(def_id.to_def_id()).is_none() {
                 let nominal_vis = tcx.visibility(def_id);
                 if !nominal_vis.is_at_least(ev.reachable, tcx) {
                     span_bug!(
diff --git a/compiler/rustc_middle/src/mir/mono.rs b/compiler/rustc_middle/src/mir/mono.rs
index 0d98e055d95..440771b3d68 100644
--- a/compiler/rustc_middle/src/mir/mono.rs
+++ b/compiler/rustc_middle/src/mir/mono.rs
@@ -10,7 +10,7 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHas
 use rustc_data_structures::unord::UnordMap;
 use rustc_hashes::Hash128;
 use rustc_hir::ItemId;
-use rustc_hir::attrs::InlineAttr;
+use rustc_hir::attrs::{InlineAttr, Linkage};
 use rustc_hir::def_id::{CrateNum, DefId, DefIdSet, LOCAL_CRATE};
 use rustc_macros::{HashStable, TyDecodable, TyEncodable};
 use rustc_query_system::ich::StableHashingContext;
@@ -368,22 +368,6 @@ pub struct MonoItemData {
     pub size_estimate: usize,
 }
 
-/// Specifies the linkage type for a `MonoItem`.
-///
-/// See <https://llvm.org/docs/LangRef.html#linkage-types> for more details about these variants.
-#[derive(Copy, Clone, PartialEq, Debug, TyEncodable, TyDecodable, HashStable)]
-pub enum Linkage {
-    External,
-    AvailableExternally,
-    LinkOnceAny,
-    LinkOnceODR,
-    WeakAny,
-    WeakODR,
-    Internal,
-    ExternalWeak,
-    Common,
-}
-
 /// Specifies the symbol visibility with regards to dynamic linking.
 ///
 /// Visibility doesn't have any effect when linkage is internal.
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 73e1661106e..e70c98ab704 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -1925,21 +1925,50 @@ impl<'tcx> TyCtxt<'tcx> {
         self.impl_trait_ref(def_id).map(|tr| tr.skip_binder().def_id)
     }
 
-    /// If the given `DefId` is an associated item, returns the `DefId` of the parent trait or impl.
-    pub fn assoc_parent(self, def_id: DefId) -> Option<DefId> {
-        self.def_kind(def_id).is_assoc().then(|| self.parent(def_id))
+    /// If the given `DefId` is an associated item, returns the `DefId` and `DefKind` of the parent trait or impl.
+    pub fn assoc_parent(self, def_id: DefId) -> Option<(DefId, DefKind)> {
+        if !self.def_kind(def_id).is_assoc() {
+            return None;
+        }
+        let parent = self.parent(def_id);
+        let def_kind = self.def_kind(parent);
+        Some((parent, def_kind))
     }
 
     /// If the given `DefId` is an associated item of a trait,
     /// returns the `DefId` of the trait; otherwise, returns `None`.
     pub fn trait_of_assoc(self, def_id: DefId) -> Option<DefId> {
-        self.assoc_parent(def_id).filter(|id| self.def_kind(id) == DefKind::Trait)
+        match self.assoc_parent(def_id) {
+            Some((id, DefKind::Trait)) => Some(id),
+            _ => None,
+        }
     }
 
     /// If the given `DefId` is an associated item of an impl,
     /// returns the `DefId` of the impl; otherwise returns `None`.
     pub fn impl_of_assoc(self, def_id: DefId) -> Option<DefId> {
-        self.assoc_parent(def_id).filter(|id| matches!(self.def_kind(id), DefKind::Impl { .. }))
+        match self.assoc_parent(def_id) {
+            Some((id, DefKind::Impl { .. })) => Some(id),
+            _ => None,
+        }
+    }
+
+    /// If the given `DefId` is an associated item of an inherent impl,
+    /// returns the `DefId` of the impl; otherwise, returns `None`.
+    pub fn inherent_impl_of_assoc(self, def_id: DefId) -> Option<DefId> {
+        match self.assoc_parent(def_id) {
+            Some((id, DefKind::Impl { of_trait: false })) => Some(id),
+            _ => None,
+        }
+    }
+
+    /// If the given `DefId` is an associated item of a trait impl,
+    /// returns the `DefId` of the impl; otherwise, returns `None`.
+    pub fn trait_impl_of_assoc(self, def_id: DefId) -> Option<DefId> {
+        match self.assoc_parent(def_id) {
+            Some((id, DefKind::Impl { of_trait: true })) => Some(id),
+            _ => None,
+        }
     }
 
     pub fn is_exportable(self, def_id: DefId) -> bool {
diff --git a/compiler/rustc_mir_transform/src/check_call_recursion.rs b/compiler/rustc_mir_transform/src/check_call_recursion.rs
index 6d61ac2dd80..a9acb1da5a3 100644
--- a/compiler/rustc_mir_transform/src/check_call_recursion.rs
+++ b/compiler/rustc_mir_transform/src/check_call_recursion.rs
@@ -43,8 +43,8 @@ impl<'tcx> MirLint<'tcx> for CheckDropRecursion {
 
         // First check if `body` is an `fn drop()` of `Drop`
         if let DefKind::AssocFn = tcx.def_kind(def_id)
-        && let Some(trait_ref) =
-            tcx.impl_of_assoc(def_id.to_def_id()).and_then(|def_id| tcx.impl_trait_ref(def_id))
+        && let Some(impl_id) = tcx.trait_impl_of_assoc(def_id.to_def_id())
+        && let trait_ref = tcx.impl_trait_ref(impl_id).unwrap()
         && tcx.is_lang_item(trait_ref.instantiate_identity().def_id, LangItem::Drop)
         // avoid erroneous `Drop` impls from causing ICEs below
         && let sig = tcx.fn_sig(def_id).instantiate_identity()
diff --git a/compiler/rustc_mir_transform/src/check_packed_ref.rs b/compiler/rustc_mir_transform/src/check_packed_ref.rs
index dcb812c7899..100104e9de0 100644
--- a/compiler/rustc_mir_transform/src/check_packed_ref.rs
+++ b/compiler/rustc_mir_transform/src/check_packed_ref.rs
@@ -40,7 +40,7 @@ impl<'tcx> Visitor<'tcx> for PackedRefChecker<'_, 'tcx> {
         if context.is_borrow() && util::is_disaligned(self.tcx, self.body, self.typing_env, *place)
         {
             let def_id = self.body.source.instance.def_id();
-            if let Some(impl_def_id) = self.tcx.impl_of_assoc(def_id)
+            if let Some(impl_def_id) = self.tcx.trait_impl_of_assoc(def_id)
                 && self.tcx.is_builtin_derived(impl_def_id)
             {
                 // If we ever reach here it means that the generated derive
diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs
index c687036f544..c6760b3583f 100644
--- a/compiler/rustc_mir_transform/src/shim.rs
+++ b/compiler/rustc_mir_transform/src/shim.rs
@@ -75,7 +75,7 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceKind<'tcx>) -> Body<
             build_call_shim(tcx, instance, Some(adjustment), CallKind::Direct(def_id))
         }
         ty::InstanceKind::FnPtrShim(def_id, ty) => {
-            let trait_ = tcx.trait_of_assoc(def_id).unwrap();
+            let trait_ = tcx.parent(def_id);
             // Supports `Fn` or `async Fn` traits.
             let adjustment = match tcx
                 .fn_trait_kind_from_def_id(trait_)
diff --git a/compiler/rustc_monomorphize/src/partitioning.rs b/compiler/rustc_monomorphize/src/partitioning.rs
index d76b27d9970..628ea2b63de 100644
--- a/compiler/rustc_monomorphize/src/partitioning.rs
+++ b/compiler/rustc_monomorphize/src/partitioning.rs
@@ -104,7 +104,7 @@ use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
 use rustc_data_structures::sync;
 use rustc_data_structures::unord::{UnordMap, UnordSet};
 use rustc_hir::LangItem;
-use rustc_hir::attrs::InlineAttr;
+use rustc_hir::attrs::{InlineAttr, Linkage};
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{DefId, DefIdSet, LOCAL_CRATE};
 use rustc_hir::definitions::DefPathDataName;
@@ -112,7 +112,7 @@ use rustc_middle::bug;
 use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use rustc_middle::middle::exported_symbols::{SymbolExportInfo, SymbolExportLevel};
 use rustc_middle::mir::mono::{
-    CodegenUnit, CodegenUnitNameBuilder, InstantiationMode, Linkage, MonoItem, MonoItemData,
+    CodegenUnit, CodegenUnitNameBuilder, InstantiationMode, MonoItem, MonoItemData,
     MonoItemPartitions, Visibility,
 };
 use rustc_middle::ty::print::{characteristic_def_id_of_type, with_no_trimmed_paths};
@@ -650,17 +650,18 @@ fn characteristic_def_id_of_mono_item<'tcx>(
             // its self-type. If the self-type does not provide a characteristic
             // DefId, we use the location of the impl after all.
 
-            if tcx.trait_of_assoc(def_id).is_some() {
+            let assoc_parent = tcx.assoc_parent(def_id);
+
+            if let Some((_, DefKind::Trait)) = assoc_parent {
                 let self_ty = instance.args.type_at(0);
                 // This is a default implementation of a trait method.
                 return characteristic_def_id_of_type(self_ty).or(Some(def_id));
             }
 
-            if let Some(impl_def_id) = tcx.impl_of_assoc(def_id) {
-                if tcx.sess.opts.incremental.is_some()
-                    && tcx
-                        .trait_id_of_impl(impl_def_id)
-                        .is_some_and(|def_id| tcx.is_lang_item(def_id, LangItem::Drop))
+            if let Some((impl_def_id, DefKind::Impl { of_trait })) = assoc_parent {
+                if of_trait
+                    && tcx.sess.opts.incremental.is_some()
+                    && tcx.is_lang_item(tcx.trait_id_of_impl(impl_def_id).unwrap(), LangItem::Drop)
                 {
                     // Put `Drop::drop` into the same cgu as `drop_in_place`
                     // since `drop_in_place` is the only thing that can
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index 165f8fe1995..df1db65c06e 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -332,6 +332,9 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
                 &Attribute::Parsed(AttributeKind::Coroutine(attr_span)) => {
                     self.check_coroutine(attr_span, target)
                 }
+                &Attribute::Parsed(AttributeKind::Linkage(_, attr_span)) => {
+                    self.check_linkage(attr_span, span, target);
+                }
                 Attribute::Unparsed(attr_item) => {
                     style = Some(attr_item.style);
                     match attr.path().as_slice() {
@@ -395,7 +398,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
                         [sym::autodiff_forward, ..] | [sym::autodiff_reverse, ..] => {
                             self.check_autodiff(hir_id, attr, span, target)
                         }
-                        [sym::linkage, ..] => self.check_linkage(attr, span, target),
                         [
                             // ok
                             sym::allow
@@ -2707,7 +2709,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
         }
     }
 
-    fn check_linkage(&self, attr: &Attribute, span: Span, target: Target) {
+    fn check_linkage(&self, attr_span: Span, span: Span, target: Target) {
         match target {
             Target::Fn
             | Target::Method(..)
@@ -2715,7 +2717,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
             | Target::ForeignStatic
             | Target::ForeignFn => {}
             _ => {
-                self.dcx().emit_err(errors::Linkage { attr_span: attr.span(), span });
+                self.dcx().emit_err(errors::Linkage { attr_span, span });
             }
         }
     }
diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs
index de52973acbb..08d06402000 100644
--- a/compiler/rustc_passes/src/dead.rs
+++ b/compiler/rustc_passes/src/dead.rs
@@ -371,7 +371,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
     /// will be ignored for the purposes of dead code analysis (see PR #85200
     /// for discussion).
     fn should_ignore_item(&mut self, def_id: DefId) -> bool {
-        if let Some(impl_of) = self.tcx.impl_of_assoc(def_id) {
+        if let Some(impl_of) = self.tcx.trait_impl_of_assoc(def_id) {
             if !self.tcx.is_automatically_derived(impl_of) {
                 return false;
             }
diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index 8526b233ba2..c5fcbdfb42f 100644
--- a/compiler/rustc_resolve/src/diagnostics.rs
+++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -1016,16 +1016,14 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
         .emit()
     }
 
-    /// Lookup typo candidate in scope for a macro or import.
-    fn early_lookup_typo_candidate(
+    pub(crate) fn add_scope_set_candidates(
         &mut self,
+        suggestions: &mut Vec<TypoSuggestion>,
         scope_set: ScopeSet<'ra>,
         parent_scope: &ParentScope<'ra>,
-        ident: Ident,
+        ctxt: SyntaxContext,
         filter_fn: &impl Fn(Res) -> bool,
-    ) -> Option<TypoSuggestion> {
-        let mut suggestions = Vec::new();
-        let ctxt = ident.span.ctxt();
+    ) {
         self.cm().visit_scopes(scope_set, parent_scope, ctxt, |this, scope, use_prelude, _| {
             match scope {
                 Scope::DeriveHelpers(expn_id) => {
@@ -1041,28 +1039,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
                     }
                 }
                 Scope::DeriveHelpersCompat => {
-                    let res = Res::NonMacroAttr(NonMacroAttrKind::DeriveHelperCompat);
-                    if filter_fn(res) {
-                        for derive in parent_scope.derives {
-                            let parent_scope = &ParentScope { derives: &[], ..*parent_scope };
-                            let Ok((Some(ext), _)) = this.reborrow().resolve_macro_path(
-                                derive,
-                                Some(MacroKind::Derive),
-                                parent_scope,
-                                false,
-                                false,
-                                None,
-                                None,
-                            ) else {
-                                continue;
-                            };
-                            suggestions.extend(
-                                ext.helper_attrs
-                                    .iter()
-                                    .map(|name| TypoSuggestion::typo_from_name(*name, res)),
-                            );
-                        }
-                    }
+                    // Never recommend deprecated helper attributes.
                 }
                 Scope::MacroRules(macro_rules_scope) => {
                     if let MacroRulesScope::Binding(macro_rules_binding) = macro_rules_scope.get() {
@@ -1076,7 +1053,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
                     }
                 }
                 Scope::Module(module, _) => {
-                    this.add_module_candidates(module, &mut suggestions, filter_fn, None);
+                    this.add_module_candidates(module, suggestions, filter_fn, None);
                 }
                 Scope::MacroUsePrelude => {
                     suggestions.extend(this.macro_use_prelude.iter().filter_map(
@@ -1134,6 +1111,19 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
 
             None::<()>
         });
+    }
+
+    /// Lookup typo candidate in scope for a macro or import.
+    fn early_lookup_typo_candidate(
+        &mut self,
+        scope_set: ScopeSet<'ra>,
+        parent_scope: &ParentScope<'ra>,
+        ident: Ident,
+        filter_fn: &impl Fn(Res) -> bool,
+    ) -> Option<TypoSuggestion> {
+        let mut suggestions = Vec::new();
+        let ctxt = ident.span.ctxt();
+        self.add_scope_set_candidates(&mut suggestions, scope_set, parent_scope, ctxt, filter_fn);
 
         // Make sure error reporting is deterministic.
         suggestions.sort_by(|a, b| a.candidate.as_str().cmp(b.candidate.as_str()));
diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs
index 7ab932d9f2a..dc01c94af57 100644
--- a/compiler/rustc_resolve/src/ident.rs
+++ b/compiler/rustc_resolve/src/ident.rs
@@ -459,17 +459,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
                         }
                     }
                     Scope::DeriveHelpersCompat => {
-                        // FIXME: Try running this logic earlier, to allocate name bindings for
-                        // legacy derive helpers when creating an attribute invocation with
-                        // following derives. Legacy derive helpers are not common, so it shouldn't
-                        // affect performance. It should also allow to remove the `derives`
-                        // component from `ParentScope`.
                         let mut result = Err(Determinacy::Determined);
                         for derive in parent_scope.derives {
                             let parent_scope = &ParentScope { derives: &[], ..*parent_scope };
                             match this.reborrow().resolve_macro_path(
                                 derive,
-                                Some(MacroKind::Derive),
+                                MacroKind::Derive,
                                 parent_scope,
                                 true,
                                 force,
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index e52cbeb733a..1e4ab57a316 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -4315,7 +4315,6 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
             qself,
             path,
             ns,
-            path_span,
             source.defer_to_typeck(),
             finalize,
             source,
@@ -4438,7 +4437,6 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
         qself: &Option<Box<QSelf>>,
         path: &[Segment],
         primary_ns: Namespace,
-        span: Span,
         defer_to_typeck: bool,
         finalize: Finalize,
         source: PathSource<'_, 'ast, 'ra>,
@@ -4463,21 +4461,11 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
         }
 
         assert!(primary_ns != MacroNS);
-
-        if qself.is_none() {
-            let path_seg = |seg: &Segment| PathSegment::from_ident(seg.ident);
-            let path = Path { segments: path.iter().map(path_seg).collect(), span, tokens: None };
-            if let Ok((_, res)) = self.r.cm().resolve_macro_path(
-                &path,
-                None,
-                &self.parent_scope,
-                false,
-                false,
-                None,
-                None,
-            ) {
-                return Ok(Some(PartialRes::new(res)));
-            }
+        if qself.is_none()
+            && let PathResult::NonModule(res) =
+                self.r.cm().maybe_resolve_path(path, Some(MacroNS), &self.parent_scope, None)
+        {
+            return Ok(Some(res));
         }
 
         Ok(fin_res)
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index c8cab5a0fe9..6a753b38035 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -38,8 +38,8 @@ use crate::late::{
 };
 use crate::ty::fast_reject::SimplifiedType;
 use crate::{
-    Module, ModuleKind, ModuleOrUniformRoot, PathResult, PathSource, Resolver, Segment, errors,
-    path_names_to_string,
+    Module, ModuleKind, ModuleOrUniformRoot, PathResult, PathSource, Resolver, ScopeSet, Segment,
+    errors, path_names_to_string,
 };
 
 type Res = def::Res<ast::NodeId>;
@@ -2458,45 +2458,30 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
                     }
                 }
 
+                if let RibKind::Module(module) = rib.kind
+                    && let ModuleKind::Block = module.kind
+                {
+                    self.r.add_module_candidates(module, &mut names, &filter_fn, Some(ctxt));
+                } else if let RibKind::Module(module) = rib.kind {
+                    // Encountered a module item, abandon ribs and look into that module and preludes.
+                    self.r.add_scope_set_candidates(
+                        &mut names,
+                        ScopeSet::Late(ns, module, None),
+                        &self.parent_scope,
+                        ctxt,
+                        filter_fn,
+                    );
+                    break;
+                }
+
                 if let RibKind::MacroDefinition(def) = rib.kind
                     && def == self.r.macro_def(ctxt)
                 {
                     // If an invocation of this macro created `ident`, give up on `ident`
                     // and switch to `ident`'s source from the macro definition.
                     ctxt.remove_mark();
-                    continue;
-                }
-
-                // Items in scope
-                if let RibKind::Module(module) = rib.kind {
-                    // Items from this module
-                    self.r.add_module_candidates(module, &mut names, &filter_fn, Some(ctxt));
-
-                    if let ModuleKind::Block = module.kind {
-                        // We can see through blocks
-                    } else {
-                        // Items from the prelude
-                        if !module.no_implicit_prelude {
-                            names.extend(self.r.extern_prelude.keys().flat_map(|ident| {
-                                let res = Res::Def(DefKind::Mod, CRATE_DEF_ID.to_def_id());
-                                filter_fn(res)
-                                    .then_some(TypoSuggestion::typo_from_ident(ident.0, res))
-                            }));
-
-                            if let Some(prelude) = self.r.prelude {
-                                self.r.add_module_candidates(prelude, &mut names, &filter_fn, None);
-                            }
-                        }
-                        break;
-                    }
                 }
             }
-            // Add primitive types to the mix
-            if filter_fn(Res::PrimTy(PrimTy::Bool)) {
-                names.extend(PrimTy::ALL.iter().map(|prim_ty| {
-                    TypoSuggestion::typo_from_name(prim_ty.name(), Res::PrimTy(*prim_ty))
-                }))
-            }
         } else {
             // Search in module.
             let mod_path = &path[..path.len() - 1];
diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs
index 9f25635f1fd..72ed8990241 100644
--- a/compiler/rustc_resolve/src/macros.rs
+++ b/compiler/rustc_resolve/src/macros.rs
@@ -398,7 +398,7 @@ impl<'ra, 'tcx> ResolverExpand for Resolver<'ra, 'tcx> {
                 resolution.exts = Some(
                     match self.cm().resolve_macro_path(
                         &resolution.path,
-                        Some(MacroKind::Derive),
+                        MacroKind::Derive,
                         &parent_scope,
                         true,
                         force,
@@ -563,7 +563,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
     ) -> Result<(Arc<SyntaxExtension>, Res), Indeterminate> {
         let (ext, res) = match self.cm().resolve_macro_or_delegation_path(
             path,
-            Some(kind),
+            kind,
             parent_scope,
             true,
             force,
@@ -710,7 +710,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
     pub(crate) fn resolve_macro_path<'r>(
         self: CmResolver<'r, 'ra, 'tcx>,
         path: &ast::Path,
-        kind: Option<MacroKind>,
+        kind: MacroKind,
         parent_scope: &ParentScope<'ra>,
         trace: bool,
         force: bool,
@@ -733,7 +733,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
     fn resolve_macro_or_delegation_path<'r>(
         mut self: CmResolver<'r, 'ra, 'tcx>,
         ast_path: &ast::Path,
-        kind: Option<MacroKind>,
+        kind: MacroKind,
         parent_scope: &ParentScope<'ra>,
         trace: bool,
         force: bool,
@@ -747,7 +747,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
 
         // Possibly apply the macro helper hack
         if deleg_impl.is_none()
-            && kind == Some(MacroKind::Bang)
+            && kind == MacroKind::Bang
             && let [segment] = path.as_slice()
             && segment.ident.span.ctxt().outer_expn_data().local_inner_macros
         {
@@ -775,7 +775,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
             };
 
             if trace {
-                let kind = kind.expect("macro kind must be specified if tracing is enabled");
                 // FIXME: Should be an output of Speculative Resolution.
                 self.multi_segment_macro_resolutions.borrow_mut().push((
                     path,
@@ -790,10 +789,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
             self.prohibit_imported_non_macro_attrs(None, res.ok(), path_span);
             res
         } else {
-            let scope_set = kind.map_or(ScopeSet::All(MacroNS), ScopeSet::Macro);
             let binding = self.reborrow().early_resolve_ident_in_lexical_scope(
                 path[0].ident,
-                scope_set,
+                ScopeSet::Macro(kind),
                 parent_scope,
                 None,
                 force,
@@ -805,7 +803,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
             }
 
             if trace {
-                let kind = kind.expect("macro kind must be specified if tracing is enabled");
                 // FIXME: Should be an output of Speculative Resolution.
                 self.single_segment_macro_resolutions.borrow_mut().push((
                     path[0].ident,
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index acbed7a9eed..416ce27367e 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -545,6 +545,7 @@ symbols! {
         autodiff_forward,
         autodiff_reverse,
         automatically_derived,
+        available_externally,
         avx,
         avx10_target_feature,
         avx512_target_feature,
@@ -676,6 +677,7 @@ symbols! {
         cold_path,
         collapse_debuginfo,
         column,
+        common,
         compare_bytes,
         compare_exchange,
         compare_exchange_weak,
@@ -956,6 +958,7 @@ symbols! {
         extern_prelude,
         extern_system_varargs,
         extern_types,
+        extern_weak,
         external,
         external_doc,
         f,
@@ -1213,6 +1216,7 @@ symbols! {
         instruction_set,
         integer_: "integer", // underscore to avoid clashing with the function `sym::integer` below
         integral,
+        internal,
         internal_features,
         into_async_iter_into_iter,
         into_future,
@@ -1287,6 +1291,8 @@ symbols! {
         linkage,
         linker,
         linker_messages,
+        linkonce,
+        linkonce_odr,
         lint_reasons,
         literal,
         load,
@@ -2360,6 +2366,8 @@ symbols! {
         wasm_abi,
         wasm_import_module,
         wasm_target_feature,
+        weak,
+        weak_odr,
         where_clause_attrs,
         while_let,
         width,
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index 581191b2036..884d53732fe 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -1507,7 +1507,7 @@ fn confirm_builtin_candidate<'cx, 'tcx>(
     let tcx = selcx.tcx();
     let self_ty = obligation.predicate.self_ty();
     let item_def_id = obligation.predicate.def_id;
-    let trait_def_id = tcx.trait_of_assoc(item_def_id).unwrap();
+    let trait_def_id = tcx.parent(item_def_id);
     let args = tcx.mk_args(&[self_ty.into()]);
     let (term, obligations) = if tcx.is_lang_item(trait_def_id, LangItem::DiscriminantKind) {
         let discriminant_def_id =
diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs
index 6546dde39ac..c5f0cb8016e 100644
--- a/library/core/src/ptr/const_ptr.rs
+++ b/library/core/src/ptr/const_ptr.rs
@@ -1569,6 +1569,15 @@ impl<T> *const [T] {
     }
 }
 
+impl<T> *const T {
+    /// Casts from a pointer-to-`T` to a pointer-to-`[T; N]`.
+    #[inline]
+    #[unstable(feature = "ptr_cast_array", issue = "144514")]
+    pub const fn cast_array<const N: usize>(self) -> *const [T; N] {
+        self.cast()
+    }
+}
+
 impl<T, const N: usize> *const [T; N] {
     /// Returns a raw pointer to the array's buffer.
     ///
diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs
index 4add964141a..3fe4b08d459 100644
--- a/library/core/src/ptr/mut_ptr.rs
+++ b/library/core/src/ptr/mut_ptr.rs
@@ -1990,6 +1990,15 @@ impl<T> *mut [T] {
     }
 }
 
+impl<T> *mut T {
+    /// Casts from a pointer-to-`T` to a pointer-to-`[T; N]`.
+    #[inline]
+    #[unstable(feature = "ptr_cast_array", issue = "144514")]
+    pub const fn cast_array<const N: usize>(self) -> *mut [T; N] {
+        self.cast()
+    }
+}
+
 impl<T, const N: usize> *mut [T; N] {
     /// Returns a raw pointer to the array's buffer.
     ///
diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs
index da382b8715e..117eb18826e 100644
--- a/library/core/src/ptr/non_null.rs
+++ b/library/core/src/ptr/non_null.rs
@@ -193,6 +193,13 @@ impl<T: Sized> NonNull<T> {
         // requirements for a reference.
         unsafe { &mut *self.cast().as_ptr() }
     }
+
+    /// Casts from a pointer-to-`T` to a pointer-to-`[T; N]`.
+    #[inline]
+    #[unstable(feature = "ptr_cast_array", issue = "144514")]
+    pub const fn cast_array<const N: usize>(self) -> NonNull<[T; N]> {
+        self.cast()
+    }
 }
 
 impl<T: PointeeSized> NonNull<T> {
diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs
index 64f5b5dd831..dfbb3628350 100644
--- a/library/core/src/slice/mod.rs
+++ b/library/core/src/slice/mod.rs
@@ -328,7 +328,7 @@ impl<T> [T] {
         } else {
             // SAFETY: We explicitly check for the correct number of elements,
             //   and do not let the reference outlive the slice.
-            Some(unsafe { &*(self.as_ptr().cast::<[T; N]>()) })
+            Some(unsafe { &*(self.as_ptr().cast_array()) })
         }
     }
 
@@ -359,7 +359,7 @@ impl<T> [T] {
             // SAFETY: We explicitly check for the correct number of elements,
             //   do not let the reference outlive the slice,
             //   and require exclusive access to the entire slice to mutate the chunk.
-            Some(unsafe { &mut *(self.as_mut_ptr().cast::<[T; N]>()) })
+            Some(unsafe { &mut *(self.as_mut_ptr().cast_array()) })
         }
     }
 
@@ -387,7 +387,7 @@ impl<T> [T] {
 
         // SAFETY: We explicitly check for the correct number of elements,
         //   and do not let the references outlive the slice.
-        Some((unsafe { &*(first.as_ptr().cast::<[T; N]>()) }, tail))
+        Some((unsafe { &*(first.as_ptr().cast_array()) }, tail))
     }
 
     /// Returns a mutable array reference to the first `N` items in the slice and the remaining
@@ -420,7 +420,7 @@ impl<T> [T] {
         // SAFETY: We explicitly check for the correct number of elements,
         //   do not let the reference outlive the slice,
         //   and enforce exclusive mutability of the chunk by the split.
-        Some((unsafe { &mut *(first.as_mut_ptr().cast::<[T; N]>()) }, tail))
+        Some((unsafe { &mut *(first.as_mut_ptr().cast_array()) }, tail))
     }
 
     /// Returns an array reference to the last `N` items in the slice and the remaining slice.
@@ -448,7 +448,7 @@ impl<T> [T] {
 
         // SAFETY: We explicitly check for the correct number of elements,
         //   and do not let the references outlive the slice.
-        Some((init, unsafe { &*(last.as_ptr().cast::<[T; N]>()) }))
+        Some((init, unsafe { &*(last.as_ptr().cast_array()) }))
     }
 
     /// Returns a mutable array reference to the last `N` items in the slice and the remaining
@@ -482,7 +482,7 @@ impl<T> [T] {
         // SAFETY: We explicitly check for the correct number of elements,
         //   do not let the reference outlive the slice,
         //   and enforce exclusive mutability of the chunk by the split.
-        Some((init, unsafe { &mut *(last.as_mut_ptr().cast::<[T; N]>()) }))
+        Some((init, unsafe { &mut *(last.as_mut_ptr().cast_array()) }))
     }
 
     /// Returns an array reference to the last `N` items in the slice.
@@ -511,7 +511,7 @@ impl<T> [T] {
 
         // SAFETY: We explicitly check for the correct number of elements,
         //   and do not let the references outlive the slice.
-        Some(unsafe { &*(last.as_ptr().cast::<[T; N]>()) })
+        Some(unsafe { &*(last.as_ptr().cast_array()) })
     }
 
     /// Returns a mutable array reference to the last `N` items in the slice.
@@ -542,7 +542,7 @@ impl<T> [T] {
         // SAFETY: We explicitly check for the correct number of elements,
         //   do not let the reference outlive the slice,
         //   and require exclusive access to the entire slice to mutate the chunk.
-        Some(unsafe { &mut *(last.as_mut_ptr().cast::<[T; N]>()) })
+        Some(unsafe { &mut *(last.as_mut_ptr().cast_array()) })
     }
 
     /// Returns a reference to an element or subslice depending on the type of
@@ -846,7 +846,7 @@ impl<T> [T] {
     #[must_use]
     pub const fn as_array<const N: usize>(&self) -> Option<&[T; N]> {
         if self.len() == N {
-            let ptr = self.as_ptr() as *const [T; N];
+            let ptr = self.as_ptr().cast_array();
 
             // SAFETY: The underlying array of a slice can be reinterpreted as an actual array `[T; N]` if `N` is not greater than the slice's length.
             let me = unsafe { &*ptr };
@@ -864,7 +864,7 @@ impl<T> [T] {
     #[must_use]
     pub const fn as_mut_array<const N: usize>(&mut self) -> Option<&mut [T; N]> {
         if self.len() == N {
-            let ptr = self.as_mut_ptr() as *mut [T; N];
+            let ptr = self.as_mut_ptr().cast_array();
 
             // SAFETY: The underlying array of a slice can be reinterpreted as an actual array `[T; N]` if `N` is not greater than the slice's length.
             let me = unsafe { &mut *ptr };
diff --git a/library/coretests/tests/io/borrowed_buf.rs b/library/coretests/tests/io/borrowed_buf.rs
index 4074148436c..aaa98d26ff8 100644
--- a/library/coretests/tests/io/borrowed_buf.rs
+++ b/library/coretests/tests/io/borrowed_buf.rs
@@ -66,7 +66,7 @@ fn clear() {
 
 #[test]
 fn set_init() {
-    let buf: &mut [_] = &mut [MaybeUninit::uninit(); 16];
+    let buf: &mut [_] = &mut [MaybeUninit::zeroed(); 16];
     let mut rbuf: BorrowedBuf<'_> = buf.into();
 
     unsafe {
@@ -134,7 +134,7 @@ fn reborrow_written() {
 
 #[test]
 fn cursor_set_init() {
-    let buf: &mut [_] = &mut [MaybeUninit::uninit(); 16];
+    let buf: &mut [_] = &mut [MaybeUninit::zeroed(); 16];
     let mut rbuf: BorrowedBuf<'_> = buf.into();
 
     unsafe {
diff --git a/library/std/src/sync/mpsc.rs b/library/std/src/sync/mpsc.rs
index 41d1dd3ce67..03d7fddc2fa 100644
--- a/library/std/src/sync/mpsc.rs
+++ b/library/std/src/sync/mpsc.rs
@@ -697,14 +697,14 @@ impl<T> SyncSender<T> {
     /// let sync_sender2 = sync_sender.clone();
     ///
     /// // First thread owns sync_sender
-    /// thread::spawn(move || {
+    /// let handle1 = thread::spawn(move || {
     ///     sync_sender.send(1).unwrap();
     ///     sync_sender.send(2).unwrap();
     ///     // Thread blocked
     /// });
     ///
     /// // Second thread owns sync_sender2
-    /// thread::spawn(move || {
+    /// let handle2 = thread::spawn(move || {
     ///     // This will return an error and send
     ///     // no message if the buffer is full
     ///     let _ = sync_sender2.try_send(3);
@@ -722,6 +722,10 @@ impl<T> SyncSender<T> {
     ///     Ok(msg) => println!("message {msg} received"),
     ///     Err(_) => println!("the third message was never sent"),
     /// }
+    ///
+    /// // Wait for threads to complete
+    /// handle1.join().unwrap();
+    /// handle2.join().unwrap();
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn try_send(&self, t: T) -> Result<(), TrySendError<T>> {
diff --git a/library/std/src/sys_common/mod.rs b/library/std/src/sys_common/mod.rs
index cce88d936b7..24b6cff1309 100644
--- a/library/std/src/sys_common/mod.rs
+++ b/library/std/src/sys_common/mod.rs
@@ -51,17 +51,16 @@ pub trait FromInner<Inner> {
     fn from_inner(inner: Inner) -> Self;
 }
 
-// Computes (value*numer)/denom without overflow, as long as both
-// (numer*denom) and the overall result fit into i64 (which is the case
-// for our time conversions).
+// Computes (value*numerator)/denom without overflow, as long as both (numerator*denom) and the
+// overall result fit into i64 (which is the case for our time conversions).
 #[allow(dead_code)] // not used on all platforms
-pub fn mul_div_u64(value: u64, numer: u64, denom: u64) -> u64 {
+pub fn mul_div_u64(value: u64, numerator: u64, denom: u64) -> u64 {
     let q = value / denom;
     let r = value % denom;
     // Decompose value as (value/denom*denom + value%denom),
-    // substitute into (value*numer)/denom and simplify.
-    // r < denom, so (denom*numer) is the upper bound of (r*numer)
-    q * numer + r * numer / denom
+    // substitute into (value*numerator)/denom and simplify.
+    // r < denom, so (denom*numerator) is the upper bound of (r*numerator)
+    q * numerator + r * numerator / denom
 }
 
 pub fn ignore_notfound<T>(result: crate::io::Result<T>) -> crate::io::Result<()> {
diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md
index b942e4bfa61..b53494ed98d 100644
--- a/src/doc/rustc/src/SUMMARY.md
+++ b/src/doc/rustc/src/SUMMARY.md
@@ -23,6 +23,7 @@
 - [Linker-plugin-based LTO](linker-plugin-lto.md)
 - [Checking Conditional Configurations](check-cfg.md)
     - [Cargo Specifics](check-cfg/cargo-specifics.md)
+- [Remap source paths](remap-source-paths.md)
 - [Exploit Mitigations](exploit-mitigations.md)
 - [Symbol Mangling](symbol-mangling/index.md)
     - [v0 Symbol Format](symbol-mangling/v0.md)
diff --git a/src/doc/rustc/src/command-line-arguments.md b/src/doc/rustc/src/command-line-arguments.md
index d45ad1be27b..0b15fbc24df 100644
--- a/src/doc/rustc/src/command-line-arguments.md
+++ b/src/doc/rustc/src/command-line-arguments.md
@@ -418,22 +418,15 @@ This flag takes a number that specifies the width of the terminal in characters.
 Formatting of diagnostics will take the width into consideration to make them better fit on the screen.
 
 <a id="option-remap-path-prefix"></a>
-## `--remap-path-prefix`: remap source names in output
+## `--remap-path-prefix`: remap source paths in output
 
 Remap source path prefixes in all output, including compiler diagnostics,
-debug information, macro expansions, etc. It takes a value of the form
-`FROM=TO` where a path prefix equal to `FROM` is rewritten to the value `TO`.
-The `FROM` may itself contain an `=` symbol, but the `TO` value may not. This
-flag may be specified multiple times.
-
-This is useful for normalizing build products, for example by removing the
-current directory out of pathnames emitted into the object files. The
-replacement is purely textual, with no consideration of the current system's
-pathname syntax. For example `--remap-path-prefix foo=bar` will match
-`foo/lib.rs` but not `./foo/lib.rs`.
-
-When multiple remappings are given and several of them match, the **last**
-matching one is applied.
+debug information, macro expansions, etc. It takes a value of the form `FROM=TO`
+where a path prefix equal to `FROM` is rewritten to the value `TO`. This flag may be
+specified multiple times.
+
+Refer to the [Remap source paths](remap-source-paths.md) section of this book for
+further details and explanation.
 
 <a id="option-json"></a>
 ## `--json`: configure json messages printed by the compiler
diff --git a/src/doc/rustc/src/remap-source-paths.md b/src/doc/rustc/src/remap-source-paths.md
new file mode 100644
index 00000000000..03f5d98091c
--- /dev/null
+++ b/src/doc/rustc/src/remap-source-paths.md
@@ -0,0 +1,53 @@
+# Remap source paths
+
+`rustc` supports remapping source paths prefixes **as a best effort** in all compiler generated
+output, including compiler diagnostics, debugging information, macro expansions, etc.
+
+This is useful for normalizing build products, for example by removing the current directory
+out of the paths emitted into object files.
+
+The remapping is done via the `--remap-path-prefix` option.
+
+## `--remap-path-prefix`
+
+It takes a value of the form `FROM=TO` where a path prefix equal to `FROM` is rewritten
+to the value `TO`. `FROM` may itself contain an `=` symbol, but `TO` value may not.
+
+The replacement is purely textual, with no consideration of the current system's path separator.
+
+When multiple remappings are given and several of them match, the **last** matching one is applied.
+
+### Example
+
+```bash
+rustc --remap-path-prefix "/home/user/project=/redacted"
+```
+
+This example replaces all occurrences of `/home/user/project` in emitted paths with `/redacted`.
+
+## Caveats and Limitations
+
+### Linkers generated paths
+
+On some platforms like `x86_64-pc-windows-msvc`, the linker may embed absolute host paths and compiler
+arguments into debug info files (like `.pdb`) independently of `rustc`.
+
+Additionally, on Apple platforms, linkers generate [OSO entries] which are not remapped by the compiler
+and need to be manually remapped with `-oso_prefix`.
+
+The `--remap-path-prefix` option does not affect these linker-generated paths.
+
+### Textual replacement only
+
+The remapping is strictly textual and does not account for different path separator conventions across
+platforms. Care must be taken when specifying prefixes, especially on Windows where both `/` and `\` may
+appear in paths.
+
+### External tools
+
+Paths introduced by external tools or environment variables may not be covered by `--remap-path-prefix`
+unless explicitly accounted for.
+
+For example, generated code introduced by Cargo's build script may still contain un-remapped paths.
+
+[OSO entries]: https://wiki.dwarfstd.org/Apple%27s_%22Lazy%22_DWARF_Scheme.md
diff --git a/src/librustdoc/html/markdown/footnotes.rs b/src/librustdoc/html/markdown/footnotes.rs
index 7ee012c4da2..a81d8dd6035 100644
--- a/src/librustdoc/html/markdown/footnotes.rs
+++ b/src/librustdoc/html/markdown/footnotes.rs
@@ -23,6 +23,8 @@ struct FootnoteDef<'a> {
     content: Vec<Event<'a>>,
     /// The number that appears in the footnote reference and list.
     id: usize,
+    /// The number of footnote references.
+    num_refs: usize,
 }
 
 impl<'a, I: Iterator<Item = SpannedEvent<'a>>> Footnotes<'a, I> {
@@ -33,21 +35,25 @@ impl<'a, I: Iterator<Item = SpannedEvent<'a>>> Footnotes<'a, I> {
         Footnotes { inner: iter, footnotes: FxIndexMap::default(), existing_footnotes, start_id }
     }
 
-    fn get_entry(&mut self, key: &str) -> (&mut Vec<Event<'a>>, usize) {
+    fn get_entry(&mut self, key: &str) -> (&mut Vec<Event<'a>>, usize, &mut usize) {
         let new_id = self.footnotes.len() + 1 + self.start_id;
         let key = key.to_owned();
-        let FootnoteDef { content, id } =
-            self.footnotes.entry(key).or_insert(FootnoteDef { content: Vec::new(), id: new_id });
+        let FootnoteDef { content, id, num_refs } = self
+            .footnotes
+            .entry(key)
+            .or_insert(FootnoteDef { content: Vec::new(), id: new_id, num_refs: 0 });
         // Don't allow changing the ID of existing entries, but allow changing the contents.
-        (content, *id)
+        (content, *id, num_refs)
     }
 
     fn handle_footnote_reference(&mut self, reference: &CowStr<'a>) -> Event<'a> {
         // When we see a reference (to a footnote we may not know) the definition of,
         // reserve a number for it, and emit a link to that number.
-        let (_, id) = self.get_entry(reference);
+        let (_, id, num_refs) = self.get_entry(reference);
+        *num_refs += 1;
+        let fnref_suffix = if *num_refs <= 1 { "".to_owned() } else { format!("-{num_refs}") };
         let reference = format!(
-            "<sup id=\"fnref{0}\"><a href=\"#fn{0}\">{1}</a></sup>",
+            "<sup id=\"fnref{0}{fnref_suffix}\"><a href=\"#fn{0}\">{1}</a></sup>",
             id,
             // Although the ID count is for the whole page, the footnote reference
             // are local to the item so we make this ID "local" when displayed.
@@ -85,7 +91,7 @@ impl<'a, I: Iterator<Item = SpannedEvent<'a>>> Iterator for Footnotes<'a, I> {
                     // When we see a footnote definition, collect the associated content, and store
                     // that for rendering later.
                     let content = self.collect_footnote_def();
-                    let (entry_content, _) = self.get_entry(&def);
+                    let (entry_content, _, _) = self.get_entry(&def);
                     *entry_content = content;
                 }
                 Some(e) => return Some(e),
@@ -113,7 +119,7 @@ fn render_footnotes_defs(mut footnotes: Vec<FootnoteDef<'_>>) -> String {
     // browser generated for <li> are right.
     footnotes.sort_by_key(|x| x.id);
 
-    for FootnoteDef { mut content, id } in footnotes {
+    for FootnoteDef { mut content, id, num_refs } in footnotes {
         write!(ret, "<li id=\"fn{id}\">").unwrap();
         let mut is_paragraph = false;
         if let Some(&Event::End(TagEnd::Paragraph)) = content.last() {
@@ -121,7 +127,16 @@ fn render_footnotes_defs(mut footnotes: Vec<FootnoteDef<'_>>) -> String {
             is_paragraph = true;
         }
         html::push_html(&mut ret, content.into_iter());
-        write!(ret, "&nbsp;<a href=\"#fnref{id}\">↩</a>").unwrap();
+        if num_refs <= 1 {
+            write!(ret, "&nbsp;<a href=\"#fnref{id}\">↩</a>").unwrap();
+        } else {
+            // There are multiple references to single footnote. Make the first
+            // back link a single "a" element to make touch region larger.
+            write!(ret, "&nbsp;<a href=\"#fnref{id}\">↩&nbsp;<sup>1</sup></a>").unwrap();
+            for refid in 2..=num_refs {
+                write!(ret, "&nbsp;<sup><a href=\"#fnref{id}-{refid}\">{refid}</a></sup>").unwrap();
+            }
+        }
         if is_paragraph {
             ret.push_str("</p>");
         }
diff --git a/src/tools/miri/src/helpers.rs b/src/tools/miri/src/helpers.rs
index a8e2151afe6..1b5d9d50996 100644
--- a/src/tools/miri/src/helpers.rs
+++ b/src/tools/miri/src/helpers.rs
@@ -32,6 +32,8 @@ pub enum AccessKind {
 ///
 /// A `None` namespace indicates we are looking for a module.
 fn try_resolve_did(tcx: TyCtxt<'_>, path: &[&str], namespace: Option<Namespace>) -> Option<DefId> {
+    let _trace = enter_trace_span!("try_resolve_did", ?path);
+
     /// Yield all children of the given item, that have the given name.
     fn find_children<'tcx: 'a, 'a>(
         tcx: TyCtxt<'tcx>,
diff --git a/src/tools/miri/src/shims/time.rs b/src/tools/miri/src/shims/time.rs
index b5b35797fec..6e56fdfe35a 100644
--- a/src/tools/miri/src/shims/time.rs
+++ b/src/tools/miri/src/shims/time.rs
@@ -322,8 +322,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
 
         // Since our emulated ticks in `mach_absolute_time` *are* nanoseconds,
         // no scaling needs to happen.
-        let (numer, denom) = (1, 1);
-        this.write_int_fields(&[numer.into(), denom.into()], &info)?;
+        let (numerator, denom) = (1, 1);
+        this.write_int_fields(&[numerator.into(), denom.into()], &info)?;
 
         interp_ok(Scalar::from_i32(0)) // KERN_SUCCESS
     }
diff --git a/src/tools/unicode-table-generator/src/raw_emitter.rs b/src/tools/unicode-table-generator/src/raw_emitter.rs
index e9e0efc4594..03ed9499e26 100644
--- a/src/tools/unicode-table-generator/src/raw_emitter.rs
+++ b/src/tools/unicode-table-generator/src/raw_emitter.rs
@@ -341,7 +341,7 @@ impl Canonicalized {
         for &w in unique_words {
             unique_mapping.entry(w).or_insert_with(|| {
                 canonical_words.push(w);
-                UniqueMapping::Canonical(canonical_words.len())
+                UniqueMapping::Canonical(canonical_words.len() - 1)
             });
         }
         assert_eq!(canonicalized_words.len() + canonical_words.len(), unique_words.len());
diff --git a/tests/rustdoc/footnote-reference-ids.rs b/tests/rustdoc/footnote-reference-ids.rs
new file mode 100644
index 00000000000..ffa04e1d767
--- /dev/null
+++ b/tests/rustdoc/footnote-reference-ids.rs
@@ -0,0 +1,23 @@
+// This test ensures that multiple references to a single footnote and
+// corresponding back links work as expected.
+
+#![crate_name = "foo"]
+
+//@ has 'foo/index.html'
+//@ has - '//*[@class="docblock"]/p/sup[@id="fnref1"]/a[@href="#fn1"]' '1'
+//@ has - '//*[@class="docblock"]/p/sup[@id="fnref2"]/a[@href="#fn2"]' '2'
+//@ has - '//*[@class="docblock"]/p/sup[@id="fnref2-2"]/a[@href="#fn2"]' '2'
+//@ has - '//li[@id="fn1"]/p' 'meow'
+//@ has - '//li[@id="fn1"]/p/a[@href="#fnref1"]' '↩'
+//@ has - '//li[@id="fn2"]/p' 'uwu'
+//@ has - '//li[@id="fn2"]/p/a[@href="#fnref2"]/sup' '1'
+//@ has - '//li[@id="fn2"]/p/sup/a[@href="#fnref2-2"]' '2'
+
+//! # Footnote, references and back links
+//!
+//! Single: [^a].
+//!
+//! Double: [^b] [^b].
+//!
+//! [^a]: meow
+//! [^b]: uwu
diff --git a/tests/rustdoc/footnote-reference-in-footnote-def.rs b/tests/rustdoc/footnote-reference-in-footnote-def.rs
index db3f9a59ef8..504d0bdb8f7 100644
--- a/tests/rustdoc/footnote-reference-in-footnote-def.rs
+++ b/tests/rustdoc/footnote-reference-in-footnote-def.rs
@@ -9,7 +9,7 @@
 //@ has - '//li[@id="fn1"]/p/sup[@id="fnref2"]/a[@href="#fn2"]' '2'
 //@ has - '//li[@id="fn1"]//a[@href="#fn2"]' '2'
 //@ has - '//li[@id="fn2"]/p' 'uwu'
-//@ has - '//li[@id="fn2"]/p/sup[@id="fnref1"]/a[@href="#fn1"]' '1'
+//@ has - '//li[@id="fn2"]/p/sup[@id="fnref1-2"]/a[@href="#fn1"]' '1'
 //@ has - '//li[@id="fn2"]//a[@href="#fn1"]' '1'
 
 //! # footnote-hell
diff --git a/tests/ui/attributes/auxiliary/derive_macro_with_helper.rs b/tests/ui/attributes/auxiliary/derive_macro_with_helper.rs
new file mode 100644
index 00000000000..128af50ce36
--- /dev/null
+++ b/tests/ui/attributes/auxiliary/derive_macro_with_helper.rs
@@ -0,0 +1,8 @@
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+
+#[proc_macro_derive(Derive, attributes(arg))]
+pub fn derive(_: TokenStream) -> TokenStream {
+    TokenStream::new()
+}
diff --git a/tests/ui/attributes/helper-attr-interpolated-non-lit-arg.rs b/tests/ui/attributes/helper-attr-interpolated-non-lit-arg.rs
new file mode 100644
index 00000000000..17c9ad1bd48
--- /dev/null
+++ b/tests/ui/attributes/helper-attr-interpolated-non-lit-arg.rs
@@ -0,0 +1,20 @@
+// Regression test for <https://github.com/rust-lang/rust/issues/140612>.
+//@ proc-macro: derive_macro_with_helper.rs
+//@ edition: 2018
+//@ check-pass
+
+macro_rules! expand {
+    ($text:expr) => {
+        #[derive(derive_macro_with_helper::Derive)]
+        // This inert attr is completely valid because it follows the grammar
+        // `#` `[` SimplePath DelimitedTokenStream `]`.
+        // However, we used to incorrectly delay a bug here and ICE when trying to parse `$text` as
+        // the inside of a "meta item list" which may only begin with literals or paths.
+        #[arg($text)]
+        pub struct Foo;
+    };
+}
+
+expand!(1 + 1);
+
+fn main() {}
diff --git a/tests/ui/attributes/malformed-attrs.stderr b/tests/ui/attributes/malformed-attrs.stderr
index 705050e9a7d..aa4891459aa 100644
--- a/tests/ui/attributes/malformed-attrs.stderr
+++ b/tests/ui/attributes/malformed-attrs.stderr
@@ -90,25 +90,6 @@ error: malformed `cfi_encoding` attribute input
 LL | #[cfi_encoding]
    | ^^^^^^^^^^^^^^^ help: must be of the form: `#[cfi_encoding = "encoding"]`
 
-error: malformed `linkage` attribute input
-  --> $DIR/malformed-attrs.rs:170:5
-   |
-LL |     #[linkage]
-   |     ^^^^^^^^^^
-   |
-   = note: for more information, visit <https://doc.rust-lang.org/reference/linkage.html>
-help: the following are the possible correct uses
-   |
-LL |     #[linkage = "available_externally"]
-   |               ++++++++++++++++++++++++
-LL |     #[linkage = "common"]
-   |               ++++++++++
-LL |     #[linkage = "extern_weak"]
-   |               +++++++++++++++
-LL |     #[linkage = "external"]
-   |               ++++++++++++
-   = and 5 other candidates
-
 error: malformed `allow` attribute input
   --> $DIR/malformed-attrs.rs:175:1
    |
@@ -659,6 +640,24 @@ LL |     #[unsafe(ffi_const = 1)]
    |     |                  didn't expect any arguments here
    |     help: must be of the form: `#[ffi_const]`
 
+error[E0539]: malformed `linkage` attribute input
+  --> $DIR/malformed-attrs.rs:170:5
+   |
+LL |     #[linkage]
+   |     ^^^^^^^^^^ expected this to be of the form `linkage = "..."`
+   |
+help: try changing it to one of the following valid forms of the attribute
+   |
+LL |     #[linkage = "available_externally"]
+   |               ++++++++++++++++++++++++
+LL |     #[linkage = "common"]
+   |               ++++++++++
+LL |     #[linkage = "extern_weak"]
+   |               +++++++++++++++
+LL |     #[linkage = "external"]
+   |               ++++++++++++
+   = and 5 other candidates
+
 error[E0565]: malformed `automatically_derived` attribute input
   --> $DIR/malformed-attrs.rs:188:1
    |
diff --git a/tests/ui/hygiene/arguments.stderr b/tests/ui/hygiene/arguments.stderr
index 0d8d652b6f3..fe92daf6437 100644
--- a/tests/ui/hygiene/arguments.stderr
+++ b/tests/ui/hygiene/arguments.stderr
@@ -1,6 +1,9 @@
 error[E0412]: cannot find type `S` in this scope
   --> $DIR/arguments.rs:14:8
    |
+LL |         struct S;
+   |                - you might have meant to refer to this struct
+...
 LL |     m!(S, S);
    |        ^ not found in this scope
 
diff --git a/tests/ui/hygiene/cross-crate-name-hiding-2.stderr b/tests/ui/hygiene/cross-crate-name-hiding-2.stderr
index a5d509fab99..fe3a12e93a7 100644
--- a/tests/ui/hygiene/cross-crate-name-hiding-2.stderr
+++ b/tests/ui/hygiene/cross-crate-name-hiding-2.stderr
@@ -3,6 +3,11 @@ error[E0422]: cannot find struct, variant or union type `MyStruct` in this scope
    |
 LL |     let x = MyStruct {};
    |             ^^^^^^^^ not found in this scope
+   |
+  ::: $DIR/auxiliary/use_by_macro.rs:15:1
+   |
+LL | x!(my_struct);
+   | ------------- you might have meant to refer to this struct
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/hygiene/globs.stderr b/tests/ui/hygiene/globs.stderr
index 31f25b182f1..85946bf34bc 100644
--- a/tests/ui/hygiene/globs.stderr
+++ b/tests/ui/hygiene/globs.stderr
@@ -48,7 +48,10 @@ error[E0425]: cannot find function `f` in this scope
   --> $DIR/globs.rs:61:12
    |
 LL | n!(f);
-   | ----- in this macro invocation
+   | -----
+   | |  |
+   | |  you might have meant to refer to this function
+   | in this macro invocation
 ...
 LL |                     $j();
    |                     -- due to this macro variable
@@ -56,15 +59,16 @@ LL |                     $j();
 LL |         n!(f);
    |            ^ not found in this scope
    |
-   = help: consider importing this function:
-           foo::f
    = note: this error originates in the macro `n` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0425]: cannot find function `f` in this scope
   --> $DIR/globs.rs:65:17
    |
 LL | n!(f);
-   | ----- in this macro invocation
+   | -----
+   | |  |
+   | |  you might have meant to refer to this function
+   | in this macro invocation
 ...
 LL |                     $j();
    |                     -- due to this macro variable
@@ -72,8 +76,6 @@ LL |                     $j();
 LL |                 f
    |                 ^ not found in this scope
    |
-   = help: consider importing this function:
-           foo::f
    = note: this error originates in the macro `n` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to 4 previous errors
diff --git a/tests/ui/linkage-attr/linkage3.rs b/tests/ui/linkage-attr/linkage3.rs
index f95e5eecc48..74a6fd6600b 100644
--- a/tests/ui/linkage-attr/linkage3.rs
+++ b/tests/ui/linkage-attr/linkage3.rs
@@ -5,7 +5,7 @@
 extern "C" {
     #[linkage = "foo"]
     static foo: *const i32;
-//~^ ERROR: invalid linkage specified
+//~^^ ERROR: malformed `linkage` attribute input [E0539]
 }
 
 fn main() {
diff --git a/tests/ui/linkage-attr/linkage3.stderr b/tests/ui/linkage-attr/linkage3.stderr
index 5f7b7ef227c..f1215f09aea 100644
--- a/tests/ui/linkage-attr/linkage3.stderr
+++ b/tests/ui/linkage-attr/linkage3.stderr
@@ -1,8 +1,27 @@
-error: invalid linkage specified
-  --> $DIR/linkage3.rs:7:5
+error[E0539]: malformed `linkage` attribute input
+  --> $DIR/linkage3.rs:6:5
    |
-LL |     static foo: *const i32;
-   |     ^^^^^^^^^^^^^^^^^^^^^^
+LL |     #[linkage = "foo"]
+   |     ^^^^^^^^^^^^-----^
+   |                 |
+   |                 valid arguments are `available_externally`, `common`, `extern_weak`, `external`, `internal`, `linkonce`, `linkonce_odr`, `weak` or `weak_odr`
+   |
+help: try changing it to one of the following valid forms of the attribute
+   |
+LL -     #[linkage = "foo"]
+LL +     #[linkage = "available_externally"]
+   |
+LL -     #[linkage = "foo"]
+LL +     #[linkage = "common"]
+   |
+LL -     #[linkage = "foo"]
+LL +     #[linkage = "extern_weak"]
+   |
+LL -     #[linkage = "foo"]
+LL +     #[linkage = "external"]
+   |
+   = and 5 other candidates
 
 error: aborting due to 1 previous error
 
+For more information about this error, try `rustc --explain E0539`.
diff --git a/tests/ui/proc-macro/proc-macro-attributes.stderr b/tests/ui/proc-macro/proc-macro-attributes.stderr
index 2cc57383eb3..892728901fb 100644
--- a/tests/ui/proc-macro/proc-macro-attributes.stderr
+++ b/tests/ui/proc-macro/proc-macro-attributes.stderr
@@ -2,7 +2,13 @@ error: cannot find attribute `C` in this scope
   --> $DIR/proc-macro-attributes.rs:9:3
    |
 LL | #[C]
-   |   ^ help: a derive helper attribute with a similar name exists: `B`
+   |   ^
+   |
+help: the derive macro `B` accepts the similarly named `B` attribute
+   |
+LL - #[C]
+LL + #[B]
+   |
 
 error[E0659]: `B` is ambiguous
   --> $DIR/proc-macro-attributes.rs:6:3
diff --git a/tests/ui/typeck/suggestions/suggest-add-wrapper-issue-145294.rs b/tests/ui/typeck/suggestions/suggest-add-wrapper-issue-145294.rs
new file mode 100644
index 00000000000..cfe167cf88d
--- /dev/null
+++ b/tests/ui/typeck/suggestions/suggest-add-wrapper-issue-145294.rs
@@ -0,0 +1,26 @@
+// Suppress the suggestion that adding a wrapper.
+// When expected_ty and expr_ty are the same ADT,
+// we prefer to compare their internal generic params,
+// so when the current variant corresponds to an unresolved infer,
+// the suggestion is rejected.
+// e.g. `Ok(Some("hi"))` is type of `Result<Option<&str>, _>`,
+// where `E` is still an unresolved inference variable.
+
+fn foo() -> Result<Option<String>, ()> {
+    todo!()
+}
+
+#[derive(PartialEq, Debug)]
+enum Bar<T, E> {
+    A(T),
+    B(E),
+}
+
+fn bar() -> Bar<String, ()> {
+    todo!()
+}
+
+fn main() {
+    assert_eq!(Ok(Some("hi")), foo()); //~ ERROR mismatched types [E0308]
+    assert_eq!(Bar::A("hi"), bar()); //~ ERROR mismatched types [E0308]
+}
diff --git a/tests/ui/typeck/suggestions/suggest-add-wrapper-issue-145294.stderr b/tests/ui/typeck/suggestions/suggest-add-wrapper-issue-145294.stderr
new file mode 100644
index 00000000000..5e4ad132210
--- /dev/null
+++ b/tests/ui/typeck/suggestions/suggest-add-wrapper-issue-145294.stderr
@@ -0,0 +1,21 @@
+error[E0308]: mismatched types
+  --> $DIR/suggest-add-wrapper-issue-145294.rs:24:32
+   |
+LL |     assert_eq!(Ok(Some("hi")), foo());
+   |                                ^^^^^ expected `Result<Option<&str>, _>`, found `Result<Option<String>, ()>`
+   |
+   = note: expected enum `Result<Option<&str>, _>`
+              found enum `Result<Option<String>, ()>`
+
+error[E0308]: mismatched types
+  --> $DIR/suggest-add-wrapper-issue-145294.rs:25:30
+   |
+LL |     assert_eq!(Bar::A("hi"), bar());
+   |                              ^^^^^ expected `Bar<&str, _>`, found `Bar<String, ()>`
+   |
+   = note: expected enum `Bar<&str, _>`
+              found enum `Bar<String, ()>`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/typos.toml b/typos.toml
index 4035f206a46..317aafc8615 100644
--- a/typos.toml
+++ b/typos.toml
@@ -52,7 +52,6 @@ ERROR_DS_NOT_AUTHORITIVE_FOR_DST_NC = "ERROR_DS_NOT_AUTHORITIVE_FOR_DST_NC"
 ERROR_MCA_OCCURED = "ERROR_MCA_OCCURED"
 ERRNO_ACCES = "ERRNO_ACCES"
 tolen = "tolen"
-numer = "numer"
 
 [default]
 extend-ignore-words-re = [