Repository: paritytech/substrate
File: frame/support/procedural/src/pallet/parse/mod.rs (Rust)

Code before:
					genesis_config = Some(g);
				},
				Some(PalletAttr::GenesisBuild(span)) if genesis_build.is_none() => {
					let g = genesis_build::GenesisBuildDef::try_from(span, index, item)?;
					genesis_build = Some(g);
				},
				Some(PalletAttr::Origin(_)) if origin.is_none() =>
					origin = Some(origin::OriginDef::try_from(index, item)?),
				Some(PalletAttr::Inherent(_)) if inherent.is_none() =>
					inherent = Some(inherent::InherentDef::try_from(index, item)?),
				Some(PalletAttr::Storage(span)) => {
					let mut storage_def = storage::StorageDef::try_from(span, index, item)?;
					// check for #[benchmarking(cached)] calls
					if let syn::Item::Type(typ) = item {
						for attr in typ.attrs.as_slice() {
							if attr.style == AttrStyle::Outer {
								if let Some(seg) = attr.path.segments.last() {
									if let Ok(_) =
										syn::parse2::<keyword::benchmarking>(seg.to_token_stream())
									{
										if let Ok(group) = syn::parse2::<Group>(attr.tokens.clone())
										{
											if let Ok(_) =
												syn::parse2::<keyword::cached>(group.stream())
											{
												storage_def.benchmarking_cached = true;
											}
										}
									}
								}
							}
						}
					}
					storages.push(storage_def);
				},
				Some(PalletAttr::ValidateUnsigned(_)) if validate_unsigned.is_none() => {
					let v = validate_unsigned::ValidateUnsignedDef::try_from(index, item)?;
					validate_unsigned = Some(v);
				},
				Some(PalletAttr::TypeValue(span)) =>
					type_values.push(type_value::TypeValueDef::try_from(span, index, item)?),
				Some(PalletAttr::ExtraConstants(_)) =>
					extra_constants =
						Some(extra_constants::ExtraConstantsDef::try_from(index, item)?),
				Some(attr) => {
					let msg = "Invalid duplicated attribute";
					return Err(syn::Error::new(attr.span(), msg))
				},
				None => (),
			}
		}

Review comment (performance):
Why do we parse this here?

Why isn't that done around here: https://github.com/paritytech/substrate/blob/dd1f1b5f291aa2325eddf5f26037b84cfbbe0957/frame/support/procedural/src/pallet/parse/storage.rs#L674 ?

We already parse there the other `pallet::whatever` attributes. Yes, here it would be `benchmarking(cached)`, but it should still be done there.

Code after:
				Some(PalletAttr::GenesisBuild(span)) if genesis_build.is_none() => {
					let g = genesis_build::GenesisBuildDef::try_from(span, index, item)?;
					genesis_build = Some(g);
				},
				Some(PalletAttr::Origin(_)) if origin.is_none() =>
					origin = Some(origin::OriginDef::try_from(index, item)?),
				Some(PalletAttr::Inherent(_)) if inherent.is_none() =>
					inherent = Some(inherent::InherentDef::try_from(index, item)?),
				Some(PalletAttr::Storage(span)) =>
					storages.push(storage::StorageDef::try_from(span, index, item)?),
				Some(PalletAttr::ValidateUnsigned(_)) if validate_unsigned.is_none() => {
					let v = validate_unsigned::ValidateUnsignedDef::try_from(index, item)?;
					validate_unsigned = Some(v);
				},
				Some(PalletAttr::TypeValue(span)) =>
					type_values.push(type_value::TypeValueDef::try_from(span, index, item)?),
				Some(PalletAttr::ExtraConstants(_)) =>
					extra_constants =
						Some(extra_constants::ExtraConstantsDef::try_from(index, item)?),
				Some(attr) => {
					let msg = "Invalid duplicated attribute";
					return Err(syn::Error::new(attr.span(), msg))
				},
				None => (),
			}
		}

		if genesis_config.is_some() != genesis_build.is_some() {
			let msg = format!(
				"`#[pallet::genesis_config]` and `#[pallet::genesis_build]` attributes must be \
				either both used or both not used, instead genesis_config is {} and genesis_build \
				is {}",
				genesis_config.as_ref().map_or("unused", |_| "used"),
				genesis_build.as_ref().map_or("unused", |_| "used"),
			);
			return Err(syn::Error::new(item_span, msg))
		}

		let def = Def {
			item,
			config: config
				.ok_or_else(|| syn::Error::new(item_span, "Missing `#[pallet::config]`"))?,
			pallet_struct: pallet_struct
				.ok_or_else(|| syn::Error::new(item_span, "Missing `#[pallet::pallet]`"))?,
			hooks,
			call,
			extra_constants,
			genesis_config,
			genesis_build,
			validate_unsigned,
			error,