add dyn for Fn (#2212)

* add dyn for Fn

* revert invalid-imports changes

* add one more dyn in doc comments
This commit is contained in:
Cameron Taggart 2020-06-23 09:24:26 -06:00 committed by GitHub
parent 810e6a84c8
commit 1a7d6de1b2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 88 additions and 87 deletions

1
.gitignore vendored
View File

@ -10,3 +10,4 @@ yarn.lock
/publish
/publish.exe
.vscode
webdriver.json

View File

@ -40,7 +40,7 @@ In addition to the shims we talked about above which JS generates the macro
```
#[no_mangle]
pub extern "C" fn __wbindgen_describe_greet() {
<Fn(&str)>::describe();
<dyn Fn(&str)>::describe();
}
```

View File

@ -86,7 +86,7 @@ functions imported into Rust.
Mentioned above not all Rust types will fit within 32 bits. While we can
communicate an `f64` we don't necessarily have the ability to use all the bits.
Types like `&str` need to communicate two items, a pointer and a length (64
bits). Other types like `&Closure<Fn()>` have even more information to
bits). Other types like `&Closure<dyn Fn()>` have even more information to
transmit.
As a result we need a method of communicating more data through the signatures

View File

@ -11,17 +11,17 @@ JavaScript in two variants:
## Stack-Lifetime Closures
Closures with a stack lifetime are passed to JavaScript as either `&Fn` or `&mut
FnMut` trait objects:
Closures with a stack lifetime are passed to JavaScript as either `&dyn Fn` or `&mut
dyn FnMut` trait objects:
```rust
// Import JS functions that take closures
#[wasm_bindgen]
extern "C" {
fn takes_immutable_closure(f: &Fn());
fn takes_immutable_closure(f: &dyn Fn());
fn takes_mutable_closure(f: &mut FnMut());
fn takes_mutable_closure(f: &mut dyn FnMut());
}
// Usage
@ -45,7 +45,7 @@ Closures also support arguments and return values like exports do, for example:
```rust
#[wasm_bindgen]
extern "C" {
fn takes_closure_that_takes_int_and_returns_string(x: &Fn(u32) -> String);
fn takes_closure_that_takes_int_and_returns_string(x: &dyn Fn(u32) -> String);
}
takes_closure_that_takes_int_and_returns_string(&|x: u32| -> String {
@ -81,7 +81,7 @@ as arguments and returns.
```rust
#[wasm_bindgen]
extern "C" {
fn setInterval(closure: &Closure<FnMut()>, millis: u32) -> f64;
fn setInterval(closure: &Closure<dyn FnMut()>, millis: u32) -> f64;
fn cancelInterval(token: f64);
#[wasm_bindgen(js_namespace = console)]
@ -90,7 +90,7 @@ extern "C" {
#[wasm_bindgen]
pub struct Interval {
closure: Closure<FnMut()>,
closure: Closure<dyn FnMut()>,
token: f64,
}

View File

@ -16,7 +16,7 @@ all Web APIs)][webidl] have relatively straightforward translations into
* Callbacks are all represented as `js_sys::Function`. This means that all
callbacks going through `web-sys` are a raw JS value. You can work with this
by either juggling actual `js_sys::Function` instances or you can create a
`Closure<FnMut(...)>`, extract the underlying `JsValue` with `as_ref`, and
`Closure<dyn FnMut(...)>`, extract the underlying `JsValue` with `as_ref`, and
then use `JsCast::unchecked_ref` to convert it to a `js_sys::Function`.
[webidl]: https://heycam.github.io/webidl/

View File

@ -48,7 +48,7 @@ use crate::UnwrapThrowExt;
///
/// #[wasm_bindgen]
/// extern "C" {
/// fn setInterval(closure: &Closure<FnMut()>, time: u32) -> i32;
/// fn setInterval(closure: &Closure<dyn FnMut()>, time: u32) -> i32;
/// fn clearInterval(id: i32);
///
/// #[wasm_bindgen(js_namespace = console)]
@ -58,7 +58,7 @@ use crate::UnwrapThrowExt;
/// #[wasm_bindgen]
/// pub struct IntervalHandle {
/// interval_id: i32,
/// _closure: Closure<FnMut()>,
/// _closure: Closure<dyn FnMut()>,
/// }
///
/// impl Drop for IntervalHandle {
@ -73,7 +73,7 @@ use crate::UnwrapThrowExt;
/// // a JS closure.
/// let cb = Closure::wrap(Box::new(|| {
/// log("interval elapsed!");
/// }) as Box<FnMut()>);
/// }) as Box<dyn FnMut()>);
///
/// // Next we pass this via reference to the `setInterval` function, and
/// // `setInterval` gets a handle to the corresponding JS closure.
@ -101,7 +101,7 @@ use crate::UnwrapThrowExt;
/// #[wasm_bindgen]
/// pub struct IntervalHandle {
/// interval_id: i32,
/// _closure: Closure<FnMut()>,
/// _closure: Closure<dyn FnMut()>,
/// }
///
/// impl Drop for IntervalHandle {
@ -115,7 +115,7 @@ use crate::UnwrapThrowExt;
/// pub fn run() -> Result<IntervalHandle, JsValue> {
/// let cb = Closure::wrap(Box::new(|| {
/// web_sys::console::log_1(&"inverval elapsed!".into());
/// }) as Box<FnMut()>);
/// }) as Box<dyn FnMut()>);
///
/// let window = web_sys::window().unwrap();
/// let interval_id = window.set_interval_with_callback_and_timeout_and_arguments_0(
@ -144,7 +144,7 @@ use crate::UnwrapThrowExt;
///
/// #[wasm_bindgen]
/// extern "C" {
/// fn requestAnimationFrame(closure: &Closure<FnMut()>) -> u32;
/// fn requestAnimationFrame(closure: &Closure<dyn FnMut()>) -> u32;
/// fn cancelAnimationFrame(id: u32);
///
/// #[wasm_bindgen(js_namespace = console)]
@ -154,7 +154,7 @@ use crate::UnwrapThrowExt;
/// #[wasm_bindgen]
/// pub struct AnimationFrameHandle {
/// animation_id: u32,
/// _closure: Closure<FnMut()>,
/// _closure: Closure<dyn FnMut()>,
/// }
///
/// impl Drop for AnimationFrameHandle {
@ -377,12 +377,12 @@ where
// NB: we use a specific `T` for this `Closure<T>` impl block to avoid every
// call site having to provide an explicit, turbo-fished type like
// `Closure::<FnOnce()>::once(...)`.
// `Closure::<dyn FnOnce()>::once(...)`.
impl Closure<dyn FnOnce()> {
/// Create a `Closure` from a function that can only be called once.
///
/// Since we have no way of enforcing that JS cannot attempt to call this
/// `FnOne(A...) -> R` more than once, this produces a `Closure<FnMut(A...)
/// `FnOne(A...) -> R` more than once, this produces a `Closure<dyn FnMut(A...)
/// -> R>` that will dynamically throw a JavaScript error if called more
/// than once.
///
@ -404,7 +404,7 @@ impl Closure<dyn FnOnce()> {
///
/// // Create a `Closure` from `f`. Note that the `Closure`'s type parameter
/// // is `FnMut`, even though `f` is `FnOnce`.
/// let closure: Closure<FnMut() -> String> = Closure::once(f);
/// let closure: Closure<dyn FnMut() -> String> = Closure::once(f);
/// ```
pub fn once<F, A, R>(fn_once: F) -> Closure<F::FnMut>
where

View File

@ -7,89 +7,89 @@ use wasm_bindgen_test::*;
#[wasm_bindgen(module = "tests/wasm/closures.js")]
extern "C" {
fn works_call(a: &Fn());
fn works_thread(a: &Fn(u32) -> u32) -> u32;
fn works_call(a: &dyn Fn());
fn works_thread(a: &dyn Fn(u32) -> u32) -> u32;
fn cannot_reuse_call(a: &Fn());
fn cannot_reuse_call(a: &dyn Fn());
#[wasm_bindgen(catch)]
fn cannot_reuse_call_again() -> Result<(), JsValue>;
fn long_lived_call1(a: &Closure<Fn()>);
fn long_lived_call2(a: &Closure<FnMut(u32) -> u32>) -> u32;
fn long_lived_call1(a: &Closure<dyn Fn()>);
fn long_lived_call2(a: &Closure<dyn FnMut(u32) -> u32>) -> u32;
fn many_arity_call1(a: &Closure<Fn()>);
fn many_arity_call2(a: &Closure<Fn(u32)>);
fn many_arity_call3(a: &Closure<Fn(u32, u32)>);
fn many_arity_call4(a: &Closure<Fn(u32, u32, u32)>);
fn many_arity_call5(a: &Closure<Fn(u32, u32, u32, u32)>);
fn many_arity_call6(a: &Closure<Fn(u32, u32, u32, u32, u32)>);
fn many_arity_call7(a: &Closure<Fn(u32, u32, u32, u32, u32, u32)>);
fn many_arity_call8(a: &Closure<Fn(u32, u32, u32, u32, u32, u32, u32)>);
fn many_arity_call9(a: &Closure<Fn(u32, u32, u32, u32, u32, u32, u32, u32)>);
fn many_arity_call1(a: &Closure<dyn Fn()>);
fn many_arity_call2(a: &Closure<dyn Fn(u32)>);
fn many_arity_call3(a: &Closure<dyn Fn(u32, u32)>);
fn many_arity_call4(a: &Closure<dyn Fn(u32, u32, u32)>);
fn many_arity_call5(a: &Closure<dyn Fn(u32, u32, u32, u32)>);
fn many_arity_call6(a: &Closure<dyn Fn(u32, u32, u32, u32, u32)>);
fn many_arity_call7(a: &Closure<dyn Fn(u32, u32, u32, u32, u32, u32)>);
fn many_arity_call8(a: &Closure<dyn Fn(u32, u32, u32, u32, u32, u32, u32)>);
fn many_arity_call9(a: &Closure<dyn Fn(u32, u32, u32, u32, u32, u32, u32, u32)>);
#[wasm_bindgen(js_name = many_arity_call1)]
fn many_arity_call_mut1(a: &Closure<FnMut()>);
fn many_arity_call_mut1(a: &Closure<dyn FnMut()>);
#[wasm_bindgen(js_name = many_arity_call2)]
fn many_arity_call_mut2(a: &Closure<FnMut(u32)>);
fn many_arity_call_mut2(a: &Closure<dyn FnMut(u32)>);
#[wasm_bindgen(js_name = many_arity_call3)]
fn many_arity_call_mut3(a: &Closure<FnMut(u32, u32)>);
fn many_arity_call_mut3(a: &Closure<dyn FnMut(u32, u32)>);
#[wasm_bindgen(js_name = many_arity_call4)]
fn many_arity_call_mut4(a: &Closure<FnMut(u32, u32, u32)>);
fn many_arity_call_mut4(a: &Closure<dyn FnMut(u32, u32, u32)>);
#[wasm_bindgen(js_name = many_arity_call5)]
fn many_arity_call_mut5(a: &Closure<FnMut(u32, u32, u32, u32)>);
fn many_arity_call_mut5(a: &Closure<dyn FnMut(u32, u32, u32, u32)>);
#[wasm_bindgen(js_name = many_arity_call6)]
fn many_arity_call_mut6(a: &Closure<FnMut(u32, u32, u32, u32, u32)>);
fn many_arity_call_mut6(a: &Closure<dyn FnMut(u32, u32, u32, u32, u32)>);
#[wasm_bindgen(js_name = many_arity_call7)]
fn many_arity_call_mut7(a: &Closure<FnMut(u32, u32, u32, u32, u32, u32)>);
fn many_arity_call_mut7(a: &Closure<dyn FnMut(u32, u32, u32, u32, u32, u32)>);
#[wasm_bindgen(js_name = many_arity_call8)]
fn many_arity_call_mut8(a: &Closure<FnMut(u32, u32, u32, u32, u32, u32, u32)>);
fn many_arity_call_mut8(a: &Closure<dyn FnMut(u32, u32, u32, u32, u32, u32, u32)>);
#[wasm_bindgen(js_name = many_arity_call9)]
fn many_arity_call_mut9(a: &Closure<FnMut(u32, u32, u32, u32, u32, u32, u32, u32)>);
fn many_arity_call_mut9(a: &Closure<dyn FnMut(u32, u32, u32, u32, u32, u32, u32, u32)>);
#[wasm_bindgen(js_name = many_arity_call1)]
fn many_arity_stack1(a: &Fn());
fn many_arity_stack1(a: &dyn Fn());
#[wasm_bindgen(js_name = many_arity_call2)]
fn many_arity_stack2(a: &Fn(u32));
fn many_arity_stack2(a: &dyn Fn(u32));
#[wasm_bindgen(js_name = many_arity_call3)]
fn many_arity_stack3(a: &Fn(u32, u32));
fn many_arity_stack3(a: &dyn Fn(u32, u32));
#[wasm_bindgen(js_name = many_arity_call4)]
fn many_arity_stack4(a: &Fn(u32, u32, u32));
fn many_arity_stack4(a: &dyn Fn(u32, u32, u32));
#[wasm_bindgen(js_name = many_arity_call5)]
fn many_arity_stack5(a: &Fn(u32, u32, u32, u32));
fn many_arity_stack5(a: &dyn Fn(u32, u32, u32, u32));
#[wasm_bindgen(js_name = many_arity_call6)]
fn many_arity_stack6(a: &Fn(u32, u32, u32, u32, u32));
fn many_arity_stack6(a: &dyn Fn(u32, u32, u32, u32, u32));
#[wasm_bindgen(js_name = many_arity_call7)]
fn many_arity_stack7(a: &Fn(u32, u32, u32, u32, u32, u32));
fn many_arity_stack7(a: &dyn Fn(u32, u32, u32, u32, u32, u32));
#[wasm_bindgen(js_name = many_arity_call8)]
fn many_arity_stack8(a: &Fn(u32, u32, u32, u32, u32, u32, u32));
fn many_arity_stack8(a: &dyn Fn(u32, u32, u32, u32, u32, u32, u32));
#[wasm_bindgen(js_name = many_arity_call9)]
fn many_arity_stack9(a: &Fn(u32, u32, u32, u32, u32, u32, u32, u32));
fn many_arity_stack9(a: &dyn Fn(u32, u32, u32, u32, u32, u32, u32, u32));
fn long_lived_dropping_cache(a: &Closure<Fn()>);
fn long_lived_dropping_cache(a: &Closure<dyn Fn()>);
#[wasm_bindgen(catch)]
fn long_lived_dropping_call() -> Result<(), JsValue>;
fn long_fnmut_recursive_cache(a: &Closure<FnMut()>);
fn long_fnmut_recursive_cache(a: &Closure<dyn FnMut()>);
#[wasm_bindgen(catch)]
fn long_fnmut_recursive_call() -> Result<(), JsValue>;
fn fnmut_call(a: &mut FnMut());
fn fnmut_thread(a: &mut FnMut(u32) -> u32) -> u32;
fn fnmut_call(a: &mut dyn FnMut());
fn fnmut_thread(a: &mut dyn FnMut(u32) -> u32) -> u32;
fn fnmut_bad_call(a: &mut FnMut());
fn fnmut_bad_call(a: &mut dyn FnMut());
#[wasm_bindgen(catch)]
fn fnmut_bad_again(a: bool) -> Result<(), JsValue>;
fn string_arguments_call(a: &mut FnMut(String));
fn string_arguments_call(a: &mut dyn FnMut(String));
fn string_ret_call(a: &mut FnMut(String) -> String);
fn string_ret_call(a: &mut dyn FnMut(String) -> String);
fn drop_during_call_save(a: &Closure<Fn()>);
fn drop_during_call_save(a: &Closure<dyn Fn()>);
fn drop_during_call_call();
fn js_test_closure_returner();
fn calling_it_throws(a: &Closure<FnMut()>) -> bool;
fn calling_it_throws(a: &Closure<dyn FnMut()>) -> bool;
fn call_val(f: &JsValue);
@ -98,18 +98,18 @@ extern "C" {
fn pass_reference_first_arg_twice(
a: RefFirstArgument,
b: &Closure<FnMut(&RefFirstArgument)>,
c: &Closure<FnMut(&RefFirstArgument)>,
b: &Closure<dyn FnMut(&RefFirstArgument)>,
c: &Closure<dyn FnMut(&RefFirstArgument)>,
);
#[wasm_bindgen(js_name = pass_reference_first_arg_twice)]
fn pass_reference_first_arg_twice2(
a: RefFirstArgument,
b: &mut FnMut(&RefFirstArgument),
c: &mut FnMut(&RefFirstArgument),
b: &mut dyn FnMut(&RefFirstArgument),
c: &mut dyn FnMut(&RefFirstArgument),
);
fn call_destroyed(a: &JsValue);
fn js_store_forgotten_closure(closure: &Closure<Fn()>);
fn js_store_forgotten_closure(closure: &Closure<dyn Fn()>);
fn js_call_forgotten_closure();
}
@ -130,7 +130,7 @@ fn cannot_reuse() {
#[wasm_bindgen_test]
fn debug() {
let closure = Closure::wrap(Box::new(|| {}) as Box<FnMut()>);
let closure = Closure::wrap(Box::new(|| {}) as Box<dyn FnMut()>);
assert_eq!(&format!("{:?}", closure), "Closure { ... }");
}
@ -379,7 +379,7 @@ fn drop_drops() {
}
}
let a = A;
let x: Closure<Fn()> = Closure::new(move || drop(&a));
let x: Closure<dyn Fn()> = Closure::new(move || drop(&a));
drop(x);
unsafe {
assert!(HIT);
@ -402,7 +402,7 @@ fn drop_during_call_ok() {
let rc2 = rc.clone();
let x = 3;
let a = A;
let x: Closure<Fn()> = Closure::new(move || {
let x: Closure<dyn Fn()> = Closure::new(move || {
// "drop ourselves"
drop(rc2.borrow_mut().take().unwrap());
@ -437,7 +437,7 @@ fn drop_during_call_ok() {
#[wasm_bindgen_test]
fn test_closure_returner() {
type ClosureType = FnMut() -> BadStruct;
type ClosureType = dyn FnMut() -> BadStruct;
use js_sys::{Object, Reflect};
use wasm_bindgen::JsCast;
@ -481,22 +481,22 @@ pub struct RefFirstArgument {
fn reference_as_first_argument_builds_at_all() {
#[wasm_bindgen]
extern "C" {
fn ref_first_arg1(a: &Fn(&JsValue));
fn ref_first_arg2(a: &mut FnMut(&JsValue));
fn ref_first_arg3(a: &Closure<Fn(&JsValue)>);
fn ref_first_arg4(a: &Closure<FnMut(&JsValue)>);
fn ref_first_custom1(a: &Fn(&RefFirstArgument));
fn ref_first_custom2(a: &mut FnMut(&RefFirstArgument));
fn ref_first_custom3(a: &Closure<Fn(&RefFirstArgument)>);
fn ref_first_custom4(a: &Closure<FnMut(&RefFirstArgument)>);
fn ref_first_arg1(a: &dyn Fn(&JsValue));
fn ref_first_arg2(a: &mut dyn FnMut(&JsValue));
fn ref_first_arg3(a: &Closure<dyn Fn(&JsValue)>);
fn ref_first_arg4(a: &Closure<dyn FnMut(&JsValue)>);
fn ref_first_custom1(a: &dyn Fn(&RefFirstArgument));
fn ref_first_custom2(a: &mut dyn FnMut(&RefFirstArgument));
fn ref_first_custom3(a: &Closure<dyn Fn(&RefFirstArgument)>);
fn ref_first_custom4(a: &Closure<dyn FnMut(&RefFirstArgument)>);
}
Closure::wrap(Box::new(|_: &JsValue| ()) as Box<Fn(&JsValue)>);
Closure::wrap(Box::new(|_: &JsValue| ()) as Box<FnMut(&JsValue)>);
Closure::wrap(Box::new(|_: &JsValue| ()) as Box<dyn Fn(&JsValue)>);
Closure::wrap(Box::new(|_: &JsValue| ()) as Box<dyn FnMut(&JsValue)>);
Closure::once(|_: &JsValue| ());
Closure::once_into_js(|_: &JsValue| ());
Closure::wrap(Box::new(|_: &RefFirstArgument| ()) as Box<Fn(&RefFirstArgument)>);
Closure::wrap(Box::new(|_: &RefFirstArgument| ()) as Box<FnMut(&RefFirstArgument)>);
Closure::wrap(Box::new(|_: &RefFirstArgument| ()) as Box<dyn Fn(&RefFirstArgument)>);
Closure::wrap(Box::new(|_: &RefFirstArgument| ()) as Box<dyn FnMut(&RefFirstArgument)>);
Closure::once(|_: &RefFirstArgument| ());
Closure::once_into_js(|_: &RefFirstArgument| ());
}
@ -553,25 +553,25 @@ fn call_destroyed_doesnt_segfault() {
}
let a = A(1, 1);
let a = Closure::wrap(Box::new(move || drop(&a)) as Box<Fn()>);
let a = Closure::wrap(Box::new(move || drop(&a)) as Box<dyn Fn()>);
let b = a.as_ref().clone();
drop(a);
call_destroyed(&b);
let a = A(2, 2);
let a = Closure::wrap(Box::new(move || drop(&a)) as Box<FnMut()>);
let a = Closure::wrap(Box::new(move || drop(&a)) as Box<dyn FnMut()>);
let b = a.as_ref().clone();
drop(a);
call_destroyed(&b);
let a = A(1, 1);
let a = Closure::wrap(Box::new(move |_: &JsValue| drop(&a)) as Box<Fn(&JsValue)>);
let a = Closure::wrap(Box::new(move |_: &JsValue| drop(&a)) as Box<dyn Fn(&JsValue)>);
let b = a.as_ref().clone();
drop(a);
call_destroyed(&b);
let a = A(2, 2);
let a = Closure::wrap(Box::new(move |_: &JsValue| drop(&a)) as Box<FnMut(&JsValue)>);
let a = Closure::wrap(Box::new(move |_: &JsValue| drop(&a)) as Box<dyn FnMut(&JsValue)>);
let b = a.as_ref().clone();
drop(a);
call_destroyed(&b);
@ -579,7 +579,7 @@ fn call_destroyed_doesnt_segfault() {
#[wasm_bindgen_test]
fn forget_works() {
let a = Closure::wrap(Box::new(|| {}) as Box<Fn()>);
let a = Closure::wrap(Box::new(|| {}) as Box<dyn Fn()>);
js_store_forgotten_closure(&a);
a.forget();
js_call_forgotten_closure();