wit-bindgen icon indicating copy to clipboard operation
wit-bindgen copied to clipboard

Unable to use `serde` macros in `additional_derives` when importing `wasi::http` types

Open landonxjames opened this issue 1 year ago • 4 comments

I have a simple library testing out the wasi:http types. When I try to add an additional_derives: [serde::Serialize, serde::Deserialize] to the wit_bindgen::generate! macro definition I get the below error. Not sure if thise repo or the wasi-http repo would be better for this issue, but trying here first.

Reproduction can be found in this repo. Uncommenting this line will cause the error.

error[E0277]: the trait bound `wasi::io::error::Error: Deserialize<'_>` is not satisfied
    --> src/lib.rs:5:1
     |
5    | / wit_bindgen::generate!({
6    | | world: "wasi-http-tests",
7    | | exports: {
8    | |     "wasi-http-tests:component/client/wasi-http-tests-client": WasiHttpTestsClient,
9    | | },
10   | | additional_derives: [serde::Serialize, serde::Deserialize]
11   | | });
     | |__^ the trait `Deserialize<'_>` is not implemented for `wasi::io::error::Error`
     |
     = help: the following other types implement trait `Deserialize<'de>`:
               bool
               char
               isize
               i8
               i16
               i32
               i64
               i128
             and 137 others
note: required by a bound in `newtype_variant`
    --> /Users/lnj/.cargo/registry/src/index.crates.io-6f17d22bba15001f/serde-1.0.193/src/de/mod.rs:2119:12
     |
2117 |     fn newtype_variant<T>(self) -> Result<T, Self::Error>
     |        --------------- required by a bound in this associated function
2118 |     where
2119 |         T: Deserialize<'de>,
     |            ^^^^^^^^^^^^^^^^ required by this bound in `VariantAccess::newtype_variant`
     = note: this error originates in the macro `wit_bindgen::generate` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0277]: the trait bound `wasi::io::error::Error: Serialize` is not satisfied
   --> src/lib.rs:5:1
    |
5   | / wit_bindgen::generate!({
6   | | world: "wasi-http-tests",
7   | | exports: {
8   | |     "wasi-http-tests:component/client/wasi-http-tests-client": WasiHttpTestsClient,
9   | | },
10  | | additional_derives: [serde::Serialize, serde::Deserialize]
11  | | });
    | |__^ the trait `Serialize` is not implemented for `wasi::io::error::Error`
    |
    = help: the following other types implement trait `Serialize`:
              bool
              char
              isize
              i8
              i16
              i32
              i64
              i128
            and 136 others
note: required by a bound in `serialize_newtype_variant`
   --> /Users/lnj/.cargo/registry/src/index.crates.io-6f17d22bba15001f/serde-1.0.193/src/ser/mod.rs:936:12
    |
928 |     fn serialize_newtype_variant<T: ?Sized>(
    |        ------------------------- required by a bound in this associated function
...
936 |         T: Serialize;
    |            ^^^^^^^^^ required by this bound in `Serializer::serialize_newtype_variant`
    = note: this error originates in the macro `wit_bindgen::generate` (in Nightly builds, run with -Z macro-backtrace for more info)

landonxjames avatar Jan 10 '24 02:01 landonxjames

wasi::io::error::Error is a resource type, so it will never be able to impl Serialize or Deserialize. So, the bug here is that the derives are being applied to the type alias created for https://github.com/WebAssembly/wasi-http/blob/main/wit/types.wit#L7

pchickey avatar Jan 10 '24 04:01 pchickey

Another related bug I just encountered: When a variant contains a case and the type associated with that case is a resource the serde macros cause a build failure. So the following wit fails to build

resource perf-event {
    constructor();
    parse-string: func(input: string) -> result<some-event, string>;
  }

  resource constructor-perf-event {
    constructor(input: string);
    get-data: func() -> some-event;
  }

  variant supported-events {
    none,
    my-event(constructor-perf-event),
    foo(perf-event)
  }

  resource variant-perf-event {
    constructor(input: supported-events);
    get-child-event: func() -> supported-events;
  }

Due to the resource types not implementing Serialize.


error[E0277]: the trait bound `component::events::PerfEvent: Serialize` is not satisfied
   --> src/bindings.rs:601:46
    |
601 |                 #[derive(serde::Deserialize, serde::Serialize)]
    |                                              ^^^^^^^^^^^^^^^^ the trait `Serialize` is not implemented for `component::events::PerfEvent`
...
605 |                     Foo(PerfEvent),
    |                         -------------- required by a bound introduced by this call

I think this is further evidence to motivate some kind of attribute system in WIT so things like serde traits can be properly targeted to the correct types.

landonxjames avatar Mar 27 '24 21:03 landonxjames

wasi::io::error::Error is a resource type, so it will never be able to impl Serialize or Deserialize. So, the bug here is that the derives are being applied to the type alias created for https://github.com/WebAssembly/wasi-http/blob/main/wit/types.wit#L7

This is correct, if I add additional derives, I expect it to only be added to records and not custom resources, or at least a way to specify what resources not to apply to.

Is there any solution currently to using serde for types but ignoring for resources/ fixing for resources?

LUK3ARK avatar May 26 '24 13:05 LUK3ARK