about summary refs log tree commit diff
path: root/src/test/ui/lint
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2021-09-22 06:43:33 +0000
committerbors <bors@rust-lang.org>2021-09-22 06:43:33 +0000
commitce45663e14dac3f0f58be698cc530bc2e6e21682 (patch)
treedf12c759560d579029acad20d2df9bbf94178ede /src/test/ui/lint
parent77f4143fa26a1434088f532d2ba7ec51e0a392fd (diff)
parent08e026675ee38bb4ca81106e766a6456c8b7382e (diff)
downloadrust-ce45663e14dac3f0f58be698cc530bc2e6e21682.tar.gz
rust-ce45663e14dac3f0f58be698cc530bc2e6e21682.zip
Auto merge of #88865 - guswynn:must_not_suspend, r=oli-obk
Implement `#[must_not_suspend]`

implements #83310

Some notes on the impl:

1. The code that searches for the attribute on the ADT is basically copied from the `must_use` lint. It's not shared, as the logic did diverge
2. The RFC does specify that the attribute can be placed on fn's (and fn-like objects), like `must_use`. I think this is a direct copy from the `must_use` reference definition. This implementation does NOT support this, as I felt that ADT's (+ `impl Trait` + `dyn Trait`) cover the usecase's people actually want on the RFC, and adding an imp for the fn call case would be significantly harder. The `must_use` impl can do a single check at fn call stmt time, but `must_not_suspend` would need to answer the question: "for some value X with type T, find any fn call that COULD have produced this value". That would require significant changes to `generator_interior.rs`, and I would need mentorship on that. `@eholk` and I are discussing it.
3. `@estebank` do you know a way I can make the user-provided `reason` note pop out? right now it seems quite hidden

Also, I am not sure if we should run perf on this

r? `@nikomatsakis`
Diffstat (limited to 'src/test/ui/lint')
-rw-r--r--src/test/ui/lint/must_not_suspend/boxed.rs25
-rw-r--r--src/test/ui/lint/must_not_suspend/boxed.stderr26
-rw-r--r--src/test/ui/lint/must_not_suspend/dedup.rs20
-rw-r--r--src/test/ui/lint/must_not_suspend/dedup.stderr19
-rw-r--r--src/test/ui/lint/must_not_suspend/feature-gate-must_not_suspend.rs9
-rw-r--r--src/test/ui/lint/must_not_suspend/feature-gate-must_not_suspend.stderr12
-rw-r--r--src/test/ui/lint/must_not_suspend/generic.rs20
-rw-r--r--src/test/ui/lint/must_not_suspend/handled.rs28
-rw-r--r--src/test/ui/lint/must_not_suspend/other_items.rs8
-rw-r--r--src/test/ui/lint/must_not_suspend/other_items.stderr10
-rw-r--r--src/test/ui/lint/must_not_suspend/ref.rs29
-rw-r--r--src/test/ui/lint/must_not_suspend/ref.stderr27
-rw-r--r--src/test/ui/lint/must_not_suspend/return.rs9
-rw-r--r--src/test/ui/lint/must_not_suspend/return.stderr12
-rw-r--r--src/test/ui/lint/must_not_suspend/trait.rs28
-rw-r--r--src/test/ui/lint/must_not_suspend/trait.stderr37
-rw-r--r--src/test/ui/lint/must_not_suspend/unit.rs25
-rw-r--r--src/test/ui/lint/must_not_suspend/unit.stderr26
-rw-r--r--src/test/ui/lint/must_not_suspend/warn.rs25
-rw-r--r--src/test/ui/lint/must_not_suspend/warn.stderr22
20 files changed, 417 insertions, 0 deletions
diff --git a/src/test/ui/lint/must_not_suspend/boxed.rs b/src/test/ui/lint/must_not_suspend/boxed.rs
new file mode 100644
index 00000000000..1f823fc559d
--- /dev/null
+++ b/src/test/ui/lint/must_not_suspend/boxed.rs
@@ -0,0 +1,25 @@
+// edition:2018
+#![feature(must_not_suspend)]
+#![deny(must_not_suspend)]
+
+#[must_not_suspend = "You gotta use Umm's, ya know?"]
+struct Umm {
+    i: i64
+}
+
+
+fn bar() -> Box<Umm> {
+    Box::new(Umm {
+        i: 1
+    })
+}
+
+async fn other() {}
+
+pub async fn uhoh() {
+    let _guard = bar(); //~ ERROR boxed `Umm` held across
+    other().await;
+}
+
+fn main() {
+}
diff --git a/src/test/ui/lint/must_not_suspend/boxed.stderr b/src/test/ui/lint/must_not_suspend/boxed.stderr
new file mode 100644
index 00000000000..edc62b6d687
--- /dev/null
+++ b/src/test/ui/lint/must_not_suspend/boxed.stderr
@@ -0,0 +1,26 @@
+error: boxed `Umm` held across a suspend point, but should not be
+  --> $DIR/boxed.rs:20:9
+   |
+LL |     let _guard = bar();
+   |         ^^^^^^
+LL |     other().await;
+   |     ------------- the value is held across this suspend point
+   |
+note: the lint level is defined here
+  --> $DIR/boxed.rs:3:9
+   |
+LL | #![deny(must_not_suspend)]
+   |         ^^^^^^^^^^^^^^^^
+note: You gotta use Umm's, ya know?
+  --> $DIR/boxed.rs:20:9
+   |
+LL |     let _guard = bar();
+   |         ^^^^^^
+help: consider using a block (`{ ... }`) to shrink the value's scope, ending before the suspend point
+  --> $DIR/boxed.rs:20:9
+   |
+LL |     let _guard = bar();
+   |         ^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/lint/must_not_suspend/dedup.rs b/src/test/ui/lint/must_not_suspend/dedup.rs
new file mode 100644
index 00000000000..040fff5a5a5
--- /dev/null
+++ b/src/test/ui/lint/must_not_suspend/dedup.rs
@@ -0,0 +1,20 @@
+// edition:2018
+#![feature(must_not_suspend)]
+#![deny(must_not_suspend)]
+
+#[must_not_suspend]
+struct No {}
+
+async fn shushspend() {}
+
+async fn wheeee<T>(t: T) {
+    shushspend().await;
+    drop(t);
+}
+
+async fn yes() {
+    wheeee(No {}).await; //~ ERROR `No` held across
+}
+
+fn main() {
+}
diff --git a/src/test/ui/lint/must_not_suspend/dedup.stderr b/src/test/ui/lint/must_not_suspend/dedup.stderr
new file mode 100644
index 00000000000..542b7a3bc7e
--- /dev/null
+++ b/src/test/ui/lint/must_not_suspend/dedup.stderr
@@ -0,0 +1,19 @@
+error: `No` held across a suspend point, but should not be
+  --> $DIR/dedup.rs:16:12
+   |
+LL |     wheeee(No {}).await;
+   |     -------^^^^^------- the value is held across this suspend point
+   |
+note: the lint level is defined here
+  --> $DIR/dedup.rs:3:9
+   |
+LL | #![deny(must_not_suspend)]
+   |         ^^^^^^^^^^^^^^^^
+help: consider using a block (`{ ... }`) to shrink the value's scope, ending before the suspend point
+  --> $DIR/dedup.rs:16:12
+   |
+LL |     wheeee(No {}).await;
+   |            ^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/lint/must_not_suspend/feature-gate-must_not_suspend.rs b/src/test/ui/lint/must_not_suspend/feature-gate-must_not_suspend.rs
new file mode 100644
index 00000000000..1554408c174
--- /dev/null
+++ b/src/test/ui/lint/must_not_suspend/feature-gate-must_not_suspend.rs
@@ -0,0 +1,9 @@
+// edition:2018
+
+#[must_not_suspend = "You gotta use Umm's, ya know?"] //~ ERROR the `#[must_not_suspend]`
+struct Umm {
+    _i: i64
+}
+
+fn main() {
+}
diff --git a/src/test/ui/lint/must_not_suspend/feature-gate-must_not_suspend.stderr b/src/test/ui/lint/must_not_suspend/feature-gate-must_not_suspend.stderr
new file mode 100644
index 00000000000..ab20a8be874
--- /dev/null
+++ b/src/test/ui/lint/must_not_suspend/feature-gate-must_not_suspend.stderr
@@ -0,0 +1,12 @@
+error[E0658]: the `#[must_not_suspend]` attribute is an experimental feature
+  --> $DIR/feature-gate-must_not_suspend.rs:3:1
+   |
+LL | #[must_not_suspend = "You gotta use Umm's, ya know?"]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #83310 <https://github.com/rust-lang/rust/issues/83310> for more information
+   = help: add `#![feature(must_not_suspend)]` to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/lint/must_not_suspend/generic.rs b/src/test/ui/lint/must_not_suspend/generic.rs
new file mode 100644
index 00000000000..b3effa020c4
--- /dev/null
+++ b/src/test/ui/lint/must_not_suspend/generic.rs
@@ -0,0 +1,20 @@
+// edition:2018
+// run-pass
+//
+// this test shows a case where the lint doesn't fire in generic code
+#![feature(must_not_suspend)]
+#![deny(must_not_suspend)]
+
+#[must_not_suspend]
+struct No {}
+
+async fn shushspend() {}
+
+async fn wheeee<T>(t: T) {
+    shushspend().await;
+    drop(t);
+}
+
+fn main() {
+    let _fut = wheeee(No {});
+}
diff --git a/src/test/ui/lint/must_not_suspend/handled.rs b/src/test/ui/lint/must_not_suspend/handled.rs
new file mode 100644
index 00000000000..8714be6449f
--- /dev/null
+++ b/src/test/ui/lint/must_not_suspend/handled.rs
@@ -0,0 +1,28 @@
+// edition:2018
+// run-pass
+#![feature(must_not_suspend)]
+#![deny(must_not_suspend)]
+
+#[must_not_suspend = "You gotta use Umm's, ya know?"]
+struct Umm {
+    _i: i64
+}
+
+
+fn bar() -> Umm {
+    Umm {
+        _i: 1
+    }
+}
+
+async fn other() {}
+
+pub async fn uhoh() {
+    {
+        let _guard = bar();
+    }
+    other().await;
+}
+
+fn main() {
+}
diff --git a/src/test/ui/lint/must_not_suspend/other_items.rs b/src/test/ui/lint/must_not_suspend/other_items.rs
new file mode 100644
index 00000000000..5aa1abb14d3
--- /dev/null
+++ b/src/test/ui/lint/must_not_suspend/other_items.rs
@@ -0,0 +1,8 @@
+// edition:2018
+#![feature(must_not_suspend)]
+#![deny(must_not_suspend)]
+
+#[must_not_suspend] //~ ERROR attribute should be
+mod inner {}
+
+fn main() {}
diff --git a/src/test/ui/lint/must_not_suspend/other_items.stderr b/src/test/ui/lint/must_not_suspend/other_items.stderr
new file mode 100644
index 00000000000..41c8896921b
--- /dev/null
+++ b/src/test/ui/lint/must_not_suspend/other_items.stderr
@@ -0,0 +1,10 @@
+error: `must_not_suspend` attribute should be applied to a struct, enum, or trait
+  --> $DIR/other_items.rs:5:1
+   |
+LL | #[must_not_suspend]
+   | ^^^^^^^^^^^^^^^^^^^
+LL | mod inner {}
+   | ------------ is not a struct, enum, or trait
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/lint/must_not_suspend/ref.rs b/src/test/ui/lint/must_not_suspend/ref.rs
new file mode 100644
index 00000000000..738dd9e0465
--- /dev/null
+++ b/src/test/ui/lint/must_not_suspend/ref.rs
@@ -0,0 +1,29 @@
+// edition:2018
+#![feature(must_not_suspend)]
+#![deny(must_not_suspend)]
+
+#[must_not_suspend = "You gotta use Umm's, ya know?"]
+struct Umm {
+    i: i64
+}
+
+struct Bar {
+    u: Umm,
+}
+
+async fn other() {}
+
+impl Bar {
+    async fn uhoh(&mut self) {
+        let guard = &mut self.u; //~ ERROR `Umm` held across
+
+        other().await;
+
+        *guard = Umm {
+            i: 2
+        }
+    }
+}
+
+fn main() {
+}
diff --git a/src/test/ui/lint/must_not_suspend/ref.stderr b/src/test/ui/lint/must_not_suspend/ref.stderr
new file mode 100644
index 00000000000..78b44b00625
--- /dev/null
+++ b/src/test/ui/lint/must_not_suspend/ref.stderr
@@ -0,0 +1,27 @@
+error: `Umm` held across a suspend point, but should not be
+  --> $DIR/ref.rs:18:26
+   |
+LL |         let guard = &mut self.u;
+   |                          ^^^^^^
+LL | 
+LL |         other().await;
+   |         ------------- the value is held across this suspend point
+   |
+note: the lint level is defined here
+  --> $DIR/ref.rs:3:9
+   |
+LL | #![deny(must_not_suspend)]
+   |         ^^^^^^^^^^^^^^^^
+note: You gotta use Umm's, ya know?
+  --> $DIR/ref.rs:18:26
+   |
+LL |         let guard = &mut self.u;
+   |                          ^^^^^^
+help: consider using a block (`{ ... }`) to shrink the value's scope, ending before the suspend point
+  --> $DIR/ref.rs:18:26
+   |
+LL |         let guard = &mut self.u;
+   |                          ^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/lint/must_not_suspend/return.rs b/src/test/ui/lint/must_not_suspend/return.rs
new file mode 100644
index 00000000000..5b1fa5e2721
--- /dev/null
+++ b/src/test/ui/lint/must_not_suspend/return.rs
@@ -0,0 +1,9 @@
+// edition:2018
+#![feature(must_not_suspend)]
+#![deny(must_not_suspend)]
+
+#[must_not_suspend] //~ ERROR attribute should be
+fn foo() -> i32 {
+    0
+}
+fn main() {}
diff --git a/src/test/ui/lint/must_not_suspend/return.stderr b/src/test/ui/lint/must_not_suspend/return.stderr
new file mode 100644
index 00000000000..fdada85eb4d
--- /dev/null
+++ b/src/test/ui/lint/must_not_suspend/return.stderr
@@ -0,0 +1,12 @@
+error: `must_not_suspend` attribute should be applied to a struct, enum, or trait
+  --> $DIR/return.rs:5:1
+   |
+LL |   #[must_not_suspend]
+   |   ^^^^^^^^^^^^^^^^^^^
+LL | / fn foo() -> i32 {
+LL | |     0
+LL | | }
+   | |_- is not a struct, enum, or trait
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/lint/must_not_suspend/trait.rs b/src/test/ui/lint/must_not_suspend/trait.rs
new file mode 100644
index 00000000000..6c911cb4b0f
--- /dev/null
+++ b/src/test/ui/lint/must_not_suspend/trait.rs
@@ -0,0 +1,28 @@
+// edition:2018
+#![feature(must_not_suspend)]
+#![deny(must_not_suspend)]
+
+#[must_not_suspend]
+trait Wow {}
+
+impl Wow for i32 {}
+
+fn r#impl() -> impl Wow {
+    1
+}
+
+fn r#dyn() -> Box<dyn Wow> {
+    Box::new(1)
+}
+
+async fn other() {}
+
+pub async fn uhoh() {
+    let _guard1 = r#impl(); //~ ERROR implementer of `Wow` held across
+    let _guard2 = r#dyn(); //~ ERROR boxed `Wow` trait object held across
+
+    other().await;
+}
+
+fn main() {
+}
diff --git a/src/test/ui/lint/must_not_suspend/trait.stderr b/src/test/ui/lint/must_not_suspend/trait.stderr
new file mode 100644
index 00000000000..d19ffddd482
--- /dev/null
+++ b/src/test/ui/lint/must_not_suspend/trait.stderr
@@ -0,0 +1,37 @@
+error: implementer of `Wow` held across a suspend point, but should not be
+  --> $DIR/trait.rs:21:9
+   |
+LL |     let _guard1 = r#impl();
+   |         ^^^^^^^
+...
+LL |     other().await;
+   |     ------------- the value is held across this suspend point
+   |
+note: the lint level is defined here
+  --> $DIR/trait.rs:3:9
+   |
+LL | #![deny(must_not_suspend)]
+   |         ^^^^^^^^^^^^^^^^
+help: consider using a block (`{ ... }`) to shrink the value's scope, ending before the suspend point
+  --> $DIR/trait.rs:21:9
+   |
+LL |     let _guard1 = r#impl();
+   |         ^^^^^^^
+
+error: boxed `Wow` trait object held across a suspend point, but should not be
+  --> $DIR/trait.rs:22:9
+   |
+LL |     let _guard2 = r#dyn();
+   |         ^^^^^^^
+LL | 
+LL |     other().await;
+   |     ------------- the value is held across this suspend point
+   |
+help: consider using a block (`{ ... }`) to shrink the value's scope, ending before the suspend point
+  --> $DIR/trait.rs:22:9
+   |
+LL |     let _guard2 = r#dyn();
+   |         ^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/lint/must_not_suspend/unit.rs b/src/test/ui/lint/must_not_suspend/unit.rs
new file mode 100644
index 00000000000..d3a19f70432
--- /dev/null
+++ b/src/test/ui/lint/must_not_suspend/unit.rs
@@ -0,0 +1,25 @@
+// edition:2018
+#![feature(must_not_suspend)]
+#![deny(must_not_suspend)]
+
+#[must_not_suspend = "You gotta use Umm's, ya know?"]
+struct Umm {
+    i: i64
+}
+
+
+fn bar() -> Umm {
+    Umm {
+        i: 1
+    }
+}
+
+async fn other() {}
+
+pub async fn uhoh() {
+    let _guard = bar(); //~ ERROR `Umm` held across
+    other().await;
+}
+
+fn main() {
+}
diff --git a/src/test/ui/lint/must_not_suspend/unit.stderr b/src/test/ui/lint/must_not_suspend/unit.stderr
new file mode 100644
index 00000000000..425c076823d
--- /dev/null
+++ b/src/test/ui/lint/must_not_suspend/unit.stderr
@@ -0,0 +1,26 @@
+error: `Umm` held across a suspend point, but should not be
+  --> $DIR/unit.rs:20:9
+   |
+LL |     let _guard = bar();
+   |         ^^^^^^
+LL |     other().await;
+   |     ------------- the value is held across this suspend point
+   |
+note: the lint level is defined here
+  --> $DIR/unit.rs:3:9
+   |
+LL | #![deny(must_not_suspend)]
+   |         ^^^^^^^^^^^^^^^^
+note: You gotta use Umm's, ya know?
+  --> $DIR/unit.rs:20:9
+   |
+LL |     let _guard = bar();
+   |         ^^^^^^
+help: consider using a block (`{ ... }`) to shrink the value's scope, ending before the suspend point
+  --> $DIR/unit.rs:20:9
+   |
+LL |     let _guard = bar();
+   |         ^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/lint/must_not_suspend/warn.rs b/src/test/ui/lint/must_not_suspend/warn.rs
new file mode 100644
index 00000000000..50a696ba523
--- /dev/null
+++ b/src/test/ui/lint/must_not_suspend/warn.rs
@@ -0,0 +1,25 @@
+// edition:2018
+// run-pass
+#![feature(must_not_suspend)]
+
+#[must_not_suspend = "You gotta use Umm's, ya know?"]
+struct Umm {
+    _i: i64
+}
+
+
+fn bar() -> Umm {
+    Umm {
+        _i: 1
+    }
+}
+
+async fn other() {}
+
+pub async fn uhoh() {
+    let _guard = bar(); //~ WARNING `Umm` held across
+    other().await;
+}
+
+fn main() {
+}
diff --git a/src/test/ui/lint/must_not_suspend/warn.stderr b/src/test/ui/lint/must_not_suspend/warn.stderr
new file mode 100644
index 00000000000..24f52275b43
--- /dev/null
+++ b/src/test/ui/lint/must_not_suspend/warn.stderr
@@ -0,0 +1,22 @@
+warning: `Umm` held across a suspend point, but should not be
+  --> $DIR/warn.rs:20:9
+   |
+LL |     let _guard = bar();
+   |         ^^^^^^
+LL |     other().await;
+   |     ------------- the value is held across this suspend point
+   |
+   = note: `#[warn(must_not_suspend)]` on by default
+note: You gotta use Umm's, ya know?
+  --> $DIR/warn.rs:20:9
+   |
+LL |     let _guard = bar();
+   |         ^^^^^^
+help: consider using a block (`{ ... }`) to shrink the value's scope, ending before the suspend point
+  --> $DIR/warn.rs:20:9
+   |
+LL |     let _guard = bar();
+   |         ^^^^^^
+
+warning: 1 warning emitted
+