From 6f8a944ba4311cbcf5922132721095c226c6fbab Mon Sep 17 00:00:00 2001
From: Kevin Reid <kpreid@switchb.org>
Date: Sun, 14 Jan 2024 16:18:44 -0800
Subject: [PATCH] Change return type of unstable `Waker::noop()` from `Waker`
 to `&Waker`.

The advantage of this is that it does not need to be assigned to a
variable to be used in a `Context` creation, which is the most common
thing to want to do with a noop waker.

If an owned noop waker is desired, it can be created by cloning, but the
reverse is harder. Alternatively, both versions could be provided, like
`futures::task::noop_waker()` and `futures::task::noop_waker_ref()`, but
that seems to me to be API clutter for a very small benefit, whereas
having the `&'static` reference available is a large benefit.

Previous discussion on the tracking issue starting here:
https://github.com/rust-lang/rust/issues/98286#issuecomment-1862159766
---
 library/core/src/task/wake.rs | 17 ++++++++++++-----
 1 file changed, 12 insertions(+), 5 deletions(-)

diff --git a/library/core/src/task/wake.rs b/library/core/src/task/wake.rs
index 9c41b8b4f46..077852b0120 100644
--- a/library/core/src/task/wake.rs
+++ b/library/core/src/task/wake.rs
@@ -329,12 +329,14 @@ impl Waker {
         Waker { waker }
     }
 
-    /// Creates a new `Waker` that does nothing when `wake` is called.
+    /// Returns a reference to a `Waker` that does nothing when used.
     ///
     /// This is mostly useful for writing tests that need a [`Context`] to poll
     /// some futures, but are not expecting those futures to wake the waker or
     /// do not need to do anything specific if it happens.
     ///
+    /// If an owned `Waker` is needed, `clone()` this one.
+    ///
     /// # Examples
     ///
     /// ```
@@ -343,8 +345,7 @@ impl Waker {
     /// use std::future::Future;
     /// use std::task;
     ///
-    /// let waker = task::Waker::noop();
-    /// let mut cx = task::Context::from_waker(&waker);
+    /// let mut cx = task::Context::from_waker(task::Waker::noop());
     ///
     /// let mut future = Box::pin(async { 10 });
     /// assert_eq!(future.as_mut().poll(&mut cx), task::Poll::Ready(10));
@@ -352,7 +353,12 @@ impl Waker {
     #[inline]
     #[must_use]
     #[unstable(feature = "noop_waker", issue = "98286")]
-    pub const fn noop() -> Waker {
+    pub const fn noop() -> &'static Waker {
+        // Ideally all this data would be explicitly `static` because it is used by reference and
+        // only ever needs one copy. But `const fn`s (and `const` items) cannot refer to statics,
+        // even though their values can be promoted to static. (That might change; see #119618.)
+        // An alternative would be a `pub static NOOP: &Waker`, but associated static items are not
+        // currently allowed either, and making it non-associated would be unergonomic.
         const VTABLE: RawWakerVTable = RawWakerVTable::new(
             // Cloning just returns a new no-op raw waker
             |_| RAW,
@@ -364,8 +370,9 @@ impl Waker {
             |_| {},
         );
         const RAW: RawWaker = RawWaker::new(ptr::null(), &VTABLE);
+        const WAKER_REF: &Waker = &Waker { waker: RAW };
 
-        Waker { waker: RAW }
+        WAKER_REF
     }
 
     /// Get a reference to the underlying [`RawWaker`].