Skip to content

Commit 160b561

Browse files
authored
Support custom derives on Request and Response (#438)
Replace the bespoke "derive_serde" with a more flexible "derive = [<path>, <path>, ...]" form. Deprecate the old "derive_serde" form, and emit deprecation warnings.
1 parent 67cb619 commit 160b561

13 files changed

+411
-66
lines changed

plugins/src/lib.rs

+244-65
Large diffs are not rendered by default.

plugins/tests/service.rs

+52-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use serde::{Deserialize, Serialize};
2+
use std::hash::Hash;
13
use tarpc::context;
24

35
#[test]
@@ -72,7 +74,6 @@ fn service_with_cfg_rpc() {
7274

7375
#[test]
7476
fn syntax() {
75-
#[tarpc::service]
7677
trait Syntax {
7778
#[deny(warnings)]
7879
#[allow(non_snake_case)]
@@ -92,3 +93,53 @@ fn syntax() {
9293
async fn one_arg_implicit_return_error(one: String);
9394
}
9495
}
96+
97+
#[test]
98+
fn custom_derives() {
99+
#[tarpc::service(derive = [Clone, Hash])]
100+
trait Foo {
101+
async fn foo();
102+
}
103+
104+
fn requires_clone(_: impl Clone) {}
105+
fn requires_hash(_: impl Hash) {}
106+
107+
let x = FooRequest::Foo {};
108+
requires_clone(x.clone());
109+
requires_hash(x);
110+
}
111+
112+
#[test]
113+
fn implicit_serde() {
114+
#[tarpc::service]
115+
trait Foo {
116+
async fn foo();
117+
}
118+
119+
fn requires_serde<T>(_: T)
120+
where
121+
for<'de> T: Serialize + Deserialize<'de>,
122+
{
123+
}
124+
125+
let x = FooRequest::Foo {};
126+
requires_serde(x);
127+
}
128+
129+
#[allow(deprecated)]
130+
#[test]
131+
fn explicit_serde() {
132+
#[tarpc::service(derive_serde = true)]
133+
trait Foo {
134+
async fn foo();
135+
}
136+
137+
fn requires_serde<T>(_: T)
138+
where
139+
for<'de> T: Serialize + Deserialize<'de>,
140+
{
141+
}
142+
143+
let x = FooRequest::Foo {};
144+
requires_serde(x);
145+
}

tarpc/tests/compile_fail.rs

+4
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,8 @@ fn ui() {
44
t.compile_fail("tests/compile_fail/*.rs");
55
#[cfg(all(feature = "serde-transport", feature = "tcp"))]
66
t.compile_fail("tests/compile_fail/serde_transport/*.rs");
7+
#[cfg(not(feature = "serde1"))]
8+
t.compile_fail("tests/compile_fail/no_serde1/*.rs");
9+
#[cfg(feature = "serde1")]
10+
t.compile_fail("tests/compile_fail/serde1/*.rs");
711
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#[tarpc::service(derive_serde = true)]
2+
trait Foo {
3+
async fn foo();
4+
}
5+
6+
fn main() {
7+
let x = FooRequest::Foo {};
8+
x.serialize();
9+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
error: To enable serde, first enable the `serde1` feature of tarpc
2+
--> tests/compile_fail/no_serde1/no_explicit_serde_without_feature.rs:1:18
3+
|
4+
1 | #[tarpc::service(derive_serde = true)]
5+
| ^^^^^^^^^^^^
6+
7+
error[E0433]: failed to resolve: use of undeclared type `FooRequest`
8+
--> tests/compile_fail/no_serde1/no_explicit_serde_without_feature.rs:7:13
9+
|
10+
7 | let x = FooRequest::Foo {};
11+
| ^^^^^^^^^^ use of undeclared type `FooRequest`
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#[tarpc::service]
2+
trait Foo {
3+
async fn foo();
4+
}
5+
6+
fn main() {
7+
let x = FooRequest::Foo {};
8+
x.serialize();
9+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
error[E0599]: no method named `serialize` found for enum `FooRequest` in the current scope
2+
--> tests/compile_fail/no_serde1/no_implicit_serde_without_feature.rs:8:7
3+
|
4+
1 | #[tarpc::service]
5+
| ----------------- method `serialize` not found for this enum
6+
...
7+
8 | x.serialize();
8+
| ^^^^^^^^^ method not found in `FooRequest`
9+
|
10+
= help: items from traits can only be used if the trait is implemented and in scope
11+
= note: the following trait defines an item `serialize`, perhaps you need to implement it:
12+
candidate #1: `serde::ser::Serialize`
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#![deny(warnings)]
2+
3+
#[tarpc::service(derive_serde = true)]
4+
trait Foo {
5+
async fn foo();
6+
}
7+
8+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
error: use of deprecated constant `_::DEPRECATED_SYNTAX`:
2+
The form `tarpc::service(derive_serde = true)` is deprecated.
3+
Use `tarpc::service(derive = [Serialize, Deserialize])`.
4+
--> tests/compile_fail/serde1/deprecated.rs:3:1
5+
|
6+
3 | #[tarpc::service(derive_serde = true)]
7+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
8+
|
9+
note: the lint level is defined here
10+
--> tests/compile_fail/serde1/deprecated.rs:1:9
11+
|
12+
1 | #![deny(warnings)]
13+
| ^^^^^^^^
14+
= note: `#[deny(deprecated)]` implied by `#[deny(warnings)]`
15+
= note: this error originates in the attribute macro `tarpc::service` (in Nightly builds, run with -Z macro-backtrace for more info)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#![allow(deprecated)]
2+
#[tarpc::service(derive = [Clone], derive_serde = true)]
3+
trait Foo {
4+
async fn foo();
5+
}
6+
7+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
error: tarpc does not support `derive_serde` and `derive` at the same time
2+
--> tests/compile_fail/serde1/incompatible.rs:2:1
3+
|
4+
2 | #[tarpc::service(derive = [Clone], derive_serde = true)]
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6+
|
7+
= note: this error originates in the attribute macro `tarpc::service` (in Nightly builds, run with -Z macro-backtrace for more info)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#![allow(deprecated)]
2+
3+
use std::fmt::Formatter;
4+
5+
#[tarpc::service(derive_serde = false)]
6+
trait Foo {
7+
async fn foo();
8+
}
9+
10+
fn foo(f: &mut Formatter) {
11+
let x = FooRequest::Foo {};
12+
tarpc::serde::Serialize::serialize(&x, f);
13+
}
14+
15+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
error[E0277]: the trait bound `FooRequest: Serialize` is not satisfied
2+
--> tests/compile_fail/serde1/opt_out_serde.rs:12:40
3+
|
4+
12 | tarpc::serde::Serialize::serialize(&x, f);
5+
| ---------------------------------- ^^ the trait `Serialize` is not implemented for `FooRequest`
6+
| |
7+
| required by a bound introduced by this call
8+
|
9+
= help: the following other types implement trait `Serialize`:
10+
bool
11+
char
12+
isize
13+
i8
14+
i16
15+
i32
16+
i64
17+
i128
18+
and $N others

0 commit comments

Comments
 (0)