diff options
| author | bors <bors@rust-lang.org> | 2021-09-22 06:43:33 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2021-09-22 06:43:33 +0000 |
| commit | ce45663e14dac3f0f58be698cc530bc2e6e21682 (patch) | |
| tree | df12c759560d579029acad20d2df9bbf94178ede /src/test/ui/lint | |
| parent | 77f4143fa26a1434088f532d2ba7ec51e0a392fd (diff) | |
| parent | 08e026675ee38bb4ca81106e766a6456c8b7382e (diff) | |
| download | rust-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')
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 + |
