From 675ba3834574870c5bca4033578644b57b31dffd Mon Sep 17 00:00:00 2001 From: Oleksandr Babak Date: Sun, 31 Aug 2025 14:34:29 +0200 Subject: [PATCH 1/2] feat: add `from_fn_ptr` to `Waker` and `LocalWaker` --- library/core/src/task/wake.rs | 44 +++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/library/core/src/task/wake.rs b/library/core/src/task/wake.rs index bb7efe582f7a3..178717fe42eac 100644 --- a/library/core/src/task/wake.rs +++ b/library/core/src/task/wake.rs @@ -584,6 +584,28 @@ impl Waker { pub fn vtable(&self) -> &'static RawWakerVTable { self.waker.vtable } + + /// Constructs a `Waker` from a function pointer. + #[inline] + #[must_use] + #[unstable(feature = "waker_from_fn_ptr", issue = "146055")] + pub const fn from_fn_ptr(f: fn()) -> Self { + // SAFETY: Unsafe is used for transmutes, pointer came from `fn()` so it + // is sound to transmute it back to `fn()`. + static VTABLE: RawWakerVTable = unsafe { + RawWakerVTable::new( + |this| RawWaker::new(this, &VTABLE), + |this| transmute::<*const (), fn()>(this)(), + |this| transmute::<*const (), fn()>(this)(), + |_| {}, + ) + }; + let raw = RawWaker::new(f as *const (), &VTABLE); + + // SAFETY: `clone` is just a copy, `drop` is a no-op while `wake` and + // `wake_by_ref` just call the function pointer. + unsafe { Self::from_raw(raw) } + } } #[stable(feature = "futures_api", since = "1.36.0")] @@ -879,6 +901,28 @@ impl LocalWaker { pub fn vtable(&self) -> &'static RawWakerVTable { self.waker.vtable } + + /// Constructs a `LocalWaker` from a function pointer. + #[inline] + #[must_use] + #[unstable(feature = "waker_from_fn_ptr", issue = "146055")] + pub const fn from_fn_ptr(f: fn()) -> Self { + // SAFETY: Unsafe is used for transmutes, pointer came from `fn()` so it + // is sound to transmute it back to `fn()`. + static VTABLE: RawWakerVTable = unsafe { + RawWakerVTable::new( + |this| RawWaker::new(this, &VTABLE), + |this| transmute::<*const (), fn()>(this)(), + |this| transmute::<*const (), fn()>(this)(), + |_| {}, + ) + }; + let raw = RawWaker::new(f as *const (), &VTABLE); + + // SAFETY: `clone` is just a copy, `drop` is a no-op while `wake` and + // `wake_by_ref` just call the function pointer. + unsafe { Self::from_raw(raw) } + } } #[unstable(feature = "local_waker", issue = "118959")] impl Clone for LocalWaker { From 75835fb8255df8ccfab39ed1d2dec6f28d23d97e Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Mon, 3 Nov 2025 17:17:14 -0800 Subject: [PATCH 2/2] Repoint Waker::from_fn_ptr from feature request issue to tracking issue --- library/core/src/task/wake.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/core/src/task/wake.rs b/library/core/src/task/wake.rs index 178717fe42eac..480b3c4577eb6 100644 --- a/library/core/src/task/wake.rs +++ b/library/core/src/task/wake.rs @@ -588,7 +588,7 @@ impl Waker { /// Constructs a `Waker` from a function pointer. #[inline] #[must_use] - #[unstable(feature = "waker_from_fn_ptr", issue = "146055")] + #[unstable(feature = "waker_from_fn_ptr", issue = "148457")] pub const fn from_fn_ptr(f: fn()) -> Self { // SAFETY: Unsafe is used for transmutes, pointer came from `fn()` so it // is sound to transmute it back to `fn()`. @@ -905,7 +905,7 @@ impl LocalWaker { /// Constructs a `LocalWaker` from a function pointer. #[inline] #[must_use] - #[unstable(feature = "waker_from_fn_ptr", issue = "146055")] + #[unstable(feature = "waker_from_fn_ptr", issue = "148457")] pub const fn from_fn_ptr(f: fn()) -> Self { // SAFETY: Unsafe is used for transmutes, pointer came from `fn()` so it // is sound to transmute it back to `fn()`.