diff --git a/cumulus/polkadot-parachain/polkadot-parachain-lib/src/command.rs b/cumulus/polkadot-parachain/polkadot-parachain-lib/src/command.rs
index 43fb551f80d29e62749d371b59e34d96f14bbd1f..63562f192aee4b839d43f275a29bb36509fae111 100644
--- a/cumulus/polkadot-parachain/polkadot-parachain-lib/src/command.rs
+++ b/cumulus/polkadot-parachain/polkadot-parachain-lib/src/command.rs
@@ -39,7 +39,6 @@ use sc_cli::{Result, SubstrateCli};
 use sp_runtime::traits::AccountIdConversion;
 #[cfg(feature = "runtime-benchmarks")]
 use sp_runtime::traits::HashingFor;
-use std::panic::{RefUnwindSafe, UnwindSafe};
 
 /// Structure that can be used in order to provide customizers for different functionalities of the
 /// node binary that is being built using this library.
@@ -55,8 +54,7 @@ pub fn new_aura_node_spec<Block>(
 	extra_args: &NodeExtraArgs,
 ) -> Box<dyn DynNodeSpec>
 where
-	Block: NodeBlock + UnwindSafe + RefUnwindSafe,
-	Block::BoundedHeader: UnwindSafe + RefUnwindSafe,
+	Block: NodeBlock,
 {
 	match aura_id {
 		AuraConsensusId::Sr25519 => crate::service::new_aura_node_spec::<
diff --git a/prdoc/pr_5839.prdoc b/prdoc/pr_5839.prdoc
new file mode 100644
index 0000000000000000000000000000000000000000..1dc95fe5c333ffeae9f67f636d5c995079405a3f
--- /dev/null
+++ b/prdoc/pr_5839.prdoc
@@ -0,0 +1,21 @@
+# Schema: Polkadot SDK PRDoc Schema (prdoc) v1.0.0
+# See doc at https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/prdoc/schema_user.json
+
+title: Remove internal workaround for compiler bug
+
+doc:
+  - audience:
+    - Runtime Dev
+    - Node Dev
+    description: |
+      Remove a workaround we had in the `impl_runtime_apis` macro for a compiler bug that has been long fixed.
+      No impact on downstream users is expected, except relaxed trait bounds in a few places where the compiler
+      is now able to deduce more type info itself.
+
+crates:
+    - name: sp-api-proc-macro
+      bump: patch
+    - name: frame-support-procedural
+      bump: patch
+    - name: polkadot-parachain-lib
+      bump: patch
diff --git a/substrate/frame/support/procedural/src/runtime/expand/mod.rs b/substrate/frame/support/procedural/src/runtime/expand/mod.rs
index f34ab1cef5436ffd6fccfff628a94d149a9ed5f5..666bc03aa415df6b495cd479e62cb929f8767cd8 100644
--- a/substrate/frame/support/procedural/src/runtime/expand/mod.rs
+++ b/substrate/frame/support/procedural/src/runtime/expand/mod.rs
@@ -77,7 +77,7 @@ pub fn expand(def: Def, legacy_ordering: bool) -> TokenStream2 {
 	};
 
 	let res = expander::Expander::new("construct_runtime")
-		.dry(std::env::var("FRAME_EXPAND").is_err())
+		.dry(std::env::var("EXPAND_MACROS").is_err())
 		.verbose(true)
 		.write_to_out_dir(res)
 		.expect("Does not fail because of IO in OUT_DIR; qed");
diff --git a/substrate/primitives/api/proc-macro/src/impl_runtime_apis.rs b/substrate/primitives/api/proc-macro/src/impl_runtime_apis.rs
index 21397abc8fc62ad1fab87a1be9bad78973e76fd3..de922e3253e47c929ea348f187f3440a0ed1f33a 100644
--- a/substrate/primitives/api/proc-macro/src/impl_runtime_apis.rs
+++ b/substrate/primitives/api/proc-macro/src/impl_runtime_apis.rs
@@ -18,7 +18,7 @@
 use crate::{
 	common::API_VERSION_ATTRIBUTE,
 	utils::{
-		extract_all_signature_types, extract_block_type_from_trait_path, extract_impl_trait,
+		extract_block_type_from_trait_path, extract_impl_trait,
 		extract_parameter_names_types_and_borrows, generate_crate_access,
 		generate_runtime_mod_name_for_trait, parse_runtime_api_version, prefix_function_with_trait,
 		versioned_trait_name, AllowSelfRefInParameters, RequireQualifiedTraitPath,
@@ -632,11 +632,6 @@ impl<'a> Fold for ApiRuntimeImplToApiRuntimeApiImpl<'a> {
 	}
 
 	fn fold_item_impl(&mut self, mut input: ItemImpl) -> ItemImpl {
-		// All this `UnwindSafe` magic below here is required for this rust bug:
-		// https://github.com/rust-lang/rust/issues/24159
-		// Before we directly had the final block type and rust could determine that it is unwind
-		// safe, but now we just have a generic parameter `Block`.
-
 		let crate_ = generate_crate_access();
 
 		// Implement the trait for the `RuntimeApiImpl`
@@ -644,9 +639,9 @@ impl<'a> Fold for ApiRuntimeImplToApiRuntimeApiImpl<'a> {
 			Box::new(parse_quote!( RuntimeApiImpl<__SrApiBlock__, RuntimeApiImplCall> ));
 
 		input.generics.params.push(parse_quote!(
-			__SrApiBlock__: #crate_::BlockT + std::panic::UnwindSafe +
-				std::panic::RefUnwindSafe
+			__SrApiBlock__: #crate_::BlockT
 		));
+
 		input
 			.generics
 			.params
@@ -661,17 +656,6 @@ impl<'a> Fold for ApiRuntimeImplToApiRuntimeApiImpl<'a> {
 
 		where_clause.predicates.push(parse_quote! { &'static RuntimeApiImplCall: Send });
 
-		// Require that all types used in the function signatures are unwind safe.
-		extract_all_signature_types(&input.items).iter().for_each(|i| {
-			where_clause.predicates.push(parse_quote! {
-				#i: std::panic::UnwindSafe + std::panic::RefUnwindSafe
-			});
-		});
-
-		where_clause.predicates.push(parse_quote! {
-			__SrApiBlock__::Header: std::panic::UnwindSafe + std::panic::RefUnwindSafe
-		});
-
 		input.attrs = filter_cfg_attrs(&input.attrs);
 
 		fold::fold_item_impl(self, input)
diff --git a/substrate/primitives/api/proc-macro/src/utils.rs b/substrate/primitives/api/proc-macro/src/utils.rs
index 94da6748cbdb36070c34d48b9b2405518b4aad52..dc993c2ac420ef431a4222afa24e2c0e47f5465d 100644
--- a/substrate/primitives/api/proc-macro/src/utils.rs
+++ b/substrate/primitives/api/proc-macro/src/utils.rs
@@ -22,8 +22,8 @@ use proc_macro_crate::{crate_name, FoundCrate};
 use quote::{format_ident, quote};
 use syn::{
 	parse_quote, punctuated::Punctuated, spanned::Spanned, token::And, Attribute, Error, Expr,
-	ExprLit, FnArg, GenericArgument, Ident, ImplItem, ItemImpl, Lit, Meta, MetaNameValue, Pat,
-	Path, PathArguments, Result, ReturnType, Signature, Token, Type, TypePath,
+	ExprLit, FnArg, GenericArgument, Ident, ItemImpl, Lit, Meta, MetaNameValue, Pat, Path,
+	PathArguments, Result, ReturnType, Signature, Token, Type, TypePath,
 };
 
 /// Generates the access to the `sc_client` crate.
@@ -159,37 +159,6 @@ pub fn prefix_function_with_trait<F: ToString>(trait_: &Ident, function: &F) ->
 	format!("{}_{}", trait_, function.to_string())
 }
 
-/// Extract all types that appear in signatures in the given `ImplItem`'s.
-///
-/// If a type is a reference, the inner type is extracted (without the reference).
-pub fn extract_all_signature_types(items: &[ImplItem]) -> Vec<Type> {
-	items
-		.iter()
-		.filter_map(|i| match i {
-			ImplItem::Fn(method) => Some(&method.sig),
-			_ => None,
-		})
-		.flat_map(|sig| {
-			let ret_ty = match &sig.output {
-				ReturnType::Default => None,
-				ReturnType::Type(_, ty) => Some((**ty).clone()),
-			};
-
-			sig.inputs
-				.iter()
-				.filter_map(|i| match i {
-					FnArg::Typed(arg) => Some(&arg.ty),
-					_ => None,
-				})
-				.map(|ty| match &**ty {
-					Type::Reference(t) => (*t.elem).clone(),
-					_ => (**ty).clone(),
-				})
-				.chain(ret_ty)
-		})
-		.collect()
-}
-
 /// Extracts the block type from a trait path.
 ///
 /// It is expected that the block type is the first type in the generic arguments.