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

Proposal: Use Symbol for trait impls

Open KSXGitHub opened this issue 5 years ago • 6 comments

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

KSXGitHub avatar Apr 07 '20 04:04 KSXGitHub

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!

alexcrichton avatar Apr 09 '20 15:04 alexcrichton

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

ImUrX avatar Sep 09 '20 10:09 ImUrX

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)

mariannegoldin avatar Oct 09 '20 17:10 mariannegoldin

@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.

KSXGitHub avatar Oct 10 '20 01:10 KSXGitHub

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?

shahzeb1 avatar Mar 21 '24 19:03 shahzeb1

This might also be related to this discussion: https://github.com/rustwasm/wasm-bindgen/discussions/3254