Make getter
s, setter
s, and constructor
s compiler errors for enums
#4278
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This PR implements a compile-time check to verify that enums have no methods with
#[wasm_bindgen(getter)]
,#[wasm_bindgen(setter)]
, and#[wasm_bindgen(constructor)]
. This was previously accepted and resulted in incorrect JS code gen.The check is implemented like I outlined in this comment. There are 3 new internal marker traits (
SupportsConstructor
,SupportsInstanceProperty
,SupportsStaticProperty
) that are implemented bystruct
s with#[wasm_bindgen]
and notenum
s. Exported function then generate aconst _: ()
that checks whether theSelf
type (if any) implements those traits. I useddiagnostic::on_unimplemented
to make the trait errors easily understandable for users.Example error for using
#[wasm_bindgen(constructor)]
on an enum calledRustEnum
:As we can see, the error message is clear and even offers a suggestion to fix the error.
This PR is virtually a minimal implementation of a technique we could use a lot more. E.g. it can be used to verify that the
Self
type actually has a#[wasm_bindgen]
macro (the test file I added includes an example where exactly this case does not cause an error). However, I kept it minimal so we can concentrate on the "how" this PR does things.As for the how: I initially wanted to add just a single trait (something like
IsStruct
) and then let constructors/getters/setters/etc. assert that they are on a struct. This did work, but resulted in error messages that were a lot worse. By using traits that describe the capabilities of the type and not what the type is, error messages can be a lot more specific. Plus, adding/removing/changing capabilities seems easier at scale.