Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Express "Duck-Typed Interface" as trait #1771

Closed
garrettmaring opened this issue Sep 18, 2019 · 4 comments
Closed

Express "Duck-Typed Interface" as trait #1771

garrettmaring opened this issue Sep 18, 2019 · 4 comments

Comments

@garrettmaring
Copy link

Motivation

To be able to use traits witn wasm-bindgen as an alternative to "Duck-Type Interface"s.

pub trait Quacks {
    fn quack(&self) -> String;
}

#[wasm_bindgen]
pub fn make_em_quack_to_this(duck: impl Quacks) {
    let _s = duck.quack();
}

Currently, this produces two errors:

  1. #[wasm_bindgen] can only be applied to a function, struct, enum, impl, or extern block

I'd love to here move about traits and wasm-bindgen. I've looked through several issues such as rustwasm/rfcs#11 but seem to be missing some likely longer discussion.

  1. the trait bound impl Quacks: wasm_bindgen::convert::traits::FromWasmAbi is not satisfied

Reading through https://docs.rs/wasm-bindgen/0.2.50/wasm_bindgen/convert/index.html it seems to as though implementing your own conversions is discouraged. It might be necessary to support traits like this but I am not sure.

I should note, is it possible to implement the various conversion traits for the example above? I'm wondering if it has been tried.

Proposed Solution

Enable the following example.

pub trait Quacks {
    fn quack(&self) -> String;
}

#[wasm_bindgen]
pub fn make_em_quack_to_this(duck: impl Quacks) {
    let _s = duck.quack();
}

The trait would generate a TypeScript interface called Quacks as well as a JavaScript object. This will likely need to leverage Closure.

Alternatives

Use the recommended "Duck-Typed Interface".

Additional Context

"Duck-Typed Interfaces" are defined in the docs as such:

#[wasm_bindgen]
extern "C" {
    pub type Quacks;

    #[wasm_bindgen(structural, method)]
    pub fn quack(this: &Quacks) -> String;
}

#[wasm_bindgen]
pub fn make_em_quack_to_this(duck: &Quacks) {
    let _s = duck.quack();
}
@alexcrichton
Copy link
Contributor

Thanks for the report here! I agree this would be pretty slick to support, but unfortunately I'm not sure how it would be possible to support. I think the best thing to do in lieu of it though is to use the duck-typed interface pattern, and does that work for your use case?

@garrettmaring
Copy link
Author

I'm able to use the duck-typed interface pattern for now 👍

In general, is a tricky for types like Box<dyn Quacks> to be supported in wasm? I'm curious about the future of traits and Box with WebAssembly.

@alexcrichton
Copy link
Contributor

Ok sounds good!

Unfortunately traits going back and forth aren't supported in wasm right now, and there's not a great way of passing in either a RUst argument or a JS argument to something like make_em_quack_to_this. For that you'd have to use a Rust-internal API which is trait bound, and use that from Rust instead.

@alexcrichton
Copy link
Contributor

I'm going to close this because we're unlikely to support trait objects going back and forth.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants