@@ -190,6 +190,9 @@ unsafe extern "C" fn trampoline_indirect<T: FnOnce()>(env: ClosureEnv) {
190
190
///
191
191
/// // `(&'static P0, impl FnOnce(&'static P0))` → `Closure`
192
192
/// const _: Closure = (&42, |_: &i32| {}).into_closure_const();
193
+ ///
194
+ /// // `(usize, impl FnOnce(usize))` → `Closure`
195
+ /// const _: Closure = (42usize, |_: usize| {}).into_closure_const();
193
196
/// ```
194
197
pub trait IntoClosureConst {
195
198
/// Perform conversion to [`Closure`], potentially using a compile-time
@@ -222,7 +225,28 @@ impl<T: FnOnce(&'static P0) + Copy + Send + 'static, P0: Sync + 'static> const I
222
225
}
223
226
224
227
if size_of :: < T > ( ) == 0 {
225
- unsafe { Closure :: from_raw_parts ( trampoline_zst_param :: < T , P0 > , transmute ( self . 0 ) ) }
228
+ unsafe { Closure :: from_raw_parts ( trampoline_ptr_spec :: < T , P0 > , transmute ( self . 0 ) ) }
229
+ } else {
230
+ ( move || ( self . 1 ) ( self . 0 ) ) . into_closure_const ( )
231
+ }
232
+ }
233
+ }
234
+
235
+ /// Packs `usize` directly in [`ClosureEnv`][] if `T` is zero-sized.
236
+ ///
237
+ /// Due to compiler restrictions, this optimization is currently impossible
238
+ /// to do in the generic constructor ([`Closure::from_fn_const`]).
239
+ // FIXME: See above
240
+ impl < T : FnOnce ( usize ) + Copy + Send + ' static > const IntoClosureConst for ( usize , T ) {
241
+ fn into_closure_const ( self ) -> Closure {
242
+ unsafe extern "C" fn trampoline_usize_spec < T : FnOnce ( usize ) > ( env : ClosureEnv ) {
243
+ let p0: usize = unsafe { transmute ( env) } ;
244
+ let func: T = unsafe { transmute ( ( ) ) } ;
245
+ func ( p0)
246
+ }
247
+
248
+ if size_of :: < T > ( ) == 0 {
249
+ unsafe { Closure :: from_raw_parts ( trampoline_usize_spec :: < T > , transmute ( self . 0 ) ) }
226
250
} else {
227
251
( move || ( self . 1 ) ( self . 0 ) ) . into_closure_const ( )
228
252
}
@@ -303,4 +327,10 @@ mod tests {
303
327
const C : Closure = ( & 42 , |x : & i32 | assert_eq ! ( * x, 42 ) ) . into_closure_const ( ) ;
304
328
C . call ( ) ;
305
329
}
330
+
331
+ #[ test]
332
+ fn usize_env_spec ( ) {
333
+ const C : Closure = ( 42usize , |x : usize | assert_eq ! ( x, 42 ) ) . into_closure_const ( ) ;
334
+ C . call ( ) ;
335
+ }
306
336
}
0 commit comments