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

Make getters, setters, and constructors compiler errors for enums #4278

Merged
Merged
Changes from 1 commit
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
ad495c9
Make `getter`s, `setter`s, and `constructor`s compiler errors for enums
RunDevelopment Nov 18, 2024
e967962
Better error messages
RunDevelopment Nov 18, 2024
888ead1
rustfmt
RunDevelopment Nov 18, 2024
77c3696
Merge branch 'main' into error-enum-getter-setter-constructor
RunDevelopment Nov 29, 2024
f07b885
Add `rustversion` and `diagnostic` feature
RunDevelopment Nov 29, 2024
526400f
Different code gen for static asserts
RunDevelopment Nov 29, 2024
81f2d43
Use Rust 1.78.0 to run UI tests
RunDevelopment Nov 29, 2024
9342b6d
Fixed span
RunDevelopment Nov 29, 2024
0f75414
Updated other ui tests
RunDevelopment Nov 29, 2024
95715ec
Export marker traits under `::__rt::marker`
RunDevelopment Nov 29, 2024
4a83589
Merge branch 'main' into error-enum-getter-setter-constructor
RunDevelopment Dec 7, 2024
053c60e
Feature suggestions
RunDevelopment Dec 7, 2024
db953cc
Shared check struct
RunDevelopment Dec 7, 2024
ed462cc
Fixed main debug warning
RunDevelopment Dec 7, 2024
6ac1419
Terser error messages
RunDevelopment Dec 7, 2024
2802d40
Removed `extern crate rustversion`
RunDevelopment Dec 8, 2024
9355f5c
Merge branch 'main' into error-enum-getter-setter-constructor
RunDevelopment Dec 8, 2024
49f6c4d
Move `marker.rs` file under `rt`
RunDevelopment Dec 8, 2024
7512b07
Document `msrv` feature
RunDevelopment Dec 8, 2024
5e461ff
Remove useless `automatically_derived`
RunDevelopment Dec 8, 2024
bd9f847
Updated UI tests
RunDevelopment Dec 8, 2024
80ab2ef
Update changelog
RunDevelopment Dec 8, 2024
b240d26
Apply suggestions from code review
RunDevelopment Dec 8, 2024
e1d2358
Test MSRV and resolver v1 of new crate feature
daxpedda Dec 8, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Make getters, setters, and constructors compiler errors for enums
RunDevelopment committed Nov 18, 2024
commit ad495c9bf274cbf280938330a8255bbbb7307a44
51 changes: 46 additions & 5 deletions crates/backend/src/codegen.rs
Original file line number Diff line number Diff line change
@@ -224,6 +224,13 @@ impl ToTokens for ast::Struct {
let unwrap_fn = Ident::new(&shared::unwrap_function(&name_str), Span::call_site());
let wasm_bindgen = &self.wasm_bindgen;
(quote! {
#[automatically_derived]
impl #wasm_bindgen::marker::SupportsConstructor for #name {}
#[automatically_derived]
impl #wasm_bindgen::marker::SupportsInstanceProperty for #name {}
#[automatically_derived]
impl #wasm_bindgen::marker::SupportsStaticProperty for #name {}

#[automatically_derived]
impl #wasm_bindgen::describe::WasmDescribe for #name {
fn describe() {
@@ -780,12 +787,43 @@ impl TryToTokens for ast::Export {
let nargs = self.function.arguments.len() as u32;
let attrs = &self.function.rust_attrs;

let start_check = if self.start {
quote! { const _ASSERT: fn() = || -> #projection::Abi { loop {} }; }
} else {
quote! {}
let mut checks = Vec::new();
if self.start {
checks.push(quote! { const _ASSERT: fn() = || -> #projection::Abi { loop {} }; });
};

if let Some(class) = self.rust_class.as_ref() {
// change span of class, so it points to the location of the
// function causing the assert to fail
let mut class = class.clone();
class.set_span(self.rust_name.span());

match &self.method_kind {
ast::MethodKind::Constructor => {
checks.push(quote! {
const fn assert_supports_constructor<T: #wasm_bindgen::marker::SupportsConstructor>() {}
assert_supports_constructor::<#class>();
});
}
ast::MethodKind::Operation(operation) => match operation.kind {
ast::OperationKind::Getter(_) | ast::OperationKind::Setter(_) => {
if operation.is_static {
checks.push(quote! {
const fn assert_supports_static_property<T: #wasm_bindgen::marker::SupportsStaticProperty>() {}
assert_supports_static_property::<#class>();
});
} else {
checks.push(quote! {
const fn assert_supports_instance_property<T: #wasm_bindgen::marker::SupportsInstanceProperty>() {}
assert_supports_instance_property::<#class>();
});
}
}
_ => {}
},
}
}

(quote! {
#[automatically_derived]
const _: () = {
@@ -796,7 +834,10 @@ impl TryToTokens for ast::Export {
)]
#[cfg_attr(wasm_bindgen_unstable_test_coverage, coverage(off))]
pub unsafe extern "C" fn #generated_name(#(#args),*) -> #wasm_bindgen::convert::WasmRet<#projection::Abi> {
#start_check
#[automatically_derived]
const _: () = {
#(#checks)*
};

let #ret = #call;
#convert_ret
73 changes: 73 additions & 0 deletions crates/macro/ui-tests/unsupported-options.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
use wasm_bindgen::prelude::*;

#[wasm_bindgen]
pub struct RustStruct {
data: u32,
}

#[wasm_bindgen]
impl RustStruct {
pub fn instance_method(&self) {}
fn priv_instance_method(&self) {}

#[wasm_bindgen(constructor)]
pub fn new() -> Self {
Self { data: 0 }
}

#[wasm_bindgen(getter)]
pub fn prop(self) -> u32 {
32
}
#[wasm_bindgen(setter)]
pub fn set_prop(self, _value: u32) {}

#[wasm_bindgen(getter)]
pub fn static_prop() -> u32 {
32
}
#[wasm_bindgen(setter)]
pub fn set_static_prop(_value: u32) {}

#[wasm_bindgen(indexing_getter)]
pub fn indexing_getter(self) -> u32 {
32
}
#[wasm_bindgen(indexing_setter)]
pub fn indexing_setter(self, _value: u32) {}
#[wasm_bindgen(indexing_deleter)]
pub fn indexing_deleter(self, _value: u32) {}
}

#[wasm_bindgen]
pub enum RustEnum {
A = 0,
B = 1,
}

#[wasm_bindgen]
impl RustEnum {
pub fn instance_method(self) {}
fn priv_instance_method(self) {}

#[wasm_bindgen(constructor)]
pub fn new() -> Self {
Self::A
}

#[wasm_bindgen(getter)]
pub fn prop(self) -> u32 {
32
}
#[wasm_bindgen(setter)]
pub fn set_prop(self, _value: u32) {}

#[wasm_bindgen(getter)]
pub fn static_prop() -> u32 {
32
}
#[wasm_bindgen(setter)]
pub fn set_static_prop(_value: u32) {}
}

fn main() {}
75 changes: 75 additions & 0 deletions crates/macro/ui-tests/unsupported-options.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
error[E0277]: JavaScript constructors are not supported for `RustEnum`
--> ui-tests/unsupported-options.rs:54:12
|
54 | pub fn new() -> Self {
| ^^^ the trait `SupportsConstructor` is not implemented for `RustEnum`
|
= note: `#[wasm_bindgen(constructor)]` is generally only supported for `struct`s with `#[wasm_bindgen]` and cannot be used for `enum`s.
= note: Consider removing the `constructor` option and using a regular static method instead.
= help: the trait `SupportsConstructor` is implemented for `RustStruct`
note: required by a bound in `__wasm_bindgen_generated_RustEnum_new::_::assert_supports_constructor`
--> ui-tests/unsupported-options.rs:48:1
|
48 | #[wasm_bindgen]
| ^^^^^^^^^^^^^^^ required by this bound in `assert_supports_constructor`
= note: this error originates in the attribute macro `wasm_bindgen` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0277]: JavaScript instance getters and setters are not supported for `RustEnum`
--> ui-tests/unsupported-options.rs:59:12
|
59 | pub fn prop(self) -> u32 {
| ^^^^ the trait `SupportsInstanceProperty` is not implemented for `RustEnum`
|
= note: `#[wasm_bindgen(getter)]` and `#[wasm_bindgen(setter)]` are generally only supported for `struct`s with `#[wasm_bindgen]`. They cannot be used for `enum`s.
= help: the trait `SupportsInstanceProperty` is implemented for `RustStruct`
note: required by a bound in `__wasm_bindgen_generated_RustEnum_prop::_::assert_supports_instance_property`
--> ui-tests/unsupported-options.rs:48:1
|
48 | #[wasm_bindgen]
| ^^^^^^^^^^^^^^^ required by this bound in `assert_supports_instance_property`
= note: this error originates in the attribute macro `wasm_bindgen` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0277]: JavaScript instance getters and setters are not supported for `RustEnum`
--> ui-tests/unsupported-options.rs:63:12
|
63 | pub fn set_prop(self, _value: u32) {}
| ^^^^^^^^ the trait `SupportsInstanceProperty` is not implemented for `RustEnum`
|
= note: `#[wasm_bindgen(getter)]` and `#[wasm_bindgen(setter)]` are generally only supported for `struct`s with `#[wasm_bindgen]`. They cannot be used for `enum`s.
= help: the trait `SupportsInstanceProperty` is implemented for `RustStruct`
note: required by a bound in `__wasm_bindgen_generated_RustEnum_set_prop::_::assert_supports_instance_property`
--> ui-tests/unsupported-options.rs:48:1
|
48 | #[wasm_bindgen]
| ^^^^^^^^^^^^^^^ required by this bound in `assert_supports_instance_property`
= note: this error originates in the attribute macro `wasm_bindgen` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0277]: JavaScript static getters and setters are not supported for `RustEnum`
--> ui-tests/unsupported-options.rs:66:12
|
66 | pub fn static_prop() -> u32 {
| ^^^^^^^^^^^ the trait `SupportsStaticProperty` is not implemented for `RustEnum`
|
= note: `#[wasm_bindgen(getter)]` and `#[wasm_bindgen(setter)]` are generally only supported for `struct`s with `#[wasm_bindgen]`. They cannot be used for `enum`s.
= help: the trait `SupportsStaticProperty` is implemented for `RustStruct`
note: required by a bound in `__wasm_bindgen_generated_RustEnum_static_prop::_::assert_supports_static_property`
--> ui-tests/unsupported-options.rs:48:1
|
48 | #[wasm_bindgen]
| ^^^^^^^^^^^^^^^ required by this bound in `assert_supports_static_property`
= note: this error originates in the attribute macro `wasm_bindgen` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0277]: JavaScript static getters and setters are not supported for `RustEnum`
--> ui-tests/unsupported-options.rs:70:12
|
70 | pub fn set_static_prop(_value: u32) {}
| ^^^^^^^^^^^^^^^ the trait `SupportsStaticProperty` is not implemented for `RustEnum`
|
= note: `#[wasm_bindgen(getter)]` and `#[wasm_bindgen(setter)]` are generally only supported for `struct`s with `#[wasm_bindgen]`. They cannot be used for `enum`s.
= help: the trait `SupportsStaticProperty` is implemented for `RustStruct`
note: required by a bound in `__wasm_bindgen_generated_RustEnum_set_static_prop::_::assert_supports_static_property`
--> ui-tests/unsupported-options.rs:48:1
|
48 | #[wasm_bindgen]
| ^^^^^^^^^^^^^^^ required by this bound in `assert_supports_static_property`
= note: this error originates in the attribute macro `wasm_bindgen` (in Nightly builds, run with -Z macro-backtrace for more info)
7 changes: 4 additions & 3 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -16,7 +16,7 @@ use alloc::boxed::Box;
use alloc::string::String;
use alloc::vec::Vec;
use core::convert::TryFrom;
use core::marker;
use core::marker::PhantomData;
use core::mem;
use core::ops::{
Add, BitAnd, BitOr, BitXor, Deref, DerefMut, Div, Mul, Neg, Not, Rem, Shl, Shr, Sub,
@@ -71,6 +71,7 @@ pub use wasm_bindgen_macro::link_to;
pub mod closure;
pub mod convert;
pub mod describe;
pub mod marker;
mod link;

mod cast;
@@ -92,7 +93,7 @@ if_std! {
/// but for now it may be slightly slow.
pub struct JsValue {
idx: u32,
_marker: marker::PhantomData<*mut u8>, // not at all threadsafe
_marker: PhantomData<*mut u8>, // not at all threadsafe
}

const JSIDX_OFFSET: u32 = 128; // keep in sync with js/mod.rs
@@ -119,7 +120,7 @@ impl JsValue {
const fn _new(idx: u32) -> JsValue {
JsValue {
idx,
_marker: marker::PhantomData,
_marker: PhantomData,
}
}

58 changes: 58 additions & 0 deletions src/marker.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
//! This module contains marker traits used by `wasm-bindgen` to verify its
//! generated code.
//!
//! # ⚠️ Unstable
//!
//! This is an internal module, no stability guarantees are provided. Use at
//! your own risk.

/// Marker trait for types that support `#[wasm_bindgen(constructor)]`.
///
/// **DO NOT** implement this trait manually. It is implemented automatically
/// for types that support constructors.
///
/// # ⚠️ Unstable
///
/// This is part of the internal [`convert`](crate::marker) module, **no
/// stability guarantees** are provided. Use at your own risk. See its
/// documentation for more details.
#[diagnostic::on_unimplemented(
message = "JavaScript constructors are not supported for `{Self}`",
note = "`#[wasm_bindgen(constructor)]` is generally only supported for `struct`s with `#[wasm_bindgen]` and cannot be used for `enum`s.",
note = "Consider removing the `constructor` option and using a regular static method instead.",
)]
pub trait SupportsConstructor {}

/// Marker trait for types that support `#[wasm_bindgen(getter)]` or
/// `#[wasm_bindgen(Setter)]` on instance methods.
///
/// **DO NOT** implement this trait manually. It is implemented automatically
/// for types that support instance properties.
///
/// # ⚠️ Unstable
///
/// This is part of the internal [`convert`](crate::marker) module, **no
/// stability guarantees** are provided. Use at your own risk. See its
/// documentation for more details.
#[diagnostic::on_unimplemented(
message = "JavaScript instance getters and setters are not supported for `{Self}`",
note = "`#[wasm_bindgen(getter)]` and `#[wasm_bindgen(setter)]` are generally only supported for `struct`s with `#[wasm_bindgen]`. They cannot be used for `enum`s.",
)]
pub trait SupportsInstanceProperty {}

/// Marker trait for types that support `#[wasm_bindgen(getter)]` or
/// `#[wasm_bindgen(Setter)]` on static methods.
///
/// **DO NOT** implement this trait manually. It is implemented automatically
/// for types that support static properties.
///
/// # ⚠️ Unstable
///
/// This is part of the internal [`convert`](crate::marker) module, **no
/// stability guarantees** are provided. Use at your own risk. See its
/// documentation for more details.
#[diagnostic::on_unimplemented(
message = "JavaScript static getters and setters are not supported for `{Self}`",
note = "`#[wasm_bindgen(getter)]` and `#[wasm_bindgen(setter)]` are generally only supported for `struct`s with `#[wasm_bindgen]`. They cannot be used for `enum`s.",
)]
pub trait SupportsStaticProperty {}