From 2d988e5f606d3a00d9100d8abac8d366465f159d Mon Sep 17 00:00:00 2001
From: Kian Paimani <5588131+kianenigma@users.noreply.github.com>
Date: Sun, 14 Aug 2022 20:06:02 +0100
Subject: [PATCH] Proposal: Flatten `AllPallets` and similar types (#11813)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* flratten AllPallets types

* feature flag it

* fix

* fix

* fmt

* remove todo

* Update frame/support/src/traits/metadata.rs

Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com>

* Update frame/support/src/migrations.rs

Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com>

* fix

* mark as deprecated

* add docs

* fix ui test?

* fmt

Co-authored-by: parity-processbot <>
Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com>
---
 substrate/frame/support/Cargo.toml            |  4 ++
 .../procedural/src/construct_runtime/mod.rs   | 60 +++++++------------
 .../src/pallet/expand/pallet_struct.rs        |  6 +-
 substrate/frame/support/src/dispatch.rs       |  4 +-
 substrate/frame/support/src/lib.rs            | 10 ++++
 substrate/frame/support/src/migrations.rs     |  5 +-
 substrate/frame/support/src/traits.rs         |  5 +-
 substrate/frame/support/src/traits/filter.rs  | 11 ----
 substrate/frame/support/src/traits/hooks.rs   | 37 ++++++++++--
 substrate/frame/support/src/traits/members.rs |  9 ++-
 .../frame/support/src/traits/metadata.rs      | 41 ++++---------
 substrate/frame/support/src/traits/misc.rs    | 13 +++-
 substrate/frame/support/src/traits/storage.rs |  5 +-
 substrate/frame/support/test/tests/pallet.rs  | 13 ++--
 .../tests/pallet_ui/hooks_invalid_item.stderr |  6 +-
 15 files changed, 121 insertions(+), 108 deletions(-)

diff --git a/substrate/frame/support/Cargo.toml b/substrate/frame/support/Cargo.toml
index a69133961e9..1b6488bbd47 100644
--- a/substrate/frame/support/Cargo.toml
+++ b/substrate/frame/support/Cargo.toml
@@ -73,3 +73,7 @@ no-metadata-docs = ["frame-support-procedural/no-metadata-docs"]
 # By default some types have documentation, `full-metadata-docs` allows to add documentation to
 # more types in the metadata.
 full-metadata-docs = ["scale-info/docs"]
+# Generate impl-trait for tuples with the given number of tuples. Will be needed as the number of
+# pallets in a runtime grows. Does increase the compile time!
+tuples-96 = []
+tuples-128 = []
diff --git a/substrate/frame/support/procedural/src/construct_runtime/mod.rs b/substrate/frame/support/procedural/src/construct_runtime/mod.rs
index 7b4156a94db..042af31be6b 100644
--- a/substrate/frame/support/procedural/src/construct_runtime/mod.rs
+++ b/substrate/frame/support/procedural/src/construct_runtime/mod.rs
@@ -308,47 +308,26 @@ fn decl_all_pallets<'a>(
 		names.push(&pallet_declaration.name);
 	}
 
-	// Make nested tuple structure like:
-	// `((FirstPallet, (SecondPallet, ( ... , LastPallet) ... ))))`
-	// But ignore the system pallet.
-	let all_pallets_without_system = names
-		.iter()
-		.filter(|n| **n != SYSTEM_PALLET_NAME)
-		.rev()
-		.fold(TokenStream2::default(), |combined, name| quote!((#name, #combined)));
-
-	// Make nested tuple structure like:
-	// `((FirstPallet, (SecondPallet, ( ... , LastPallet) ... ))))`
-	let all_pallets_with_system = names
-		.iter()
-		.rev()
-		.fold(TokenStream2::default(), |combined, name| quote!((#name, #combined)));
-
-	// Make nested tuple structure like:
-	// `((LastPallet, (SecondLastPallet, ( ... , FirstPallet) ... ))))`
-	// But ignore the system pallet.
-	let all_pallets_without_system_reversed = names
-		.iter()
-		.filter(|n| **n != SYSTEM_PALLET_NAME)
-		.fold(TokenStream2::default(), |combined, name| quote!((#name, #combined)));
-
-	// Make nested tuple structure like:
-	// `((LastPallet, (SecondLastPallet, ( ... , FirstPallet) ... ))))`
-	let all_pallets_with_system_reversed = names
-		.iter()
-		.fold(TokenStream2::default(), |combined, name| quote!((#name, #combined)));
-
 	let system_pallet = match names.iter().find(|n| **n == SYSTEM_PALLET_NAME) {
 		Some(name) => name,
 		None =>
 			return syn::Error::new(
 				proc_macro2::Span::call_site(),
 				"`System` pallet declaration is missing. \
-				 Please add this line: `System: frame_system::{Pallet, Call, Storage, Config, Event<T>},`",
+					 Please add this line: `System: frame_system::{Pallet, Call, Storage, Config, Event<T>},`",
 			)
 			.into_compile_error(),
 	};
 
+	let names_without_system =
+		names.iter().filter(|n| **n != SYSTEM_PALLET_NAME).collect::<Vec<_>>();
+	let names_reversed = names.clone().into_iter().rev().collect::<Vec<_>>();
+	let names_without_system_reverse =
+		names_without_system.clone().into_iter().rev().collect::<Vec<_>>();
+	let names_reversed_with_system_first = std::iter::once(system_pallet)
+		.chain(names_without_system_reverse.clone().into_iter())
+		.collect::<Vec<_>>();
+
 	quote!(
 		#types
 
@@ -364,25 +343,28 @@ fn decl_all_pallets<'a>(
 		pub type AllPallets = AllPalletsWithSystem;
 
 		/// All pallets included in the runtime as a nested tuple of types.
-		pub type AllPalletsWithSystem = ( #all_pallets_with_system );
+		pub type AllPalletsWithSystem = ( #(#names),* );
 
 		/// All pallets included in the runtime as a nested tuple of types.
 		/// Excludes the System pallet.
-		pub type AllPalletsWithoutSystem = ( #all_pallets_without_system );
+		pub type AllPalletsWithoutSystem = ( #(#names_without_system),* );
 
 		/// All pallets included in the runtime as a nested tuple of types in reversed order.
 		/// Excludes the System pallet.
-		pub type AllPalletsWithoutSystemReversed = ( #all_pallets_without_system_reversed );
+		#[deprecated(note = "Using reverse pallet orders is deprecated. use only \
+		`AllPalletWithSystem or AllPalletsWithoutSystem`")]
+		pub type AllPalletsWithoutSystemReversed =( #(#names_without_system_reverse),* );
 
 		/// All pallets included in the runtime as a nested tuple of types in reversed order.
-		pub type AllPalletsWithSystemReversed = ( #all_pallets_with_system_reversed );
+		#[deprecated(note = "Using reverse pallet orders is deprecated. use only \
+		`AllPalletWithSystem or AllPalletsWithoutSystem`")]
+		pub type AllPalletsWithSystemReversed = ( #(#names_reversed),* );
 
 		/// All pallets included in the runtime as a nested tuple of types in reversed order.
 		/// With the system pallet first.
-		pub type AllPalletsReversedWithSystemFirst = (
-			#system_pallet,
-			AllPalletsWithoutSystemReversed
-		);
+		#[deprecated(note = "Using reverse pallet orders is deprecated. use only \
+		`AllPalletWithSystem or AllPalletsWithoutSystem`")]
+		pub type AllPalletsReversedWithSystemFirst = ( #(#names_reversed_with_system_first),* );
 	)
 }
 
diff --git a/substrate/frame/support/procedural/src/pallet/expand/pallet_struct.rs b/substrate/frame/support/procedural/src/pallet/expand/pallet_struct.rs
index a4a8acc10f7..f0fb6bacedf 100644
--- a/substrate/frame/support/procedural/src/pallet/expand/pallet_struct.rs
+++ b/substrate/frame/support/procedural/src/pallet/expand/pallet_struct.rs
@@ -240,9 +240,7 @@ pub fn expand_pallet_struct(def: &mut Def) -> proc_macro2::TokenStream {
 			#config_where_clause
 		{
 			fn count() -> usize { 1 }
-			fn accumulate(
-				acc: &mut #frame_support::sp_std::vec::Vec<#frame_support::traits::PalletInfoData>
-			) {
+			fn infos() -> #frame_support::sp_std::vec::Vec<#frame_support::traits::PalletInfoData> {
 				use #frame_support::traits::PalletInfoAccess;
 				let item = #frame_support::traits::PalletInfoData {
 					index: Self::index(),
@@ -250,7 +248,7 @@ pub fn expand_pallet_struct(def: &mut Def) -> proc_macro2::TokenStream {
 					module_name: Self::module_name(),
 					crate_version: Self::crate_version(),
 				};
-				acc.push(item);
+				#frame_support::sp_std::vec![item]
 			}
 		}
 
diff --git a/substrate/frame/support/src/dispatch.rs b/substrate/frame/support/src/dispatch.rs
index fb0b658cd93..a658f01fa68 100644
--- a/substrate/frame/support/src/dispatch.rs
+++ b/substrate/frame/support/src/dispatch.rs
@@ -2207,7 +2207,7 @@ macro_rules! decl_module {
 			for $mod_type<$trait_instance $(, $instance)?> where $( $other_where_bounds )*
 		{
 			fn count() -> usize { 1 }
-			fn accumulate(acc: &mut $crate::sp_std::vec::Vec<$crate::traits::PalletInfoData>) {
+			fn infos() -> $crate::sp_std::vec::Vec<$crate::traits::PalletInfoData> {
 				use $crate::traits::PalletInfoAccess;
 				let item = $crate::traits::PalletInfoData {
 					index: Self::index(),
@@ -2215,7 +2215,7 @@ macro_rules! decl_module {
 					module_name: Self::module_name(),
 					crate_version: Self::crate_version(),
 				};
-				acc.push(item);
+				vec![item]
 			}
 		}
 
diff --git a/substrate/frame/support/src/lib.rs b/substrate/frame/support/src/lib.rs
index 8e43df82a28..7e4c944330f 100644
--- a/substrate/frame/support/src/lib.rs
+++ b/substrate/frame/support/src/lib.rs
@@ -16,6 +16,16 @@
 // limitations under the License.
 
 //! Support code for the runtime.
+//!
+//! ## Note on Tuple Traits
+//!
+//! Many of the traits defined in [`traits`] have auto-implementations on tuples as well. Usually,
+//! the tuple is a function of number of pallets in the runtime. By default, the traits are
+//! implemented for tuples of up to 64 items.
+//
+// If you have more pallets in your runtime, or for any other reason need more, enabled `tuples-96`
+// or the `tuples-128` complication flag. Note that these features *will increase* the compilation
+// of this crate.
 
 #![cfg_attr(not(feature = "std"), no_std)]
 
diff --git a/substrate/frame/support/src/migrations.rs b/substrate/frame/support/src/migrations.rs
index 05833e0515c..f594b98ede4 100644
--- a/substrate/frame/support/src/migrations.rs
+++ b/substrate/frame/support/src/migrations.rs
@@ -19,6 +19,7 @@ use crate::{
 	traits::{GetStorageVersion, PalletInfoAccess},
 	weights::{RuntimeDbWeight, Weight},
 };
+use impl_trait_for_tuples::impl_for_tuples;
 
 /// Trait used by [`migrate_from_pallet_version_to_storage_version`] to do the actual migration.
 pub trait PalletVersionToStorageVersionHelper {
@@ -42,7 +43,9 @@ impl<T: GetStorageVersion + PalletInfoAccess> PalletVersionToStorageVersionHelpe
 	}
 }
 
-#[impl_trait_for_tuples::impl_for_tuples(30)]
+#[cfg_attr(all(not(feature = "tuples-96"), not(feature = "tuples-128")), impl_for_tuples(64))]
+#[cfg_attr(all(feature = "tuples-96", not(feature = "tuples-128")), impl_for_tuples(96))]
+#[cfg_attr(feature = "tuples-128", impl_for_tuples(128))]
 impl PalletVersionToStorageVersionHelper for T {
 	fn migrate(db_weight: &RuntimeDbWeight) -> Weight {
 		let mut weight: Weight = 0;
diff --git a/substrate/frame/support/src/traits.rs b/substrate/frame/support/src/traits.rs
index 72d6d6682f1..16504beb169 100644
--- a/substrate/frame/support/src/traits.rs
+++ b/substrate/frame/support/src/traits.rs
@@ -50,7 +50,7 @@ mod error;
 pub use error::PalletError;
 
 mod filter;
-pub use filter::{ClearFilterGuard, FilterStack, FilterStackGuard, InstanceFilter, IntegrityTest};
+pub use filter::{ClearFilterGuard, FilterStack, FilterStackGuard, InstanceFilter};
 
 mod misc;
 pub use misc::{
@@ -81,7 +81,8 @@ mod hooks;
 #[cfg(feature = "std")]
 pub use hooks::GenesisBuild;
 pub use hooks::{
-	Hooks, OnFinalize, OnGenesis, OnIdle, OnInitialize, OnRuntimeUpgrade, OnTimestampSet,
+	Hooks, IntegrityTest, OnFinalize, OnGenesis, OnIdle, OnInitialize, OnRuntimeUpgrade,
+	OnTimestampSet,
 };
 #[cfg(feature = "try-runtime")]
 pub use hooks::{OnRuntimeUpgradeHelpersExt, ON_RUNTIME_UPGRADE_PREFIX};
diff --git a/substrate/frame/support/src/traits/filter.rs b/substrate/frame/support/src/traits/filter.rs
index 95e5954184b..cdd82a3124e 100644
--- a/substrate/frame/support/src/traits/filter.rs
+++ b/substrate/frame/support/src/traits/filter.rs
@@ -180,17 +180,6 @@ macro_rules! impl_filter_stack {
 	}
 }
 
-/// Type that provide some integrity tests.
-///
-/// This implemented for modules by `decl_module`.
-#[impl_trait_for_tuples::impl_for_tuples(30)]
-pub trait IntegrityTest {
-	/// Run integrity test.
-	///
-	/// The test is not executed in a externalities provided environment.
-	fn integrity_test() {}
-}
-
 #[cfg(test)]
 pub mod test_impl_filter_stack {
 	use super::*;
diff --git a/substrate/frame/support/src/traits/hooks.rs b/substrate/frame/support/src/traits/hooks.rs
index 385db4e4d1a..2b7234006e0 100644
--- a/substrate/frame/support/src/traits/hooks.rs
+++ b/substrate/frame/support/src/traits/hooks.rs
@@ -38,7 +38,9 @@ pub trait OnInitialize<BlockNumber> {
 	}
 }
 
-#[impl_for_tuples(30)]
+#[cfg_attr(all(not(feature = "tuples-96"), not(feature = "tuples-128")), impl_for_tuples(64))]
+#[cfg_attr(all(feature = "tuples-96", not(feature = "tuples-128")), impl_for_tuples(96))]
+#[cfg_attr(feature = "tuples-128", impl_for_tuples(128))]
 impl<BlockNumber: Clone> OnInitialize<BlockNumber> for Tuple {
 	fn on_initialize(n: BlockNumber) -> crate::weights::Weight {
 		let mut weight = 0;
@@ -50,7 +52,9 @@ impl<BlockNumber: Clone> OnInitialize<BlockNumber> for Tuple {
 /// The block finalization trait.
 ///
 /// Implementing this lets you express what should happen for your pallet when the block is ending.
-#[impl_for_tuples(30)]
+#[cfg_attr(all(not(feature = "tuples-96"), not(feature = "tuples-128")), impl_for_tuples(64))]
+#[cfg_attr(all(feature = "tuples-96", not(feature = "tuples-128")), impl_for_tuples(96))]
+#[cfg_attr(feature = "tuples-128", impl_for_tuples(128))]
 pub trait OnFinalize<BlockNumber> {
 	/// The block is being finalized. Implement to have something happen.
 	///
@@ -79,7 +83,9 @@ pub trait OnIdle<BlockNumber> {
 	}
 }
 
-#[impl_for_tuples(30)]
+#[cfg_attr(all(not(feature = "tuples-96"), not(feature = "tuples-128")), impl_for_tuples(64))]
+#[cfg_attr(all(feature = "tuples-96", not(feature = "tuples-128")), impl_for_tuples(96))]
+#[cfg_attr(feature = "tuples-128", impl_for_tuples(128))]
 impl<BlockNumber: Copy + AtLeast32BitUnsigned> OnIdle<BlockNumber> for Tuple {
 	fn on_idle(n: BlockNumber, remaining_weight: crate::weights::Weight) -> crate::weights::Weight {
 		let on_idle_functions: &[fn(
@@ -105,7 +111,9 @@ impl<BlockNumber: Copy + AtLeast32BitUnsigned> OnIdle<BlockNumber> for Tuple {
 /// Implementing this trait for a pallet let's you express operations that should
 /// happen at genesis. It will be called in an externalities provided environment and
 /// will see the genesis state after all pallets have written their genesis state.
-#[impl_for_tuples(30)]
+#[cfg_attr(all(not(feature = "tuples-96"), not(feature = "tuples-128")), impl_for_tuples(64))]
+#[cfg_attr(all(feature = "tuples-96", not(feature = "tuples-128")), impl_for_tuples(96))]
+#[cfg_attr(feature = "tuples-128", impl_for_tuples(128))]
 pub trait OnGenesis {
 	/// Something that should happen at genesis.
 	fn on_genesis() {}
@@ -187,7 +195,9 @@ pub trait OnRuntimeUpgrade {
 	}
 }
 
-#[impl_for_tuples(30)]
+#[cfg_attr(all(not(feature = "tuples-96"), not(feature = "tuples-128")), impl_for_tuples(64))]
+#[cfg_attr(all(feature = "tuples-96", not(feature = "tuples-128")), impl_for_tuples(96))]
+#[cfg_attr(feature = "tuples-128", impl_for_tuples(128))]
 impl OnRuntimeUpgrade for Tuple {
 	fn on_runtime_upgrade() -> crate::weights::Weight {
 		let mut weight = 0;
@@ -210,6 +220,19 @@ impl OnRuntimeUpgrade for Tuple {
 	}
 }
 
+/// Type that provide some integrity tests.
+///
+/// This implemented for modules by `decl_module`.
+#[cfg_attr(all(not(feature = "tuples-96"), not(feature = "tuples-128")), impl_for_tuples(64))]
+#[cfg_attr(all(feature = "tuples-96", not(feature = "tuples-128")), impl_for_tuples(96))]
+#[cfg_attr(feature = "tuples-128", impl_for_tuples(128))]
+pub trait IntegrityTest {
+	/// Run integrity test.
+	///
+	/// The test is not executed in a externalities provided environment.
+	fn integrity_test() {}
+}
+
 /// The pallet hooks trait. Implementing this lets you express some logic to execute.
 pub trait Hooks<BlockNumber> {
 	/// The block is being finalized. Implement to have something happen.
@@ -321,7 +344,9 @@ pub trait GenesisBuild<T, I = ()>: Default + sp_runtime::traits::MaybeSerializeD
 }
 
 /// A trait which is called when the timestamp is set in the runtime.
-#[impl_for_tuples(30)]
+#[cfg_attr(all(not(feature = "tuples-96"), not(feature = "tuples-128")), impl_for_tuples(64))]
+#[cfg_attr(all(feature = "tuples-96", not(feature = "tuples-128")), impl_for_tuples(96))]
+#[cfg_attr(feature = "tuples-128", impl_for_tuples(128))]
 pub trait OnTimestampSet<Moment> {
 	/// Called when the timestamp is set.
 	fn on_timestamp_set(moment: Moment);
diff --git a/substrate/frame/support/src/traits/members.rs b/substrate/frame/support/src/traits/members.rs
index 8c69a2aaccb..daf2d3aa651 100644
--- a/substrate/frame/support/src/traits/members.rs
+++ b/substrate/frame/support/src/traits/members.rs
@@ -17,6 +17,7 @@
 
 //! Traits for dealing with the idea of membership.
 
+use impl_trait_for_tuples::impl_for_tuples;
 use sp_std::{marker::PhantomData, prelude::*};
 
 /// A trait for querying whether a type can be said to "contain" a value.
@@ -25,7 +26,9 @@ pub trait Contains<T> {
 	fn contains(t: &T) -> bool;
 }
 
-#[impl_trait_for_tuples::impl_for_tuples(1, 30)]
+#[cfg_attr(all(not(feature = "tuples-96"), not(feature = "tuples-128")), impl_for_tuples(64))]
+#[cfg_attr(all(feature = "tuples-96", not(feature = "tuples-128")), impl_for_tuples(96))]
+#[cfg_attr(feature = "tuples-128", impl_for_tuples(128))]
 impl<T> Contains<T> for Tuple {
 	fn contains(t: &T) -> bool {
 		for_tuples!( #(
@@ -41,7 +44,9 @@ pub trait ContainsPair<A, B> {
 	fn contains(a: &A, b: &B) -> bool;
 }
 
-#[impl_trait_for_tuples::impl_for_tuples(0, 30)]
+#[cfg_attr(all(not(feature = "tuples-96"), not(feature = "tuples-128")), impl_for_tuples(64))]
+#[cfg_attr(all(feature = "tuples-96", not(feature = "tuples-128")), impl_for_tuples(96))]
+#[cfg_attr(feature = "tuples-128", impl_for_tuples(128))]
 impl<A, B> ContainsPair<A, B> for Tuple {
 	fn contains(a: &A, b: &B) -> bool {
 		for_tuples!( #(
diff --git a/substrate/frame/support/src/traits/metadata.rs b/substrate/frame/support/src/traits/metadata.rs
index d3dc57e1ee5..b0dd5bd5160 100644
--- a/substrate/frame/support/src/traits/metadata.rs
+++ b/substrate/frame/support/src/traits/metadata.rs
@@ -18,6 +18,7 @@
 //! Traits for managing information attached to pallets and their constituents.
 
 use codec::{Decode, Encode};
+use impl_trait_for_tuples::impl_for_tuples;
 use sp_runtime::RuntimeDebug;
 use sp_std::prelude::*;
 
@@ -70,40 +71,22 @@ pub trait PalletsInfoAccess {
 	///
 	/// You probably don't want this function but `infos()` instead.
 	fn count() -> usize {
-		0
+		// for backwards compatibility with XCM-3, Mark is deprecated.
+		Self::infos().len()
 	}
 
-	/// Extend the given vector by all of the pallets' information that this type represents.
-	///
-	/// You probably don't want this function but `infos()` instead.
-	fn accumulate(_accumulator: &mut Vec<PalletInfoData>) {}
-
 	/// All of the pallets' information that this type represents.
-	fn infos() -> Vec<PalletInfoData> {
-		let mut result = Vec::with_capacity(Self::count());
-		Self::accumulate(&mut result);
-		result
-	}
+	fn infos() -> Vec<PalletInfoData>;
 }
 
-impl PalletsInfoAccess for () {}
-impl<T: PalletsInfoAccess> PalletsInfoAccess for (T,) {
-	fn count() -> usize {
-		T::count()
-	}
-	fn accumulate(acc: &mut Vec<PalletInfoData>) {
-		T::accumulate(acc)
-	}
-}
-
-impl<T1: PalletsInfoAccess, T2: PalletsInfoAccess> PalletsInfoAccess for (T1, T2) {
-	fn count() -> usize {
-		T1::count() + T2::count()
-	}
-	fn accumulate(acc: &mut Vec<PalletInfoData>) {
-		// The AllPallets type tuplises the pallets in reverse order, so we unreverse them here.
-		T2::accumulate(acc);
-		T1::accumulate(acc);
+#[cfg_attr(all(not(feature = "tuples-96"), not(feature = "tuples-128")), impl_for_tuples(64))]
+#[cfg_attr(all(feature = "tuples-96", not(feature = "tuples-128")), impl_for_tuples(96))]
+#[cfg_attr(feature = "tuples-128", impl_for_tuples(128))]
+impl PalletsInfoAccess for Tuple {
+	fn infos() -> Vec<PalletInfoData> {
+		let mut res = vec![];
+		for_tuples!( #( res.extend(Tuple::infos()); )* );
+		res
 	}
 }
 
diff --git a/substrate/frame/support/src/traits/misc.rs b/substrate/frame/support/src/traits/misc.rs
index fa59fa92f92..0f781d0bbd4 100644
--- a/substrate/frame/support/src/traits/misc.rs
+++ b/substrate/frame/support/src/traits/misc.rs
@@ -19,6 +19,7 @@
 
 use crate::dispatch::Parameter;
 use codec::{CompactLen, Decode, DecodeLimit, Encode, EncodeLike, Input, MaxEncodedLen};
+use impl_trait_for_tuples::impl_for_tuples;
 use scale_info::{build::Fields, meta_type, Path, Type, TypeInfo, TypeParameter};
 use sp_arithmetic::traits::{CheckedAdd, CheckedMul, CheckedSub, Saturating};
 #[doc(hidden)]
@@ -467,14 +468,18 @@ impl<A, B> SameOrOther<A, B> {
 }
 
 /// Handler for when a new account has been created.
-#[impl_trait_for_tuples::impl_for_tuples(30)]
+#[cfg_attr(all(not(feature = "tuples-96"), not(feature = "tuples-128")), impl_for_tuples(64))]
+#[cfg_attr(all(feature = "tuples-96", not(feature = "tuples-128")), impl_for_tuples(96))]
+#[cfg_attr(feature = "tuples-128", impl_for_tuples(128))]
 pub trait OnNewAccount<AccountId> {
 	/// A new account `who` has been registered.
 	fn on_new_account(who: &AccountId);
 }
 
 /// The account with the given id was reaped.
-#[impl_trait_for_tuples::impl_for_tuples(30)]
+#[cfg_attr(all(not(feature = "tuples-96"), not(feature = "tuples-128")), impl_for_tuples(64))]
+#[cfg_attr(all(feature = "tuples-96", not(feature = "tuples-128")), impl_for_tuples(96))]
+#[cfg_attr(feature = "tuples-128", impl_for_tuples(128))]
 pub trait OnKilledAccount<AccountId> {
 	/// The account with the given id was reaped.
 	fn on_killed_account(who: &AccountId);
@@ -632,7 +637,9 @@ impl<Origin: PartialEq> PrivilegeCmp<Origin> for EqualPrivilegeOnly {
 /// but cannot preform any alterations. More specifically alterations are
 /// not forbidden, but they are not persisted in any way after the worker
 /// has finished.
-#[impl_trait_for_tuples::impl_for_tuples(30)]
+#[cfg_attr(all(not(feature = "tuples-96"), not(feature = "tuples-128")), impl_for_tuples(64))]
+#[cfg_attr(all(feature = "tuples-96", not(feature = "tuples-128")), impl_for_tuples(96))]
+#[cfg_attr(feature = "tuples-128", impl_for_tuples(128))]
 pub trait OffchainWorker<BlockNumber> {
 	/// This function is being called after every block import (when fully synced).
 	///
diff --git a/substrate/frame/support/src/traits/storage.rs b/substrate/frame/support/src/traits/storage.rs
index e484140cc2f..d40d82c28e8 100644
--- a/substrate/frame/support/src/traits/storage.rs
+++ b/substrate/frame/support/src/traits/storage.rs
@@ -17,6 +17,7 @@
 
 //! Traits for encoding data related to pallet's storage items.
 
+use impl_trait_for_tuples::impl_for_tuples;
 use sp_std::prelude::*;
 
 /// An instance of a pallet in the storage.
@@ -71,7 +72,9 @@ pub trait StorageInfoTrait {
 	fn storage_info() -> Vec<StorageInfo>;
 }
 
-#[impl_trait_for_tuples::impl_for_tuples(30)]
+#[cfg_attr(all(not(feature = "tuples-96"), not(feature = "tuples-128")), impl_for_tuples(64))]
+#[cfg_attr(all(feature = "tuples-96", not(feature = "tuples-128")), impl_for_tuples(96))]
+#[cfg_attr(feature = "tuples-128", impl_for_tuples(128))]
 impl StorageInfoTrait for Tuple {
 	fn storage_info() -> Vec<StorageInfo> {
 		let mut res = vec![];
diff --git a/substrate/frame/support/test/tests/pallet.rs b/substrate/frame/support/test/tests/pallet.rs
index 6b72327eb49..c4bbc59c703 100644
--- a/substrate/frame/support/test/tests/pallet.rs
+++ b/substrate/frame/support/test/tests/pallet.rs
@@ -1597,8 +1597,9 @@ fn test_storage_info() {
 #[test]
 fn assert_type_all_pallets_reversed_with_system_first_is_correct() {
 	// Just ensure the 2 types are same.
+	#[allow(deprecated)]
 	fn _a(_t: AllPalletsReversedWithSystemFirst) {}
-	fn _b(t: (System, (Example4, (Example2, (Example,))))) {
+	fn _b(t: (System, Example4, Example2, Example)) {
 		_a(t)
 	}
 }
@@ -1607,7 +1608,7 @@ fn assert_type_all_pallets_reversed_with_system_first_is_correct() {
 fn assert_type_all_pallets_with_system_is_correct() {
 	// Just ensure the 2 types are same.
 	fn _a(_t: AllPalletsWithSystem) {}
-	fn _b(t: (System, (Example, (Example2, (Example4,))))) {
+	fn _b(t: (System, Example, Example2, Example4)) {
 		_a(t)
 	}
 }
@@ -1616,7 +1617,7 @@ fn assert_type_all_pallets_with_system_is_correct() {
 fn assert_type_all_pallets_without_system_is_correct() {
 	// Just ensure the 2 types are same.
 	fn _a(_t: AllPalletsWithoutSystem) {}
-	fn _b(t: (Example, (Example2, (Example4,)))) {
+	fn _b(t: (Example, Example2, Example4)) {
 		_a(t)
 	}
 }
@@ -1624,8 +1625,9 @@ fn assert_type_all_pallets_without_system_is_correct() {
 #[test]
 fn assert_type_all_pallets_with_system_reversed_is_correct() {
 	// Just ensure the 2 types are same.
+	#[allow(deprecated)]
 	fn _a(_t: AllPalletsWithSystemReversed) {}
-	fn _b(t: (Example4, (Example2, (Example, (System,))))) {
+	fn _b(t: (Example4, Example2, Example, System)) {
 		_a(t)
 	}
 }
@@ -1633,8 +1635,9 @@ fn assert_type_all_pallets_with_system_reversed_is_correct() {
 #[test]
 fn assert_type_all_pallets_without_system_reversed_is_correct() {
 	// Just ensure the 2 types are same.
+	#[allow(deprecated)]
 	fn _a(_t: AllPalletsWithoutSystemReversed) {}
-	fn _b(t: (Example4, (Example2, (Example,)))) {
+	fn _b(t: (Example4, Example2, Example)) {
 		_a(t)
 	}
 }
diff --git a/substrate/frame/support/test/tests/pallet_ui/hooks_invalid_item.stderr b/substrate/frame/support/test/tests/pallet_ui/hooks_invalid_item.stderr
index d1a89fbb850..ff52a094d6f 100644
--- a/substrate/frame/support/test/tests/pallet_ui/hooks_invalid_item.stderr
+++ b/substrate/frame/support/test/tests/pallet_ui/hooks_invalid_item.stderr
@@ -1,13 +1,13 @@
 error[E0107]: missing generics for trait `Hooks`
-   --> $DIR/hooks_invalid_item.rs:12:18
+   --> tests/pallet_ui/hooks_invalid_item.rs:12:18
     |
 12  |     impl<T: Config> Hooks for Pallet<T> {}
     |                     ^^^^^ expected 1 generic argument
     |
 note: trait defined here, with 1 generic parameter: `BlockNumber`
-   --> $DIR/hooks.rs:214:11
+   --> $WORKSPACE/frame/support/src/traits/hooks.rs
     |
-214 | pub trait Hooks<BlockNumber> {
+    | pub trait Hooks<BlockNumber> {
     |           ^^^^^ -----------
 help: add missing generic argument
     |
-- 
GitLab