diff --git a/derive/src/to_delegate.rs b/derive/src/to_delegate.rs index 870da9c88..b4d2073c6 100644 --- a/derive/src/to_delegate.rs +++ b/derive/src/to_delegate.rs @@ -336,12 +336,14 @@ fn is_option_type(ty: &syn::Type) -> bool { } fn generate_where_clause_serialization_predicates(item_trait: &syn::ItemTrait) -> Vec { + #[derive(Default)] struct FindTyParams { trait_generics: HashSet, serialize_type_params: HashSet, deserialize_type_params: HashSet, visiting_return_type: bool, visiting_fn_arg: bool, + visiting_subscriber_arg: bool, } impl<'ast> Visit<'ast> for FindTyParams { fn visit_type_param(&mut self, ty_param: &'ast syn::TypeParam) { @@ -356,10 +358,14 @@ fn generate_where_clause_serialization_predicates(item_trait: &syn::ItemTrait) - if self.visiting_return_type && self.trait_generics.contains(&segment.ident) { self.serialize_type_params.insert(segment.ident.clone()); } - if self.visiting_fn_arg && self.trait_generics.contains(&segment.ident) { + if self.visiting_fn_arg && + self.trait_generics.contains(&segment.ident) && + !self.visiting_subscriber_arg { self.deserialize_type_params.insert(segment.ident.clone()); } - visit::visit_path_segment(self, segment) + self.visiting_subscriber_arg = self.visiting_fn_arg && segment.ident == SUBCRIBER_TYPE_IDENT; + visit::visit_path_segment(self, segment); + self.visiting_subscriber_arg = false; } fn visit_fn_arg(&mut self, arg: &'ast syn::FnArg) { self.visiting_fn_arg = true; @@ -367,13 +373,7 @@ fn generate_where_clause_serialization_predicates(item_trait: &syn::ItemTrait) - self.visiting_fn_arg = false; } } - let mut visitor = FindTyParams { - visiting_return_type: false, - visiting_fn_arg: false, - trait_generics: HashSet::new(), - serialize_type_params: HashSet::new(), - deserialize_type_params: HashSet::new(), - }; + let mut visitor = FindTyParams::default(); visitor.visit_item_trait(item_trait); item_trait.generics diff --git a/derive/tests/compiletests.rs b/derive/tests/compiletests.rs index 60d493da1..00ca38cf9 100644 --- a/derive/tests/compiletests.rs +++ b/derive/tests/compiletests.rs @@ -7,7 +7,11 @@ fn run_mode(mode: &'static str) { config.mode = mode.parse().expect("Invalid mode"); config.src_base = PathBuf::from(format!("tests/{}", mode)); - config.target_rustcflags = Some("-L ../target/debug/ -L ../target/debug/deps/".to_owned()); + config.target_rustcflags = Some(String::from( + "\ + -L ../target/debug/ \ + -L ../target/debug/deps/ \ + ")); config.clean_rmeta(); // If your tests import the parent crate, this helps with E0464 compiletest::run_tests(&config); @@ -16,4 +20,5 @@ fn run_mode(mode: &'static str) { #[test] fn compile_test() { run_mode("ui"); + run_mode("run-pass"); } diff --git a/derive/tests/run-pass/pubsub-subscription-type-without-deserialize.rs b/derive/tests/run-pass/pubsub-subscription-type-without-deserialize.rs new file mode 100644 index 000000000..af012656d --- /dev/null +++ b/derive/tests/run-pass/pubsub-subscription-type-without-deserialize.rs @@ -0,0 +1,49 @@ +extern crate serde; +#[macro_use] +extern crate serde_derive; +extern crate jsonrpc_core; +extern crate jsonrpc_pubsub; +#[macro_use] +extern crate jsonrpc_derive; + +use std::sync::Arc; +use jsonrpc_core::Result; +use jsonrpc_pubsub::{typed::Subscriber, SubscriptionId, Session, PubSubHandler}; + +#[rpc] +pub trait Rpc { + type Metadata; + + /// Hello subscription + #[pubsub(subscription = "hello", subscribe, name = "hello_subscribe", alias("hello_sub"))] + fn subscribe(&self, _: Self::Metadata, _: Subscriber); + + /// Unsubscribe from hello subscription. + #[pubsub(subscription = "hello", unsubscribe, name = "hello_unsubscribe")] + fn unsubscribe(&self, _: Option, _: SubscriptionId) -> Result; +} + +// One way serialization +#[derive(Serialize)] +struct SerializeOnly { + foo: String, +} + +struct RpcImpl; +impl Rpc for RpcImpl { + type Metadata = Arc; + + fn subscribe(&self, _: Self::Metadata, _: Subscriber) { + unimplemented!(); + } + + fn unsubscribe(&self, _: Option, _: SubscriptionId) -> Result { + unimplemented!(); + } +} + +fn main() { + let mut io = PubSubHandler::default(); + let rpc = RpcImpl; + io.extend_with(rpc.to_delegate()); +}