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 32d4683f3dd5..8a582e171fb7 100644 --- a/substrate/primitives/api/proc-macro/src/impl_runtime_apis.rs +++ b/substrate/primitives/api/proc-macro/src/impl_runtime_apis.rs @@ -867,27 +867,38 @@ fn impl_runtime_apis_impl_inner( let runtime_api_versions = generate_runtime_api_versions(api_impls)?; let wasm_interface = generate_wasm_interface(api_impls)?; let api_impls_for_runtime_api = generate_api_impl_for_runtime_api(api_impls)?; - let modules: Vec = uses + let modules = match uses .iter() .map(|item| { let mut path: Vec = vec![]; - fn call(path: &mut Vec, item: &UseTree) { + fn call(path: &mut Vec, item: &UseTree) -> Result<()> { match &item { syn::UseTree::Path(use_path) => { path.push(use_path.ident.clone()); - call(path, use_path.tree.as_ref()); + call(path, use_path.tree.as_ref()) + }, + syn::UseTree::Glob(_) => Ok(()), + syn::UseTree::Name(_) | syn::UseTree::Rename(_) | syn::UseTree::Group(_) => { + let error = Error::new( + item.span(), + "Unsupported syntax used to import api implementaions from an extension module. \ + Try using `pub use ::*` or `use ::*`", + ); + return Err(error) }, - syn::UseTree::Glob(_) => (), - syn::UseTree::Name(_) | syn::UseTree::Rename(_) | syn::UseTree::Group(_) => - unimplemented!(), } } - call(&mut path, &item.tree); + call(&mut path, &item.tree)?; let tok = quote::quote! {#(#path)::*}; - syn::parse::(tok.into()).unwrap() + Ok(syn::parse::(tok.into()) + .expect("Can't happen, a valid TypePath was used in the `UseTree`")) }) - .collect(); - + .collect::>>() + .map_err(|e| e.into_compile_error()) + { + Ok(items) => items, + Err(e) => return Ok(e), + }; let dispatch_impl = generate_dispatch_function(api_impls, Kind::Main(&modules))?; let runtime_metadata = @@ -1039,7 +1050,7 @@ mod tests { }; // Parse the items - let RuntimeApiImpls { impls: mut api_impls, uses : _ } = + let RuntimeApiImpls { impls: mut api_impls, uses: _ } = syn::parse2::(code).unwrap(); // Run the renamer which is being run first in the `impl_runtime_apis!` macro. diff --git a/substrate/primitives/api/test/tests/ui/incorrect_extension_import.rs b/substrate/primitives/api/test/tests/ui/incorrect_extension_import.rs new file mode 100644 index 000000000000..96cbf1206171 --- /dev/null +++ b/substrate/primitives/api/test/tests/ui/incorrect_extension_import.rs @@ -0,0 +1,61 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use sp_runtime::traits::Block as BlockT; +use substrate_test_runtime_client::runtime::Block; + +struct Runtime {} + +sp_api::decl_runtime_apis! { + #[api_version(2)] + pub trait Api { + fn test1(); + fn test2(); + #[api_version(3)] + fn test3(); + #[api_version(4)] + fn test4(); + } +} + +sp_api::impl_runtime_apis! { + impl sp_api::Core for Runtime { + fn version() -> sp_version::RuntimeVersion { + unimplemented!() + } + fn execute_block(_: Block) { + unimplemented!() + } + fn initialize_block(_: &::Header) -> sp_runtime::ExtrinsicInclusionMode { + unimplemented!() + } + } + + use example::{api, *}; +} + +#[sp_api::impl_runtime_apis_ext] +mod example { + use super::*; + #[api_version(2)] + impl self::Api for Runtime { + fn test1() {} + fn test2() {} + } +} + +fn main() {} diff --git a/substrate/primitives/api/test/tests/ui/incorrect_extension_import.stderr b/substrate/primitives/api/test/tests/ui/incorrect_extension_import.stderr new file mode 100644 index 000000000000..8eaa6dbc0456 --- /dev/null +++ b/substrate/primitives/api/test/tests/ui/incorrect_extension_import.stderr @@ -0,0 +1,21 @@ +error: Unsupported syntax used to import api implementaions from an extension module. Try using `pub use ::*` or `use ::*` + --> tests/ui/incorrect_extension_import.rs:48:15 + | +48 | use example::{api, *}; + | ^^^^^^^^ + +error[E0412]: cannot find type `RuntimeApiImpl` in this scope + --> tests/ui/incorrect_extension_import.rs:51:1 + | +51 | #[sp_api::impl_runtime_apis_ext] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope + | + = note: this error originates in the attribute macro `sp_api::impl_runtime_apis_ext` (in Nightly builds, run with -Z macro-backtrace for more info) + +warning: unused import: `sp_runtime::traits::Block` + --> tests/ui/incorrect_extension_import.rs:18:5 + | +18 | use sp_runtime::traits::Block as BlockT; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(unused_imports)]` on by default