Skip to content

Commit 5fe99dc

Browse files
committed
feat(closure): add a specific impl of IntoClosureConst for passing exactly one usize
1 parent 118d76a commit 5fe99dc

File tree

1 file changed

+31
-1
lines changed

1 file changed

+31
-1
lines changed

src/r3_core/src/closure.rs

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,9 @@ unsafe extern "C" fn trampoline_indirect<T: FnOnce()>(env: ClosureEnv) {
190190
///
191191
/// // `(&'static P0, impl FnOnce(&'static P0))` → `Closure`
192192
/// const _: Closure = (&42, |_: &i32| {}).into_closure_const();
193+
///
194+
/// // `(usize, impl FnOnce(usize))` → `Closure`
195+
/// const _: Closure = (42usize, |_: usize| {}).into_closure_const();
193196
/// ```
194197
pub trait IntoClosureConst {
195198
/// 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
222225
}
223226

224227
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)) }
226250
} else {
227251
(move || (self.1)(self.0)).into_closure_const()
228252
}
@@ -303,4 +327,10 @@ mod tests {
303327
const C: Closure = (&42, |x: &i32| assert_eq!(*x, 42)).into_closure_const();
304328
C.call();
305329
}
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+
}
306336
}

0 commit comments

Comments
 (0)