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

Proposal: Use Symbol for trait impls #2073

Open
KSXGitHub opened this issue Apr 7, 2020 · 6 comments · May be fixed by #2871
Open

Proposal: Use Symbol for trait impls #2073

KSXGitHub opened this issue Apr 7, 2020 · 6 comments · May be fixed by #2871

Comments

@KSXGitHub
Copy link
Contributor

KSXGitHub commented Apr 7, 2020

Motivation

Currently, #[wasm_bindgen] cannot be applied to trait impls, I guess this is to avoid method name collision? If that is the case, then JavaScript Symbol is a perfect solution for this.

Proposed Solution

Convert trait methods to JavaScript methods with symbols for names, and trait names can be converted to a namespace object of symbols. For example:

This code:

// src/lib.rs
use wasm_bindgen::prelude::*;

#[wasm_bindgen]
pub struct Foo {
    value: i32,
}

#[wasm_bindgen]
impl Foo {
    #[wasm_bindgen(constructor)]
    pub fn new(value: i32) -> Self {
        Foo { value }
    }

    #[wasm_bindgen]
    pub fn read(&self) -> i32 {
        self.value
    }
}

#[wasm_bingen]
trait Read {
    fn read(&self) -> i32;
}

#[wasm_bindgen]
impl Read for Foo {
    #[wasm_bindgen]
    fn read(&self) -> i32 {
        self.value
    }
}

can be converted to this TypeScript declaration:

// from Read trait in the Rust source
// all Rust structs that impl Read trait will be converted to TypeScript classes that implements Read interface
export interface Read {
  // from Read::read in the Rust source
  [Read.read](this: this): number
}

// from Read trait in the Rust source
// namespaces in TypeScript are just objects in JavaScript
export declare namespace Read {
  // from Read::read in the Rust source
  const read: unique symbol;
  type read = typeof read;
}

export declare class Foo implements Read {
  public constructor(value: number);
  public read(this: Foo): number;

  // from Read::read in the Rust source
  public [Read.read](this: this): number;
}

Note

In the JavaScript glue code, Read object must always be created before class Foo.

Alternatives

Additional Context

@alexcrichton
Copy link
Contributor

Currently there isn't support for traits mostly because no one's worked on it yet, not necesesarily because of symbol collisions. Implementing this seems fine to me though, and I'd be curious to see what it would look like!

@ImUrX
Copy link

ImUrX commented Sep 9, 2020

I have a lot of interwined enums, and enums cant have methods for wasm_bindgen, so this for simplifying a lot of utils would be awesome

@mariannegoldin
Copy link

mariannegoldin commented Oct 9, 2020

Tl;dr: Looking for a mentor for a first open source contribution for this issue

I am new to wasm and have been learning about wasm-bindgen. I’ve been focusing on using wasm-bindgen to port types over to JavaScript so that Rust libraries that can be used in the front-end. The goal is to produce front-end compatible classes to handle monetary values, similar to those supported in a Go Money library.

I would like to work on this issue, however, I am new to the level of engineering (virtual machine, assembly code) that this effort would likely entail. I have more experience as an implementor of existing Rust libraries and this would be my first Rust open source contribution.

Would anyone in the be interested in mentoring/pairing on this effort with me?

Thanks!
Marianne
(Rust Discord @nini_raviolette)

@KSXGitHub
Copy link
Contributor Author

@ImUrX

I have a lot of interwined enums, and enums cant have methods for wasm_bindgen, so this for simplifying a lot of utils would be awesome

Technically speaking, methods are just function that get called in a weird way (there are no methods in Haskell, only functions, even for "traits"). But it was wasm_bindgen decision to convert Rust impl/trait functions in Rust to methods in JavaScript.

@shahzeb1
Copy link

It's been 4 years since this issue. Would be great to be able to use wasm_bindgen with impl+trait.

I assume this isn't being worked on anywhere?

@haraldreingruber-dedalus
Copy link
Contributor

This might also be related to this discussion: #3254

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

Successfully merging a pull request may close this issue.

6 participants