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`
This commit is contained in:
Jules Bertholet 2021-08-10 10:38:49 -04:00 committed by GitHub
parent 41c22e6052
commit 4770fab854
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 46 additions and 9 deletions

View File

@ -261,6 +261,8 @@ pub struct ImportType {
pub extends: Vec<syn::Path>,
/// A custom prefix to add and attempt to fall back to, if the type isn't found
pub vendor_prefixes: Vec<Ident>,
/// If present, don't generate a `Deref` impl
pub no_deref: bool,
}
/// The metadata for an Enum being imported

View File

@ -618,6 +618,8 @@ impl ToTokens for ast::ImportType {
}
});
let no_deref = self.no_deref;
(quote! {
#[allow(bad_style)]
#(#attrs)*
@ -644,15 +646,6 @@ impl ToTokens for ast::ImportType {
}
}
impl core::ops::Deref for #rust_name {
type Target = #internal_obj;
#[inline]
fn deref(&self) -> &#internal_obj {
&self.obj
}
}
impl IntoWasmAbi for #rust_name {
type Abi = <JsValue as IntoWasmAbi>::Abi;
@ -779,6 +772,21 @@ impl ToTokens for ast::ImportType {
})
.to_tokens(tokens);
if !no_deref {
(quote! {
#[allow(clippy::all)]
impl core::ops::Deref for #rust_name {
type Target = #internal_obj;
#[inline]
fn deref(&self) -> &#internal_obj {
&self.obj
}
}
})
.to_tokens(tokens);
}
for superclass in self.extends.iter() {
(quote! {
#[allow(clippy::all)]

View File

@ -52,6 +52,7 @@ macro_rules! attrgen {
(inspectable, Inspectable(Span)),
(is_type_of, IsTypeOf(Span, syn::Expr)),
(extends, Extends(Span, syn::Path)),
(no_deref, NoDeref(Span)),
(vendor_prefix, VendorPrefix(Span, Ident)),
(variadic, Variadic(Span)),
(typescript_custom_section, TypescriptCustomSection(Span)),
@ -612,6 +613,7 @@ impl ConvertToAst<BindgenAttrs> for syn::ForeignItemType {
let shim = format!("__wbg_instanceof_{}_{}", self.ident, ShortHash(&self.ident));
let mut extends = Vec::new();
let mut vendor_prefixes = Vec::new();
let no_deref = attrs.no_deref().is_some();
for (used, attr) in attrs.attrs.iter() {
match attr {
BindgenAttr::Extends(_, e) => {
@ -637,6 +639,7 @@ impl ConvertToAst<BindgenAttrs> for syn::ForeignItemType {
js_name,
extends,
vendor_prefixes,
no_deref,
}))
}
}

View File

@ -0,0 +1,24 @@
# `no_deref`
The `no_deref` attribute can be used to say that no `Deref` impl should be
generated for an imported type. If this attribute is not present, a `Deref` impl
will be generated with a `Target` of the type's first `extends` attribute, or
`Target = JsValue` if there are no `extends` attributes.
```rust
#[wasm_bindgen]
extern "C" {
type Foo;
#[wasm_bindgen(method)]
fn baz(this: &Foo)
#[wasm_bindgen(extends = Foo, no_deref)]
type Bar;
}
fn do_stuff(bar: &Bar) {
bar.baz() // Does not compile
}
```