about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorOli Scherer <git-spam-no-reply9815368754983@oli-obk.de>2024-04-11 13:15:34 +0000
committerOli Scherer <git-spam-no-reply9815368754983@oli-obk.de>2024-04-24 08:05:29 +0000
commitaef0f4024aec24fd7e53dbc51883457e44fe17ce (patch)
tree25a26930a8cc3441951ba159f1a632092df41655 /src
parenta589632dad58c2669b7984019efb59917a16ac67 (diff)
downloadrust-aef0f4024aec24fd7e53dbc51883457e44fe17ce.tar.gz
rust-aef0f4024aec24fd7e53dbc51883457e44fe17ce.zip
Error on using `yield` without also using `#[coroutine]` on the closure
And suggest adding the `#[coroutine]` to the closure
Diffstat (limited to 'src')
-rw-r--r--src/doc/unstable-book/src/language-features/coroutines.md23
-rw-r--r--src/doc/unstable-book/src/the-unstable-book.md4
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-5238.rs4
-rw-r--r--src/tools/clippy/tests/ui/large_futures.fixed1
-rw-r--r--src/tools/clippy/tests/ui/large_futures.rs1
-rw-r--r--src/tools/clippy/tests/ui/large_futures.stderr16
-rw-r--r--src/tools/clippy/tests/ui/redundant_locals.rs6
-rw-r--r--src/tools/miri/tests/fail/coroutine-pinned-moved.rs4
-rw-r--r--src/tools/miri/tests/pass/coroutine.rs36
-rw-r--r--src/tools/miri/tests/pass/stacked-borrows/coroutine-self-referential.rs4
-rw-r--r--src/tools/miri/tests/pass/track-caller-attribute.rs6
-rw-r--r--src/tools/rust-analyzer/crates/ide-db/src/generated/lints.rs6
-rw-r--r--src/tools/rustfmt/tests/source/immovable_coroutines.rs3
-rw-r--r--src/tools/rustfmt/tests/target/immovable_coroutines.rs3
14 files changed, 59 insertions, 58 deletions
diff --git a/src/doc/unstable-book/src/language-features/coroutines.md b/src/doc/unstable-book/src/language-features/coroutines.md
index f8e5a22fbd5..9fb07594650 100644
--- a/src/doc/unstable-book/src/language-features/coroutines.md
+++ b/src/doc/unstable-book/src/language-features/coroutines.md
@@ -26,13 +26,13 @@ tweaks to the overall design.
 A syntactical example of a coroutine is:
 
 ```rust
-#![feature(coroutines, coroutine_trait)]
+#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
 
 use std::ops::{Coroutine, CoroutineState};
 use std::pin::Pin;
 
 fn main() {
-    let mut coroutine = || {
+    let mut coroutine = #[coroutine] || {
         yield 1;
         return "foo"
     };
@@ -48,7 +48,8 @@ fn main() {
 }
 ```
 
-Coroutines are closure-like literals which can contain a `yield` statement. The
+Coroutines are closure-like literals which are annotated with `#[coroutine]`
+and can contain a `yield` statement. The
 `yield` statement takes an optional expression of a value to yield out of the
 coroutine. All coroutine literals implement the `Coroutine` trait in the
 `std::ops` module. The `Coroutine` trait has one main method, `resume`, which
@@ -58,13 +59,13 @@ An example of the control flow of coroutines is that the following example
 prints all numbers in order:
 
 ```rust
-#![feature(coroutines, coroutine_trait)]
+#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
 
 use std::ops::Coroutine;
 use std::pin::Pin;
 
 fn main() {
-    let mut coroutine = || {
+    let mut coroutine = #[coroutine] || {
         println!("2");
         yield;
         println!("4");
@@ -78,9 +79,9 @@ fn main() {
 }
 ```
 
-At this time the main intended use case of coroutines is an implementation
-primitive for async/await syntax, but coroutines will likely be extended to
-ergonomic implementations of iterators and other primitives in the future.
+At this time the main use case of coroutines is an implementation
+primitive for `async`/`await` and `gen` syntax, but coroutines
+will likely be extended to other primitives in the future.
 Feedback on the design and usage is always appreciated!
 
 ### The `Coroutine` trait
@@ -163,14 +164,14 @@ which point all state is saved off in the coroutine and a value is returned.
 Let's take a look at an example to see what's going on here:
 
 ```rust
-#![feature(coroutines, coroutine_trait)]
+#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
 
 use std::ops::Coroutine;
 use std::pin::Pin;
 
 fn main() {
     let ret = "foo";
-    let mut coroutine = move || {
+    let mut coroutine = #[coroutine] move || {
         yield 1;
         return ret
     };
@@ -183,7 +184,7 @@ fn main() {
 This coroutine literal will compile down to something similar to:
 
 ```rust
-#![feature(arbitrary_self_types, coroutines, coroutine_trait)]
+#![feature(arbitrary_self_types, coroutine_trait)]
 
 use std::ops::{Coroutine, CoroutineState};
 use std::pin::Pin;
diff --git a/src/doc/unstable-book/src/the-unstable-book.md b/src/doc/unstable-book/src/the-unstable-book.md
index 0f4fb405669..63134f7ae28 100644
--- a/src/doc/unstable-book/src/the-unstable-book.md
+++ b/src/doc/unstable-book/src/the-unstable-book.md
@@ -5,13 +5,13 @@ each one organized by a "feature flag." That is, when using an unstable
 feature of Rust, you must use a flag, like this:
 
 ```rust
-#![feature(coroutines, coroutine_trait)]
+#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
 
 use std::ops::{Coroutine, CoroutineState};
 use std::pin::Pin;
 
 fn main() {
-    let mut coroutine = || {
+    let mut coroutine = #[coroutine] || {
         yield 1;
         return "foo"
     };
diff --git a/src/tools/clippy/tests/ui/crashes/ice-5238.rs b/src/tools/clippy/tests/ui/crashes/ice-5238.rs
index b1fc3fb9d25..fe03a39ad1b 100644
--- a/src/tools/clippy/tests/ui/crashes/ice-5238.rs
+++ b/src/tools/clippy/tests/ui/crashes/ice-5238.rs
@@ -1,9 +1,9 @@
 // Regression test for #5238 / https://github.com/rust-lang/rust/pull/69562
 
-#![feature(coroutines, coroutine_trait)]
+#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
 
 fn main() {
-    let _ = || {
+    let _ = #[coroutine] || {
         yield;
     };
 }
diff --git a/src/tools/clippy/tests/ui/large_futures.fixed b/src/tools/clippy/tests/ui/large_futures.fixed
index aa8c3021b97..1e87859f452 100644
--- a/src/tools/clippy/tests/ui/large_futures.fixed
+++ b/src/tools/clippy/tests/ui/large_futures.fixed
@@ -1,4 +1,3 @@
-#![feature(coroutines)]
 #![warn(clippy::large_futures)]
 #![allow(clippy::never_loop)]
 #![allow(clippy::future_not_send)]
diff --git a/src/tools/clippy/tests/ui/large_futures.rs b/src/tools/clippy/tests/ui/large_futures.rs
index fc6ea458d3d..3f4ea2ebf8b 100644
--- a/src/tools/clippy/tests/ui/large_futures.rs
+++ b/src/tools/clippy/tests/ui/large_futures.rs
@@ -1,4 +1,3 @@
-#![feature(coroutines)]
 #![warn(clippy::large_futures)]
 #![allow(clippy::never_loop)]
 #![allow(clippy::future_not_send)]
diff --git a/src/tools/clippy/tests/ui/large_futures.stderr b/src/tools/clippy/tests/ui/large_futures.stderr
index 5709c7b77a0..00082e579c5 100644
--- a/src/tools/clippy/tests/ui/large_futures.stderr
+++ b/src/tools/clippy/tests/ui/large_futures.stderr
@@ -1,5 +1,5 @@
 error: large future with a size of 16385 bytes
-  --> tests/ui/large_futures.rs:11:9
+  --> tests/ui/large_futures.rs:10:9
    |
 LL |         big_fut([0u8; 1024 * 16]).await;
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider `Box::pin` on it: `Box::pin(big_fut([0u8; 1024 * 16]))`
@@ -8,37 +8,37 @@ LL |         big_fut([0u8; 1024 * 16]).await;
    = help: to override `-D warnings` add `#[allow(clippy::large_futures)]`
 
 error: large future with a size of 16386 bytes
-  --> tests/ui/large_futures.rs:15:5
+  --> tests/ui/large_futures.rs:14:5
    |
 LL |     f.await
    |     ^ help: consider `Box::pin` on it: `Box::pin(f)`
 
 error: large future with a size of 16387 bytes
-  --> tests/ui/large_futures.rs:20:9
+  --> tests/ui/large_futures.rs:19:9
    |
 LL |         wait().await;
    |         ^^^^^^ help: consider `Box::pin` on it: `Box::pin(wait())`
 
 error: large future with a size of 16387 bytes
-  --> tests/ui/large_futures.rs:25:13
+  --> tests/ui/large_futures.rs:24:13
    |
 LL |             wait().await;
    |             ^^^^^^ help: consider `Box::pin` on it: `Box::pin(wait())`
 
 error: large future with a size of 65540 bytes
-  --> tests/ui/large_futures.rs:33:5
+  --> tests/ui/large_futures.rs:32:5
    |
 LL |     foo().await;
    |     ^^^^^ help: consider `Box::pin` on it: `Box::pin(foo())`
 
 error: large future with a size of 49159 bytes
-  --> tests/ui/large_futures.rs:35:5
+  --> tests/ui/large_futures.rs:34:5
    |
 LL |     calls_fut(fut).await;
    |     ^^^^^^^^^^^^^^ help: consider `Box::pin` on it: `Box::pin(calls_fut(fut))`
 
 error: large future with a size of 65540 bytes
-  --> tests/ui/large_futures.rs:48:5
+  --> tests/ui/large_futures.rs:47:5
    |
 LL | /     async {
 LL | |
@@ -59,7 +59,7 @@ LL +     })
    |
 
 error: large future with a size of 65540 bytes
-  --> tests/ui/large_futures.rs:60:13
+  --> tests/ui/large_futures.rs:59:13
    |
 LL | /             async {
 LL | |                 let x = [0i32; 1024 * 16];
diff --git a/src/tools/clippy/tests/ui/redundant_locals.rs b/src/tools/clippy/tests/ui/redundant_locals.rs
index f6909828aa9..e9d77182a91 100644
--- a/src/tools/clippy/tests/ui/redundant_locals.rs
+++ b/src/tools/clippy/tests/ui/redundant_locals.rs
@@ -1,7 +1,7 @@
 //@aux-build:proc_macros.rs
 #![allow(unused, clippy::no_effect, clippy::needless_pass_by_ref_mut)]
 #![warn(clippy::redundant_locals)]
-#![feature(async_closure, coroutines)]
+#![feature(async_closure, coroutines, stmt_expr_attributes)]
 
 extern crate proc_macros;
 use proc_macros::{external, with_span};
@@ -191,11 +191,11 @@ fn issue12225() {
         let v4 = v4;
         dbg!(&v4);
     });
-    assert_static(static || {
+    assert_static(#[coroutine] static || {
         let v5 = v5;
         yield;
     });
-    assert_static(|| {
+    assert_static(#[coroutine] || {
         let v6 = v6;
         yield;
     });
diff --git a/src/tools/miri/tests/fail/coroutine-pinned-moved.rs b/src/tools/miri/tests/fail/coroutine-pinned-moved.rs
index 005ae7e9132..8648be2a264 100644
--- a/src/tools/miri/tests/fail/coroutine-pinned-moved.rs
+++ b/src/tools/miri/tests/fail/coroutine-pinned-moved.rs
@@ -1,5 +1,5 @@
 //@compile-flags: -Zmiri-disable-validation -Zmiri-disable-stacked-borrows
-#![feature(coroutines, coroutine_trait)]
+#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
 
 use std::{
     ops::{Coroutine, CoroutineState},
@@ -7,7 +7,7 @@ use std::{
 };
 
 fn firstn() -> impl Coroutine<Yield = u64, Return = ()> {
-    static move || {
+    #[coroutine] static move || {
         let mut num = 0;
         let num = &mut num;
         *num += 0;
diff --git a/src/tools/miri/tests/pass/coroutine.rs b/src/tools/miri/tests/pass/coroutine.rs
index 7e1f64df04d..e76abfc4185 100644
--- a/src/tools/miri/tests/pass/coroutine.rs
+++ b/src/tools/miri/tests/pass/coroutine.rs
@@ -1,6 +1,6 @@
 //@revisions: stack tree
 //@[tree]compile-flags: -Zmiri-tree-borrows
-#![feature(coroutines, coroutine_trait, never_type)]
+#![feature(coroutines, coroutine_trait, never_type, stmt_expr_attributes)]
 
 use std::fmt::Debug;
 use std::mem::ManuallyDrop;
@@ -43,9 +43,9 @@ fn basic() {
         panic!()
     }
 
-    finish(1, false, || yield 1);
+    finish(1, false, #[coroutine] || yield 1);
 
-    finish(3, false, || {
+    finish(3, false, #[coroutine] || {
         let mut x = 0;
         yield 1;
         x += 1;
@@ -55,27 +55,27 @@ fn basic() {
         assert_eq!(x, 2);
     });
 
-    finish(7 * 8 / 2, false, || {
+    finish(7 * 8 / 2, false, #[coroutine] || {
         for i in 0..8 {
             yield i;
         }
     });
 
-    finish(1, false, || {
+    finish(1, false, #[coroutine] || {
         if true {
             yield 1;
         } else {
         }
     });
 
-    finish(1, false, || {
+    finish(1, false, #[coroutine] || {
         if false {
         } else {
             yield 1;
         }
     });
 
-    finish(2, false, || {
+    finish(2, false, #[coroutine] || {
         if {
             yield 1;
             false
@@ -88,7 +88,7 @@ fn basic() {
 
     // also test self-referential coroutines
     assert_eq!(
-        finish(5, true, static || {
+        finish(5, true, #[coroutine] static || {
             let mut x = 5;
             let y = &mut x;
             *y = 5;
@@ -99,7 +99,7 @@ fn basic() {
         10
     );
     assert_eq!(
-        finish(5, true, || {
+        finish(5, true, #[coroutine] || {
             let mut x = Box::new(5);
             let y = &mut *x;
             *y = 5;
@@ -111,7 +111,7 @@ fn basic() {
     );
 
     let b = true;
-    finish(1, false, || {
+    finish(1, false, #[coroutine] || {
         yield 1;
         if b {
             return;
@@ -123,7 +123,7 @@ fn basic() {
         drop(x);
     });
 
-    finish(3, false, || {
+    finish(3, false, #[coroutine] || {
         yield 1;
         #[allow(unreachable_code)]
         let _x: (String, !) = (String::new(), {
@@ -172,7 +172,7 @@ fn smoke_resume_arg() {
     }
 
     drain(
-        &mut |mut b| {
+        &mut #[coroutine] |mut b| {
             while b != 0 {
                 b = yield (b + 1);
             }
@@ -181,21 +181,21 @@ fn smoke_resume_arg() {
         vec![(1, Yielded(2)), (-45, Yielded(-44)), (500, Yielded(501)), (0, Complete(-1))],
     );
 
-    expect_drops(2, || drain(&mut |a| yield a, vec![(DropMe, Yielded(DropMe))]));
+    expect_drops(2, || drain(&mut #[coroutine] |a| yield a, vec![(DropMe, Yielded(DropMe))]));
 
     expect_drops(6, || {
         drain(
-            &mut |a| yield yield a,
+            &mut #[coroutine] |a| yield yield a,
             vec![(DropMe, Yielded(DropMe)), (DropMe, Yielded(DropMe)), (DropMe, Complete(DropMe))],
         )
     });
 
     #[allow(unreachable_code)]
-    expect_drops(2, || drain(&mut |a| yield return a, vec![(DropMe, Complete(DropMe))]));
+    expect_drops(2, || drain(&mut #[coroutine] |a| yield return a, vec![(DropMe, Complete(DropMe))]));
 
     expect_drops(2, || {
         drain(
-            &mut |a: DropMe| {
+            &mut #[coroutine] |a: DropMe| {
                 if false { yield () } else { a }
             },
             vec![(DropMe, Complete(DropMe))],
@@ -205,7 +205,7 @@ fn smoke_resume_arg() {
     expect_drops(4, || {
         drain(
             #[allow(unused_assignments, unused_variables)]
-            &mut |mut a: DropMe| {
+            &mut #[coroutine] |mut a: DropMe| {
                 a = yield;
                 a = yield;
                 a = yield;
@@ -228,7 +228,7 @@ fn uninit_fields() {
     }
 
     fn run<T>(x: bool, y: bool) {
-        let mut c = || {
+        let mut c = #[coroutine] || {
             if x {
                 let _a: T;
                 if y {
diff --git a/src/tools/miri/tests/pass/stacked-borrows/coroutine-self-referential.rs b/src/tools/miri/tests/pass/stacked-borrows/coroutine-self-referential.rs
index c4b15c8758b..bb98e024a0a 100644
--- a/src/tools/miri/tests/pass/stacked-borrows/coroutine-self-referential.rs
+++ b/src/tools/miri/tests/pass/stacked-borrows/coroutine-self-referential.rs
@@ -1,6 +1,6 @@
 // See https://github.com/rust-lang/unsafe-code-guidelines/issues/148:
 // this fails when Stacked Borrows is strictly applied even to `!Unpin` types.
-#![feature(coroutines, coroutine_trait)]
+#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
 
 use std::{
     ops::{Coroutine, CoroutineState},
@@ -8,7 +8,7 @@ use std::{
 };
 
 fn firstn() -> impl Coroutine<Yield = u64, Return = ()> {
-    static move || {
+    #[coroutine] static move || {
         let mut num = 0;
         let num = &mut num;
 
diff --git a/src/tools/miri/tests/pass/track-caller-attribute.rs b/src/tools/miri/tests/pass/track-caller-attribute.rs
index d88bcc98858..c3803af3cc8 100644
--- a/src/tools/miri/tests/pass/track-caller-attribute.rs
+++ b/src/tools/miri/tests/pass/track-caller-attribute.rs
@@ -232,7 +232,7 @@ fn test_coroutine() {
     }
 
     #[rustfmt::skip]
-    let coroutine = #[track_caller] |arg: String| {
+    let coroutine = #[track_caller] #[coroutine] |arg: String| {
         yield ("first", arg.clone(), Location::caller());
         yield ("second", arg.clone(), Location::caller());
     };
@@ -255,7 +255,7 @@ fn test_coroutine() {
     assert_eq!(mono_loc.column(), 42);
 
     #[rustfmt::skip]
-    let non_tracked_coroutine = || { yield Location::caller(); };
+    let non_tracked_coroutine = #[coroutine] || { yield Location::caller(); };
     let non_tracked_line = line!() - 1; // This is the line of the coroutine, not its caller
     let non_tracked_loc = match Box::pin(non_tracked_coroutine).as_mut().resume(()) {
         CoroutineState::Yielded(val) => val,
@@ -263,7 +263,7 @@ fn test_coroutine() {
     };
     assert_eq!(non_tracked_loc.file(), file!());
     assert_eq!(non_tracked_loc.line(), non_tracked_line);
-    assert_eq!(non_tracked_loc.column(), 44);
+    assert_eq!(non_tracked_loc.column(), 57);
 }
 
 fn main() {
diff --git a/src/tools/rust-analyzer/crates/ide-db/src/generated/lints.rs b/src/tools/rust-analyzer/crates/ide-db/src/generated/lints.rs
index d50088e6cf1..c92d4e78ffa 100644
--- a/src/tools/rust-analyzer/crates/ide-db/src/generated/lints.rs
+++ b/src/tools/rust-analyzer/crates/ide-db/src/generated/lints.rs
@@ -3869,7 +3869,7 @@ use std::ops::{Coroutine, CoroutineState};
 use std::pin::Pin;
 
 fn main() {
-    let mut coroutine = || {
+    let mut coroutine = #[coroutine] || {
         yield 1;
         return "foo"
     };
@@ -3901,7 +3901,7 @@ use std::ops::Coroutine;
 use std::pin::Pin;
 
 fn main() {
-    let mut coroutine = || {
+    let mut coroutine = #[coroutine] || {
         println!("2");
         yield;
         println!("4");
@@ -4007,7 +4007,7 @@ use std::pin::Pin;
 
 fn main() {
     let ret = "foo";
-    let mut coroutine = move || {
+    let mut coroutine = #[coroutine] move || {
         yield 1;
         return ret
     };
diff --git a/src/tools/rustfmt/tests/source/immovable_coroutines.rs b/src/tools/rustfmt/tests/source/immovable_coroutines.rs
index 3b94af0c96c..539049577a0 100644
--- a/src/tools/rustfmt/tests/source/immovable_coroutines.rs
+++ b/src/tools/rustfmt/tests/source/immovable_coroutines.rs
@@ -1,7 +1,8 @@
 #![feature(coroutines)]
 
 unsafe fn foo() {
-    let mut ga = static || { 
+    let mut ga = #[coroutine]
+    static || {
         yield 1;
     };
 }
diff --git a/src/tools/rustfmt/tests/target/immovable_coroutines.rs b/src/tools/rustfmt/tests/target/immovable_coroutines.rs
index f52cfa00f97..539049577a0 100644
--- a/src/tools/rustfmt/tests/target/immovable_coroutines.rs
+++ b/src/tools/rustfmt/tests/target/immovable_coroutines.rs
@@ -1,7 +1,8 @@
 #![feature(coroutines)]
 
 unsafe fn foo() {
-    let mut ga = static || {
+    let mut ga = #[coroutine]
+    static || {
         yield 1;
     };
 }