ronantakizawa/codereview-bench huggingface dataset:
Repository: paritytech/substrate
File: frame/nfts/src/features/attributes.rs (Rust)

Code before:
	/// This function returns an [`IncorrectData`](crate::Error::IncorrectData) error if the
	/// provided attribute `key` is incorrectly formatted.
	pub fn construct_attribute_key(
		key: Vec<u8>,
	) -> Result<BoundedVec<u8, T::KeyLimit>, DispatchError> {
		Ok(BoundedVec::try_from(key).map_err(|_| Error::<T, I>::IncorrectData)?)
	}

	/// A helper method to construct an attribute's value.
	///
	/// # Errors
	///
	/// This function returns an [`IncorrectData`](crate::Error::IncorrectData) error if the
	/// provided `value` is incorrectly formatted.
	pub fn construct_attribute_value(
		value: Vec<u8>,
	) -> Result<BoundedVec<u8, T::ValueLimit>, DispatchError> {
		Ok(BoundedVec::try_from(value).map_err(|_| Error::<T, I>::IncorrectData)?)
	}

	/// A helper method to check whether a system attribute is set for a given item.
	///
	/// # Errors
	///
	/// This function returns an [`IncorrectData`](crate::Error::IncorrectData) error if the
	/// provided pallet attribute is incorrectly formatted.
	pub fn has_system_attribute(
		collection: &T::CollectionId,
		item: &T::ItemId,
		attribute_key: PalletAttributes<T::CollectionId>,
	) -> Result<bool, DispatchError> {
		let attribute = (
			&collection,
			Some(item),
			AttributeNamespace::Pallet,
			&Self::construct_attribute_key(attribute_key.encode())?,
		);
		Ok(Attribute::<T, I>::contains_key(attribute))
	}
}


Review comment (refactor):
```suggestion
	/// provided pallet attribute is too long.
```

Code after:
	/// This function returns an [`IncorrectData`](crate::Error::IncorrectData) error if the
	/// provided attribute `key` is too long.
	pub fn construct_attribute_key(
		key: Vec<u8>,
	) -> Result<BoundedVec<u8, T::KeyLimit>, DispatchError> {
		Ok(BoundedVec::try_from(key).map_err(|_| Error::<T, I>::IncorrectData)?)
	}

	/// A helper method to construct an attribute's value.
	///
	/// # Errors
	///
	/// This function returns an [`IncorrectData`](crate::Error::IncorrectData) error if the
	/// provided `value` is too long.
	pub fn construct_attribute_value(
		value: Vec<u8>,
	) -> Result<BoundedVec<u8, T::ValueLimit>, DispatchError> {
		Ok(BoundedVec::try_from(value).map_err(|_| Error::<T, I>::IncorrectData)?)
	}

	/// A helper method to check whether a system attribute is set for a given item.
	///
	/// # Errors
	///
	/// This function returns an [`IncorrectData`](crate::Error::IncorrectData) error if the
	/// provided pallet attribute is too long.
	pub fn has_system_attribute(
		collection: &T::CollectionId,
		item: &T::ItemId,
		attribute_key: PalletAttributes<T::CollectionId>,
	) -> Result<bool, DispatchError> {
		let attribute = (
			&collection,
			Some(item),
			AttributeNamespace::Pallet,
			&Self::construct_attribute_key(attribute_key.encode())?,
		);
		Ok(Attribute::<T, I>::contains_key(attribute))
	}
}
Repository: paritytech/substrate
File: frame/nfts/src/features/metadata.rs (Rust)

Code before:
		}

		let details =
			Collection::<T, I>::get(&collection).ok_or(Error::<T, I>::UnknownCollection)?;
		let collection_config = Self::get_collection_config(&collection)?;

		ensure!(
			maybe_check_origin.is_none() ||
				collection_config.is_setting_enabled(CollectionSetting::UnlockedMetadata),
			Error::<T, I>::LockedCollectionMetadata
		);

		CollectionMetadataOf::<T, I>::try_mutate_exists(collection, |metadata| {
			let deposit = metadata.take().ok_or(Error::<T, I>::UnknownCollection)?.deposit;
			T::Currency::unreserve(&details.owner, deposit);
			Self::deposit_event(Event::CollectionMetadataCleared { collection });
			Ok(())
		})
	}

	/// A helper method to construct metadata.
	///
	/// # Errors
	///
	/// This function returns an [`IncorrectMetadata`](crate::Error::IncorrectMetadata) dispatch
	/// error if the provided metadata is incorrectly formatted.
	pub fn construct_metadata(
		metadata: Vec<u8>,
	) -> Result<BoundedVec<u8, T::StringLimit>, DispatchError> {
		Ok(BoundedVec::try_from(metadata).map_err(|_| Error::<T, I>::IncorrectMetadata)?)
	}
}


Review comment (refactor):
```suggestion
	/// error if the provided metadata is too long.
```

Code after:
		}

		let details =
			Collection::<T, I>::get(&collection).ok_or(Error::<T, I>::UnknownCollection)?;
		let collection_config = Self::get_collection_config(&collection)?;

		ensure!(
			maybe_check_origin.is_none() ||
				collection_config.is_setting_enabled(CollectionSetting::UnlockedMetadata),
			Error::<T, I>::LockedCollectionMetadata
		);

		CollectionMetadataOf::<T, I>::try_mutate_exists(collection, |metadata| {
			let deposit = metadata.take().ok_or(Error::<T, I>::UnknownCollection)?.deposit;
			T::Currency::unreserve(&details.owner, deposit);
			Self::deposit_event(Event::CollectionMetadataCleared { collection });
			Ok(())
		})
	}

	/// A helper method to construct metadata.
	///
	/// # Errors
	///
	/// This function returns an [`IncorrectMetadata`](crate::Error::IncorrectMetadata) dispatch
	/// error if the provided metadata is too long.
	pub fn construct_metadata(
		metadata: Vec<u8>,
	) -> Result<BoundedVec<u8, T::StringLimit>, DispatchError> {
		Ok(BoundedVec::try_from(metadata).map_err(|_| Error::<T, I>::IncorrectMetadata)?)
	}
}
Repository: paritytech/substrate
File: frame/glutton/src/lib.rs (Rust)

Code before:

#[frame_support::pallet]
pub mod pallet {
	use super::*;

	#[pallet::config]
	pub trait Config: frame_system::Config {
		/// The overarching event type.
		type RuntimeEvent: From<Event> + IsType<<Self as frame_system::Config>::RuntimeEvent>;

		/// The admin origin that can set computational limits and initialize the pallet.
		type AdminOrigin: EnsureOrigin<Self::RuntimeOrigin>;

		/// Weight information for this pallet.
		type WeightInfo: WeightInfo;
	}

	#[pallet::pallet]
	pub struct Pallet<T>(_);

	#[pallet::event]
	#[pallet::generate_deposit(pub(super) fn deposit_event)]
	pub enum Event {
		/// The pallet has been (re)initialized.
		PalletInitialized {
			/// The pallet initialization state.
			reinit: bool,
		},
		/// The computation limit has been updated.
		ComputationLimitSet {
			/// The computation limit.
			compute: FixedU64,
		},
		/// The storage limit has been updated.
		StorageLimitSet {
			/// The storage limit.
			storage: FixedU64,
		},
	}

	#[pallet::error]
	pub enum Error<T> {
		/// The pallet was already initialized.
		///
		/// Set `witness_count` to `Some` to bypass this error.
		AlreadyInitialized,

		/// The limit was over [`crate::RESOURCE_HARD_LIMIT`].
		InsaneLimit,
	}


Review comment (suggestion):
```suggestion
			/// Whether the pallet has been re-initialized.
```

Code after:
pub const RESOURCE_HARD_LIMIT: FixedU64 = FixedU64::from_u32(10);

#[frame_support::pallet]
pub mod pallet {
	use super::*;

	#[pallet::config]
	pub trait Config: frame_system::Config {
		/// The overarching event type.
		type RuntimeEvent: From<Event> + IsType<<Self as frame_system::Config>::RuntimeEvent>;

		/// The admin origin that can set computational limits and initialize the pallet.
		type AdminOrigin: EnsureOrigin<Self::RuntimeOrigin>;

		/// Weight information for this pallet.
		type WeightInfo: WeightInfo;
	}

	#[pallet::pallet]
	pub struct Pallet<T>(_);

	#[pallet::event]
	#[pallet::generate_deposit(pub(super) fn deposit_event)]
	pub enum Event {
		/// The pallet has been (re)initialized.
		PalletInitialized {
			/// Whether the pallet has been re-initialized.
			reinit: bool,
		},
		/// The computation limit has been updated.
		ComputationLimitSet {
			/// The computation limit.
			compute: FixedU64,
		},
		/// The storage limit has been updated.
		StorageLimitSet {
			/// The storage limit.
			storage: FixedU64,
		},
	}

	#[pallet::error]
	pub enum Error<T> {
		/// The pallet was already initialized.
		///
		/// Set `witness_count` to `Some` to bypass this error.
		AlreadyInitialized,

		/// The limit was over [`crate::RESOURCE_HARD_LIMIT`].
		InsaneLimit,
	}
Repository: paritytech/substrate
File: frame/contracts/build.rs (Rust)

Code before:
					"Invalid MigrationStep::VERSION in {:?}",
					path
				);

				return Some(version)
			}
			None
		})
		.max()
		.expect("Failed to find any files matching the 'src/migration/vxx.rs' pattern.")
}

/// Generates a module that exposes the latest migration version, and the benchmark migrations type.
fn main() -> Result<(), Box<dyn std::error::Error>> {
	let out_dir = std::env::var("OUT_DIR")?;
	let path = std::path::Path::new(&out_dir).join("migration_codegen.rs");
	let mut f = std::fs::File::create(&path)?;
	let version = get_latest_version();
	write!(
		f,
		"
         pub mod codegen {{
		  use crate::NoopMigration;
		  /// The latest migration version, pulled from the latest migration file.
		  pub const LATEST_MIGRATION_VERSION: u16 = {version};
		  /// The Migration Steps used for benchmarking, the migration framework.
		  pub type BenchMigrations = (NoopMigration<{}>, NoopMigration<{version}>);
		}}",
		version - 1,
	)?;
	Ok(())
}


Review comment (suggestion):
```suggestion
		  /// The Migration Steps used for benchmarking the migration framework.
```

Code after:
					"Invalid MigrationStep::VERSION in {:?}",
					path
				);

				return Some(version)
			}
			None
		})
		.max()
		.expect("Failed to find any files matching the 'src/migration/vxx.rs' pattern.")
}

/// Generates a module that exposes the latest migration version, and the benchmark migrations type.
fn main() -> Result<(), Box<dyn std::error::Error>> {
	let out_dir = std::env::var("OUT_DIR")?;
	let path = std::path::Path::new(&out_dir).join("migration_codegen.rs");
	let mut f = std::fs::File::create(&path)?;
	let version = get_latest_version();
	write!(
		f,
		"
         pub mod codegen {{
		  use crate::NoopMigration;
		  /// The latest migration version, pulled from the latest migration file.
		  pub const LATEST_MIGRATION_VERSION: u16 = {version};
		  /// The Migration Steps used for benchmarking the migration framework.
		  pub type BenchMigrations = (NoopMigration<{}>, NoopMigration<{version}>);
		}}",
		version - 1,
	)?;

	println!("cargo:rerun-if-changed=src/migration");
	Ok(())
}
Repository: paritytech/substrate
File: frame/contracts/src/tests.rs (Rust)

Code before:
	fn default() -> Self {
		Filters { filter: (|_| true) }
	}
}

parameter_types! {
	static CallFilter: Filters = Default::default();
}

impl TestFilter {
	pub fn set_filter(filter: fn(&RuntimeCall) -> bool) {
		CallFilter::mutate(|fltr| fltr.filter = filter);
	}
}

impl Contains<RuntimeCall> for TestFilter {
	fn contains(call: &RuntimeCall) -> bool {
		(CallFilter::get().filter)(call)
	}
}

parameter_types! {
	pub static UnstableInterface: bool = true;
}

#[cfg(feature = "unsafe-debug")]
#[derive(Clone, PartialEq, Eq, Debug)]
struct DebugFrame {
	code_hash: CodeHash<Test>,
	call: ExportedFunction,
	input: Vec<u8>,
	result: Option<Vec<u8>>,
}

#[cfg(feature = "unsafe-debug")]
thread_local! {
	static DEBUG_EXECUTION_TRACE: RefCell<Vec<DebugFrame>> = RefCell::new(Vec::new());
}

#[cfg(feature = "unsafe-debug")]
pub struct TestDebugger;
#[cfg(feature = "unsafe-debug")]
impl ExecutionObserver<CodeHash<Test>> for TestDebugger {
	fn before_call(code_hash: &CodeHash<Test>, entry_point: ExportedFunction, input_data: &[u8]) {
		DEBUG_EXECUTION_TRACE.with(|d| {
			d.borrow_mut().push(DebugFrame {
				code_hash: code_hash.clone(),
				call: entry_point,
				input: input_data.to_vec(),
				result: None,
			})

Review comment (bug):
I would move all your tests to src/tests/unsafe_debug_tests.rs
and then gate `mod unsafe_debug_tests;` with the feature

Code after:

parameter_types! {
	static CallFilter: Filters = Default::default();
}

impl TestFilter {
	pub fn set_filter(filter: fn(&RuntimeCall) -> bool) {
		CallFilter::mutate(|fltr| fltr.filter = filter);
	}
}

impl Contains<RuntimeCall> for TestFilter {
	fn contains(call: &RuntimeCall) -> bool {
		(CallFilter::get().filter)(call)
	}
}

parameter_types! {
	pub static UnstableInterface: bool = true;
}

impl Config for Test {
	type Time = Timestamp;
	type Randomness = Randomness;
	type Currency = Balances;
	type RuntimeEvent = RuntimeEvent;
	type RuntimeCall = RuntimeCall;
	type CallFilter = TestFilter;
	type CallStack = [Frame<Self>; 5];
	type WeightPrice = Self;
	type WeightInfo = ();
	type ChainExtension =
		(TestExtension, DisabledExtension, RevertingExtension, TempStorageExtension);
	type Schedule = MySchedule;
	type DepositPerByte = DepositPerByte;
	type DepositPerItem = DepositPerItem;
	type DefaultDepositLimit = DefaultDepositLimit;
	type AddressGenerator = DefaultAddressGenerator;
	type MaxCodeLen = ConstU32<{ 123 * 1024 }>;
	type MaxStorageKeyLen = ConstU32<128>;
	type UnsafeUnstableInterface = UnstableInterface;
	type MaxDebugBufferLen = ConstU32<{ 2 * 1024 * 1024 }>;
	type RuntimeHoldReason = RuntimeHoldReason;
	type Migrations = crate::migration::codegen::BenchMigrations;
	type CodeHashLockupDepositPercent = CodeHashLockupDepositPercent;
	type MaxDelegateDependencies = MaxDelegateDependencies;
	#[cfg(feature = "unsafe-debug")]
	type Debug = unsafe_debug::TestDebugger;
}

pub const ALICE: AccountId32 = AccountId32::new([1u8; 32]);
Repository: paritytech/substrate
File: frame/support/procedural/src/derive_impl.rs (Rust)

Code before:
use std::collections::HashSet;
use syn::{
	parse2, parse_quote, spanned::Spanned, token, Ident, ImplItem, ItemImpl, Path, Result, Token,
};

mod keyword {
	syn::custom_keyword!(runtime_type);
	syn::custom_keyword!(no_aggregated_types);
}

#[derive(derive_syn_parse::Parse, PartialEq, Eq)]
pub enum PalletAttrType {
	#[peek(keyword::runtime_type, name = "runtime_type")]
	RuntimeType(keyword::runtime_type),
}

#[derive(derive_syn_parse::Parse)]
pub struct PalletAttr {
	_pound: Token![#],
	#[bracket]
	_bracket: token::Bracket,
	#[inside(_bracket)]
	typ: PalletAttrType,
}

fn take_first_item_pallet_attr<Attr>(item: &mut syn::ImplItemType) -> syn::Result<Option<Attr>>
where
	Attr: syn::parse::Parse,
{
	let attrs = &mut item.attrs;
	if let Some(pallet_attr) = attrs.get(0) {
		Ok(Some(syn::parse2(pallet_attr.into_token_stream())?))
	} else {
		Ok(None)
	}
}

#[derive(Parse, Debug)]
pub struct DeriveImplAttrArgs {
	pub default_impl_path: Path,
	_as: Option<Token![as]>,
	#[parse_if(_as.is_some())]
	pub disambiguation_path: Option<Path>,
	_comma: Option<Token![,]>,
	#[parse_if(_comma.is_some())]
	pub no_aggregated_types: Option<keyword::no_aggregated_types>,
}

impl ForeignPath for DeriveImplAttrArgs {
	fn foreign_path(&self) -> &Path {
		&self.default_impl_path

Review comment (suggestion):
```suggestion
fn get_first_item_pallet_attr<Attr>(item: &syn::ImplItemType) -> syn::Result<Option<Attr>>
```

`take` would mean it removes it. 

Code after:
use std::collections::HashSet;
use syn::{
	parse2, parse_quote, spanned::Spanned, token, Ident, ImplItem, ItemImpl, Path, Result, Token,
};

mod keyword {
	syn::custom_keyword!(inject_runtime_type);
	syn::custom_keyword!(no_aggregated_types);
}

#[derive(derive_syn_parse::Parse, PartialEq, Eq)]
pub enum PalletAttrType {
	#[peek(keyword::inject_runtime_type, name = "inject_runtime_type")]
	RuntimeType(keyword::inject_runtime_type),
}

#[derive(derive_syn_parse::Parse)]
pub struct PalletAttr {
	_pound: Token![#],
	#[bracket]
	_bracket: token::Bracket,
	#[inside(_bracket)]
	typ: PalletAttrType,
}

fn get_first_item_pallet_attr<Attr>(item: &syn::ImplItemType) -> syn::Result<Option<Attr>>
where
	Attr: syn::parse::Parse,
{
	item.attrs.get(0).map(|a| syn::parse2(a.into_token_stream())).transpose()
}

#[derive(Parse, Debug)]
pub struct DeriveImplAttrArgs {
	pub default_impl_path: Path,
	_as: Option<Token![as]>,
	#[parse_if(_as.is_some())]
	pub disambiguation_path: Option<Path>,
	_comma: Option<Token![,]>,
	#[parse_if(_comma.is_some())]
	pub no_aggregated_types: Option<keyword::no_aggregated_types>,
}

impl ForeignPath for DeriveImplAttrArgs {
	fn foreign_path(&self) -> &Path {
		&self.default_impl_path
	}
}

impl ToTokens for DeriveImplAttrArgs {
	fn to_tokens(&self, tokens: &mut TokenStream2) {
Repository: paritytech/substrate
File: frame/support/procedural/src/derive_impl.rs (Rust)

Code before:

#[derive(derive_syn_parse::Parse, PartialEq, Eq)]
pub enum PalletAttrType {
	#[peek(keyword::runtime_type, name = "runtime_type")]
	RuntimeType(keyword::runtime_type),
}

#[derive(derive_syn_parse::Parse)]
pub struct PalletAttr {
	_pound: Token![#],
	#[bracket]
	_bracket: token::Bracket,
	#[inside(_bracket)]
	typ: PalletAttrType,
}

fn take_first_item_pallet_attr<Attr>(item: &mut syn::ImplItemType) -> syn::Result<Option<Attr>>
where
	Attr: syn::parse::Parse,
{
	let attrs = &mut item.attrs;
	if let Some(pallet_attr) = attrs.get(0) {
		Ok(Some(syn::parse2(pallet_attr.into_token_stream())?))
	} else {
		Ok(None)
	}
}

#[derive(Parse, Debug)]
pub struct DeriveImplAttrArgs {
	pub default_impl_path: Path,
	_as: Option<Token![as]>,
	#[parse_if(_as.is_some())]
	pub disambiguation_path: Option<Path>,
	_comma: Option<Token![,]>,
	#[parse_if(_comma.is_some())]
	pub no_aggregated_types: Option<keyword::no_aggregated_types>,
}

impl ForeignPath for DeriveImplAttrArgs {
	fn foreign_path(&self) -> &Path {
		&self.default_impl_path
	}
}

impl ToTokens for DeriveImplAttrArgs {
	fn to_tokens(&self, tokens: &mut TokenStream2) {
		tokens.extend(self.default_impl_path.to_token_stream());
		tokens.extend(self._as.to_token_stream());
		tokens.extend(self.disambiguation_path.to_token_stream());
		tokens.extend(self._comma.to_token_stream());

Review comment (suggestion):
```suggestion
	item.attrs.get(0).map(|a| syn::parse2(a.into_token_stream()).transpose()
```

Code after:

#[derive(derive_syn_parse::Parse, PartialEq, Eq)]
pub enum PalletAttrType {
	#[peek(keyword::inject_runtime_type, name = "inject_runtime_type")]
	RuntimeType(keyword::inject_runtime_type),
}

#[derive(derive_syn_parse::Parse)]
pub struct PalletAttr {
	_pound: Token![#],
	#[bracket]
	_bracket: token::Bracket,
	#[inside(_bracket)]
	typ: PalletAttrType,
}

fn get_first_item_pallet_attr<Attr>(item: &syn::ImplItemType) -> syn::Result<Option<Attr>>
where
	Attr: syn::parse::Parse,
{
	item.attrs.get(0).map(|a| syn::parse2(a.into_token_stream())).transpose()
}

#[derive(Parse, Debug)]
pub struct DeriveImplAttrArgs {
	pub default_impl_path: Path,
	_as: Option<Token![as]>,
	#[parse_if(_as.is_some())]
	pub disambiguation_path: Option<Path>,
	_comma: Option<Token![,]>,
	#[parse_if(_comma.is_some())]
	pub no_aggregated_types: Option<keyword::no_aggregated_types>,
}

impl ForeignPath for DeriveImplAttrArgs {
	fn foreign_path(&self) -> &Path {
		&self.default_impl_path
	}
}

impl ToTokens for DeriveImplAttrArgs {
	fn to_tokens(&self, tokens: &mut TokenStream2) {
		tokens.extend(self.default_impl_path.to_token_stream());
		tokens.extend(self._as.to_token_stream());
		tokens.extend(self.disambiguation_path.to_token_stream());
		tokens.extend(self._comma.to_token_stream());
		tokens.extend(self.no_aggregated_types.to_token_stream());
	}
}

/// Gets the [`Ident`] representation of the given [`ImplItem`], if one exists. Otherwise
Repository: paritytech/substrate
File: primitives/api/proc-macro/src/impl_runtime_apis.rs (Rust)

Code before:

		pub mod api {
			use super::*;

			#dispatch_impl

			#wasm_interface
		}
	);

	let impl_ = expander::Expander::new("impl_runtime_apis")
		.dry(std::env::var("SP_API_EXPAND").is_err())
		.verbose(true)
		.write_to_out_dir(impl_)
		.expect("Does not fail because of IO in OUT_DIR; qed");

	Ok(impl_)
}

// Filters all attributes except the cfg ones.
fn filter_cfg_attrs(attrs: &[Attribute]) -> Vec<Attribute> {
	attrs.iter().filter(|a| a.path().is_ident("cfg")).cloned().collect()
}

// Parse feature flagged api_version.
// E.g. `#[cfg_attr(feature = "enable-staging-api", api_version(99))]`
fn extract_cfg_api_version(attrs: &Vec<Attribute>, span: Span) -> Result<Option<(String, u64)>> {
	let cfg_attrs = attrs.iter().filter(|a| a.path().is_ident("cfg_attr")).collect::<Vec<_>>();

	let mut cfg_api_version_attr = Vec::new();
	for cfg_attr in cfg_attrs {
		let mut feature_name = None;
		let mut api_version = None;
		cfg_attr.parse_nested_meta(|m| {
			if m.path.is_ident("feature") {
				let a = m.value()?;
				let b: LitStr = a.parse()?;
				feature_name = Some(b.value());
			} else if m.path.is_ident(API_VERSION_ATTRIBUTE) {
				let content;
				parenthesized!(content in m.input);
				let ver: LitInt = content.parse()?;
				api_version = Some(ver.base10_parse::<u64>()?);
			}
			Ok(())
		})?;

		// If there is a cfg attribute containing api_version - save if for processing
		if let (Some(feature_name), Some(api_version)) = (feature_name, api_version) {
			cfg_api_version_attr.push((feature_name, api_version, cfg_attr.span()));
		}

Review comment (suggestion):
```suggestion
/// Parse feature flagged api_version.
/// E.g. `#[cfg_attr(feature = "enable-staging-api", api_version(99))]`
```

Code after:
				"Found multiple #[{}] attributes for an API implementation. \
				Each runtime API can have only one version.",
				API_VERSION_ATTRIBUTE
			),
		))
	}

	// Parse the runtime version if there exists one.
	Ok(ApiVersion {
		custom: api_ver.first().map(|v| parse_runtime_api_version(v)).transpose()?,
		feature_gated: extract_cfg_api_version(attrs, span)?,
	})
}

#[cfg(test)]
mod tests {
	use super::*;

	#[test]
	fn filter_non_cfg_attributes() {
		let cfg_std: Attribute = parse_quote!(#[cfg(feature = "std")]);
		let cfg_benchmarks: Attribute = parse_quote!(#[cfg(feature = "runtime-benchmarks")]);

		let attrs = vec![
			cfg_std.clone(),
			parse_quote!(#[derive(Debug)]),
			parse_quote!(#[test]),
			cfg_benchmarks.clone(),
			parse_quote!(#[allow(non_camel_case_types)]),
		];

		let filtered = filter_cfg_attrs(&attrs);
		assert_eq!(filtered.len(), 2);
		assert_eq!(cfg_std, filtered[0]);
		assert_eq!(cfg_benchmarks, filtered[1]);
	}
}