diff --git a/tests/wellknown-compiled/Cargo.toml b/tests/wellknown-compiled/Cargo.toml index 5a5c83738..075369ba3 100644 --- a/tests/wellknown-compiled/Cargo.toml +++ b/tests/wellknown-compiled/Cargo.toml @@ -16,4 +16,5 @@ tonic = { path = "../../tonic" } prost = "0.9" [build-dependencies] +prost-build = "0.9" tonic-build = { path = "../../tonic-build" } diff --git a/tests/wellknown-compiled/build.rs b/tests/wellknown-compiled/build.rs index 01301f581..cb07fcae5 100644 --- a/tests/wellknown-compiled/build.rs +++ b/tests/wellknown-compiled/build.rs @@ -1,6 +1,13 @@ fn main() { + let mut config = prost_build::Config::new(); + config.extern_path(".google.protobuf.Empty", "()"); + tonic_build::configure() .compile_well_known_types(true) - .compile(&["proto/google.proto"], &["proto"]) + .compile_with_config( + config, + &["proto/google.proto", "proto/test.proto"], + &["proto"], + ) .unwrap(); } diff --git a/tests/wellknown-compiled/proto/test.proto b/tests/wellknown-compiled/proto/test.proto new file mode 100644 index 000000000..2e4d3b4dd --- /dev/null +++ b/tests/wellknown-compiled/proto/test.proto @@ -0,0 +1,11 @@ +syntax = "proto3"; +package test; + +import "google/protobuf/empty.proto"; + +message Input { +} + +service Service { + rpc Call(Input) returns (google.protobuf.Empty); +} diff --git a/tests/wellknown-compiled/src/lib.rs b/tests/wellknown-compiled/src/lib.rs index 2d287e7d7..60ab404d1 100644 --- a/tests/wellknown-compiled/src/lib.rs +++ b/tests/wellknown-compiled/src/lib.rs @@ -1,9 +1,18 @@ -pub mod google { - pub mod protobuf { - tonic::include_proto!("google.protobuf"); +pub mod gen { + pub mod google { + pub mod protobuf { + tonic::include_proto!("google.protobuf"); + } + } + + pub mod test { + tonic::include_proto!("test"); } } pub fn grok() { - let _empty = crate::google::protobuf::Empty {}; + let _any = crate::gen::google::protobuf::Any { + type_url: "foo".to_owned(), + value: Vec::new(), + }; } diff --git a/tonic-build/src/prost.rs b/tonic-build/src/prost.rs index 108cf807a..3b0f5148d 100644 --- a/tonic-build/src/prost.rs +++ b/tonic-build/src/prost.rs @@ -49,6 +49,9 @@ pub fn compile_protos(proto: impl AsRef) -> io::Result<()> { const PROST_CODEC_PATH: &str = "tonic::codec::ProstCodec"; +/// Non-path Rust types allowed for request/response types. +const NON_PATH_TYPE_ALLOWLIST: &[&str] = &["()"]; + impl crate::Service for Service { const CODEC_PATH: &'static str = PROST_CODEC_PATH; @@ -105,34 +108,25 @@ impl crate::Method for Method { proto_path: &str, compile_well_known_types: bool, ) -> (TokenStream, TokenStream) { - let request = if (is_google_type(&self.input_proto_type) && !compile_well_known_types) - || self.input_type.starts_with("::") - { - self.input_type.parse::().unwrap() - } else if self.input_type.starts_with("crate::") { - syn::parse_str::(&self.input_type) - .unwrap() - .to_token_stream() - } else { - syn::parse_str::(&format!("{}::{}", proto_path, self.input_type)) - .unwrap() - .to_token_stream() - }; - - let response = if (is_google_type(&self.output_proto_type) && !compile_well_known_types) - || self.output_type.starts_with("::") - { - self.output_type.parse::().unwrap() - } else if self.output_type.starts_with("crate::") { - syn::parse_str::(&self.output_type) - .unwrap() - .to_token_stream() - } else { - syn::parse_str::(&format!("{}::{}", proto_path, self.output_type)) - .unwrap() - .to_token_stream() + let convert_type = |proto_type: &str, rust_type: &str| -> TokenStream { + if (is_google_type(proto_type) && !compile_well_known_types) + || rust_type.starts_with("::") + || NON_PATH_TYPE_ALLOWLIST.iter().any(|ty| *ty == rust_type) + { + rust_type.parse::().unwrap() + } else if rust_type.starts_with("crate::") { + syn::parse_str::(rust_type) + .unwrap() + .to_token_stream() + } else { + syn::parse_str::(&format!("{}::{}", proto_path, rust_type)) + .unwrap() + .to_token_stream() + } }; + let request = convert_type(&self.input_proto_type, &self.input_type); + let response = convert_type(&self.output_proto_type, &self.output_type); (request, response) } }