Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 3c7cca7

Browse files
authoredJan 16, 2024
Rollup merge of rust-lang#119984 - kpreid:waker-noop, r=dtolnay
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. It also avoids unnecessarily executing the dynamically dispatched drop function when the noop waker is dropped. If an owned noop waker is desired, it can be created by cloning, but the reverse is harder to do since it requires declaring a constant. 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 reduction in boilerplate. [Previous discussion on the tracking issue starting here](rust-lang#98286 (comment))
2 parents 3ef303b + 7052188 commit 3c7cca7

24 files changed

+46
-60
lines changed
 

‎library/core/src/task/wake.rs

+12-5
Original file line numberDiff line numberDiff line change
@@ -329,12 +329,14 @@ impl Waker {
329329
Waker { waker }
330330
}
331331

332-
/// Creates a new `Waker` that does nothing when `wake` is called.
332+
/// Returns a reference to a `Waker` that does nothing when used.
333333
///
334334
/// This is mostly useful for writing tests that need a [`Context`] to poll
335335
/// some futures, but are not expecting those futures to wake the waker or
336336
/// do not need to do anything specific if it happens.
337337
///
338+
/// If an owned `Waker` is needed, `clone()` this one.
339+
///
338340
/// # Examples
339341
///
340342
/// ```
@@ -343,16 +345,20 @@ impl Waker {
343345
/// use std::future::Future;
344346
/// use std::task;
345347
///
346-
/// let waker = task::Waker::noop();
347-
/// let mut cx = task::Context::from_waker(&waker);
348+
/// let mut cx = task::Context::from_waker(task::Waker::noop());
348349
///
349350
/// let mut future = Box::pin(async { 10 });
350351
/// assert_eq!(future.as_mut().poll(&mut cx), task::Poll::Ready(10));
351352
/// ```
352353
#[inline]
353354
#[must_use]
354355
#[unstable(feature = "noop_waker", issue = "98286")]
355-
pub const fn noop() -> Waker {
356+
pub const fn noop() -> &'static Waker {
357+
// Ideally all this data would be explicitly `static` because it is used by reference and
358+
// only ever needs one copy. But `const fn`s (and `const` items) cannot refer to statics,
359+
// even though their values can be promoted to static. (That might change; see #119618.)
360+
// An alternative would be a `pub static NOOP: &Waker`, but associated static items are not
361+
// currently allowed either, and making it non-associated would be unergonomic.
356362
const VTABLE: RawWakerVTable = RawWakerVTable::new(
357363
// Cloning just returns a new no-op raw waker
358364
|_| RAW,
@@ -364,8 +370,9 @@ impl Waker {
364370
|_| {},
365371
);
366372
const RAW: RawWaker = RawWaker::new(ptr::null(), &VTABLE);
373+
const WAKER_REF: &Waker = &Waker { waker: RAW };
367374

368-
Waker { waker: RAW }
375+
WAKER_REF
369376
}
370377

371378
/// Get a reference to the underlying [`RawWaker`].

‎library/core/tests/async_iter/mod.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,7 @@ fn into_async_iter() {
77
let async_iter = async_iter::from_iter(0..3);
88
let mut async_iter = pin!(async_iter.into_async_iter());
99

10-
let waker = core::task::Waker::noop();
11-
let mut cx = &mut core::task::Context::from_waker(&waker);
10+
let mut cx = &mut core::task::Context::from_waker(core::task::Waker::noop());
1211

1312
assert_eq!(async_iter.as_mut().poll_next(&mut cx), Poll::Ready(Some(0)));
1413
assert_eq!(async_iter.as_mut().poll_next(&mut cx), Poll::Ready(Some(1)));

‎src/tools/miri/tests/pass/async-fn.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,7 @@ async fn uninhabited_variant() {
7676
fn run_fut<T>(fut: impl Future<Output = T>) -> T {
7777
use std::task::{Context, Poll, Waker};
7878

79-
let waker = Waker::noop();
80-
let mut context = Context::from_waker(&waker);
79+
let mut context = Context::from_waker(Waker::noop());
8180

8281
let mut pinned = Box::pin(fut);
8382
loop {

‎src/tools/miri/tests/pass/dyn-star.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -93,8 +93,7 @@ fn dispatch_on_pin_mut() {
9393
let mut fut = async_main();
9494

9595
// Poll loop, just to test the future...
96-
let waker = Waker::noop();
97-
let ctx = &mut Context::from_waker(&waker);
96+
let ctx = &mut Context::from_waker(Waker::noop());
9897

9998
loop {
10099
match unsafe { Pin::new_unchecked(&mut fut).poll(ctx) } {

‎src/tools/miri/tests/pass/future-self-referential.rs

+2-4
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,7 @@ impl Future for DoStuff {
7777
}
7878

7979
fn run_fut<T>(fut: impl Future<Output = T>) -> T {
80-
let waker = Waker::noop();
81-
let mut context = Context::from_waker(&waker);
80+
let mut context = Context::from_waker(Waker::noop());
8281

8382
let mut pinned = pin!(fut);
8483
loop {
@@ -90,8 +89,7 @@ fn run_fut<T>(fut: impl Future<Output = T>) -> T {
9089
}
9190

9291
fn self_referential_box() {
93-
let waker = Waker::noop();
94-
let cx = &mut Context::from_waker(&waker);
92+
let cx = &mut Context::from_waker(Waker::noop());
9593

9694
async fn my_fut() -> i32 {
9795
let val = 10;

‎src/tools/miri/tests/pass/issues/issue-miri-2068.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,7 @@ use std::task::{Context, Poll, Waker};
66

77
pub fn fuzzing_block_on<O, F: Future<Output = O>>(fut: F) -> O {
88
let mut fut = std::pin::pin!(fut);
9-
let waker = Waker::noop();
10-
let mut context = Context::from_waker(&waker);
9+
let mut context = Context::from_waker(Waker::noop());
1110
loop {
1211
match fut.as_mut().poll(&mut context) {
1312
Poll::Ready(v) => return v,

‎src/tools/miri/tests/pass/move-data-across-await-point.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,7 @@ fn data_moved() {
5656
fn run_fut<T>(fut: impl Future<Output = T>) -> T {
5757
use std::task::{Context, Poll, Waker};
5858

59-
let waker = Waker::noop();
60-
let mut context = Context::from_waker(&waker);
59+
let mut context = Context::from_waker(Waker::noop());
6160

6261
let mut pinned = Box::pin(fut);
6362
loop {

‎tests/coverage/async.coverage

+1-2
Original file line numberDiff line numberDiff line change
@@ -117,8 +117,7 @@
117117
LL| | #[coverage(off)]
118118
LL| | pub fn block_on<F: Future>(mut future: F) -> F::Output {
119119
LL| | let mut future = pin!(future);
120-
LL| | let waker = Waker::noop();
121-
LL| | let mut context = Context::from_waker(&waker);
120+
LL| | let mut context = Context::from_waker(Waker::noop());
122121
LL| |
123122
LL| | loop {
124123
LL| | if let Poll::Ready(val) = future.as_mut().poll(&mut context) {

‎tests/coverage/async.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -110,8 +110,7 @@ mod executor {
110110
#[coverage(off)]
111111
pub fn block_on<F: Future>(mut future: F) -> F::Output {
112112
let mut future = pin!(future);
113-
let waker = Waker::noop();
114-
let mut context = Context::from_waker(&waker);
113+
let mut context = Context::from_waker(Waker::noop());
115114

116115
loop {
117116
if let Poll::Ready(val) = future.as_mut().poll(&mut context) {

‎tests/coverage/async2.coverage

+1-2
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,7 @@
4141
LL| | #[coverage(off)]
4242
LL| | pub fn block_on<F: Future>(mut future: F) -> F::Output {
4343
LL| | let mut future = pin!(future);
44-
LL| | let waker = Waker::noop();
45-
LL| | let mut context = Context::from_waker(&waker);
44+
LL| | let mut context = Context::from_waker(Waker::noop());
4645
LL| |
4746
LL| | loop {
4847
LL| | if let Poll::Ready(val) = future.as_mut().poll(&mut context) {

‎tests/coverage/async2.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,7 @@ mod executor {
3939
#[coverage(off)]
4040
pub fn block_on<F: Future>(mut future: F) -> F::Output {
4141
let mut future = pin!(future);
42-
let waker = Waker::noop();
43-
let mut context = Context::from_waker(&waker);
42+
let mut context = Context::from_waker(Waker::noop());
4443

4544
loop {
4645
if let Poll::Ready(val) = future.as_mut().poll(&mut context) {

‎tests/coverage/async_block.coverage

+1-2
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,7 @@
2424
LL| | #[coverage(off)]
2525
LL| | pub fn block_on<F: Future>(mut future: F) -> F::Output {
2626
LL| | let mut future = pin!(future);
27-
LL| | let waker = Waker::noop();
28-
LL| | let mut context = Context::from_waker(&waker);
27+
LL| | let mut context = Context::from_waker(Waker::noop());
2928
LL| |
3029
LL| | loop {
3130
LL| | if let Poll::Ready(val) = future.as_mut().poll(&mut context) {

‎tests/coverage/async_block.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,7 @@ mod executor {
2323
#[coverage(off)]
2424
pub fn block_on<F: Future>(mut future: F) -> F::Output {
2525
let mut future = pin!(future);
26-
let waker = Waker::noop();
27-
let mut context = Context::from_waker(&waker);
26+
let mut context = Context::from_waker(Waker::noop());
2827

2928
loop {
3029
if let Poll::Ready(val) = future.as_mut().poll(&mut context) {
+8-8
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,28 @@
11
Function name: closure_macro_async::load_configuration_files
2-
Raw bytes (9): 0x[01, 01, 00, 01, 01, 1e, 01, 02, 02]
2+
Raw bytes (9): 0x[01, 01, 00, 01, 01, 1f, 01, 02, 02]
33
Number of files: 1
44
- file 0 => global file 1
55
Number of expressions: 0
66
Number of file 0 mappings: 1
7-
- Code(Counter(0)) at (prev + 30, 1) to (start + 2, 2)
7+
- Code(Counter(0)) at (prev + 31, 1) to (start + 2, 2)
88

99
Function name: closure_macro_async::test
10-
Raw bytes (9): 0x[01, 01, 00, 01, 01, 22, 01, 00, 2b]
10+
Raw bytes (9): 0x[01, 01, 00, 01, 01, 23, 01, 00, 2b]
1111
Number of files: 1
1212
- file 0 => global file 1
1313
Number of expressions: 0
1414
Number of file 0 mappings: 1
15-
- Code(Counter(0)) at (prev + 34, 1) to (start + 0, 43)
15+
- Code(Counter(0)) at (prev + 35, 1) to (start + 0, 43)
1616

1717
Function name: closure_macro_async::test::{closure#0}
18-
Raw bytes (43): 0x[01, 01, 02, 01, 05, 05, 02, 07, 01, 22, 2b, 01, 21, 02, 02, 09, 00, 0f, 05, 00, 12, 00, 13, 02, 00, 12, 00, 13, 05, 00, 54, 00, 55, 02, 02, 09, 02, 0b, 07, 03, 01, 00, 02]
18+
Raw bytes (43): 0x[01, 01, 02, 01, 05, 05, 02, 07, 01, 23, 2b, 01, 21, 02, 02, 09, 00, 0f, 05, 00, 12, 00, 13, 02, 00, 12, 00, 13, 05, 00, 54, 00, 55, 02, 02, 09, 02, 0b, 07, 03, 01, 00, 02]
1919
Number of files: 1
2020
- file 0 => global file 1
2121
Number of expressions: 2
2222
- expression 0 operands: lhs = Counter(0), rhs = Counter(1)
2323
- expression 1 operands: lhs = Counter(1), rhs = Expression(0, Sub)
2424
Number of file 0 mappings: 7
25-
- Code(Counter(0)) at (prev + 34, 43) to (start + 1, 33)
25+
- Code(Counter(0)) at (prev + 35, 43) to (start + 1, 33)
2626
- Code(Expression(0, Sub)) at (prev + 2, 9) to (start + 0, 15)
2727
= (c0 - c1)
2828
- Code(Counter(1)) at (prev + 0, 18) to (start + 0, 19)
@@ -35,10 +35,10 @@ Number of file 0 mappings: 7
3535
= (c1 + (c0 - c1))
3636

3737
Function name: closure_macro_async::test::{closure#0}::{closure#0}
38-
Raw bytes (9): 0x[01, 01, 00, 01, 01, 24, 12, 00, 54]
38+
Raw bytes (9): 0x[01, 01, 00, 01, 01, 25, 12, 00, 54]
3939
Number of files: 1
4040
- file 0 => global file 1
4141
Number of expressions: 0
4242
Number of file 0 mappings: 1
43-
- Code(Counter(0)) at (prev + 36, 18) to (start + 0, 84)
43+
- Code(Counter(0)) at (prev + 37, 18) to (start + 0, 84)
4444

‎tests/coverage/closure_macro_async.coverage

+1-2
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,7 @@
5454
LL| | #[coverage(off)]
5555
LL| | pub fn block_on<F: Future>(mut future: F) -> F::Output {
5656
LL| | let mut future = pin!(future);
57-
LL| | let waker = Waker::noop();
58-
LL| | let mut context = Context::from_waker(&waker);
57+
LL| | let mut context = Context::from_waker(Waker::noop());
5958
LL| |
6059
LL| | loop {
6160
LL| | if let Poll::Ready(val) = future.as_mut().poll(&mut context) {

‎tests/coverage/closure_macro_async.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ macro_rules! bail {
1515

1616
macro_rules! on_error {
1717
($value:expr, $error_message:expr) => {
18-
$value.or_else(|e| { // FIXME(85000): no coverage in closure macros
18+
$value.or_else(|e| {
19+
// FIXME(85000): no coverage in closure macros
1920
let message = format!($error_message, e);
2021
if message.len() > 0 {
2122
println!("{}", message);
@@ -53,8 +54,7 @@ mod executor {
5354
#[coverage(off)]
5455
pub fn block_on<F: Future>(mut future: F) -> F::Output {
5556
let mut future = pin!(future);
56-
let waker = Waker::noop();
57-
let mut context = Context::from_waker(&waker);
57+
let mut context = Context::from_waker(Waker::noop());
5858

5959
loop {
6060
if let Poll::Ready(val) = future.as_mut().poll(&mut context) {

‎tests/ui/async-await/for-await-passthrough.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,7 @@ async fn real_main() {
2525

2626
fn main() {
2727
let future = real_main();
28-
let waker = std::task::Waker::noop();
29-
let mut cx = &mut core::task::Context::from_waker(&waker);
28+
let mut cx = &mut core::task::Context::from_waker(std::task::Waker::noop());
3029
let mut future = core::pin::pin!(future);
3130
while let core::task::Poll::Pending = future.as_mut().poll(&mut cx) {}
3231
}

‎tests/ui/async-await/for-await.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,7 @@ async fn real_main() {
1717

1818
fn main() {
1919
let future = real_main();
20-
let waker = std::task::Waker::noop();
21-
let mut cx = &mut core::task::Context::from_waker(&waker);
20+
let mut cx = &mut core::task::Context::from_waker(std::task::Waker::noop());
2221
let mut future = core::pin::pin!(future);
2322
while let core::task::Poll::Pending = future.as_mut().poll(&mut cx) {}
2423
}

‎tests/ui/async-await/in-trait/async-default-fn-overridden.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,7 @@ fn main() {
4040
let mut fut = pin!(async_main());
4141

4242
// Poll loop, just to test the future...
43-
let waker = Waker::noop();
44-
let ctx = &mut Context::from_waker(&waker);
43+
let ctx = &mut Context::from_waker(Waker::noop());
4544

4645
loop {
4746
match fut.as_mut().poll(ctx) {

‎tests/ui/async-await/in-trait/dont-project-to-specializable-projection.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,7 @@ fn main() {
4343
let mut fut = pin!(async_main());
4444

4545
// Poll loop, just to test the future...
46-
let waker = Waker::noop();
47-
let ctx = &mut Context::from_waker(&waker);
46+
let ctx = &mut Context::from_waker(Waker::noop());
4847

4948
loop {
5049
match fut.as_mut().poll(ctx) {

‎tests/ui/async-await/in-trait/dont-project-to-specializable-projection.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ LL | default async fn foo(_: T) -> &'static str {
2121
= note: specialization behaves in inconsistent and surprising ways with async functions in traits, and for now is disallowed
2222

2323
error[E0599]: no method named `poll` found for struct `Pin<&mut impl Future<Output = ()>>` in the current scope
24-
--> $DIR/dont-project-to-specializable-projection.rs:50:28
24+
--> $DIR/dont-project-to-specializable-projection.rs:49:28
2525
|
2626
LL | match fut.as_mut().poll(ctx) {
2727
| ^^^^ method not found in `Pin<&mut impl Future<Output = ()>>`

‎tests/ui/coroutine/async-gen-yield-ty-is-unit.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ async gen fn gen_fn() -> &'static str {
1111

1212
pub fn main() {
1313
let async_iterator = pin!(gen_fn());
14-
let waker = Waker::noop();
15-
let ctx = &mut Context::from_waker(&waker);
14+
let ctx = &mut Context::from_waker(Waker::noop());
1615
async_iterator.poll_next(ctx);
1716
}

‎tests/ui/coroutine/async_gen_fn_iter.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,7 @@ fn main() {
7474
let mut fut = pin!(async_main());
7575

7676
// Poll loop, just to test the future...
77-
let waker = Waker::noop();
78-
let ctx = &mut Context::from_waker(&waker);
77+
let ctx = &mut Context::from_waker(Waker::noop());
7978

8079
loop {
8180
match fut.as_mut().poll(ctx) {

‎tests/ui/dyn-star/dispatch-on-pin-mut.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,14 @@ async fn async_main() {
1919
// ------------------------------------------------------------------------- //
2020
// Implementation Details Below...
2121

22-
use std::task::*;
2322
use std::pin::pin;
23+
use std::task::*;
2424

2525
fn main() {
2626
let mut fut = pin!(async_main());
2727

2828
// Poll loop, just to test the future...
29-
let waker = Waker::noop();
30-
let ctx = &mut Context::from_waker(&waker);
29+
let ctx = &mut Context::from_waker(Waker::noop());
3130

3231
loop {
3332
match fut.as_mut().poll(ctx) {

0 commit comments

Comments
 (0)
Please sign in to comment.