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 = &'static 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_wrap(closures!(@closure $FnArgs $($var)* {
295 let result = self($($var),*);
296
297 debug_assert_eq!(Rc::strong_count(&rc2), 1);
300 let option_closure = rc2.borrow_mut().take();
301 debug_assert!(option_closure.is_some());
302 drop(option_closure);
303
304 result
305 }));
306
307 let js_val = closure.as_ref().clone();
308
309 *rc1.borrow_mut() = Some(closure);
310 debug_assert_eq!(Rc::strong_count(&rc1), 2);
311 drop(rc1);
312
313 js_val
314 }
315 }
316 };
317
318 ([$($unwind_safe:tt)*] $( ($($var:ident $arg1:ident $arg2:ident $arg3:ident $arg4:ident)*) )*) => ($(
319 closures!(@impl_for_args ($($var),*) FromWasmAbi [$($maybe_unwind_safe)*] $($var::from_abi($var) => $var $arg1 $arg2 $arg3 $arg4)*);
320 )*);
321}
322
323#[cfg(all(feature = "std", target_arch = "wasm32", panic = "unwind"))]
324closures! {
325 [T: core::panic::UnwindSafe,]
326 ()
327 (A a1 a2 a3 a4)
328 (A a1 a2 a3 a4 B b1 b2 b3 b4)
329 (A a1 a2 a3 a4 B b1 b2 b3 b4 C c1 c2 c3 c4)
330 (A a1 a2 a3 a4 B b1 b2 b3 b4 C c1 c2 c3 c4 D d1 d2 d3 d4)
331 (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)
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 F f1 f2 f3 f4)
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 G g1 g2 g3 g4)
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 H h1 h2 h3 h4)
335}
336
337#[cfg(not(all(feature = "std", target_arch = "wasm32", panic = "unwind")))]
338closures! {
339 []
340 ()
341 (A a1 a2 a3 a4)
342 (A a1 a2 a3 a4 B b1 b2 b3 b4)
343 (A a1 a2 a3 a4 B b1 b2 b3 b4 C c1 c2 c3 c4)
344 (A a1 a2 a3 a4 B b1 b2 b3 b4 C c1 c2 c3 c4 D d1 d2 d3 d4)
345 (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)
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 F f1 f2 f3 f4)
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 G g1 g2 g3 g4)
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 H h1 h2 h3 h4)
349}
350
351macro_rules! impl_fn_upcasts {
353 () => {
354 impl_fn_upcasts!(@arities
355 [0 []]
356 [1 [A1 B1] O1]
357 [2 [A1 B1 A2 B2] O2]
358 [3 [A1 B1 A2 B2 A3 B3] O3]
359 [4 [A1 B1 A2 B2 A3 B3 A4 B4] O4]
360 [5 [A1 B1 A2 B2 A3 B3 A4 B4 A5 B5] O5]
361 [6 [A1 B1 A2 B2 A3 B3 A4 B4 A5 B5 A6 B6] O6]
362 [7 [A1 B1 A2 B2 A3 B3 A4 B4 A5 B5 A6 B6 A7 B7] O7]
363 [8 [A1 B1 A2 B2 A3 B3 A4 B4 A5 B5 A6 B6 A7 B7 A8 B8] O8]
364 );
365 };
366
367 (@arities) => {};
368
369 (@arities [$n:tt $args:tt $($opt:ident)?] $([$rest_n:tt $rest_args:tt $($rest_opt:ident)?])*) => {
370 impl_fn_upcasts!(@same $args);
371 impl_fn_upcasts!(@cross_all $args [] $([$rest_n $rest_args $($rest_opt)?])*);
372 impl_fn_upcasts!(@arities $([$rest_n $rest_args $($rest_opt)?])*);
373 };
374
375 (@same []) => {
376 impl<R1, R2> UpcastFrom<fn() -> R1> for fn() -> R2
377 where
378 R2: UpcastFrom<R1>
379 {}
380
381 impl<'a, R1, R2> UpcastFrom<dyn Fn() -> R1 + 'a> for dyn Fn() -> R2 + 'a
382 where
383 R2: UpcastFrom<R1>
384 {}
385
386 impl<'a, R1, R2> UpcastFrom<dyn FnMut() -> R1 + 'a> for dyn FnMut() -> R2 + 'a
387 where
388 R2: UpcastFrom<R1>
389 {}
390 };
391
392 (@same [$($A1:ident $A2:ident)+]) => {
394 impl<R1, R2, $($A1, $A2),+> UpcastFrom<fn($($A1),+) -> R1> for fn($($A2),+) -> R2
395 where
396 R2: UpcastFrom<R1>,
397 $($A1: UpcastFrom<$A2>,)+
398 {}
399
400 impl<'a, R1, R2, $($A1, $A2),+> UpcastFrom<dyn Fn($($A1),+) -> R1 + 'a> for dyn Fn($($A2),+) -> R2 + 'a
401 where
402 R2: UpcastFrom<R1>,
403 $($A1: UpcastFrom<$A2>,)+
404 {}
405
406 impl<'a, R1, R2, $($A1, $A2),+> UpcastFrom<dyn FnMut($($A1),+) -> R1 + 'a> for dyn FnMut($($A2),+) -> R2 + 'a
407 where
408 R2: UpcastFrom<R1>,
409 $($A1: UpcastFrom<$A2>,)+
410 {}
411 };
412
413 (@cross_all $args:tt $opts:tt) => {};
415
416 (@cross_all $args:tt [$($opts:ident)*] [$next_n:tt $next_args:tt $next_opt:ident] $([$rest_n:tt $rest_args:tt $($rest_opt:ident)?])*) => {
418 impl_fn_upcasts!(@extend $args [$($opts)* $next_opt]);
419 impl_fn_upcasts!(@shrink $args [$($opts)* $next_opt]);
420 impl_fn_upcasts!(@cross_all $args [$($opts)* $next_opt] $([$rest_n $rest_args $($rest_opt)?])*);
421 };
422
423 (@extend [] [$($O:ident)+]) => {
425 impl<R1, R2, $($O),+> UpcastFrom<fn() -> R1> for fn($($O),+) -> R2
426 where
427 R2: UpcastFrom<R1>,
428 $($O: UpcastFrom<Undefined>,)+
429 {}
430
431 impl<'a, R1, R2, $($O),+> UpcastFrom<dyn Fn() -> R1 + 'a> for dyn Fn($($O),+) -> R2 + 'a
432 where
433 R2: UpcastFrom<R1>,
434 $($O: UpcastFrom<Undefined>,)+
435 {}
436
437 impl<'a, R1, R2, $($O),+> UpcastFrom<dyn FnMut() -> R1 + 'a> for dyn FnMut($($O),+) -> R2 + 'a
438 where
439 R2: UpcastFrom<R1>,
440 $($O: UpcastFrom<Undefined>,)+
441 {}
442 };
443
444 (@extend [$($A1:ident $A2:ident)+] [$($O:ident)+]) => {
446 impl<R1, R2, $($A1, $A2,)+ $($O),+> UpcastFrom<fn($($A1),+) -> R1> for fn($($A2,)+ $($O),+) -> R2
447 where
448 R2: UpcastFrom<R1>,
449 $($A1: UpcastFrom<$A2>,)+ $($O: UpcastFrom<Undefined>,)+
451 {}
452
453 impl<'a, R1, R2, $($A1, $A2,)+ $($O),+> UpcastFrom<dyn Fn($($A1),+) -> R1 + 'a> for dyn Fn($($A2,)+ $($O),+) -> R2 + 'a
454 where
455 R2: UpcastFrom<R1>,
456 $($A1: UpcastFrom<$A2>,)+ $($O: UpcastFrom<Undefined>,)+
458 {}
459
460 impl<'a, R1, R2, $($A1, $A2,)+ $($O),+> UpcastFrom<dyn FnMut($($A1),+) -> R1 + 'a> for dyn FnMut($($A2,)+ $($O),+) -> R2 + 'a
461 where
462 R2: UpcastFrom<R1>,
463 $($A1: UpcastFrom<$A2>,)+ $($O: UpcastFrom<Undefined>,)+
465 {}
466 };
467
468 (@shrink [] [$($O:ident)+]) => {
470 impl<R1, R2, $($O),+> UpcastFrom<fn($($O),+) -> R1> for fn() -> R2
471 where
472 R2: UpcastFrom<R1>,
473 $($O: UpcastFrom<Undefined>,)+
474 {}
475
476 impl<'a, R1, R2, $($O),+> UpcastFrom<dyn Fn($($O),+) -> R1 + 'a> for dyn Fn() -> R2 + 'a
477 where
478 R2: UpcastFrom<R1>,
479 $($O: UpcastFrom<Undefined>,)+
480 {}
481
482 impl<'a, R1, R2, $($O),+> UpcastFrom<dyn FnMut($($O),+) -> R1 + 'a> for dyn FnMut() -> R2 + 'a
483 where
484 R2: UpcastFrom<R1>,
485 $($O: UpcastFrom<Undefined>,)+
486 {}
487 };
488
489 (@shrink [$($A1:ident $A2:ident)+] [$($O:ident)+]) => {
491 impl<R1, R2, $($A1, $A2,)+ $($O),+> UpcastFrom<fn($($A1,)+ $($O),+) -> R1> for fn($($A2),+) -> R2
492 where
493 R2: UpcastFrom<R1>,
494 $($A1: UpcastFrom<$A2>,)+ $($O: UpcastFrom<Undefined>,)+
496 {}
497
498 impl<'a, R1, R2, $($A1, $A2,)+ $($O),+> UpcastFrom<dyn Fn($($A1,)+ $($O),+) -> R1 + 'a> for dyn Fn($($A2),+) -> R2 + 'a
499 where
500 R2: UpcastFrom<R1>,
501 $($A1: UpcastFrom<$A2>,)+ $($O: UpcastFrom<Undefined>,)+
503 {}
504
505 impl<'a, R1, R2, $($A1, $A2,)+ $($O),+> UpcastFrom<dyn FnMut($($A1,)+ $($O),+) -> R1 + 'a> for dyn FnMut($($A2),+) -> R2 + 'a
506 where
507 R2: UpcastFrom<R1>,
508 $($A1: UpcastFrom<$A2>,)+ $($O: UpcastFrom<Undefined>,)+
510 {}
511 };
512}
513
514impl_fn_upcasts!();
515
516#[allow(coherence_leak_check)]
524const _: () = {
525 #[cfg(all(feature = "std", target_arch = "wasm32", panic = "unwind"))]
526 closures!(@impl_for_args (&A) RefFromWasmAbi [T: core::panic::UnwindSafe,] &*A::ref_from_abi(A) => A a1 a2 a3 a4);
527
528 #[cfg(not(all(feature = "std", target_arch = "wasm32", panic = "unwind")))]
529 closures!(@impl_for_args (&A) RefFromWasmAbi [] &*A::ref_from_abi(A) => A a1 a2 a3 a4);
530};
531
532impl<'a, 'b, T1, T2> UpcastFrom<ScopedClosure<'a, T1>> for ScopedClosure<'b, T2>
536where
537 T1: ?Sized + WasmClosure,
538 T2: ?Sized + WasmClosure + UpcastFrom<T1>,
539{
540}
541
542impl<'a, 'b, T1, T2> UpcastFrom<ImmediateClosure<'a, T1>> for ImmediateClosure<'b, T2>
546where
547 T1: ?Sized + WasmClosure,
548 T2: ?Sized + WasmClosure,
549 T2: UpcastFrom<T1>,
550{
551}