1use alloc::boxed::Box;
2use core::mem;
3
4#[cfg(all(feature = "std", target_arch = "wasm32", panic = "unwind"))]
5use crate::__rt::maybe_catch_unwind;
6use crate::closure::{
7 Closure, ImmediateClosure, IntoWasmClosure, IntoWasmClosureRef, IntoWasmClosureRefMut,
8 ScopedClosure, WasmClosure, WasmClosureFnOnce, WasmClosureFnOnceAbort,
9};
10use crate::convert::slices::WasmSlice;
11use crate::convert::traits::UpcastFrom;
12use crate::convert::RefFromWasmAbi;
13use crate::convert::{FromWasmAbi, IntoWasmAbi, ReturnWasmAbi, WasmAbi, WasmRet};
14use crate::describe::{inform, WasmDescribe, FUNCTION};
15use crate::sys::Undefined;
16use crate::JsValue;
17use crate::UnwrapThrowExt;
18use crate::__rt::marker::ErasableGeneric;
19use crate::throw_str;
20#[cfg(all(feature = "std", target_arch = "wasm32", panic = "unwind"))]
21use core::panic::AssertUnwindSafe;
22
23macro_rules! closures {
24 ([$($maybe_unwind_safe:tt)*] $($rest:tt)*) => {
26 closures!(@process [$($maybe_unwind_safe)*] $($rest)*);
27 };
28
29 (@process [$($unwind_safe:tt)*] ($($var:ident $arg1:ident $arg2:ident $arg3:ident $arg4:ident)*) $($rest:tt)*) => {
31 closures!(@impl_for_args ($($var),*) FromWasmAbi [$($unwind_safe)*] $($var::from_abi($var) => $var $arg1 $arg2 $arg3 $arg4)*);
32 closures!(@process [$($unwind_safe)*] $($rest)*);
33 };
34
35 (@process [$($unwind_safe:tt)*]) => {};
37
38 (@count_one $ty:ty) => (1);
40
41 (@describe ( $($ty:ty),* )) => {
42 const ARG_COUNT: u32 = 0 $(+ closures!(@count_one $ty))*;
45 inform(ARG_COUNT);
46 $(<$ty>::describe();)*
47 };
48
49 (@closure ($($ty:ty),*) $($var:ident)* $body:block) => (move |$($var: $ty),*| $body);
53
54 (@impl_for_fn $is_mut:literal [$($mut:ident)?] $Fn:ident $FnArgs:tt $FromWasmAbi:ident $($var_expr:expr => $var:ident $arg1:ident $arg2:ident $arg3:ident $arg4:ident)*) => (const _: () = {
55 impl<$($var,)* R> IntoWasmAbi for &'_ $($mut)? (dyn $Fn $FnArgs -> R + '_)
56 where
57 Self: WasmDescribe,
58 {
59 type Abi = WasmSlice;
60
61 fn into_abi(self) -> WasmSlice {
62 unsafe {
63 let (a, b): (usize, usize) = mem::transmute(self);
64 WasmSlice { ptr: a as u32, len: b as u32 }
65 }
66 }
67 }
68
69 unsafe impl<'a, $($var,)* R> ErasableGeneric for &'a $($mut)? (dyn $Fn $FnArgs -> R + 'a)
70 where
71 $($var: ErasableGeneric,)*
72 R: ErasableGeneric
73 {
74 type Repr = &'static (dyn $Fn ($(<$var as ErasableGeneric>::Repr,)*) -> <R as ErasableGeneric>::Repr + 'static);
75 }
76
77 unsafe impl<'a, 'b, $($var,)* R> ErasableGeneric for ImmediateClosure<'a, dyn $Fn $FnArgs -> R + 'b>
78 where
79 $($var: ErasableGeneric,)*
80 R: ErasableGeneric,
81 {
82 type Repr = ImmediateClosure<'static, dyn $Fn ($(<$var as ErasableGeneric>::Repr,)*) -> <R as ErasableGeneric>::Repr + 'static>;
83 }
84
85 #[cfg(all(feature = "std", target_arch = "wasm32", panic = "unwind"))]
89 #[allow(non_snake_case)]
90 unsafe extern "C-unwind" fn invoke<$($var: $FromWasmAbi,)* R: ReturnWasmAbi>(
91 a: usize,
92 b: usize,
93 $(
94 $arg1: <$var::Abi as WasmAbi>::Prim1,
95 $arg2: <$var::Abi as WasmAbi>::Prim2,
96 $arg3: <$var::Abi as WasmAbi>::Prim3,
97 $arg4: <$var::Abi as WasmAbi>::Prim4,
98 )*
99 ) -> WasmRet<R::Abi> {
100 if a == 0 {
101 throw_str("closure invoked recursively or after being dropped");
102 }
103 let unwind_safe = (b & 0x80000000) != 0;
104 let b = b & 0x7FFFFFFF;
105 let ret = {
106 let f: & $($mut)? dyn $Fn $FnArgs -> R = mem::transmute((a, b));
107 $(
108 let $var = $var::Abi::join($arg1, $arg2, $arg3, $arg4);
109 )*
110 if unwind_safe {
111 maybe_catch_unwind(AssertUnwindSafe(|| f($($var_expr),*)))
112 } else {
113 f($($var_expr),*)
114 }
115 };
116 ret.return_abi().into()
117 }
118
119 #[cfg(not(all(feature = "std", target_arch = "wasm32", panic = "unwind")))]
121 #[allow(non_snake_case)]
122 unsafe extern "C-unwind" fn invoke<$($var: $FromWasmAbi,)* R: ReturnWasmAbi>(
123 a: usize,
124 b: usize,
125 $(
126 $arg1: <$var::Abi as WasmAbi>::Prim1,
127 $arg2: <$var::Abi as WasmAbi>::Prim2,
128 $arg3: <$var::Abi as WasmAbi>::Prim3,
129 $arg4: <$var::Abi as WasmAbi>::Prim4,
130 )*
131 ) -> WasmRet<R::Abi> {
132 if a == 0 {
133 throw_str("closure invoked recursively or after being dropped");
134 }
135 let b = b & 0x7FFFFFFF;
136 let ret = {
137 let f: & $($mut)? dyn $Fn $FnArgs -> R = mem::transmute((a, b));
138 $(
139 let $var = $var::Abi::join($arg1, $arg2, $arg3, $arg4);
140 )*
141 f($($var_expr),*)
142 };
143 ret.return_abi().into()
144 }
145
146 #[allow(clippy::fn_to_numeric_cast)]
147 impl<$($var,)* R> WasmDescribe for dyn $Fn $FnArgs -> R + '_
148 where
149 $($var: $FromWasmAbi,)*
150 R: ReturnWasmAbi,
151 {
152 #[cfg_attr(wasm_bindgen_unstable_test_coverage, coverage(off))]
153 fn describe() {
154 inform(FUNCTION);
155 inform(invoke::<$($var,)* R> as *const () as usize as u32);
156 closures!(@describe $FnArgs);
157 R::describe();
158 R::describe();
159 }
160 }
161
162 unsafe impl<'__closure, $($var,)* R> WasmClosure for dyn $Fn $FnArgs -> R + '__closure
163 where
164 Self: WasmDescribe,
165 {
166 const IS_MUT: bool = $is_mut;
167 type AsMut = dyn FnMut $FnArgs -> R + '__closure;
168 fn to_wasm_slice(r: &Self) -> WasmSlice {
169 let (ptr, len): (u32, u32) = unsafe { mem::transmute_copy(&r) };
170 WasmSlice { ptr, len }
171 }
172 }
173
174 impl<T, $($var,)* R> IntoWasmClosure<dyn $Fn $FnArgs -> R> for T
175 where
176 T: 'static + $Fn $FnArgs -> R,
177 {
178 fn unsize(self: Box<Self>) -> Box<dyn $Fn $FnArgs -> R> { self }
179 }
180 };);
181
182 (@impl_unsize_closure_ref $FnArgs:tt $FromWasmAbi:ident $($var_expr:expr => $var:ident $arg1:ident $arg2:ident $arg3:ident $arg4:ident)*) => (
186 impl<'a, 'b, T: 'a, $($var: 'a + $FromWasmAbi,)* R: 'a + ReturnWasmAbi> IntoWasmClosureRef<'b, dyn Fn $FnArgs -> R + 'a> for T
187 where
188 'a: 'b,
189 T: Fn $FnArgs -> R,
190 {
191 type Static = dyn Fn $FnArgs -> R;
192 type WithLifetime = dyn Fn $FnArgs -> R + 'b;
193 fn unsize_closure_ref(&self) -> &(dyn Fn $FnArgs -> R + 'a) { self }
194 }
195
196 impl<'a, 'b, T: 'a, $($var: 'a + $FromWasmAbi,)* R: 'a + ReturnWasmAbi> IntoWasmClosureRefMut<'b, dyn FnMut $FnArgs -> R + 'a> for T
197 where
198 'a: 'b,
199 T: FnMut $FnArgs -> R,
200 {
201 type Static = dyn FnMut $FnArgs -> R;
202 type WithLifetime = dyn FnMut $FnArgs -> R + 'b;
203 fn unsize_closure_ref(&mut self) -> &mut (dyn FnMut $FnArgs -> R + 'a) { self }
204 }
205 );
206
207 (@impl_for_args $FnArgs:tt $FromWasmAbi:ident [$($maybe_unwind_safe:tt)*] $($var_expr:expr => $var:ident $arg1:ident $arg2:ident $arg3:ident $arg4:ident)*) => {
208 closures!(@impl_for_fn false [] Fn $FnArgs $FromWasmAbi $($var_expr => $var $arg1 $arg2 $arg3 $arg4)*);
209 closures!(@impl_for_fn true [mut] FnMut $FnArgs $FromWasmAbi $($var_expr => $var $arg1 $arg2 $arg3 $arg4)*);
210 closures!(@impl_unsize_closure_ref $FnArgs $FromWasmAbi $($var_expr => $var $arg1 $arg2 $arg3 $arg4)*);
211
212 #[allow(non_snake_case, unused_parens)]
227 impl<T, $($var,)* R> WasmClosureFnOnce<dyn FnMut $FnArgs -> R, $FnArgs, R> for T
228 where
229 T: 'static + (FnOnce $FnArgs -> R),
230 $($var: $FromWasmAbi + 'static,)*
231 R: ReturnWasmAbi + 'static,
232 $($maybe_unwind_safe)*
233 {
234 fn into_fn_mut(self) -> Box<dyn FnMut $FnArgs -> R> {
235 let mut me = Some(self);
236 Box::new(move |$($var),*| {
237 let me = me.take().expect_throw("FnOnce called more than once");
238 me($($var),*)
239 })
240 }
241
242 fn into_js_function(self) -> JsValue {
243 use alloc::rc::Rc;
244 use crate::__rt::WasmRefCell;
245
246 let rc1 = Rc::new(WasmRefCell::new(None));
247 let rc2 = rc1.clone();
248
249 let closure = Closure::once(closures!(@closure $FnArgs $($var)* {
250 let result = self($($var),*);
251
252 debug_assert_eq!(Rc::strong_count(&rc2), 1);
255 let option_closure = rc2.borrow_mut().take();
256 debug_assert!(option_closure.is_some());
257 drop(option_closure);
258
259 result
260 }));
261
262 let js_val = closure.as_ref().clone();
263
264 *rc1.borrow_mut() = Some(closure);
265 debug_assert_eq!(Rc::strong_count(&rc1), 2);
266 drop(rc1);
267
268 js_val
269 }
270 }
271
272 #[allow(non_snake_case, unused_parens)]
273 impl<T, $($var,)* R> WasmClosureFnOnceAbort<dyn FnMut $FnArgs -> R, $FnArgs, R> for T
274 where
275 T: 'static + (FnOnce $FnArgs -> R),
276 $($var: $FromWasmAbi + 'static,)*
277 R: ReturnWasmAbi + 'static,
278 {
279 fn into_fn_mut(self) -> Box<dyn FnMut $FnArgs -> R> {
280 let mut me = Some(self);
281 Box::new(move |$($var),*| {
282 let me = me.take().expect_throw("FnOnce called more than once");
283 me($($var),*)
284 })
285 }
286
287 fn into_js_function(self) -> JsValue {
288 use alloc::rc::Rc;
289 use crate::__rt::WasmRefCell;
290
291 let rc1 = Rc::new(WasmRefCell::new(None));
292 let rc2 = rc1.clone();
293
294 let closure = Closure::once_aborting(closures!(@closure $FnArgs $($var)* {
296 let result = self($($var),*);
297
298 debug_assert_eq!(Rc::strong_count(&rc2), 1);
301 let option_closure = rc2.borrow_mut().take();
302 debug_assert!(option_closure.is_some());
303 drop(option_closure);
304
305 result
306 }));
307
308 let js_val = closure.as_ref().clone();
309
310 *rc1.borrow_mut() = Some(closure);
311 debug_assert_eq!(Rc::strong_count(&rc1), 2);
312 drop(rc1);
313
314 js_val
315 }
316 }
317 };
318
319 ([$($unwind_safe:tt)*] $( ($($var:ident $arg1:ident $arg2:ident $arg3:ident $arg4:ident)*) )*) => ($(
320 closures!(@impl_for_args ($($var),*) FromWasmAbi [$($maybe_unwind_safe)*] $($var::from_abi($var) => $var $arg1 $arg2 $arg3 $arg4)*);
321 )*);
322}
323
324#[cfg(all(feature = "std", target_arch = "wasm32", panic = "unwind"))]
325closures! {
326 [T: core::panic::UnwindSafe,]
327 ()
328 (A a1 a2 a3 a4)
329 (A a1 a2 a3 a4 B b1 b2 b3 b4)
330 (A a1 a2 a3 a4 B b1 b2 b3 b4 C c1 c2 c3 c4)
331 (A a1 a2 a3 a4 B b1 b2 b3 b4 C c1 c2 c3 c4 D d1 d2 d3 d4)
332 (A a1 a2 a3 a4 B b1 b2 b3 b4 C c1 c2 c3 c4 D d1 d2 d3 d4 E e1 e2 e3 e4)
333 (A a1 a2 a3 a4 B b1 b2 b3 b4 C c1 c2 c3 c4 D d1 d2 d3 d4 E e1 e2 e3 e4 F f1 f2 f3 f4)
334 (A a1 a2 a3 a4 B b1 b2 b3 b4 C c1 c2 c3 c4 D d1 d2 d3 d4 E e1 e2 e3 e4 F f1 f2 f3 f4 G g1 g2 g3 g4)
335 (A a1 a2 a3 a4 B b1 b2 b3 b4 C c1 c2 c3 c4 D d1 d2 d3 d4 E e1 e2 e3 e4 F f1 f2 f3 f4 G g1 g2 g3 g4 H h1 h2 h3 h4)
336}
337
338#[cfg(not(all(feature = "std", target_arch = "wasm32", panic = "unwind")))]
339closures! {
340 []
341 ()
342 (A a1 a2 a3 a4)
343 (A a1 a2 a3 a4 B b1 b2 b3 b4)
344 (A a1 a2 a3 a4 B b1 b2 b3 b4 C c1 c2 c3 c4)
345 (A a1 a2 a3 a4 B b1 b2 b3 b4 C c1 c2 c3 c4 D d1 d2 d3 d4)
346 (A a1 a2 a3 a4 B b1 b2 b3 b4 C c1 c2 c3 c4 D d1 d2 d3 d4 E e1 e2 e3 e4)
347 (A a1 a2 a3 a4 B b1 b2 b3 b4 C c1 c2 c3 c4 D d1 d2 d3 d4 E e1 e2 e3 e4 F f1 f2 f3 f4)
348 (A a1 a2 a3 a4 B b1 b2 b3 b4 C c1 c2 c3 c4 D d1 d2 d3 d4 E e1 e2 e3 e4 F f1 f2 f3 f4 G g1 g2 g3 g4)
349 (A a1 a2 a3 a4 B b1 b2 b3 b4 C c1 c2 c3 c4 D d1 d2 d3 d4 E e1 e2 e3 e4 F f1 f2 f3 f4 G g1 g2 g3 g4 H h1 h2 h3 h4)
350}
351
352macro_rules! impl_fn_upcasts {
354 () => {
355 impl_fn_upcasts!(@arities
356 [0 []]
357 [1 [A1 B1] O1]
358 [2 [A1 B1 A2 B2] O2]
359 [3 [A1 B1 A2 B2 A3 B3] O3]
360 [4 [A1 B1 A2 B2 A3 B3 A4 B4] O4]
361 [5 [A1 B1 A2 B2 A3 B3 A4 B4 A5 B5] O5]
362 [6 [A1 B1 A2 B2 A3 B3 A4 B4 A5 B5 A6 B6] O6]
363 [7 [A1 B1 A2 B2 A3 B3 A4 B4 A5 B5 A6 B6 A7 B7] O7]
364 [8 [A1 B1 A2 B2 A3 B3 A4 B4 A5 B5 A6 B6 A7 B7 A8 B8] O8]
365 );
366 };
367
368 (@arities) => {};
369
370 (@arities [$n:tt $args:tt $($opt:ident)?] $([$rest_n:tt $rest_args:tt $($rest_opt:ident)?])*) => {
371 impl_fn_upcasts!(@same $args);
372 impl_fn_upcasts!(@cross_all $args [] $([$rest_n $rest_args $($rest_opt)?])*);
373 impl_fn_upcasts!(@arities $([$rest_n $rest_args $($rest_opt)?])*);
374 };
375
376 (@same []) => {
377 impl<R1, R2> UpcastFrom<fn() -> R1> for fn() -> R2
378 where
379 R2: UpcastFrom<R1>
380 {}
381
382 impl<'a, R1, R2> UpcastFrom<dyn Fn() -> R1 + 'a> for dyn Fn() -> R2 + 'a
383 where
384 R2: UpcastFrom<R1>
385 {}
386
387 impl<'a, R1, R2> UpcastFrom<dyn FnMut() -> R1 + 'a> for dyn FnMut() -> R2 + 'a
388 where
389 R2: UpcastFrom<R1>
390 {}
391 };
392
393 (@same [$($A1:ident $A2:ident)+]) => {
395 impl<R1, R2, $($A1, $A2),+> UpcastFrom<fn($($A1),+) -> R1> for fn($($A2),+) -> R2
396 where
397 R2: UpcastFrom<R1>,
398 $($A1: UpcastFrom<$A2>,)+
399 {}
400
401 impl<'a, R1, R2, $($A1, $A2),+> UpcastFrom<dyn Fn($($A1),+) -> R1 + 'a> for dyn Fn($($A2),+) -> R2 + 'a
402 where
403 R2: UpcastFrom<R1>,
404 $($A1: UpcastFrom<$A2>,)+
405 {}
406
407 impl<'a, R1, R2, $($A1, $A2),+> UpcastFrom<dyn FnMut($($A1),+) -> R1 + 'a> for dyn FnMut($($A2),+) -> R2 + 'a
408 where
409 R2: UpcastFrom<R1>,
410 $($A1: UpcastFrom<$A2>,)+
411 {}
412 };
413
414 (@cross_all $args:tt $opts:tt) => {};
416
417 (@cross_all $args:tt [$($opts:ident)*] [$next_n:tt $next_args:tt $next_opt:ident] $([$rest_n:tt $rest_args:tt $($rest_opt:ident)?])*) => {
419 impl_fn_upcasts!(@extend $args [$($opts)* $next_opt]);
420 impl_fn_upcasts!(@shrink $args [$($opts)* $next_opt]);
421 impl_fn_upcasts!(@cross_all $args [$($opts)* $next_opt] $([$rest_n $rest_args $($rest_opt)?])*);
422 };
423
424 (@extend [] [$($O:ident)+]) => {
426 impl<R1, R2, $($O),+> UpcastFrom<fn() -> R1> for fn($($O),+) -> R2
427 where
428 R2: UpcastFrom<R1>,
429 $($O: UpcastFrom<Undefined>,)+
430 {}
431
432 impl<'a, R1, R2, $($O),+> UpcastFrom<dyn Fn() -> R1 + 'a> for dyn Fn($($O),+) -> R2 + 'a
433 where
434 R2: UpcastFrom<R1>,
435 $($O: UpcastFrom<Undefined>,)+
436 {}
437
438 impl<'a, R1, R2, $($O),+> UpcastFrom<dyn FnMut() -> R1 + 'a> for dyn FnMut($($O),+) -> R2 + 'a
439 where
440 R2: UpcastFrom<R1>,
441 $($O: UpcastFrom<Undefined>,)+
442 {}
443 };
444
445 (@extend [$($A1:ident $A2:ident)+] [$($O:ident)+]) => {
447 impl<R1, R2, $($A1, $A2,)+ $($O),+> UpcastFrom<fn($($A1),+) -> R1> for fn($($A2,)+ $($O),+) -> R2
448 where
449 R2: UpcastFrom<R1>,
450 $($A1: UpcastFrom<$A2>,)+ $($O: UpcastFrom<Undefined>,)+
452 {}
453
454 impl<'a, R1, R2, $($A1, $A2,)+ $($O),+> UpcastFrom<dyn Fn($($A1),+) -> R1 + 'a> for dyn Fn($($A2,)+ $($O),+) -> R2 + 'a
455 where
456 R2: UpcastFrom<R1>,
457 $($A1: UpcastFrom<$A2>,)+ $($O: UpcastFrom<Undefined>,)+
459 {}
460
461 impl<'a, R1, R2, $($A1, $A2,)+ $($O),+> UpcastFrom<dyn FnMut($($A1),+) -> R1 + 'a> for dyn FnMut($($A2,)+ $($O),+) -> R2 + 'a
462 where
463 R2: UpcastFrom<R1>,
464 $($A1: UpcastFrom<$A2>,)+ $($O: UpcastFrom<Undefined>,)+
466 {}
467 };
468
469 (@shrink [] [$($O:ident)+]) => {
471 impl<R1, R2, $($O),+> UpcastFrom<fn($($O),+) -> R1> for fn() -> R2
472 where
473 R2: UpcastFrom<R1>,
474 $($O: UpcastFrom<Undefined>,)+
475 {}
476
477 impl<'a, R1, R2, $($O),+> UpcastFrom<dyn Fn($($O),+) -> R1 + 'a> for dyn Fn() -> R2 + 'a
478 where
479 R2: UpcastFrom<R1>,
480 $($O: UpcastFrom<Undefined>,)+
481 {}
482
483 impl<'a, R1, R2, $($O),+> UpcastFrom<dyn FnMut($($O),+) -> R1 + 'a> for dyn FnMut() -> R2 + 'a
484 where
485 R2: UpcastFrom<R1>,
486 $($O: UpcastFrom<Undefined>,)+
487 {}
488 };
489
490 (@shrink [$($A1:ident $A2:ident)+] [$($O:ident)+]) => {
492 impl<R1, R2, $($A1, $A2,)+ $($O),+> UpcastFrom<fn($($A1,)+ $($O),+) -> R1> for fn($($A2),+) -> R2
493 where
494 R2: UpcastFrom<R1>,
495 $($A1: UpcastFrom<$A2>,)+ $($O: UpcastFrom<Undefined>,)+
497 {}
498
499 impl<'a, R1, R2, $($A1, $A2,)+ $($O),+> UpcastFrom<dyn Fn($($A1,)+ $($O),+) -> R1 + 'a> for dyn Fn($($A2),+) -> R2 + 'a
500 where
501 R2: UpcastFrom<R1>,
502 $($A1: UpcastFrom<$A2>,)+ $($O: UpcastFrom<Undefined>,)+
504 {}
505
506 impl<'a, R1, R2, $($A1, $A2,)+ $($O),+> UpcastFrom<dyn FnMut($($A1,)+ $($O),+) -> R1 + 'a> for dyn FnMut($($A2),+) -> R2 + 'a
507 where
508 R2: UpcastFrom<R1>,
509 $($A1: UpcastFrom<$A2>,)+ $($O: UpcastFrom<Undefined>,)+
511 {}
512 };
513}
514
515impl_fn_upcasts!();
516
517#[allow(coherence_leak_check)]
525const _: () = {
526 #[cfg(all(feature = "std", target_arch = "wasm32", panic = "unwind"))]
527 closures!(@impl_for_args (&A) RefFromWasmAbi [T: core::panic::UnwindSafe,] &*A::ref_from_abi(A) => A a1 a2 a3 a4);
528
529 #[cfg(not(all(feature = "std", target_arch = "wasm32", panic = "unwind")))]
530 closures!(@impl_for_args (&A) RefFromWasmAbi [] &*A::ref_from_abi(A) => A a1 a2 a3 a4);
531};
532
533impl<'a, 'b, T1, T2> UpcastFrom<ScopedClosure<'a, T1>> for ScopedClosure<'b, T2>
537where
538 T1: ?Sized + WasmClosure,
539 T2: ?Sized + WasmClosure + UpcastFrom<T1>,
540{
541}
542
543impl<'a, 'b, T1, T2> UpcastFrom<ImmediateClosure<'a, T1>> for ImmediateClosure<'b, T2>
547where
548 T1: ?Sized + WasmClosure,
549 T2: ?Sized + WasmClosure,
550 T2: UpcastFrom<T1>,
551{
552}