diff --git a/compiler/rustc_ast_lowering/src/errors.rs b/compiler/rustc_ast_lowering/src/errors.rs
index 72dc52a632992..a63bd4f8a0255 100644
--- a/compiler/rustc_ast_lowering/src/errors.rs
+++ b/compiler/rustc_ast_lowering/src/errors.rs
@@ -31,9 +31,26 @@ pub struct InvalidAbi {
     pub abi: Symbol,
     pub command: String,
     #[subdiagnostic]
+    pub explain: Option<InvalidAbiReason>,
+    #[subdiagnostic]
     pub suggestion: Option<InvalidAbiSuggestion>,
 }
 
+pub struct InvalidAbiReason(pub &'static str);
+
+impl rustc_errors::AddToDiagnostic for InvalidAbiReason {
+    fn add_to_diagnostic_with<F>(self, diag: &mut rustc_errors::Diagnostic, _: F)
+    where
+        F: Fn(
+            &mut rustc_errors::Diagnostic,
+            rustc_errors::SubdiagnosticMessage,
+        ) -> rustc_errors::SubdiagnosticMessage,
+    {
+        #[allow(rustc::untranslatable_diagnostic)]
+        diag.note(self.0);
+    }
+}
+
 #[derive(Subdiagnostic)]
 #[suggestion(
     ast_lowering_invalid_abi_suggestion,
diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs
index 7954297900f90..a59c83de0f46f 100644
--- a/compiler/rustc_ast_lowering/src/item.rs
+++ b/compiler/rustc_ast_lowering/src/item.rs
@@ -1,4 +1,4 @@
-use super::errors::{InvalidAbi, InvalidAbiSuggestion, MisplacedRelaxTraitBound};
+use super::errors::{InvalidAbi, InvalidAbiReason, InvalidAbiSuggestion, MisplacedRelaxTraitBound};
 use super::ResolverAstLoweringExt;
 use super::{AstOwner, ImplTraitContext, ImplTraitPosition};
 use super::{FnDeclKind, LoweringContext, ParamMode};
@@ -1271,8 +1271,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
     }
 
     pub(super) fn lower_abi(&mut self, abi: StrLit) -> abi::Abi {
-        abi::lookup(abi.symbol_unescaped.as_str()).unwrap_or_else(|| {
-            self.error_on_invalid_abi(abi);
+        abi::lookup(abi.symbol_unescaped.as_str()).unwrap_or_else(|err| {
+            self.error_on_invalid_abi(abi, err);
             abi::Abi::Rust
         })
     }
@@ -1285,7 +1285,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
         }
     }
 
-    fn error_on_invalid_abi(&self, abi: StrLit) {
+    fn error_on_invalid_abi(&self, abi: StrLit, err: abi::AbiUnsupported) {
         let abi_names = abi::enabled_names(self.tcx.features(), abi.span)
             .iter()
             .map(|s| Symbol::intern(s))
@@ -1294,6 +1294,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
         self.tcx.sess.emit_err(InvalidAbi {
             abi: abi.symbol_unescaped,
             span: abi.span,
+            explain: match err {
+                abi::AbiUnsupported::Reason { explain } => Some(InvalidAbiReason(explain)),
+                _ => None,
+            },
             suggestion: suggested_name.map(|suggested_name| InvalidAbiSuggestion {
                 span: abi.span,
                 suggestion: format!("\"{suggested_name}\""),
diff --git a/compiler/rustc_codegen_cranelift/src/abi/mod.rs b/compiler/rustc_codegen_cranelift/src/abi/mod.rs
index 2c038f22ca99b..b7f56a2986cfc 100644
--- a/compiler/rustc_codegen_cranelift/src/abi/mod.rs
+++ b/compiler/rustc_codegen_cranelift/src/abi/mod.rs
@@ -48,7 +48,9 @@ pub(crate) fn conv_to_call_conv(sess: &Session, c: Conv, default_call_conv: Call
             default_call_conv
         }
 
-        Conv::X86Intr => sess.fatal("x86-interrupt call conv not yet implemented"),
+        Conv::X86Intr | Conv::RiscvInterrupt { .. } => {
+            sess.fatal(format!("interrupt call conv {c:?} not yet implemented"))
+        }
 
         Conv::ArmAapcs => sess.fatal("aapcs call conv not yet implemented"),
         Conv::CCmseNonSecureCall => {
diff --git a/compiler/rustc_codegen_llvm/src/abi.rs b/compiler/rustc_codegen_llvm/src/abi.rs
index e02b457fd0b19..c6a7dc95d77af 100644
--- a/compiler/rustc_codegen_llvm/src/abi.rs
+++ b/compiler/rustc_codegen_llvm/src/abi.rs
@@ -383,13 +383,16 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
     }
 
     fn apply_attrs_llfn(&self, cx: &CodegenCx<'ll, 'tcx>, llfn: &'ll Value) {
-        let mut func_attrs = SmallVec::<[_; 2]>::new();
+        let mut func_attrs = SmallVec::<[_; 3]>::new();
         if self.ret.layout.abi.is_uninhabited() {
             func_attrs.push(llvm::AttributeKind::NoReturn.create_attr(cx.llcx));
         }
         if !self.can_unwind {
             func_attrs.push(llvm::AttributeKind::NoUnwind.create_attr(cx.llcx));
         }
+        if let Conv::RiscvInterrupt { kind } = self.conv {
+            func_attrs.push(llvm::CreateAttrStringValue(cx.llcx, "interrupt", kind.as_str()));
+        }
         attributes::apply_to_llfn(llfn, llvm::AttributePlace::Function, &{ func_attrs });
 
         let mut i = 0;
@@ -565,7 +568,9 @@ impl<'tcx> AbiBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> {
 impl From<Conv> for llvm::CallConv {
     fn from(conv: Conv) -> Self {
         match conv {
-            Conv::C | Conv::Rust | Conv::CCmseNonSecureCall => llvm::CCallConv,
+            Conv::C | Conv::Rust | Conv::CCmseNonSecureCall | Conv::RiscvInterrupt { .. } => {
+                llvm::CCallConv
+            }
             Conv::RustCold => llvm::ColdCallConv,
             Conv::AmdGpuKernel => llvm::AmdGpuKernel,
             Conv::AvrInterrupt => llvm::AvrInterrupt,
diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs
index ede3570510acb..898f5fd3b7095 100644
--- a/compiler/rustc_feature/src/active.rs
+++ b/compiler/rustc_feature/src/active.rs
@@ -313,6 +313,8 @@ declare_features! (
     (active, abi_msp430_interrupt, "1.16.0", Some(38487), None),
     /// Allows `extern "ptx-*" fn()`.
     (active, abi_ptx, "1.15.0", Some(38788), None),
+    /// Allows `extern "riscv-interrupt-m" fn()` and `extern "riscv-interrupt-s" fn()`.
+    (active, abi_riscv_interrupt, "CURRENT_RUSTC_VERSION", Some(111889), None),
     /// Allows `extern "x86-interrupt" fn()`.
     (active, abi_x86_interrupt, "1.17.0", Some(40180), None),
     /// Allows additional const parameter types, such as `&'static str` or user defined types
diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs
index 2af8648455bd3..7cea40fdd64c2 100644
--- a/compiler/rustc_hir_typeck/src/expr.rs
+++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -13,7 +13,7 @@ use crate::errors::{
     YieldExprOutsideOfGenerator,
 };
 use crate::fatally_break_rust;
-use crate::method::SelfSource;
+use crate::method::{MethodCallComponents, SelfSource};
 use crate::type_error_struct;
 use crate::Expectation::{self, ExpectCastableToType, ExpectHasType, NoExpectation};
 use crate::{
@@ -1281,7 +1281,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         segment.ident,
                         SelfSource::MethodCall(rcvr),
                         error,
-                        Some((rcvr, args)),
+                        Some(MethodCallComponents { receiver: rcvr, args, full_expr: expr }),
                         expected,
                         false,
                     ) {
diff --git a/compiler/rustc_hir_typeck/src/method/mod.rs b/compiler/rustc_hir_typeck/src/method/mod.rs
index 597696843c40f..6dd131aa28397 100644
--- a/compiler/rustc_hir_typeck/src/method/mod.rs
+++ b/compiler/rustc_hir_typeck/src/method/mod.rs
@@ -7,7 +7,7 @@ mod prelude2021;
 pub mod probe;
 mod suggest;
 
-pub use self::suggest::SelfSource;
+pub use self::suggest::{MethodCallComponents, SelfSource};
 pub use self::MethodError::*;
 
 use crate::errors::OpMethodGenericParams;
diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs
index b9d8c5a7540a3..2d64c5667a89e 100644
--- a/compiler/rustc_hir_typeck/src/method/suggest.rs
+++ b/compiler/rustc_hir_typeck/src/method/suggest.rs
@@ -50,6 +50,15 @@ use rustc_hir::intravisit::Visitor;
 use std::cmp::{self, Ordering};
 use std::iter;
 
+/// After identifying that `full_expr` is a method call, we use this type to keep the expression's
+/// components readily available to us to point at the right place in diagnostics.
+#[derive(Debug, Clone, Copy)]
+pub struct MethodCallComponents<'tcx> {
+    pub receiver: &'tcx hir::Expr<'tcx>,
+    pub args: &'tcx [hir::Expr<'tcx>],
+    pub full_expr: &'tcx hir::Expr<'tcx>,
+}
+
 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     fn is_fn_ty(&self, ty: Ty<'tcx>, span: Span) -> bool {
         let tcx = self.tcx;
@@ -115,7 +124,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         item_name: Ident,
         source: SelfSource<'tcx>,
         error: MethodError<'tcx>,
-        args: Option<(&'tcx hir::Expr<'tcx>, &'tcx [hir::Expr<'tcx>])>,
+        args: Option<MethodCallComponents<'tcx>>,
         expected: Expectation<'tcx>,
         trait_missing_method: bool,
     ) -> Option<DiagnosticBuilder<'_, ErrorGuaranteed>> {
@@ -257,18 +266,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     fn suggest_missing_writer(
         &self,
         rcvr_ty: Ty<'tcx>,
-        args: (&'tcx hir::Expr<'tcx>, &'tcx [hir::Expr<'tcx>]),
+        args: MethodCallComponents<'tcx>,
     ) -> DiagnosticBuilder<'_, ErrorGuaranteed> {
         let (ty_str, _ty_file) = self.tcx.short_ty_string(rcvr_ty);
-        let mut err =
-            struct_span_err!(self.tcx.sess, args.0.span, E0599, "cannot write into `{}`", ty_str);
+        let mut err = struct_span_err!(
+            self.tcx.sess,
+            args.receiver.span,
+            E0599,
+            "cannot write into `{}`",
+            ty_str
+        );
         err.span_note(
-            args.0.span,
+            args.receiver.span,
             "must implement `io::Write`, `fmt::Write`, or have a `write_fmt` method",
         );
-        if let ExprKind::Lit(_) = args.0.kind {
+        if let ExprKind::Lit(_) = args.receiver.kind {
             err.span_help(
-                args.0.span.shrink_to_lo(),
+                args.receiver.span.shrink_to_lo(),
                 "a writer is needed before this format string",
             );
         };
@@ -282,7 +296,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         rcvr_ty: Ty<'tcx>,
         item_name: Ident,
         source: SelfSource<'tcx>,
-        args: Option<(&'tcx hir::Expr<'tcx>, &'tcx [hir::Expr<'tcx>])>,
+        args: Option<MethodCallComponents<'tcx>>,
         sugg_span: Span,
         no_match_data: &mut NoMatchData<'tcx>,
         expected: Expectation<'tcx>,
@@ -953,6 +967,39 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
                 unsatisfied_bounds = true;
             }
+        } else if let ty::Adt(def, targs) = rcvr_ty.kind() && let Some(args) = args {
+            // This is useful for methods on arbitrary self types that might have a simple
+            // mutability difference, like calling a method on `Pin<&mut Self>` that is on
+            // `Pin<&Self>`.
+            if targs.len() == 1 {
+                let mut item_segment = hir::PathSegment::invalid();
+                item_segment.ident = item_name;
+                for t in [Ty::new_mut_ref, Ty::new_imm_ref, |_, _, t| t] {
+                    let new_args = tcx.mk_args_from_iter(
+                        targs
+                            .iter()
+                            .map(|arg| match arg.as_type() {
+                                Some(ty) => ty::GenericArg::from(
+                                    t(tcx, tcx.lifetimes.re_erased, ty.peel_refs()),
+                                ),
+                                _ => arg,
+                            })
+                    );
+                    let rcvr_ty = Ty::new_adt(tcx, *def, new_args);
+                    if let Ok(method) = self.lookup_method_for_diagnostic(
+                        rcvr_ty,
+                        &item_segment,
+                        span,
+                        args.full_expr,
+                        args.receiver,
+                    ) {
+                        err.span_note(
+                            tcx.def_span(method.def_id),
+                            format!("{item_kind} is available for `{rcvr_ty}`"),
+                        );
+                    }
+                }
+            }
         }
 
         let label_span_not_found = |err: &mut Diagnostic| {
@@ -1111,7 +1158,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 span,
                 rcvr_ty,
                 item_name,
-                args.map(|(_, args)| args.len() + 1),
+                args.map(|MethodCallComponents { args, .. }| args.len() + 1),
                 source,
                 no_match_data.out_of_scope_traits.clone(),
                 &unsatisfied_predicates,
@@ -1192,7 +1239,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         &self,
         rcvr_ty: Ty<'tcx>,
         item_name: Ident,
-        args: Option<(&'tcx hir::Expr<'tcx>, &'tcx [hir::Expr<'tcx>])>,
+        args: Option<MethodCallComponents<'tcx>>,
         span: Span,
         err: &mut Diagnostic,
         sources: &mut Vec<CandidateSource>,
@@ -1343,7 +1390,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         rcvr_ty: Ty<'tcx>,
         source: SelfSource<'tcx>,
         item_name: Ident,
-        args: Option<(&hir::Expr<'tcx>, &[hir::Expr<'tcx>])>,
+        args: Option<MethodCallComponents<'tcx>>,
         sugg_span: Span,
     ) {
         let mut has_unsuggestable_args = false;
@@ -1415,7 +1462,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 None
             };
             let mut applicability = Applicability::MachineApplicable;
-            let args = if let Some((receiver, args)) = args {
+            let args = if let Some(MethodCallComponents { receiver, args, .. }) = args {
                 // The first arg is the same kind as the receiver
                 let explicit_args = if first_arg.is_some() {
                     std::iter::once(receiver).chain(args.iter()).collect::<Vec<_>>()
@@ -2995,7 +3042,7 @@ pub fn all_traits(tcx: TyCtxt<'_>) -> Vec<TraitInfo> {
 
 fn print_disambiguation_help<'tcx>(
     item_name: Ident,
-    args: Option<(&'tcx hir::Expr<'tcx>, &'tcx [hir::Expr<'tcx>])>,
+    args: Option<MethodCallComponents<'tcx>>,
     err: &mut Diagnostic,
     trait_name: String,
     rcvr_ty: Ty<'_>,
@@ -3007,7 +3054,11 @@ fn print_disambiguation_help<'tcx>(
     fn_has_self_parameter: bool,
 ) {
     let mut applicability = Applicability::MachineApplicable;
-    let (span, sugg) = if let (ty::AssocKind::Fn, Some((receiver, args))) = (kind, args) {
+    let (span, sugg) = if let (
+        ty::AssocKind::Fn,
+        Some(MethodCallComponents { receiver, args, .. }),
+    ) = (kind, args)
+    {
         let args = format!(
             "({}{})",
             rcvr_ty.ref_mutability().map_or("", |mutbl| mutbl.ref_prefix_str()),
diff --git a/compiler/rustc_middle/src/mir/interpret/allocation.rs b/compiler/rustc_middle/src/mir/interpret/allocation.rs
index 2567170f39afe..c787481bfbec7 100644
--- a/compiler/rustc_middle/src/mir/interpret/allocation.rs
+++ b/compiler/rustc_middle/src/mir/interpret/allocation.rs
@@ -329,6 +329,9 @@ impl<Prov: Provenance, Bytes: AllocBytes> Allocation<Prov, (), Bytes> {
 
     /// Try to create an Allocation of `size` bytes, panics if there is not enough memory
     /// available to the compiler to do so.
+    ///
+    /// Example use case: To obtain an Allocation filled with specific data,
+    /// first call this function and then call write_scalar to fill in the right data.
     pub fn uninit(size: Size, align: Align) -> Self {
         match Self::uninit_inner(size, align, || {
             panic!("Allocation::uninit called with panic_on_fail had allocation failure");
diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs
index df39103bc1979..e362b3477c9f7 100644
--- a/compiler/rustc_middle/src/ty/layout.rs
+++ b/compiler/rustc_middle/src/ty/layout.rs
@@ -1239,6 +1239,8 @@ pub fn fn_can_unwind(tcx: TyCtxt<'_>, fn_def_id: Option<DefId>, abi: SpecAbi) ->
         | EfiApi
         | AvrInterrupt
         | AvrNonBlockingInterrupt
+        | RiscvInterruptM
+        | RiscvInterruptS
         | CCmseNonSecureCall
         | Wasm
         | PlatformIntrinsic
diff --git a/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs b/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs
index 58cc161ddcc49..d202860840c25 100644
--- a/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs
+++ b/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs
@@ -30,6 +30,8 @@ fn abi_can_unwind(abi: Abi) -> bool {
         | EfiApi
         | AvrInterrupt
         | AvrNonBlockingInterrupt
+        | RiscvInterruptM
+        | RiscvInterruptS
         | CCmseNonSecureCall
         | Wasm
         | RustIntrinsic
diff --git a/compiler/rustc_smir/src/rustc_internal/mod.rs b/compiler/rustc_smir/src/rustc_internal/mod.rs
index 39541c845b394..0d9157940f827 100644
--- a/compiler/rustc_smir/src/rustc_internal/mod.rs
+++ b/compiler/rustc_smir/src/rustc_internal/mod.rs
@@ -112,6 +112,10 @@ impl<'tcx> Tables<'tcx> {
         stable_mir::ty::TraitDef(self.create_def_id(did))
     }
 
+    pub fn const_def(&mut self, did: DefId) -> stable_mir::ty::ConstDef {
+        stable_mir::ty::ConstDef(self.create_def_id(did))
+    }
+
     fn create_def_id(&mut self, did: DefId) -> stable_mir::DefId {
         // FIXME: this becomes inefficient when we have too many ids
         for (i, &d) in self.def_ids.iter().enumerate() {
diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs
index d12de92db8a64..f782138f87056 100644
--- a/compiler/rustc_smir/src/rustc_smir/mod.rs
+++ b/compiler/rustc_smir/src/rustc_smir/mod.rs
@@ -9,11 +9,14 @@
 
 use crate::rustc_internal::{self, opaque};
 use crate::stable_mir::mir::{CopyNonOverlapping, UserTypeProjection, VariantIdx};
-use crate::stable_mir::ty::{FloatTy, IntTy, Movability, RigidTy, TyKind, UintTy};
+use crate::stable_mir::ty::{
+    allocation_filter, new_allocation, FloatTy, IntTy, Movability, RigidTy, TyKind, UintTy,
+};
 use crate::stable_mir::{self, Context};
 use rustc_hir as hir;
 use rustc_middle::mir::coverage::CodeRegion;
-use rustc_middle::mir::{self};
+use rustc_middle::mir::interpret::alloc_range;
+use rustc_middle::mir::{self, ConstantKind};
 use rustc_middle::ty::{self, Ty, TyCtxt, Variance};
 use rustc_span::def_id::{CrateNum, DefId, LOCAL_CRATE};
 use rustc_target::abi::FieldIdx;
@@ -877,6 +880,8 @@ impl<'tcx> Stable<'tcx> for ty::FnSig<'tcx> {
                 abi::Abi::PlatformIntrinsic => Abi::PlatformIntrinsic,
                 abi::Abi::Unadjusted => Abi::Unadjusted,
                 abi::Abi::RustCold => Abi::RustCold,
+                abi::Abi::RiscvInterruptM => Abi::RiscvInterruptM,
+                abi::Abi::RiscvInterruptS => Abi::RiscvInterruptS,
             },
         }
     }
@@ -1080,30 +1085,7 @@ impl<'tcx> Stable<'tcx> for mir::interpret::Allocation {
     type T = stable_mir::ty::Allocation;
 
     fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
-        let size = self.size();
-        let mut bytes: Vec<Option<u8>> = self
-            .inspect_with_uninit_and_ptr_outside_interpreter(0..size.bytes_usize())
-            .iter()
-            .copied()
-            .map(Some)
-            .collect();
-        for (i, b) in bytes.iter_mut().enumerate() {
-            if !self.init_mask().get(rustc_target::abi::Size::from_bytes(i)) {
-                *b = None;
-            }
-        }
-        stable_mir::ty::Allocation {
-            bytes: bytes,
-            provenance: {
-                let mut ptrs = Vec::new();
-                for (size, prov) in self.provenance().ptrs().iter() {
-                    ptrs.push((size.bytes_usize(), opaque(prov)));
-                }
-                stable_mir::ty::ProvenanceMap { ptrs }
-            },
-            align: self.align.bytes(),
-            mutability: self.mutability.stable(tables),
-        }
+        allocation_filter(self, alloc_range(rustc_target::abi::Size::ZERO, self.size()), tables)
     }
 }
 
@@ -1145,3 +1127,30 @@ impl<'tcx> Stable<'tcx> for ty::TraitDef {
         }
     }
 }
+
+impl<'tcx> Stable<'tcx> for rustc_middle::mir::ConstantKind<'tcx> {
+    type T = stable_mir::ty::ConstantKind;
+
+    fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+        match self {
+            ConstantKind::Ty(c) => match c.kind() {
+                ty::Value(val) => {
+                    let const_val = tables.tcx.valtree_to_const_val((c.ty(), val));
+                    stable_mir::ty::ConstantKind::Allocated(new_allocation(self, const_val, tables))
+                }
+                _ => todo!(),
+            },
+            ConstantKind::Unevaluated(unev_const, ty) => {
+                stable_mir::ty::ConstantKind::Unevaluated(stable_mir::ty::UnevaluatedConst {
+                    ty: tables.intern_ty(*ty),
+                    def: tables.const_def(unev_const.def),
+                    args: unev_const.args.stable(tables),
+                    promoted: unev_const.promoted.map(|u| u.as_u32()),
+                })
+            }
+            ConstantKind::Val(val, _) => {
+                stable_mir::ty::ConstantKind::Allocated(new_allocation(self, *val, tables))
+            }
+        }
+    }
+}
diff --git a/compiler/rustc_smir/src/stable_mir/ty.rs b/compiler/rustc_smir/src/stable_mir/ty.rs
index c487db5b732a5..e83ca88da1b69 100644
--- a/compiler/rustc_smir/src/stable_mir/ty.rs
+++ b/compiler/rustc_smir/src/stable_mir/ty.rs
@@ -1,5 +1,10 @@
+use rustc_middle::mir::interpret::{alloc_range, AllocRange, ConstValue, Pointer};
+
 use super::{mir::Mutability, mir::Safety, with, DefId};
-use crate::rustc_internal::Opaque;
+use crate::{
+    rustc_internal::{opaque, Opaque},
+    rustc_smir::{Stable, Tables},
+};
 
 #[derive(Copy, Clone, Debug)]
 pub struct Ty(pub usize);
@@ -105,6 +110,9 @@ pub struct AliasDef(pub(crate) DefId);
 #[derive(Clone, PartialEq, Eq, Debug)]
 pub struct TraitDef(pub(crate) DefId);
 
+#[derive(Clone, PartialEq, Eq, Debug)]
+pub struct ConstDef(pub(crate) DefId);
+
 impl TraitDef {
     pub fn trait_decl(&self) -> TraitDecl {
         with(|cx| cx.trait_decl(self))
@@ -178,6 +186,8 @@ pub enum Abi {
     PlatformIntrinsic,
     Unadjusted,
     RustCold,
+    RiscvInterruptM,
+    RiscvInterruptS,
 }
 
 #[derive(Clone, Debug)]
@@ -248,6 +258,7 @@ pub type Bytes = Vec<Option<u8>>;
 pub type Size = usize;
 pub type Prov = Opaque;
 pub type Align = u64;
+pub type Promoted = u32;
 pub type InitMaskMaterialized = Vec<u64>;
 
 /// Stores the provenance information of pointers stored in memory.
@@ -266,6 +277,142 @@ pub struct Allocation {
     pub mutability: Mutability,
 }
 
+impl Allocation {
+    /// Creates new empty `Allocation` from given `Align`.
+    fn new_empty_allocation(align: rustc_target::abi::Align) -> Allocation {
+        Allocation {
+            bytes: Vec::new(),
+            provenance: ProvenanceMap { ptrs: Vec::new() },
+            align: align.bytes(),
+            mutability: Mutability::Not,
+        }
+    }
+}
+
+// We need this method instead of a Stable implementation
+// because we need to get `Ty` of the const we are trying to create, to do that
+// we need to have access to `ConstantKind` but we can't access that inside Stable impl.
+pub fn new_allocation<'tcx>(
+    const_kind: &rustc_middle::mir::ConstantKind<'tcx>,
+    const_value: ConstValue<'tcx>,
+    tables: &mut Tables<'tcx>,
+) -> Allocation {
+    match const_value {
+        ConstValue::Scalar(scalar) => {
+            let size = scalar.size();
+            let align = tables
+                .tcx
+                .layout_of(rustc_middle::ty::ParamEnv::reveal_all().and(const_kind.ty()))
+                .unwrap()
+                .align;
+            let mut allocation = rustc_middle::mir::interpret::Allocation::uninit(size, align.abi);
+            allocation
+                .write_scalar(&tables.tcx, alloc_range(rustc_target::abi::Size::ZERO, size), scalar)
+                .unwrap();
+            allocation.stable(tables)
+        }
+        ConstValue::ZeroSized => {
+            let align = tables
+                .tcx
+                .layout_of(rustc_middle::ty::ParamEnv::empty().and(const_kind.ty()))
+                .unwrap()
+                .align;
+            Allocation::new_empty_allocation(align.abi)
+        }
+        ConstValue::Slice { data, start, end } => {
+            let alloc_id = tables.tcx.create_memory_alloc(data);
+            let ptr = Pointer::new(alloc_id, rustc_target::abi::Size::from_bytes(start));
+            let scalar_ptr = rustc_middle::mir::interpret::Scalar::from_pointer(ptr, &tables.tcx);
+            let scalar_len = rustc_middle::mir::interpret::Scalar::from_target_usize(
+                (end - start) as u64,
+                &tables.tcx,
+            );
+            let layout = tables
+                .tcx
+                .layout_of(rustc_middle::ty::ParamEnv::reveal_all().and(const_kind.ty()))
+                .unwrap();
+            let mut allocation =
+                rustc_middle::mir::interpret::Allocation::uninit(layout.size, layout.align.abi);
+            allocation
+                .write_scalar(
+                    &tables.tcx,
+                    alloc_range(rustc_target::abi::Size::ZERO, tables.tcx.data_layout.pointer_size),
+                    scalar_ptr,
+                )
+                .unwrap();
+            allocation
+                .write_scalar(
+                    &tables.tcx,
+                    alloc_range(tables.tcx.data_layout.pointer_size, scalar_len.size()),
+                    scalar_len,
+                )
+                .unwrap();
+            allocation.stable(tables)
+        }
+        ConstValue::ByRef { alloc, offset } => {
+            let ty_size = tables
+                .tcx
+                .layout_of(rustc_middle::ty::ParamEnv::reveal_all().and(const_kind.ty()))
+                .unwrap()
+                .size;
+            allocation_filter(&alloc.0, alloc_range(offset, ty_size), tables)
+        }
+    }
+}
+
+/// Creates an `Allocation` only from information within the `AllocRange`.
+pub fn allocation_filter<'tcx>(
+    alloc: &rustc_middle::mir::interpret::Allocation,
+    alloc_range: AllocRange,
+    tables: &mut Tables<'tcx>,
+) -> Allocation {
+    let mut bytes: Vec<Option<u8>> = alloc
+        .inspect_with_uninit_and_ptr_outside_interpreter(
+            alloc_range.start.bytes_usize()..alloc_range.end().bytes_usize(),
+        )
+        .iter()
+        .copied()
+        .map(Some)
+        .collect();
+    for (i, b) in bytes.iter_mut().enumerate() {
+        if !alloc
+            .init_mask()
+            .get(rustc_target::abi::Size::from_bytes(i + alloc_range.start.bytes_usize()))
+        {
+            *b = None;
+        }
+    }
+    let mut ptrs = Vec::new();
+    for (offset, prov) in alloc
+        .provenance()
+        .ptrs()
+        .iter()
+        .filter(|a| a.0 >= alloc_range.start && a.0 <= alloc_range.end())
+    {
+        ptrs.push((offset.bytes_usize() - alloc_range.start.bytes_usize(), opaque(prov)));
+    }
+    Allocation {
+        bytes: bytes,
+        provenance: ProvenanceMap { ptrs },
+        align: alloc.align.bytes(),
+        mutability: alloc.mutability.stable(tables),
+    }
+}
+
+#[derive(Clone, Debug)]
+pub enum ConstantKind {
+    Allocated(Allocation),
+    Unevaluated(UnevaluatedConst),
+}
+
+#[derive(Clone, Debug)]
+pub struct UnevaluatedConst {
+    pub ty: Ty,
+    pub def: ConstDef,
+    pub args: GenericArgs,
+    pub promoted: Option<Promoted>,
+}
+
 pub enum TraitSpecializationKind {
     None,
     Marker,
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 9ea9efb047c2b..745a3590720a0 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -326,6 +326,7 @@ symbols! {
         abi_efiapi,
         abi_msp430_interrupt,
         abi_ptx,
+        abi_riscv_interrupt,
         abi_sysv64,
         abi_thiscall,
         abi_unadjusted,
diff --git a/compiler/rustc_target/src/abi/call/mod.rs b/compiler/rustc_target/src/abi/call/mod.rs
index 3d2ea017d8f10..e4989bdfbcd69 100644
--- a/compiler/rustc_target/src/abi/call/mod.rs
+++ b/compiler/rustc_target/src/abi/call/mod.rs
@@ -603,6 +603,25 @@ pub enum Conv {
     AmdGpuKernel,
     AvrInterrupt,
     AvrNonBlockingInterrupt,
+
+    RiscvInterrupt {
+        kind: RiscvInterruptKind,
+    },
+}
+
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable_Generic)]
+pub enum RiscvInterruptKind {
+    Machine,
+    Supervisor,
+}
+
+impl RiscvInterruptKind {
+    pub fn as_str(&self) -> &'static str {
+        match self {
+            Self::Machine => "machine",
+            Self::Supervisor => "supervisor",
+        }
+    }
 }
 
 /// Metadata describing how the arguments to a native function
@@ -753,6 +772,12 @@ impl FromStr for Conv {
             "AmdGpuKernel" => Ok(Conv::AmdGpuKernel),
             "AvrInterrupt" => Ok(Conv::AvrInterrupt),
             "AvrNonBlockingInterrupt" => Ok(Conv::AvrNonBlockingInterrupt),
+            "RiscvInterrupt(machine)" => {
+                Ok(Conv::RiscvInterrupt { kind: RiscvInterruptKind::Machine })
+            }
+            "RiscvInterrupt(supervisor)" => {
+                Ok(Conv::RiscvInterrupt { kind: RiscvInterruptKind::Supervisor })
+            }
             _ => Err(format!("'{s}' is not a valid value for entry function call convention.")),
         }
     }
diff --git a/compiler/rustc_target/src/json.rs b/compiler/rustc_target/src/json.rs
index 75bb76a9de087..af455b6432f52 100644
--- a/compiler/rustc_target/src/json.rs
+++ b/compiler/rustc_target/src/json.rs
@@ -92,6 +92,7 @@ impl<A: ToJson> ToJson for Option<A> {
 
 impl ToJson for crate::abi::call::Conv {
     fn to_json(&self) -> Json {
+        let buf: String;
         let s = match self {
             Self::C => "C",
             Self::Rust => "Rust",
@@ -110,6 +111,10 @@ impl ToJson for crate::abi::call::Conv {
             Self::AmdGpuKernel => "AmdGpuKernel",
             Self::AvrInterrupt => "AvrInterrupt",
             Self::AvrNonBlockingInterrupt => "AvrNonBlockingInterrupt",
+            Self::RiscvInterrupt { kind } => {
+                buf = format!("RiscvInterrupt({})", kind.as_str());
+                &buf
+            }
         };
         Json::String(s.to_owned())
     }
diff --git a/compiler/rustc_target/src/spec/abi.rs b/compiler/rustc_target/src/spec/abi.rs
index dc233121f666a..550cdf6bda6f8 100644
--- a/compiler/rustc_target/src/spec/abi.rs
+++ b/compiler/rustc_target/src/spec/abi.rs
@@ -38,6 +38,8 @@ pub enum Abi {
     PlatformIntrinsic,
     Unadjusted,
     RustCold,
+    RiscvInterruptM,
+    RiscvInterruptS,
 }
 
 impl Abi {
@@ -107,11 +109,29 @@ const AbiDatas: &[AbiData] = &[
     AbiData { abi: Abi::PlatformIntrinsic, name: "platform-intrinsic" },
     AbiData { abi: Abi::Unadjusted, name: "unadjusted" },
     AbiData { abi: Abi::RustCold, name: "rust-cold" },
+    AbiData { abi: Abi::RiscvInterruptM, name: "riscv-interrupt-m" },
+    AbiData { abi: Abi::RiscvInterruptS, name: "riscv-interrupt-s" },
 ];
 
+#[derive(Copy, Clone, Debug)]
+pub enum AbiUnsupported {
+    Unrecognized,
+    Reason { explain: &'static str },
+}
+
 /// Returns the ABI with the given name (if any).
-pub fn lookup(name: &str) -> Option<Abi> {
-    AbiDatas.iter().find(|abi_data| name == abi_data.name).map(|&x| x.abi)
+pub fn lookup(name: &str) -> Result<Abi, AbiUnsupported> {
+    AbiDatas.iter().find(|abi_data| name == abi_data.name).map(|&x| x.abi).ok_or_else(|| match name {
+        "riscv-interrupt" => AbiUnsupported::Reason {
+            explain: "please use one of riscv-interrupt-m or riscv-interrupt-s for machine- or supervisor-level interrupts, respectively",
+        },
+        "riscv-interrupt-u" => AbiUnsupported::Reason {
+            explain: "user-mode interrupt handlers have been removed from LLVM pending standardization, see: https://reviews.llvm.org/D149314",
+        },
+
+        _ => AbiUnsupported::Unrecognized,
+
+    })
 }
 
 pub fn all_names() -> Vec<&'static str> {
@@ -200,6 +220,10 @@ pub fn is_stable(name: &str) -> Result<(), AbiDisabled> {
             feature: sym::abi_avr_interrupt,
             explain: "avr-interrupt and avr-non-blocking-interrupt ABIs are experimental and subject to change",
         }),
+        "riscv-interrupt-m" | "riscv-interrupt-s" => Err(AbiDisabled::Unstable {
+            feature: sym::abi_riscv_interrupt,
+            explain: "riscv-interrupt ABIs are experimental and subject to change",
+        }),
         "C-cmse-nonsecure-call" => Err(AbiDisabled::Unstable {
             feature: sym::abi_c_cmse_nonsecure_call,
             explain: "C-cmse-nonsecure-call ABI is experimental and subject to change",
@@ -260,6 +284,8 @@ impl Abi {
             PlatformIntrinsic => 32,
             Unadjusted => 33,
             RustCold => 34,
+            RiscvInterruptM => 35,
+            RiscvInterruptS => 36,
         };
         debug_assert!(
             AbiDatas
diff --git a/compiler/rustc_target/src/spec/abi/tests.rs b/compiler/rustc_target/src/spec/abi/tests.rs
index 8bea5e5efe3b0..251a12fe7aa6b 100644
--- a/compiler/rustc_target/src/spec/abi/tests.rs
+++ b/compiler/rustc_target/src/spec/abi/tests.rs
@@ -4,19 +4,19 @@ use super::*;
 #[test]
 fn lookup_Rust() {
     let abi = lookup("Rust");
-    assert!(abi.is_some() && abi.unwrap().data().name == "Rust");
+    assert!(abi.is_ok() && abi.unwrap().data().name == "Rust");
 }
 
 #[test]
 fn lookup_cdecl() {
     let abi = lookup("cdecl");
-    assert!(abi.is_some() && abi.unwrap().data().name == "cdecl");
+    assert!(abi.is_ok() && abi.unwrap().data().name == "cdecl");
 }
 
 #[test]
 fn lookup_baz() {
     let abi = lookup("baz");
-    assert!(abi.is_none());
+    assert!(matches!(abi, Err(AbiUnsupported::Unrecognized)))
 }
 
 #[test]
diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs
index 6ab0aed1ab8a7..1871239d7de70 100644
--- a/compiler/rustc_target/src/spec/mod.rs
+++ b/compiler/rustc_target/src/spec/mod.rs
@@ -2270,6 +2270,7 @@ impl Target {
             PtxKernel => self.arch == "nvptx64",
             Msp430Interrupt => self.arch == "msp430",
             AmdGpuKernel => self.arch == "amdgcn",
+            RiscvInterruptM | RiscvInterruptS => ["riscv32", "riscv64"].contains(&&self.arch[..]),
             AvrInterrupt | AvrNonBlockingInterrupt => self.arch == "avr",
             Wasm => ["wasm32", "wasm64"].contains(&&self.arch[..]),
             Thiscall { .. } => self.arch == "x86",
@@ -2701,7 +2702,7 @@ impl Target {
                 let name = (stringify!($key_name)).replace("_", "-");
                 obj.remove(&name).and_then(|o| o.as_str().and_then(|s| {
                     match lookup_abi(s) {
-                        Some(abi) => base.$key_name = Some(abi),
+                        Ok(abi) => base.$key_name = Some(abi),
                         _ => return Some(Err(format!("'{}' is not a valid value for abi", s))),
                     }
                     Some(Ok(()))
diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs
index d0a7414b4ff62..4d0b847533b82 100644
--- a/compiler/rustc_ty_utils/src/abi.rs
+++ b/compiler/rustc_ty_utils/src/abi.rs
@@ -9,6 +9,7 @@ use rustc_session::config::OptLevel;
 use rustc_span::def_id::DefId;
 use rustc_target::abi::call::{
     ArgAbi, ArgAttribute, ArgAttributes, ArgExtension, Conv, FnAbi, PassMode, Reg, RegKind,
+    RiscvInterruptKind,
 };
 use rustc_target::abi::*;
 use rustc_target::spec::abi::Abi as SpecAbi;
@@ -193,6 +194,8 @@ fn conv_from_spec_abi(tcx: TyCtxt<'_>, abi: SpecAbi) -> Conv {
         AmdGpuKernel => Conv::AmdGpuKernel,
         AvrInterrupt => Conv::AvrInterrupt,
         AvrNonBlockingInterrupt => Conv::AvrNonBlockingInterrupt,
+        RiscvInterruptM => Conv::RiscvInterrupt { kind: RiscvInterruptKind::Machine },
+        RiscvInterruptS => Conv::RiscvInterrupt { kind: RiscvInterruptKind::Supervisor },
         Wasm => Conv::C,
 
         // These API constants ought to be more specific...
diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs
index a21b5ef05e60b..e1a15b5cf9ff1 100644
--- a/compiler/rustc_ty_utils/src/instance.rs
+++ b/compiler/rustc_ty_utils/src/instance.rs
@@ -1,4 +1,5 @@
 use rustc_errors::ErrorGuaranteed;
+use rustc_hir::def::DefKind;
 use rustc_hir::def_id::DefId;
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_middle::query::Providers;
@@ -15,54 +16,48 @@ fn resolve_instance<'tcx>(
     tcx: TyCtxt<'tcx>,
     key: ty::ParamEnvAnd<'tcx, (DefId, GenericArgsRef<'tcx>)>,
 ) -> Result<Option<Instance<'tcx>>, ErrorGuaranteed> {
-    let (param_env, (def, args)) = key.into_parts();
+    let (param_env, (def_id, args)) = key.into_parts();
 
-    let result = if let Some(trait_def_id) = tcx.trait_of_item(def) {
+    let result = if let Some(trait_def_id) = tcx.trait_of_item(def_id) {
         debug!(" => associated item, attempting to find impl in param_env {:#?}", param_env);
         resolve_associated_item(
             tcx,
-            def,
+            def_id,
             param_env,
             trait_def_id,
             tcx.normalize_erasing_regions(param_env, args),
         )
     } else {
-        let ty = tcx.type_of(def);
-        let item_type = tcx.subst_and_normalize_erasing_regions(args, param_env, ty);
+        let def = if matches!(tcx.def_kind(def_id), DefKind::Fn) && tcx.is_intrinsic(def_id) {
+            debug!(" => intrinsic");
+            ty::InstanceDef::Intrinsic(def_id)
+        } else if Some(def_id) == tcx.lang_items().drop_in_place_fn() {
+            let ty = args.type_at(0);
 
-        let def = match *item_type.kind() {
-            ty::FnDef(def_id, ..) if tcx.is_intrinsic(def_id) => {
-                debug!(" => intrinsic");
-                ty::InstanceDef::Intrinsic(def)
-            }
-            ty::FnDef(def_id, args) if Some(def_id) == tcx.lang_items().drop_in_place_fn() => {
-                let ty = args.type_at(0);
-
-                if ty.needs_drop(tcx, param_env) {
-                    debug!(" => nontrivial drop glue");
-                    match *ty.kind() {
-                        ty::Closure(..)
-                        | ty::Generator(..)
-                        | ty::Tuple(..)
-                        | ty::Adt(..)
-                        | ty::Dynamic(..)
-                        | ty::Array(..)
-                        | ty::Slice(..) => {}
-                        // Drop shims can only be built from ADTs.
-                        _ => return Ok(None),
-                    }
-
-                    ty::InstanceDef::DropGlue(def_id, Some(ty))
-                } else {
-                    debug!(" => trivial drop glue");
-                    ty::InstanceDef::DropGlue(def_id, None)
+            if ty.needs_drop(tcx, param_env) {
+                debug!(" => nontrivial drop glue");
+                match *ty.kind() {
+                    ty::Closure(..)
+                    | ty::Generator(..)
+                    | ty::Tuple(..)
+                    | ty::Adt(..)
+                    | ty::Dynamic(..)
+                    | ty::Array(..)
+                    | ty::Slice(..) => {}
+                    // Drop shims can only be built from ADTs.
+                    _ => return Ok(None),
                 }
+
+                ty::InstanceDef::DropGlue(def_id, Some(ty))
+            } else {
+                debug!(" => trivial drop glue");
+                ty::InstanceDef::DropGlue(def_id, None)
             }
-            _ => {
-                debug!(" => free item");
-                ty::InstanceDef::Item(def)
-            }
+        } else {
+            debug!(" => free item");
+            ty::InstanceDef::Item(def_id)
         };
+
         Ok(Some(Instance { def, args }))
     };
     debug!("inner_resolve_instance: result={:?}", result);
diff --git a/library/test/src/term/terminfo/searcher/tests.rs b/library/test/src/term/terminfo/searcher/tests.rs
index 4227a585e2f59..e1edd3b25cf4b 100644
--- a/library/test/src/term/terminfo/searcher/tests.rs
+++ b/library/test/src/term/terminfo/searcher/tests.rs
@@ -6,14 +6,12 @@ fn test_get_dbpath_for_term() {
     // woefully inadequate test coverage
     // note: current tests won't work with non-standard terminfo hierarchies (e.g., macOS's)
     use std::env;
-    // FIXME (#9639): This needs to handle non-utf8 paths
-    fn x(t: &str) -> String {
-        let p = get_dbpath_for_term(t).expect("no terminfo entry found");
-        p.to_str().unwrap().to_string()
+    fn x(t: &str) -> PathBuf {
+        get_dbpath_for_term(t).expect(&format!("no terminfo entry found for {t:?}"))
     }
-    assert!(x("screen") == "/usr/share/terminfo/s/screen");
-    assert!(get_dbpath_for_term("") == None);
+    assert_eq!(x("screen"), PathBuf::from("/usr/share/terminfo/s/screen"));
+    assert_eq!(get_dbpath_for_term(""), None);
     env::set_var("TERMINFO_DIRS", ":");
-    assert!(x("screen") == "/usr/share/terminfo/s/screen");
+    assert_eq!(x("screen"), PathBuf::from("/usr/share/terminfo/s/screen"));
     env::remove_var("TERMINFO_DIRS");
 }
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/extern_abi.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/extern_abi.rs
index c717a9cb55b8e..e411c1c869c55 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/extern_abi.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/extern_abi.rs
@@ -30,6 +30,8 @@ const SUPPORTED_CALLING_CONVENTIONS: &[&str] = &[
     "efiapi",
     "avr-interrupt",
     "avr-non-blocking-interrupt",
+    "riscv-interrupt-m",
+    "riscv-interrupt-s",
     "C-cmse-nonsecure-call",
     "wasm",
     "system",
diff --git a/tests/rustdoc-json/enums/field_order.rs b/tests/rustdoc-json/enums/field_order.rs
new file mode 100644
index 0000000000000..e89add9cbbde5
--- /dev/null
+++ b/tests/rustdoc-json/enums/field_order.rs
@@ -0,0 +1,40 @@
+// Check that the order of fields is preserved.
+
+pub enum Whatever {
+    Foo {
+        // Important: random prefixes are used here to ensure that
+        // sorting fields by name would cause this test to fail.
+        ews_0: i32,
+        dik_1: i32,
+        hsk_2: i32,
+        djt_3: i32,
+        jnr_4: i32,
+        dfs_5: i32,
+        bja_6: i32,
+        lyc_7: i32,
+        yqd_8: i32,
+        vll_9: i32,
+    },
+}
+
+// @set 0 = '$.index[*][?(@.name == "ews_0")].id'
+// @set 1 = '$.index[*][?(@.name == "dik_1")].id'
+// @set 2 = '$.index[*][?(@.name == "hsk_2")].id'
+// @set 3 = '$.index[*][?(@.name == "djt_3")].id'
+// @set 4 = '$.index[*][?(@.name == "jnr_4")].id'
+// @set 5 = '$.index[*][?(@.name == "dfs_5")].id'
+// @set 6 = '$.index[*][?(@.name == "bja_6")].id'
+// @set 7 = '$.index[*][?(@.name == "lyc_7")].id'
+// @set 8 = '$.index[*][?(@.name == "yqd_8")].id'
+// @set 9 = '$.index[*][?(@.name == "vll_9")].id'
+
+// @is '$.index[*][?(@.name == "Foo")].inner.variant.kind.struct.fields[0]' $0
+// @is '$.index[*][?(@.name == "Foo")].inner.variant.kind.struct.fields[1]' $1
+// @is '$.index[*][?(@.name == "Foo")].inner.variant.kind.struct.fields[2]' $2
+// @is '$.index[*][?(@.name == "Foo")].inner.variant.kind.struct.fields[3]' $3
+// @is '$.index[*][?(@.name == "Foo")].inner.variant.kind.struct.fields[4]' $4
+// @is '$.index[*][?(@.name == "Foo")].inner.variant.kind.struct.fields[5]' $5
+// @is '$.index[*][?(@.name == "Foo")].inner.variant.kind.struct.fields[6]' $6
+// @is '$.index[*][?(@.name == "Foo")].inner.variant.kind.struct.fields[7]' $7
+// @is '$.index[*][?(@.name == "Foo")].inner.variant.kind.struct.fields[8]' $8
+// @is '$.index[*][?(@.name == "Foo")].inner.variant.kind.struct.fields[9]' $9
diff --git a/tests/rustdoc-json/enums/variant_order.rs b/tests/rustdoc-json/enums/variant_order.rs
new file mode 100644
index 0000000000000..17ca96213de9a
--- /dev/null
+++ b/tests/rustdoc-json/enums/variant_order.rs
@@ -0,0 +1,38 @@
+// Check that the order of variants is preserved.
+
+pub enum Foo {
+    // Important: random prefixes are used here to ensure that
+    // sorting fields by name would cause this test to fail.
+    Ews0,
+    Dik1,
+    Hsk2,
+    Djt3,
+    Jnr4,
+    Dfs5,
+    Bja6,
+    Lyc7,
+    Yqd8,
+    Vll9,
+}
+
+// @set 0 = '$.index[*][?(@.name == "Ews0")].id'
+// @set 1 = '$.index[*][?(@.name == "Dik1")].id'
+// @set 2 = '$.index[*][?(@.name == "Hsk2")].id'
+// @set 3 = '$.index[*][?(@.name == "Djt3")].id'
+// @set 4 = '$.index[*][?(@.name == "Jnr4")].id'
+// @set 5 = '$.index[*][?(@.name == "Dfs5")].id'
+// @set 6 = '$.index[*][?(@.name == "Bja6")].id'
+// @set 7 = '$.index[*][?(@.name == "Lyc7")].id'
+// @set 8 = '$.index[*][?(@.name == "Yqd8")].id'
+// @set 9 = '$.index[*][?(@.name == "Vll9")].id'
+
+// @is '$.index[*][?(@.name == "Foo")].inner.enum.variants[0]' $0
+// @is '$.index[*][?(@.name == "Foo")].inner.enum.variants[1]' $1
+// @is '$.index[*][?(@.name == "Foo")].inner.enum.variants[2]' $2
+// @is '$.index[*][?(@.name == "Foo")].inner.enum.variants[3]' $3
+// @is '$.index[*][?(@.name == "Foo")].inner.enum.variants[4]' $4
+// @is '$.index[*][?(@.name == "Foo")].inner.enum.variants[5]' $5
+// @is '$.index[*][?(@.name == "Foo")].inner.enum.variants[6]' $6
+// @is '$.index[*][?(@.name == "Foo")].inner.enum.variants[7]' $7
+// @is '$.index[*][?(@.name == "Foo")].inner.enum.variants[8]' $8
+// @is '$.index[*][?(@.name == "Foo")].inner.enum.variants[9]' $9
diff --git a/tests/rustdoc-json/structs/field_order.rs b/tests/rustdoc-json/structs/field_order.rs
new file mode 100644
index 0000000000000..a8c18323d5278
--- /dev/null
+++ b/tests/rustdoc-json/structs/field_order.rs
@@ -0,0 +1,38 @@
+// Check that the order of fields is preserved.
+
+pub struct Foo {
+    // Important: random prefixes are used here to ensure that
+    // sorting fields by name would cause this test to fail.
+    pub ews_0: i32,
+    pub dik_1: i32,
+    pub hsk_2: i32,
+    pub djt_3: i32,
+    pub jnr_4: i32,
+    pub dfs_5: i32,
+    pub bja_6: i32,
+    pub lyc_7: i32,
+    pub yqd_8: i32,
+    pub vll_9: i32,
+}
+
+// @set 0 = '$.index[*][?(@.name == "ews_0")].id'
+// @set 1 = '$.index[*][?(@.name == "dik_1")].id'
+// @set 2 = '$.index[*][?(@.name == "hsk_2")].id'
+// @set 3 = '$.index[*][?(@.name == "djt_3")].id'
+// @set 4 = '$.index[*][?(@.name == "jnr_4")].id'
+// @set 5 = '$.index[*][?(@.name == "dfs_5")].id'
+// @set 6 = '$.index[*][?(@.name == "bja_6")].id'
+// @set 7 = '$.index[*][?(@.name == "lyc_7")].id'
+// @set 8 = '$.index[*][?(@.name == "yqd_8")].id'
+// @set 9 = '$.index[*][?(@.name == "vll_9")].id'
+
+// @is '$.index[*][?(@.name == "Foo")].inner.struct.kind.plain.fields[0]' $0
+// @is '$.index[*][?(@.name == "Foo")].inner.struct.kind.plain.fields[1]' $1
+// @is '$.index[*][?(@.name == "Foo")].inner.struct.kind.plain.fields[2]' $2
+// @is '$.index[*][?(@.name == "Foo")].inner.struct.kind.plain.fields[3]' $3
+// @is '$.index[*][?(@.name == "Foo")].inner.struct.kind.plain.fields[4]' $4
+// @is '$.index[*][?(@.name == "Foo")].inner.struct.kind.plain.fields[5]' $5
+// @is '$.index[*][?(@.name == "Foo")].inner.struct.kind.plain.fields[6]' $6
+// @is '$.index[*][?(@.name == "Foo")].inner.struct.kind.plain.fields[7]' $7
+// @is '$.index[*][?(@.name == "Foo")].inner.struct.kind.plain.fields[8]' $8
+// @is '$.index[*][?(@.name == "Foo")].inner.struct.kind.plain.fields[9]' $9
diff --git a/tests/rustdoc-json/unions/field_order.rs b/tests/rustdoc-json/unions/field_order.rs
new file mode 100644
index 0000000000000..8a40bda03999c
--- /dev/null
+++ b/tests/rustdoc-json/unions/field_order.rs
@@ -0,0 +1,38 @@
+// Check that the order of fields is preserved.
+
+pub union Foo {
+    // Important: random prefixes are used here to ensure that
+    // sorting fields by name would cause this test to fail.
+    pub ews_0: i32,
+    pub dik_1: i32,
+    pub hsk_2: i32,
+    pub djt_3: i32,
+    pub jnr_4: i32,
+    pub dfs_5: i32,
+    pub bja_6: i32,
+    pub lyc_7: i32,
+    pub yqd_8: i32,
+    pub vll_9: i32,
+}
+
+// @set 0 = '$.index[*][?(@.name == "ews_0")].id'
+// @set 1 = '$.index[*][?(@.name == "dik_1")].id'
+// @set 2 = '$.index[*][?(@.name == "hsk_2")].id'
+// @set 3 = '$.index[*][?(@.name == "djt_3")].id'
+// @set 4 = '$.index[*][?(@.name == "jnr_4")].id'
+// @set 5 = '$.index[*][?(@.name == "dfs_5")].id'
+// @set 6 = '$.index[*][?(@.name == "bja_6")].id'
+// @set 7 = '$.index[*][?(@.name == "lyc_7")].id'
+// @set 8 = '$.index[*][?(@.name == "yqd_8")].id'
+// @set 9 = '$.index[*][?(@.name == "vll_9")].id'
+
+// @is '$.index[*][?(@.name == "Foo")].inner.union.fields[0]' $0
+// @is '$.index[*][?(@.name == "Foo")].inner.union.fields[1]' $1
+// @is '$.index[*][?(@.name == "Foo")].inner.union.fields[2]' $2
+// @is '$.index[*][?(@.name == "Foo")].inner.union.fields[3]' $3
+// @is '$.index[*][?(@.name == "Foo")].inner.union.fields[4]' $4
+// @is '$.index[*][?(@.name == "Foo")].inner.union.fields[5]' $5
+// @is '$.index[*][?(@.name == "Foo")].inner.union.fields[6]' $6
+// @is '$.index[*][?(@.name == "Foo")].inner.union.fields[7]' $7
+// @is '$.index[*][?(@.name == "Foo")].inner.union.fields[8]' $8
+// @is '$.index[*][?(@.name == "Foo")].inner.union.fields[9]' $9
diff --git a/tests/ui/abi/riscv-discoverability-guidance.riscv32.stderr b/tests/ui/abi/riscv-discoverability-guidance.riscv32.stderr
new file mode 100644
index 0000000000000..02082c13f91a7
--- /dev/null
+++ b/tests/ui/abi/riscv-discoverability-guidance.riscv32.stderr
@@ -0,0 +1,27 @@
+error[E0703]: invalid ABI: found `riscv-interrupt`
+  --> $DIR/riscv-discoverability-guidance.rs:17:8
+   |
+LL | extern "riscv-interrupt" fn isr() {}
+   |        ^^^^^^^^^^^^^^^^^
+   |        |
+   |        invalid ABI
+   |        help: did you mean: `"riscv-interrupt-m"`
+   |
+   = note: invoke `rustc --print=calling-conventions` for a full list of supported calling conventions.
+   = note: please use one of riscv-interrupt-m or riscv-interrupt-s for machine- or supervisor-level interrupts, respectively
+
+error[E0703]: invalid ABI: found `riscv-interrupt-u`
+  --> $DIR/riscv-discoverability-guidance.rs:23:8
+   |
+LL | extern "riscv-interrupt-u" fn isr_U() {}
+   |        ^^^^^^^^^^^^^^^^^^^
+   |        |
+   |        invalid ABI
+   |        help: did you mean: `"riscv-interrupt-m"`
+   |
+   = note: invoke `rustc --print=calling-conventions` for a full list of supported calling conventions.
+   = note: user-mode interrupt handlers have been removed from LLVM pending standardization, see: https://reviews.llvm.org/D149314
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0703`.
diff --git a/tests/ui/abi/riscv-discoverability-guidance.riscv64.stderr b/tests/ui/abi/riscv-discoverability-guidance.riscv64.stderr
new file mode 100644
index 0000000000000..02082c13f91a7
--- /dev/null
+++ b/tests/ui/abi/riscv-discoverability-guidance.riscv64.stderr
@@ -0,0 +1,27 @@
+error[E0703]: invalid ABI: found `riscv-interrupt`
+  --> $DIR/riscv-discoverability-guidance.rs:17:8
+   |
+LL | extern "riscv-interrupt" fn isr() {}
+   |        ^^^^^^^^^^^^^^^^^
+   |        |
+   |        invalid ABI
+   |        help: did you mean: `"riscv-interrupt-m"`
+   |
+   = note: invoke `rustc --print=calling-conventions` for a full list of supported calling conventions.
+   = note: please use one of riscv-interrupt-m or riscv-interrupt-s for machine- or supervisor-level interrupts, respectively
+
+error[E0703]: invalid ABI: found `riscv-interrupt-u`
+  --> $DIR/riscv-discoverability-guidance.rs:23:8
+   |
+LL | extern "riscv-interrupt-u" fn isr_U() {}
+   |        ^^^^^^^^^^^^^^^^^^^
+   |        |
+   |        invalid ABI
+   |        help: did you mean: `"riscv-interrupt-m"`
+   |
+   = note: invoke `rustc --print=calling-conventions` for a full list of supported calling conventions.
+   = note: user-mode interrupt handlers have been removed from LLVM pending standardization, see: https://reviews.llvm.org/D149314
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0703`.
diff --git a/tests/ui/abi/riscv-discoverability-guidance.rs b/tests/ui/abi/riscv-discoverability-guidance.rs
new file mode 100644
index 0000000000000..f57fcd6044ffa
--- /dev/null
+++ b/tests/ui/abi/riscv-discoverability-guidance.rs
@@ -0,0 +1,27 @@
+// ignore-tidy-linelength
+// revisions: riscv32 riscv64
+//
+// [riscv32] needs-llvm-components: riscv
+// [riscv32] compile-flags: --target=riscv32i-unknown-none-elf -C target-feature=-unaligned-scalar-mem --crate-type=rlib
+// [riscv64] needs-llvm-components: riscv
+// [riscv64] compile-flags: --target=riscv64gc-unknown-none-elf -C target-feature=-unaligned-scalar-mem --crate-type=rlib
+#![no_core]
+#![feature(
+    no_core,
+    lang_items,
+    abi_riscv_interrupt
+)]
+#[lang = "sized"]
+trait Sized {}
+
+extern "riscv-interrupt" fn isr() {}
+//~^ ERROR invalid ABI
+//~^^ NOTE invalid ABI
+//~^^^ NOTE invoke `rustc --print=calling-conventions` for a full list of supported calling conventions
+//~^^^^ NOTE please use one of riscv-interrupt-m or riscv-interrupt-s
+
+extern "riscv-interrupt-u" fn isr_U() {}
+//~^ ERROR invalid ABI
+//~^^ NOTE invalid ABI
+//~^^^ NOTE invoke `rustc --print=calling-conventions` for a full list of supported calling conventions
+//~^^^^ NOTE user-mode interrupt handlers have been removed from LLVM pending standardization
diff --git a/tests/ui/abi/unsupported.aarch64.stderr b/tests/ui/abi/unsupported.aarch64.stderr
index 980457eeab5b7..d7b4e6150ff31 100644
--- a/tests/ui/abi/unsupported.aarch64.stderr
+++ b/tests/ui/abi/unsupported.aarch64.stderr
@@ -1,53 +1,59 @@
 error[E0570]: `"ptx-kernel"` is not a supported ABI for the current target
-  --> $DIR/unsupported.rs:25:1
+  --> $DIR/unsupported.rs:30:1
    |
 LL | extern "ptx-kernel" fn ptx() {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0570]: `"amdgpu-kernel"` is not a supported ABI for the current target
-  --> $DIR/unsupported.rs:27:1
+  --> $DIR/unsupported.rs:32:1
    |
 LL | extern "amdgpu-kernel" fn amdgpu() {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0570]: `"wasm"` is not a supported ABI for the current target
-  --> $DIR/unsupported.rs:29:1
+  --> $DIR/unsupported.rs:34:1
    |
 LL | extern "wasm" fn wasm() {}
    | ^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0570]: `"aapcs"` is not a supported ABI for the current target
-  --> $DIR/unsupported.rs:31:1
+  --> $DIR/unsupported.rs:36:1
    |
 LL | extern "aapcs" fn aapcs() {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0570]: `"msp430-interrupt"` is not a supported ABI for the current target
-  --> $DIR/unsupported.rs:35:1
+  --> $DIR/unsupported.rs:42:1
    |
 LL | extern "msp430-interrupt" fn msp430() {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0570]: `"avr-interrupt"` is not a supported ABI for the current target
-  --> $DIR/unsupported.rs:37:1
+  --> $DIR/unsupported.rs:44:1
    |
 LL | extern "avr-interrupt" fn avr() {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
+error[E0570]: `"riscv-interrupt-m"` is not a supported ABI for the current target
+  --> $DIR/unsupported.rs:46:1
+   |
+LL | extern "riscv-interrupt-m" fn riscv() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
 error[E0570]: `"x86-interrupt"` is not a supported ABI for the current target
-  --> $DIR/unsupported.rs:39:1
+  --> $DIR/unsupported.rs:51:1
    |
 LL | extern "x86-interrupt" fn x86() {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0570]: `"thiscall"` is not a supported ABI for the current target
-  --> $DIR/unsupported.rs:42:1
+  --> $DIR/unsupported.rs:56:1
    |
 LL | extern "thiscall" fn thiscall() {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of calling convention not supported on this target
-  --> $DIR/unsupported.rs:46:1
+  --> $DIR/unsupported.rs:62:1
    |
 LL | extern "stdcall" fn stdcall() {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -56,6 +62,6 @@ LL | extern "stdcall" fn stdcall() {}
    = note: for more information, see issue #87678 <https://github.com/rust-lang/rust/issues/87678>
    = note: `#[warn(unsupported_calling_conventions)]` on by default
 
-error: aborting due to 8 previous errors; 1 warning emitted
+error: aborting due to 9 previous errors; 1 warning emitted
 
 For more information about this error, try `rustc --explain E0570`.
diff --git a/tests/ui/abi/unsupported.arm.stderr b/tests/ui/abi/unsupported.arm.stderr
index 450abd948863e..3a3ed2dd9c569 100644
--- a/tests/ui/abi/unsupported.arm.stderr
+++ b/tests/ui/abi/unsupported.arm.stderr
@@ -1,47 +1,53 @@
 error[E0570]: `"ptx-kernel"` is not a supported ABI for the current target
-  --> $DIR/unsupported.rs:25:1
+  --> $DIR/unsupported.rs:30:1
    |
 LL | extern "ptx-kernel" fn ptx() {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0570]: `"amdgpu-kernel"` is not a supported ABI for the current target
-  --> $DIR/unsupported.rs:27:1
+  --> $DIR/unsupported.rs:32:1
    |
 LL | extern "amdgpu-kernel" fn amdgpu() {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0570]: `"wasm"` is not a supported ABI for the current target
-  --> $DIR/unsupported.rs:29:1
+  --> $DIR/unsupported.rs:34:1
    |
 LL | extern "wasm" fn wasm() {}
    | ^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0570]: `"msp430-interrupt"` is not a supported ABI for the current target
-  --> $DIR/unsupported.rs:35:1
+  --> $DIR/unsupported.rs:42:1
    |
 LL | extern "msp430-interrupt" fn msp430() {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0570]: `"avr-interrupt"` is not a supported ABI for the current target
-  --> $DIR/unsupported.rs:37:1
+  --> $DIR/unsupported.rs:44:1
    |
 LL | extern "avr-interrupt" fn avr() {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
+error[E0570]: `"riscv-interrupt-m"` is not a supported ABI for the current target
+  --> $DIR/unsupported.rs:46:1
+   |
+LL | extern "riscv-interrupt-m" fn riscv() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
 error[E0570]: `"x86-interrupt"` is not a supported ABI for the current target
-  --> $DIR/unsupported.rs:39:1
+  --> $DIR/unsupported.rs:51:1
    |
 LL | extern "x86-interrupt" fn x86() {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0570]: `"thiscall"` is not a supported ABI for the current target
-  --> $DIR/unsupported.rs:42:1
+  --> $DIR/unsupported.rs:56:1
    |
 LL | extern "thiscall" fn thiscall() {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of calling convention not supported on this target
-  --> $DIR/unsupported.rs:46:1
+  --> $DIR/unsupported.rs:62:1
    |
 LL | extern "stdcall" fn stdcall() {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -50,6 +56,6 @@ LL | extern "stdcall" fn stdcall() {}
    = note: for more information, see issue #87678 <https://github.com/rust-lang/rust/issues/87678>
    = note: `#[warn(unsupported_calling_conventions)]` on by default
 
-error: aborting due to 7 previous errors; 1 warning emitted
+error: aborting due to 8 previous errors; 1 warning emitted
 
 For more information about this error, try `rustc --explain E0570`.
diff --git a/tests/ui/abi/unsupported.i686.stderr b/tests/ui/abi/unsupported.i686.stderr
index 0340382a45263..31b7d030bd3b4 100644
--- a/tests/ui/abi/unsupported.i686.stderr
+++ b/tests/ui/abi/unsupported.i686.stderr
@@ -1,39 +1,45 @@
 error[E0570]: `"ptx-kernel"` is not a supported ABI for the current target
-  --> $DIR/unsupported.rs:25:1
+  --> $DIR/unsupported.rs:30:1
    |
 LL | extern "ptx-kernel" fn ptx() {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0570]: `"amdgpu-kernel"` is not a supported ABI for the current target
-  --> $DIR/unsupported.rs:27:1
+  --> $DIR/unsupported.rs:32:1
    |
 LL | extern "amdgpu-kernel" fn amdgpu() {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0570]: `"wasm"` is not a supported ABI for the current target
-  --> $DIR/unsupported.rs:29:1
+  --> $DIR/unsupported.rs:34:1
    |
 LL | extern "wasm" fn wasm() {}
    | ^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0570]: `"aapcs"` is not a supported ABI for the current target
-  --> $DIR/unsupported.rs:31:1
+  --> $DIR/unsupported.rs:36:1
    |
 LL | extern "aapcs" fn aapcs() {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0570]: `"msp430-interrupt"` is not a supported ABI for the current target
-  --> $DIR/unsupported.rs:35:1
+  --> $DIR/unsupported.rs:42:1
    |
 LL | extern "msp430-interrupt" fn msp430() {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0570]: `"avr-interrupt"` is not a supported ABI for the current target
-  --> $DIR/unsupported.rs:37:1
+  --> $DIR/unsupported.rs:44:1
    |
 LL | extern "avr-interrupt" fn avr() {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 6 previous errors
+error[E0570]: `"riscv-interrupt-m"` is not a supported ABI for the current target
+  --> $DIR/unsupported.rs:46:1
+   |
+LL | extern "riscv-interrupt-m" fn riscv() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 7 previous errors
 
 For more information about this error, try `rustc --explain E0570`.
diff --git a/tests/ui/abi/unsupported.riscv32.stderr b/tests/ui/abi/unsupported.riscv32.stderr
new file mode 100644
index 0000000000000..1966e18f0a06e
--- /dev/null
+++ b/tests/ui/abi/unsupported.riscv32.stderr
@@ -0,0 +1,61 @@
+error[E0570]: `"ptx-kernel"` is not a supported ABI for the current target
+  --> $DIR/unsupported.rs:30:1
+   |
+LL | extern "ptx-kernel" fn ptx() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0570]: `"amdgpu-kernel"` is not a supported ABI for the current target
+  --> $DIR/unsupported.rs:32:1
+   |
+LL | extern "amdgpu-kernel" fn amdgpu() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0570]: `"wasm"` is not a supported ABI for the current target
+  --> $DIR/unsupported.rs:34:1
+   |
+LL | extern "wasm" fn wasm() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0570]: `"aapcs"` is not a supported ABI for the current target
+  --> $DIR/unsupported.rs:36:1
+   |
+LL | extern "aapcs" fn aapcs() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0570]: `"msp430-interrupt"` is not a supported ABI for the current target
+  --> $DIR/unsupported.rs:42:1
+   |
+LL | extern "msp430-interrupt" fn msp430() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0570]: `"avr-interrupt"` is not a supported ABI for the current target
+  --> $DIR/unsupported.rs:44:1
+   |
+LL | extern "avr-interrupt" fn avr() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0570]: `"x86-interrupt"` is not a supported ABI for the current target
+  --> $DIR/unsupported.rs:51:1
+   |
+LL | extern "x86-interrupt" fn x86() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0570]: `"thiscall"` is not a supported ABI for the current target
+  --> $DIR/unsupported.rs:56:1
+   |
+LL | extern "thiscall" fn thiscall() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: use of calling convention not supported on this target
+  --> $DIR/unsupported.rs:62:1
+   |
+LL | extern "stdcall" fn stdcall() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #87678 <https://github.com/rust-lang/rust/issues/87678>
+   = note: `#[warn(unsupported_calling_conventions)]` on by default
+
+error: aborting due to 8 previous errors; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0570`.
diff --git a/tests/ui/abi/unsupported.riscv64.stderr b/tests/ui/abi/unsupported.riscv64.stderr
new file mode 100644
index 0000000000000..1966e18f0a06e
--- /dev/null
+++ b/tests/ui/abi/unsupported.riscv64.stderr
@@ -0,0 +1,61 @@
+error[E0570]: `"ptx-kernel"` is not a supported ABI for the current target
+  --> $DIR/unsupported.rs:30:1
+   |
+LL | extern "ptx-kernel" fn ptx() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0570]: `"amdgpu-kernel"` is not a supported ABI for the current target
+  --> $DIR/unsupported.rs:32:1
+   |
+LL | extern "amdgpu-kernel" fn amdgpu() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0570]: `"wasm"` is not a supported ABI for the current target
+  --> $DIR/unsupported.rs:34:1
+   |
+LL | extern "wasm" fn wasm() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0570]: `"aapcs"` is not a supported ABI for the current target
+  --> $DIR/unsupported.rs:36:1
+   |
+LL | extern "aapcs" fn aapcs() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0570]: `"msp430-interrupt"` is not a supported ABI for the current target
+  --> $DIR/unsupported.rs:42:1
+   |
+LL | extern "msp430-interrupt" fn msp430() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0570]: `"avr-interrupt"` is not a supported ABI for the current target
+  --> $DIR/unsupported.rs:44:1
+   |
+LL | extern "avr-interrupt" fn avr() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0570]: `"x86-interrupt"` is not a supported ABI for the current target
+  --> $DIR/unsupported.rs:51:1
+   |
+LL | extern "x86-interrupt" fn x86() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0570]: `"thiscall"` is not a supported ABI for the current target
+  --> $DIR/unsupported.rs:56:1
+   |
+LL | extern "thiscall" fn thiscall() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: use of calling convention not supported on this target
+  --> $DIR/unsupported.rs:62:1
+   |
+LL | extern "stdcall" fn stdcall() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #87678 <https://github.com/rust-lang/rust/issues/87678>
+   = note: `#[warn(unsupported_calling_conventions)]` on by default
+
+error: aborting due to 8 previous errors; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0570`.
diff --git a/tests/ui/abi/unsupported.rs b/tests/ui/abi/unsupported.rs
index bcd95f1ed4cdc..57278e664b51e 100644
--- a/tests/ui/abi/unsupported.rs
+++ b/tests/ui/abi/unsupported.rs
@@ -1,4 +1,4 @@
-// revisions: x64 i686 aarch64 arm
+// revisions: x64 i686 aarch64 arm riscv32 riscv64
 //
 // [x64] needs-llvm-components: x86
 // [x64] compile-flags: --target=x86_64-unknown-linux-gnu --crate-type=rlib
@@ -8,6 +8,10 @@
 // [aarch64] compile-flags: --target=aarch64-unknown-linux-gnu --crate-type=rlib
 // [arm] needs-llvm-components: arm
 // [arm] compile-flags: --target=armv7-unknown-linux-gnueabihf --crate-type=rlib
+// [riscv32] needs-llvm-components: riscv
+// [riscv32] compile-flags: --target=riscv32i-unknown-none-elf --crate-type=rlib
+// [riscv64] needs-llvm-components: riscv
+// [riscv64] compile-flags: --target=riscv64gc-unknown-none-elf --crate-type=rlib
 #![no_core]
 #![feature(
     no_core,
@@ -17,10 +21,11 @@
     abi_avr_interrupt,
     abi_amdgpu_kernel,
     wasm_abi,
-    abi_x86_interrupt
+    abi_x86_interrupt,
+    abi_riscv_interrupt
 )]
-#[lang="sized"]
-trait Sized { }
+#[lang = "sized"]
+trait Sized {}
 
 extern "ptx-kernel" fn ptx() {}
 //~^ ERROR is not a supported ABI
@@ -32,21 +37,36 @@ extern "aapcs" fn aapcs() {}
 //[x64]~^ ERROR is not a supported ABI
 //[i686]~^^ ERROR is not a supported ABI
 //[aarch64]~^^^ ERROR is not a supported ABI
+//[riscv32]~^^^^ ERROR is not a supported ABI
+//[riscv64]~^^^^^ ERROR is not a supported ABI
 extern "msp430-interrupt" fn msp430() {}
 //~^ ERROR is not a supported ABI
 extern "avr-interrupt" fn avr() {}
 //~^ ERROR is not a supported ABI
+extern "riscv-interrupt-m" fn riscv() {}
+//[arm]~^ ERROR is not a supported ABI
+//[x64]~^^ ERROR is not a supported ABI
+//[i686]~^^^ ERROR is not a supported ABI
+//[aarch64]~^^^^ ERROR is not a supported ABI
 extern "x86-interrupt" fn x86() {}
 //[aarch64]~^ ERROR is not a supported ABI
 //[arm]~^^ ERROR is not a supported ABI
+//[riscv32]~^^^ ERROR is not a supported ABI
+//[riscv64]~^^^^ ERROR is not a supported ABI
 extern "thiscall" fn thiscall() {}
 //[x64]~^ ERROR is not a supported ABI
-//[aarch64]~^^ ERROR is not a supported ABI
-//[arm]~^^^ ERROR is not a supported ABI
+//[arm]~^^ ERROR is not a supported ABI
+//[aarch64]~^^^ ERROR is not a supported ABI
+//[riscv32]~^^^^ ERROR is not a supported ABI
+//[riscv64]~^^^^^ ERROR is not a supported ABI
 extern "stdcall" fn stdcall() {}
 //[x64]~^ WARN use of calling convention not supported
 //[x64]~^^ WARN this was previously accepted
-//[aarch64]~^^^ WARN use of calling convention not supported
-//[aarch64]~^^^^ WARN this was previously accepted
-//[arm]~^^^^^ WARN use of calling convention not supported
-//[arm]~^^^^^^ WARN this was previously accepted
+//[arm]~^^^ WARN use of calling convention not supported
+//[arm]~^^^^ WARN this was previously accepted
+//[aarch64]~^^^^^ WARN use of calling convention not supported
+//[aarch64]~^^^^^^ WARN this was previously accepted
+//[riscv32]~^^^^^^^ WARN use of calling convention not supported
+//[riscv32]~^^^^^^^^ WARN this was previously accepted
+//[riscv64]~^^^^^^^^^ WARN use of calling convention not supported
+//[riscv64]~^^^^^^^^^^ WARN this was previously accepted
diff --git a/tests/ui/abi/unsupported.x64.stderr b/tests/ui/abi/unsupported.x64.stderr
index 29eed8505b9b5..ea62cb1514807 100644
--- a/tests/ui/abi/unsupported.x64.stderr
+++ b/tests/ui/abi/unsupported.x64.stderr
@@ -1,47 +1,53 @@
 error[E0570]: `"ptx-kernel"` is not a supported ABI for the current target
-  --> $DIR/unsupported.rs:25:1
+  --> $DIR/unsupported.rs:30:1
    |
 LL | extern "ptx-kernel" fn ptx() {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0570]: `"amdgpu-kernel"` is not a supported ABI for the current target
-  --> $DIR/unsupported.rs:27:1
+  --> $DIR/unsupported.rs:32:1
    |
 LL | extern "amdgpu-kernel" fn amdgpu() {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0570]: `"wasm"` is not a supported ABI for the current target
-  --> $DIR/unsupported.rs:29:1
+  --> $DIR/unsupported.rs:34:1
    |
 LL | extern "wasm" fn wasm() {}
    | ^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0570]: `"aapcs"` is not a supported ABI for the current target
-  --> $DIR/unsupported.rs:31:1
+  --> $DIR/unsupported.rs:36:1
    |
 LL | extern "aapcs" fn aapcs() {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0570]: `"msp430-interrupt"` is not a supported ABI for the current target
-  --> $DIR/unsupported.rs:35:1
+  --> $DIR/unsupported.rs:42:1
    |
 LL | extern "msp430-interrupt" fn msp430() {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0570]: `"avr-interrupt"` is not a supported ABI for the current target
-  --> $DIR/unsupported.rs:37:1
+  --> $DIR/unsupported.rs:44:1
    |
 LL | extern "avr-interrupt" fn avr() {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
+error[E0570]: `"riscv-interrupt-m"` is not a supported ABI for the current target
+  --> $DIR/unsupported.rs:46:1
+   |
+LL | extern "riscv-interrupt-m" fn riscv() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
 error[E0570]: `"thiscall"` is not a supported ABI for the current target
-  --> $DIR/unsupported.rs:42:1
+  --> $DIR/unsupported.rs:56:1
    |
 LL | extern "thiscall" fn thiscall() {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of calling convention not supported on this target
-  --> $DIR/unsupported.rs:46:1
+  --> $DIR/unsupported.rs:62:1
    |
 LL | extern "stdcall" fn stdcall() {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -50,6 +56,6 @@ LL | extern "stdcall" fn stdcall() {}
    = note: for more information, see issue #87678 <https://github.com/rust-lang/rust/issues/87678>
    = note: `#[warn(unsupported_calling_conventions)]` on by default
 
-error: aborting due to 7 previous errors; 1 warning emitted
+error: aborting due to 8 previous errors; 1 warning emitted
 
 For more information about this error, try `rustc --explain E0570`.
diff --git a/tests/ui/feature-gates/feature-gate-abi-riscv-interrupt.rs b/tests/ui/feature-gates/feature-gate-abi-riscv-interrupt.rs
new file mode 100644
index 0000000000000..7755a46da3b51
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-abi-riscv-interrupt.rs
@@ -0,0 +1,33 @@
+// needs-llvm-components: riscv
+// compile-flags: --target=riscv32imc-unknown-none-elf --crate-type=rlib
+#![no_core]
+#![feature(no_core, lang_items)]
+#[lang = "sized"]
+trait Sized {}
+
+// Test that the riscv interrupt ABIs cannot be used when riscv_interrupt
+// feature gate is not used.
+
+extern "riscv-interrupt-m" fn f() {}
+//~^ ERROR riscv-interrupt ABIs are experimental
+extern "riscv-interrupt-s" fn f_s() {}
+//~^ ERROR riscv-interrupt ABIs are experimental
+
+trait T {
+    extern "riscv-interrupt-m" fn m();
+    //~^ ERROR riscv-interrupt ABIs are experimental
+}
+
+struct S;
+impl T for S {
+    extern "riscv-interrupt-m" fn m() {}
+    //~^ ERROR riscv-interrupt ABIs are experimental
+}
+
+impl S {
+    extern "riscv-interrupt-m" fn im() {}
+    //~^ ERROR riscv-interrupt ABIs are experimental
+}
+
+type TA = extern "riscv-interrupt-m" fn();
+//~^ ERROR riscv-interrupt ABIs are experimental
diff --git a/tests/ui/feature-gates/feature-gate-abi-riscv-interrupt.stderr b/tests/ui/feature-gates/feature-gate-abi-riscv-interrupt.stderr
new file mode 100644
index 0000000000000..60c7fa0ea67b8
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-abi-riscv-interrupt.stderr
@@ -0,0 +1,57 @@
+error[E0658]: riscv-interrupt ABIs are experimental and subject to change
+  --> $DIR/feature-gate-abi-riscv-interrupt.rs:11:8
+   |
+LL | extern "riscv-interrupt-m" fn f() {}
+   |        ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #111889 <https://github.com/rust-lang/rust/issues/111889> for more information
+   = help: add `#![feature(abi_riscv_interrupt)]` to the crate attributes to enable
+
+error[E0658]: riscv-interrupt ABIs are experimental and subject to change
+  --> $DIR/feature-gate-abi-riscv-interrupt.rs:13:8
+   |
+LL | extern "riscv-interrupt-s" fn f_s() {}
+   |        ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #111889 <https://github.com/rust-lang/rust/issues/111889> for more information
+   = help: add `#![feature(abi_riscv_interrupt)]` to the crate attributes to enable
+
+error[E0658]: riscv-interrupt ABIs are experimental and subject to change
+  --> $DIR/feature-gate-abi-riscv-interrupt.rs:17:12
+   |
+LL |     extern "riscv-interrupt-m" fn m();
+   |            ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #111889 <https://github.com/rust-lang/rust/issues/111889> for more information
+   = help: add `#![feature(abi_riscv_interrupt)]` to the crate attributes to enable
+
+error[E0658]: riscv-interrupt ABIs are experimental and subject to change
+  --> $DIR/feature-gate-abi-riscv-interrupt.rs:23:12
+   |
+LL |     extern "riscv-interrupt-m" fn m() {}
+   |            ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #111889 <https://github.com/rust-lang/rust/issues/111889> for more information
+   = help: add `#![feature(abi_riscv_interrupt)]` to the crate attributes to enable
+
+error[E0658]: riscv-interrupt ABIs are experimental and subject to change
+  --> $DIR/feature-gate-abi-riscv-interrupt.rs:28:12
+   |
+LL |     extern "riscv-interrupt-m" fn im() {}
+   |            ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #111889 <https://github.com/rust-lang/rust/issues/111889> for more information
+   = help: add `#![feature(abi_riscv_interrupt)]` to the crate attributes to enable
+
+error[E0658]: riscv-interrupt ABIs are experimental and subject to change
+  --> $DIR/feature-gate-abi-riscv-interrupt.rs:32:18
+   |
+LL | type TA = extern "riscv-interrupt-m" fn();
+   |                  ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #111889 <https://github.com/rust-lang/rust/issues/111889> for more information
+   = help: add `#![feature(abi_riscv_interrupt)]` to the crate attributes to enable
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/inline-const/instance-doesnt-depend-on-type.rs b/tests/ui/inline-const/instance-doesnt-depend-on-type.rs
new file mode 100644
index 0000000000000..bc739785c8bb7
--- /dev/null
+++ b/tests/ui/inline-const/instance-doesnt-depend-on-type.rs
@@ -0,0 +1,10 @@
+// check-pass
+// issue: 114660
+
+#![feature(inline_const)]
+
+fn main() {
+    const { core::mem::transmute::<u8, u8> };
+    // Don't resolve the instance of this inline constant to be an intrinsic,
+    // even if the type of the constant is `extern "intrinsic" fn(u8) -> u8`.
+}
diff --git a/tests/ui/proc-macro/meta-macro-hygiene.rs b/tests/ui/proc-macro/meta-macro-hygiene.rs
index 70b8d8da19b32..72fd88e119fd0 100644
--- a/tests/ui/proc-macro/meta-macro-hygiene.rs
+++ b/tests/ui/proc-macro/meta-macro-hygiene.rs
@@ -3,8 +3,10 @@
 // edition:2018
 // compile-flags: -Z span-debug -Z macro-backtrace -Z unpretty=expanded,hygiene -Z trim-diagnostic-paths=no
 // check-pass
+// ignore-tidy-linelength
 // normalize-stdout-test "\d+#" -> "0#"
 // normalize-stdout-test "expn\d{3,}" -> "expnNNN"
+// normalize-stdout-test "extern crate compiler_builtins /\* \d+ \*/" -> "extern crate compiler_builtins /* NNN */"
 //
 // We don't care about symbol ids, so we set them all to 0
 // in the stdout
@@ -22,7 +24,7 @@ macro_rules! produce_it {
         // the fact that `print_def_site` is produced by a
         // `macro_rules!` macro in `make_macro`).
         meta_macro::print_def_site!($crate::dummy!());
-    }
+    };
 }
 
 fn main() {
diff --git a/tests/ui/proc-macro/meta-macro-hygiene.stdout b/tests/ui/proc-macro/meta-macro-hygiene.stdout
index ac65ba0751238..eeb7179e6fdb9 100644
--- a/tests/ui/proc-macro/meta-macro-hygiene.stdout
+++ b/tests/ui/proc-macro/meta-macro-hygiene.stdout
@@ -1,5 +1,5 @@
 Def site: $DIR/auxiliary/make-macro.rs:7:9: 7:56 (#4)
-Input: TokenStream [Ident { ident: "$crate", span: $DIR/meta-macro-hygiene.rs:24:37: 24:43 (#3) }, Punct { ch: ':', spacing: Joint, span: $DIR/meta-macro-hygiene.rs:24:43: 24:44 (#3) }, Punct { ch: ':', spacing: Alone, span: $DIR/meta-macro-hygiene.rs:24:44: 24:45 (#3) }, Ident { ident: "dummy", span: $DIR/meta-macro-hygiene.rs:24:45: 24:50 (#3) }, Punct { ch: '!', spacing: Alone, span: $DIR/meta-macro-hygiene.rs:24:50: 24:51 (#3) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: $DIR/meta-macro-hygiene.rs:24:51: 24:53 (#3) }]
+Input: TokenStream [Ident { ident: "$crate", span: $DIR/meta-macro-hygiene.rs:26:37: 26:43 (#3) }, Punct { ch: ':', spacing: Joint, span: $DIR/meta-macro-hygiene.rs:26:43: 26:44 (#3) }, Punct { ch: ':', spacing: Alone, span: $DIR/meta-macro-hygiene.rs:26:44: 26:45 (#3) }, Ident { ident: "dummy", span: $DIR/meta-macro-hygiene.rs:26:45: 26:50 (#3) }, Punct { ch: '!', spacing: Alone, span: $DIR/meta-macro-hygiene.rs:26:50: 26:51 (#3) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: $DIR/meta-macro-hygiene.rs:26:51: 26:53 (#3) }]
 Respanned: TokenStream [Ident { ident: "$crate", span: $DIR/auxiliary/make-macro.rs:7:9: 7:56 (#4) }, Punct { ch: ':', spacing: Joint, span: $DIR/auxiliary/make-macro.rs:7:9: 7:56 (#4) }, Punct { ch: ':', spacing: Alone, span: $DIR/auxiliary/make-macro.rs:7:9: 7:56 (#4) }, Ident { ident: "dummy", span: $DIR/auxiliary/make-macro.rs:7:9: 7:56 (#4) }, Punct { ch: '!', spacing: Alone, span: $DIR/auxiliary/make-macro.rs:7:9: 7:56 (#4) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: $DIR/auxiliary/make-macro.rs:7:9: 7:56 (#4) }]
 #![feature /* 0#0 */(prelude_import)]
 // aux-build:make-macro.rs
@@ -7,8 +7,10 @@ Respanned: TokenStream [Ident { ident: "$crate", span: $DIR/auxiliary/make-macro
 // edition:2018
 // compile-flags: -Z span-debug -Z macro-backtrace -Z unpretty=expanded,hygiene -Z trim-diagnostic-paths=no
 // check-pass
+// ignore-tidy-linelength
 // normalize-stdout-test "\d+#" -> "0#"
 // normalize-stdout-test "expn\d{3,}" -> "expnNNN"
+// normalize-stdout-test "extern crate compiler_builtins /\* \d+ \*/" -> "extern crate compiler_builtins /* NNN */"
 //
 // We don't care about symbol ids, so we set them all to 0
 // in the stdout
@@ -18,7 +20,7 @@ Respanned: TokenStream [Ident { ident: "$crate", span: $DIR/auxiliary/make-macro
 use core /* 0#1 */::prelude /* 0#1 */::rust_2018 /* 0#1 */::*;
 #[macro_use /* 0#1 */]
 extern crate core /* 0#1 */;
-extern crate compiler_builtins /* 445 */ as _ /* 0#1 */;
+extern crate compiler_builtins /* NNN */ as _ /* 0#1 */;
 // Don't load unnecessary hygiene information from std
 extern crate std /* 0#0 */;
 
@@ -36,7 +38,7 @@ macro_rules! produce_it
         // relative to `meta_macro`, *not* `make_macro` (despite
         // the fact that `print_def_site` is produced by a
         // `macro_rules!` macro in `make_macro`).
-    }
+    } ;
 }
 
 fn main /* 0#0 */() { ; }
diff --git a/tests/ui/proc-macro/nonterminal-token-hygiene.rs b/tests/ui/proc-macro/nonterminal-token-hygiene.rs
index fa52a975bca85..1e9e90a6b6f08 100644
--- a/tests/ui/proc-macro/nonterminal-token-hygiene.rs
+++ b/tests/ui/proc-macro/nonterminal-token-hygiene.rs
@@ -3,12 +3,13 @@
 // check-pass
 // compile-flags: -Z span-debug -Z macro-backtrace -Z unpretty=expanded,hygiene
 // compile-flags: -Z trim-diagnostic-paths=no
+// ignore-tidy-linelength
 // normalize-stdout-test "\d+#" -> "0#"
 // normalize-stdout-test "expn\d{3,}" -> "expnNNN"
+// normalize-stdout-test "extern crate compiler_builtins /\* \d+ \*/" -> "extern crate compiler_builtins /* NNN */"
 // aux-build:test-macros.rs
 
 #![feature(decl_macro)]
-
 #![no_std] // Don't load unnecessary hygiene information from std
 extern crate std;
 
diff --git a/tests/ui/proc-macro/nonterminal-token-hygiene.stdout b/tests/ui/proc-macro/nonterminal-token-hygiene.stdout
index 4031eb98a38d4..c437853ac7287 100644
--- a/tests/ui/proc-macro/nonterminal-token-hygiene.stdout
+++ b/tests/ui/proc-macro/nonterminal-token-hygiene.stdout
@@ -6,19 +6,19 @@ PRINT-BANG INPUT (DEBUG): TokenStream [
         stream: TokenStream [
             Ident {
                 ident: "struct",
-                span: $DIR/nonterminal-token-hygiene.rs:31:5: 31:11 (#4),
+                span: $DIR/nonterminal-token-hygiene.rs:32:5: 32:11 (#4),
             },
             Ident {
                 ident: "S",
-                span: $DIR/nonterminal-token-hygiene.rs:31:12: 31:13 (#4),
+                span: $DIR/nonterminal-token-hygiene.rs:32:12: 32:13 (#4),
             },
             Punct {
                 ch: ';',
                 spacing: Alone,
-                span: $DIR/nonterminal-token-hygiene.rs:31:13: 31:14 (#4),
+                span: $DIR/nonterminal-token-hygiene.rs:32:13: 32:14 (#4),
             },
         ],
-        span: $DIR/nonterminal-token-hygiene.rs:21:27: 21:32 (#5),
+        span: $DIR/nonterminal-token-hygiene.rs:22:27: 22:32 (#5),
     },
 ]
 #![feature /* 0#0 */(prelude_import)]
@@ -28,18 +28,19 @@ PRINT-BANG INPUT (DEBUG): TokenStream [
 // check-pass
 // compile-flags: -Z span-debug -Z macro-backtrace -Z unpretty=expanded,hygiene
 // compile-flags: -Z trim-diagnostic-paths=no
+// ignore-tidy-linelength
 // normalize-stdout-test "\d+#" -> "0#"
 // normalize-stdout-test "expn\d{3,}" -> "expnNNN"
+// normalize-stdout-test "extern crate compiler_builtins /\* \d+ \*/" -> "extern crate compiler_builtins /* NNN */"
 // aux-build:test-macros.rs
 
 #![feature /* 0#0 */(decl_macro)]
-
 #![no_std /* 0#0 */]
 #[prelude_import /* 0#1 */]
 use ::core /* 0#1 */::prelude /* 0#1 */::rust_2015 /* 0#1 */::*;
 #[macro_use /* 0#1 */]
 extern crate core /* 0#2 */;
-extern crate compiler_builtins /* 445 */ as _ /* 0#2 */;
+extern crate compiler_builtins /* NNN */ as _ /* 0#2 */;
 // Don't load unnecessary hygiene information from std
 extern crate std /* 0#0 */;
 
diff --git a/tests/ui/self/arbitrary_self_type_mut_difference.rs b/tests/ui/self/arbitrary_self_type_mut_difference.rs
new file mode 100644
index 0000000000000..e75c00ae956b3
--- /dev/null
+++ b/tests/ui/self/arbitrary_self_type_mut_difference.rs
@@ -0,0 +1,13 @@
+// Related to #57994.
+use std::pin::Pin;
+struct S;
+
+impl S {
+    fn x(self: Pin<&mut Self>) {} //~ NOTE method is available for `Pin<&mut S>`
+    fn y(self: Pin<&Self>) {} //~ NOTE method is available for `Pin<&S>`
+}
+
+fn main() {
+    Pin::new(&S).x(); //~ ERROR no method named `x` found for struct `Pin<&S>` in the current scope
+    Pin::new(&mut S).y(); //~ ERROR no method named `y` found for struct `Pin<&mut S>` in the current scope
+}
diff --git a/tests/ui/self/arbitrary_self_type_mut_difference.stderr b/tests/ui/self/arbitrary_self_type_mut_difference.stderr
new file mode 100644
index 0000000000000..a56d58694aa35
--- /dev/null
+++ b/tests/ui/self/arbitrary_self_type_mut_difference.stderr
@@ -0,0 +1,27 @@
+error[E0599]: no method named `x` found for struct `Pin<&S>` in the current scope
+  --> $DIR/arbitrary_self_type_mut_difference.rs:11:18
+   |
+LL |     Pin::new(&S).x();
+   |                  ^ help: there is a method with a similar name: `y`
+   |
+note: method is available for `Pin<&mut S>`
+  --> $DIR/arbitrary_self_type_mut_difference.rs:6:5
+   |
+LL |     fn x(self: Pin<&mut Self>) {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0599]: no method named `y` found for struct `Pin<&mut S>` in the current scope
+  --> $DIR/arbitrary_self_type_mut_difference.rs:12:22
+   |
+LL |     Pin::new(&mut S).y();
+   |                      ^ help: there is a method with a similar name: `x`
+   |
+note: method is available for `Pin<&S>`
+  --> $DIR/arbitrary_self_type_mut_difference.rs:7:5
+   |
+LL |     fn y(self: Pin<&Self>) {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/tests/ui/self/arbitrary_self_types_needing_box_or_arc_wrapping.fixed b/tests/ui/self/arbitrary_self_types_needing_box_or_arc_wrapping.fixed
new file mode 100644
index 0000000000000..6a94b85b9ba59
--- /dev/null
+++ b/tests/ui/self/arbitrary_self_types_needing_box_or_arc_wrapping.fixed
@@ -0,0 +1,17 @@
+// run-rustfix
+#![allow(dead_code)]
+mod first {
+    trait Foo { fn m(self: Box<Self>); }
+    fn foo<T: Foo>(a: T) {
+        Box::new(a).m(); //~ ERROR no method named `m` found
+    }
+}
+mod second {
+    use std::sync::Arc;
+    trait Bar { fn m(self: Arc<Self>); }
+    fn bar(b: impl Bar) {
+        Arc::new(b).m(); //~ ERROR no method named `m` found
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/self/arbitrary_self_types_needing_box_or_arc_wrapping.rs b/tests/ui/self/arbitrary_self_types_needing_box_or_arc_wrapping.rs
new file mode 100644
index 0000000000000..fa480b1f72b2f
--- /dev/null
+++ b/tests/ui/self/arbitrary_self_types_needing_box_or_arc_wrapping.rs
@@ -0,0 +1,17 @@
+// run-rustfix
+#![allow(dead_code)]
+mod first {
+    trait Foo { fn m(self: Box<Self>); }
+    fn foo<T: Foo>(a: T) {
+        a.m(); //~ ERROR no method named `m` found
+    }
+}
+mod second {
+    use std::sync::Arc;
+    trait Bar { fn m(self: Arc<Self>); }
+    fn bar(b: impl Bar) {
+        b.m(); //~ ERROR no method named `m` found
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/self/arbitrary_self_types_needing_box_or_arc_wrapping.stderr b/tests/ui/self/arbitrary_self_types_needing_box_or_arc_wrapping.stderr
new file mode 100644
index 0000000000000..2ab634ad3e87b
--- /dev/null
+++ b/tests/ui/self/arbitrary_self_types_needing_box_or_arc_wrapping.stderr
@@ -0,0 +1,43 @@
+error[E0599]: no method named `m` found for type parameter `T` in the current scope
+  --> $DIR/arbitrary_self_types_needing_box_or_arc_wrapping.rs:6:11
+   |
+LL |     trait Foo { fn m(self: Box<Self>); }
+   |                    -       --------- the method might not be found because of this arbitrary self type
+   |                    |
+   |                    the method is available for `Box<T>` here
+LL |     fn foo<T: Foo>(a: T) {
+   |            - method `m` not found for this type parameter
+LL |         a.m();
+   |           ^ method not found in `T`
+...
+LL |     trait Bar { fn m(self: Arc<Self>); }
+   |                            --------- the method might not be found because of this arbitrary self type
+   |
+help: consider wrapping the receiver expression with the appropriate type
+   |
+LL |         Box::new(a).m();
+   |         +++++++++ +
+
+error[E0599]: no method named `m` found for type parameter `impl Bar` in the current scope
+  --> $DIR/arbitrary_self_types_needing_box_or_arc_wrapping.rs:13:11
+   |
+LL |     trait Foo { fn m(self: Box<Self>); }
+   |                            --------- the method might not be found because of this arbitrary self type
+...
+LL |     trait Bar { fn m(self: Arc<Self>); }
+   |                    -       --------- the method might not be found because of this arbitrary self type
+   |                    |
+   |                    the method is available for `Arc<impl Bar>` here
+LL |     fn bar(b: impl Bar) {
+   |               -------- method `m` not found for this type parameter
+LL |         b.m();
+   |           ^ method not found in `impl Bar`
+   |
+help: consider wrapping the receiver expression with the appropriate type
+   |
+LL |         Arc::new(b).m();
+   |         +++++++++ +
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/tests/ui/self/arbitrary_self_types_needing_mut_pin.fixed b/tests/ui/self/arbitrary_self_types_needing_mut_pin.fixed
new file mode 100644
index 0000000000000..ccd65ff409138
--- /dev/null
+++ b/tests/ui/self/arbitrary_self_types_needing_mut_pin.fixed
@@ -0,0 +1,12 @@
+// run-rustfix
+use std::pin::Pin;
+struct S;
+
+impl S {
+    fn x(self: Pin<&mut Self>) {
+    }
+}
+
+fn main() {
+    Pin::new(&mut S).x(); //~ ERROR no method named `x` found
+}
diff --git a/tests/ui/self/arbitrary_self_types_needing_mut_pin.rs b/tests/ui/self/arbitrary_self_types_needing_mut_pin.rs
new file mode 100644
index 0000000000000..d15676a623d39
--- /dev/null
+++ b/tests/ui/self/arbitrary_self_types_needing_mut_pin.rs
@@ -0,0 +1,12 @@
+// run-rustfix
+use std::pin::Pin;
+struct S;
+
+impl S {
+    fn x(self: Pin<&mut Self>) {
+    }
+}
+
+fn main() {
+    S.x(); //~ ERROR no method named `x` found
+}
diff --git a/tests/ui/self/arbitrary_self_types_needing_mut_pin.stderr b/tests/ui/self/arbitrary_self_types_needing_mut_pin.stderr
new file mode 100644
index 0000000000000..f34ce4dce490f
--- /dev/null
+++ b/tests/ui/self/arbitrary_self_types_needing_mut_pin.stderr
@@ -0,0 +1,20 @@
+error[E0599]: no method named `x` found for struct `S` in the current scope
+  --> $DIR/arbitrary_self_types_needing_mut_pin.rs:11:7
+   |
+LL | struct S;
+   | -------- method `x` not found for this struct
+...
+LL |     fn x(self: Pin<&mut Self>) {
+   |        - the method is available for `Pin<&mut S>` here
+...
+LL |     S.x();
+   |       ^ method not found in `S`
+   |
+help: consider wrapping the receiver expression with the appropriate type
+   |
+LL |     Pin::new(&mut S).x();
+   |     +++++++++++++  +
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/tests/ui/self/arbitrary_self_types_pin_needing_borrow.rs b/tests/ui/self/arbitrary_self_types_pin_needing_borrow.rs
new file mode 100644
index 0000000000000..d877dbe60754d
--- /dev/null
+++ b/tests/ui/self/arbitrary_self_types_pin_needing_borrow.rs
@@ -0,0 +1,13 @@
+use std::pin::Pin;
+struct S;
+
+impl S {
+    fn x(self: Pin<&mut Self>) {
+    }
+}
+
+fn main() {
+    Pin::new(S).x();
+    //~^ ERROR the trait bound `S: Deref` is not satisfied
+    //~| ERROR no method named `x` found for struct `Pin` in the current scope
+}
diff --git a/tests/ui/self/arbitrary_self_types_pin_needing_borrow.stderr b/tests/ui/self/arbitrary_self_types_pin_needing_borrow.stderr
new file mode 100644
index 0000000000000..ec985b254b340
--- /dev/null
+++ b/tests/ui/self/arbitrary_self_types_pin_needing_borrow.stderr
@@ -0,0 +1,33 @@
+error[E0277]: the trait bound `S: Deref` is not satisfied
+  --> $DIR/arbitrary_self_types_pin_needing_borrow.rs:10:14
+   |
+LL |     Pin::new(S).x();
+   |     -------- ^ the trait `Deref` is not implemented for `S`
+   |     |
+   |     required by a bound introduced by this call
+   |
+note: required by a bound in `Pin::<P>::new`
+  --> $SRC_DIR/core/src/pin.rs:LL:COL
+help: consider borrowing here
+   |
+LL |     Pin::new(&S).x();
+   |              +
+LL |     Pin::new(&mut S).x();
+   |              ++++
+
+error[E0599]: no method named `x` found for struct `Pin` in the current scope
+  --> $DIR/arbitrary_self_types_pin_needing_borrow.rs:10:17
+   |
+LL |     Pin::new(S).x();
+   |                 ^ method not found in `Pin<S>`
+   |
+note: method is available for `Pin<&mut S>`
+  --> $DIR/arbitrary_self_types_pin_needing_borrow.rs:5:5
+   |
+LL |     fn x(self: Pin<&mut Self>) {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0277, E0599.
+For more information about an error, try `rustc --explain E0277`.