Skip to content

Commit 4770fab

Browse files
Add no_deref attribute to opt out of generating deref impls for imported types (#2652)
* Add `no_deref` attribute to opt out of `Deref` impl * Document `no_deref`
1 parent 41c22e6 commit 4770fab

File tree

4 files changed

+46
-9
lines changed

4 files changed

+46
-9
lines changed

crates/backend/src/ast.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,8 @@ pub struct ImportType {
261261
pub extends: Vec<syn::Path>,
262262
/// A custom prefix to add and attempt to fall back to, if the type isn't found
263263
pub vendor_prefixes: Vec<Ident>,
264+
/// If present, don't generate a `Deref` impl
265+
pub no_deref: bool,
264266
}
265267

266268
/// The metadata for an Enum being imported

crates/backend/src/codegen.rs

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -618,6 +618,8 @@ impl ToTokens for ast::ImportType {
618618
}
619619
});
620620

621+
let no_deref = self.no_deref;
622+
621623
(quote! {
622624
#[allow(bad_style)]
623625
#(#attrs)*
@@ -644,15 +646,6 @@ impl ToTokens for ast::ImportType {
644646
}
645647
}
646648

647-
impl core::ops::Deref for #rust_name {
648-
type Target = #internal_obj;
649-
650-
#[inline]
651-
fn deref(&self) -> &#internal_obj {
652-
&self.obj
653-
}
654-
}
655-
656649
impl IntoWasmAbi for #rust_name {
657650
type Abi = <JsValue as IntoWasmAbi>::Abi;
658651

@@ -779,6 +772,21 @@ impl ToTokens for ast::ImportType {
779772
})
780773
.to_tokens(tokens);
781774

775+
if !no_deref {
776+
(quote! {
777+
#[allow(clippy::all)]
778+
impl core::ops::Deref for #rust_name {
779+
type Target = #internal_obj;
780+
781+
#[inline]
782+
fn deref(&self) -> &#internal_obj {
783+
&self.obj
784+
}
785+
}
786+
})
787+
.to_tokens(tokens);
788+
}
789+
782790
for superclass in self.extends.iter() {
783791
(quote! {
784792
#[allow(clippy::all)]

crates/macro-support/src/parser.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ macro_rules! attrgen {
5252
(inspectable, Inspectable(Span)),
5353
(is_type_of, IsTypeOf(Span, syn::Expr)),
5454
(extends, Extends(Span, syn::Path)),
55+
(no_deref, NoDeref(Span)),
5556
(vendor_prefix, VendorPrefix(Span, Ident)),
5657
(variadic, Variadic(Span)),
5758
(typescript_custom_section, TypescriptCustomSection(Span)),
@@ -612,6 +613,7 @@ impl ConvertToAst<BindgenAttrs> for syn::ForeignItemType {
612613
let shim = format!("__wbg_instanceof_{}_{}", self.ident, ShortHash(&self.ident));
613614
let mut extends = Vec::new();
614615
let mut vendor_prefixes = Vec::new();
616+
let no_deref = attrs.no_deref().is_some();
615617
for (used, attr) in attrs.attrs.iter() {
616618
match attr {
617619
BindgenAttr::Extends(_, e) => {
@@ -637,6 +639,7 @@ impl ConvertToAst<BindgenAttrs> for syn::ForeignItemType {
637639
js_name,
638640
extends,
639641
vendor_prefixes,
642+
no_deref,
640643
}))
641644
}
642645
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# `no_deref`
2+
3+
The `no_deref` attribute can be used to say that no `Deref` impl should be
4+
generated for an imported type. If this attribute is not present, a `Deref` impl
5+
will be generated with a `Target` of the type's first `extends` attribute, or
6+
`Target = JsValue` if there are no `extends` attributes.
7+
8+
```rust
9+
#[wasm_bindgen]
10+
extern "C" {
11+
type Foo;
12+
13+
#[wasm_bindgen(method)]
14+
fn baz(this: &Foo)
15+
16+
#[wasm_bindgen(extends = Foo, no_deref)]
17+
type Bar;
18+
}
19+
20+
fn do_stuff(bar: &Bar) {
21+
bar.baz() // Does not compile
22+
}
23+
24+
```

0 commit comments

Comments
 (0)