Skip to content

Commit

Permalink
Support custom derives on Request and Response (#438)
Browse files Browse the repository at this point in the history
Replace the bespoke "derive_serde" with a more flexible
"derive = [<path>, <path>, ...]" form.

Deprecate the old "derive_serde" form, and emit deprecation warnings.
  • Loading branch information
ShaneMurphy2 committed Mar 9, 2024
1 parent 67cb619 commit 160b561
Show file tree
Hide file tree
Showing 13 changed files with 411 additions and 66 deletions.
309 changes: 244 additions & 65 deletions plugins/src/lib.rs

Large diffs are not rendered by default.

53 changes: 52 additions & 1 deletion plugins/tests/service.rs
@@ -1,3 +1,5 @@
use serde::{Deserialize, Serialize};
use std::hash::Hash;
use tarpc::context;

#[test]
Expand Down Expand Up @@ -72,7 +74,6 @@ fn service_with_cfg_rpc() {

#[test]
fn syntax() {
#[tarpc::service]
trait Syntax {
#[deny(warnings)]
#[allow(non_snake_case)]
Expand All @@ -92,3 +93,53 @@ fn syntax() {
async fn one_arg_implicit_return_error(one: String);
}
}

#[test]
fn custom_derives() {
#[tarpc::service(derive = [Clone, Hash])]
trait Foo {
async fn foo();
}

fn requires_clone(_: impl Clone) {}
fn requires_hash(_: impl Hash) {}

let x = FooRequest::Foo {};
requires_clone(x.clone());
requires_hash(x);
}

#[test]
fn implicit_serde() {
#[tarpc::service]
trait Foo {
async fn foo();
}

fn requires_serde<T>(_: T)
where
for<'de> T: Serialize + Deserialize<'de>,
{
}

let x = FooRequest::Foo {};
requires_serde(x);
}

#[allow(deprecated)]
#[test]
fn explicit_serde() {
#[tarpc::service(derive_serde = true)]
trait Foo {
async fn foo();
}

fn requires_serde<T>(_: T)
where
for<'de> T: Serialize + Deserialize<'de>,
{
}

let x = FooRequest::Foo {};
requires_serde(x);
}
4 changes: 4 additions & 0 deletions tarpc/tests/compile_fail.rs
Expand Up @@ -4,4 +4,8 @@ fn ui() {
t.compile_fail("tests/compile_fail/*.rs");
#[cfg(all(feature = "serde-transport", feature = "tcp"))]
t.compile_fail("tests/compile_fail/serde_transport/*.rs");
#[cfg(not(feature = "serde1"))]
t.compile_fail("tests/compile_fail/no_serde1/*.rs");
#[cfg(feature = "serde1")]
t.compile_fail("tests/compile_fail/serde1/*.rs");
}
@@ -0,0 +1,9 @@
#[tarpc::service(derive_serde = true)]
trait Foo {
async fn foo();
}

fn main() {
let x = FooRequest::Foo {};
x.serialize();
}
@@ -0,0 +1,11 @@
error: To enable serde, first enable the `serde1` feature of tarpc
--> tests/compile_fail/no_serde1/no_explicit_serde_without_feature.rs:1:18
|
1 | #[tarpc::service(derive_serde = true)]
| ^^^^^^^^^^^^

error[E0433]: failed to resolve: use of undeclared type `FooRequest`
--> tests/compile_fail/no_serde1/no_explicit_serde_without_feature.rs:7:13
|
7 | let x = FooRequest::Foo {};
| ^^^^^^^^^^ use of undeclared type `FooRequest`
@@ -0,0 +1,9 @@
#[tarpc::service]
trait Foo {
async fn foo();
}

fn main() {
let x = FooRequest::Foo {};
x.serialize();
}
@@ -0,0 +1,12 @@
error[E0599]: no method named `serialize` found for enum `FooRequest` in the current scope
--> tests/compile_fail/no_serde1/no_implicit_serde_without_feature.rs:8:7
|
1 | #[tarpc::service]
| ----------------- method `serialize` not found for this enum
...
8 | x.serialize();
| ^^^^^^^^^ method not found in `FooRequest`
|
= help: items from traits can only be used if the trait is implemented and in scope
= note: the following trait defines an item `serialize`, perhaps you need to implement it:
candidate #1: `serde::ser::Serialize`
8 changes: 8 additions & 0 deletions tarpc/tests/compile_fail/serde1/deprecated.rs
@@ -0,0 +1,8 @@
#![deny(warnings)]

#[tarpc::service(derive_serde = true)]
trait Foo {
async fn foo();
}

fn main() {}
15 changes: 15 additions & 0 deletions tarpc/tests/compile_fail/serde1/deprecated.stderr
@@ -0,0 +1,15 @@
error: use of deprecated constant `_::DEPRECATED_SYNTAX`:
The form `tarpc::service(derive_serde = true)` is deprecated.
Use `tarpc::service(derive = [Serialize, Deserialize])`.
--> tests/compile_fail/serde1/deprecated.rs:3:1
|
3 | #[tarpc::service(derive_serde = true)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: the lint level is defined here
--> tests/compile_fail/serde1/deprecated.rs:1:9
|
1 | #![deny(warnings)]
| ^^^^^^^^
= note: `#[deny(deprecated)]` implied by `#[deny(warnings)]`
= note: this error originates in the attribute macro `tarpc::service` (in Nightly builds, run with -Z macro-backtrace for more info)
7 changes: 7 additions & 0 deletions tarpc/tests/compile_fail/serde1/incompatible.rs
@@ -0,0 +1,7 @@
#![allow(deprecated)]
#[tarpc::service(derive = [Clone], derive_serde = true)]
trait Foo {
async fn foo();
}

fn main() {}
7 changes: 7 additions & 0 deletions tarpc/tests/compile_fail/serde1/incompatible.stderr
@@ -0,0 +1,7 @@
error: tarpc does not support `derive_serde` and `derive` at the same time
--> tests/compile_fail/serde1/incompatible.rs:2:1
|
2 | #[tarpc::service(derive = [Clone], derive_serde = true)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: this error originates in the attribute macro `tarpc::service` (in Nightly builds, run with -Z macro-backtrace for more info)
15 changes: 15 additions & 0 deletions tarpc/tests/compile_fail/serde1/opt_out_serde.rs
@@ -0,0 +1,15 @@
#![allow(deprecated)]

use std::fmt::Formatter;

#[tarpc::service(derive_serde = false)]
trait Foo {
async fn foo();
}

fn foo(f: &mut Formatter) {
let x = FooRequest::Foo {};
tarpc::serde::Serialize::serialize(&x, f);
}

fn main() {}
18 changes: 18 additions & 0 deletions tarpc/tests/compile_fail/serde1/opt_out_serde.stderr
@@ -0,0 +1,18 @@
error[E0277]: the trait bound `FooRequest: Serialize` is not satisfied
--> tests/compile_fail/serde1/opt_out_serde.rs:12:40
|
12 | tarpc::serde::Serialize::serialize(&x, f);
| ---------------------------------- ^^ the trait `Serialize` is not implemented for `FooRequest`
| |
| required by a bound introduced by this call
|
= help: the following other types implement trait `Serialize`:
bool
char
isize
i8
i16
i32
i64
i128
and $N others

0 comments on commit 160b561

Please sign in to comment.