Repository: paritytech/substrate
File: primitives/api/proc-macro/src/impl_runtime_apis.rs (Rust)

Code before:
		if let Some(e) = self.errors.pop() {
			// TODO: what to do with the rest of the errors?
			return Err(e)
		}

		Ok(res)
	}
}

impl<'a> Fold for ApiImplItem<'a> {
	fn fold_impl_item_fn(&mut self, mut i: ImplItemFn) -> ImplItemFn {
		let v = extract_api_version(&i.attrs, i.span());

		let v = match v {
			Ok(ver) => ver,
			Err(e) => {
				// `api_version` attribute seems to be malformed
				self.errors.push(e);
				return fold::fold_impl_item_fn(self, i)
			},
		};

		if v.custom.is_some() {
			self.errors.push(Error::new(
				i.span(),
				"`api_version` attribute is not allowed `decl_runtime_api` method implementations",
			));
			return fold::fold_impl_item_fn(self, i)
		}

		if let Some(v) = v.feature_gated {
			// Check for a mismatch between the trait and the function implementation
			match self.trait_api_ver {
				None => {
					let mut e = Error::new(i.span(), "Found `cfg_attr` for implementation function but the trait is not versioned");
					e.combine(Error::new(self.trait_span, "Put a `cfg_attr` here"));
					self.errors.push(e);
					return fold::fold_impl_item_fn(self, i)
				},
				Some(trait_ver) if v != *trait_ver => {
					let mut e = Error::new(
						i.span(),
						"Different `cfg_attr` for the trait and the implementation function",
					);
					e.combine(Error::new(self.trait_span, "Trait `cfg_attr` is here"));
					self.errors.push(e);
					return fold::fold_impl_item_fn(self, i)
				},
				_ => {},
			}


Review comment (suggestion):
```suggestion
				"`api_version` attribute is not allowed on method implementations",
```

Code after:

	Ok(quote!( #( #impls_prepared )* ))
}

/// Auxiliary data structure that is used to convert `impl Api for Runtime` to
/// `impl Api for RuntimeApi`.
/// This requires us to replace the runtime `Block` with the node `Block`,
/// `impl Api for Runtime` with `impl Api for RuntimeApi` and replace the method implementations
/// with code that calls into the runtime.
struct ApiRuntimeImplToApiRuntimeApiImpl<'a> {
	runtime_block: &'a TypePath,
}

impl<'a> ApiRuntimeImplToApiRuntimeApiImpl<'a> {
	/// Process the given item implementation.
	fn process(mut self, input: ItemImpl) -> ItemImpl {
		let mut input = self.fold_item_impl(input);

		let crate_ = generate_crate_access();

		// Delete all functions, because all of them are default implemented by
		// `decl_runtime_apis!`. We only need to implement the `__runtime_api_internal_call_api_at`
		// function.
		input.items.clear();
		input.items.push(parse_quote! {
			fn __runtime_api_internal_call_api_at(
				&self,
				at: <__SrApiBlock__ as #crate_::BlockT>::Hash,
				params: std::vec::Vec<u8>,
				fn_name: &dyn Fn(#crate_::RuntimeVersion) -> &'static str,
			) -> std::result::Result<std::vec::Vec<u8>, #crate_::ApiError> {
				// If we are not already in a transaction, we should create a new transaction
				// and then commit/roll it back at the end!
				let transaction_depth = *std::cell::RefCell::borrow(&self.transaction_depth);

				if transaction_depth == 0 {
					self.start_transaction();
				}

				let res = (|| {
					let version = #crate_::CallApiAt::<__SrApiBlock__>::runtime_version_at(
						self.call,
						at,
					)?;

					match &mut *std::cell::RefCell::borrow_mut(&self.extensions_generated_for) {
						Some(generated_for) => {
							if *generated_for != at {
								return std::result::Result::Err(
									#crate_::ApiError::UsingSameInstanceForDifferentBlocks
								)