Skip to content

Commit 185fa56

Browse files
guswynnMark-Simulacrum
authored andcommitted
Feature gate and make must_not_suspend allow-by-default
This lint is not yet ready for stable use, primarily due to false positives in edge cases; we want to test it out more before stabilizing.
1 parent ff0e148 commit 185fa56

13 files changed

+114
-16
lines changed

compiler/rustc_lint/src/lib.rs

-1
Original file line numberDiff line numberDiff line change
@@ -300,7 +300,6 @@ fn register_builtins(store: &mut LintStore, no_interleave_lints: bool) {
300300
UNUSED_LABELS,
301301
UNUSED_PARENS,
302302
UNUSED_BRACES,
303-
MUST_NOT_SUSPEND,
304303
REDUNDANT_SEMICOLONS
305304
);
306305

compiler/rustc_lint_defs/src/builtin.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,7 @@ declare_lint! {
323323
///
324324
/// ```rust
325325
/// #![feature(must_not_suspend)]
326+
/// #![warn(must_not_suspend)]
326327
///
327328
/// #[must_not_suspend]
328329
/// struct SyncThing {}
@@ -349,8 +350,9 @@ declare_lint! {
349350
/// `MutexGuard`'s)
350351
///
351352
pub MUST_NOT_SUSPEND,
352-
Warn,
353+
Allow,
353354
"use of a `#[must_not_suspend]` value across a yield point",
355+
@feature_gate = rustc_span::symbol::sym::must_not_suspend;
354356
}
355357

356358
declare_lint! {

src/test/ui/async-await/issue-64130-non-send-future-diags.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
// edition:2018
2+
#![feature(must_not_suspend)]
3+
#![allow(must_not_suspend)]
24

35
// This tests the basic example case for the async-await-specific error.
46

src/test/ui/async-await/issue-64130-non-send-future-diags.stderr

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
error: future cannot be sent between threads safely
2-
--> $DIR/issue-64130-non-send-future-diags.rs:21:13
2+
--> $DIR/issue-64130-non-send-future-diags.rs:23:13
33
|
44
LL | is_send(foo());
55
| ^^^^^ future returned by `foo` is not `Send`
66
|
77
= help: within `impl Future`, the trait `Send` is not implemented for `MutexGuard<'_, u32>`
88
note: future is not `Send` as this value is used across an await
9-
--> $DIR/issue-64130-non-send-future-diags.rs:15:5
9+
--> $DIR/issue-64130-non-send-future-diags.rs:17:5
1010
|
1111
LL | let g = x.lock().unwrap();
1212
| - has type `MutexGuard<'_, u32>` which is not `Send`
@@ -15,7 +15,7 @@ LL | baz().await;
1515
LL | }
1616
| - `g` is later dropped here
1717
note: required by a bound in `is_send`
18-
--> $DIR/issue-64130-non-send-future-diags.rs:7:15
18+
--> $DIR/issue-64130-non-send-future-diags.rs:9:15
1919
|
2020
LL | fn is_send<T: Send>(t: T) { }
2121
| ^^^^ required by this bound in `is_send`

src/test/ui/async-await/issue-71137.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
// edition:2018
2+
#![feature(must_not_suspend)]
3+
#![allow(must_not_suspend)]
24

35
use std::future::Future;
46
use std::sync::Mutex;

src/test/ui/async-await/issue-71137.stderr

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
error: future cannot be sent between threads safely
2-
--> $DIR/issue-71137.rs:20:14
2+
--> $DIR/issue-71137.rs:22:14
33
|
44
LL | fake_spawn(wrong_mutex());
55
| ^^^^^^^^^^^^^ future returned by `wrong_mutex` is not `Send`
66
|
77
= help: within `impl Future`, the trait `Send` is not implemented for `MutexGuard<'_, i32>`
88
note: future is not `Send` as this value is used across an await
9-
--> $DIR/issue-71137.rs:12:5
9+
--> $DIR/issue-71137.rs:14:5
1010
|
1111
LL | let mut guard = m.lock().unwrap();
1212
| --------- has type `MutexGuard<'_, i32>` which is not `Send`
@@ -16,7 +16,7 @@ LL | *guard += 1;
1616
LL | }
1717
| - `mut guard` is later dropped here
1818
note: required by a bound in `fake_spawn`
19-
--> $DIR/issue-71137.rs:6:27
19+
--> $DIR/issue-71137.rs:8:27
2020
|
2121
LL | fn fake_spawn<F: Future + Send + 'static>(f: F) { }
2222
| ^^^^ required by this bound in `fake_spawn`
+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// edition:2018
2+
#![deny(must_not_suspend)] //~ ERROR the `must_not_suspend`
3+
//~| ERROR the `must_not_suspend`
4+
//~| ERROR the `must_not_suspend`
5+
6+
async fn other() {}
7+
8+
pub async fn uhoh(m: std::sync::Mutex<()>) {
9+
let _guard = m.lock().unwrap(); //~ ERROR `MutexGuard` held across
10+
other().await;
11+
}
12+
13+
fn main() {
14+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
error[E0658]: the `must_not_suspend` lint is unstable
2+
--> $DIR/gated.rs:2:1
3+
|
4+
LL | #![deny(must_not_suspend)]
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
6+
|
7+
= note: see issue #83310 <https://github.com/rust-lang/rust/issues/83310> for more information
8+
= help: add `#![feature(must_not_suspend)]` to the crate attributes to enable
9+
10+
error[E0658]: the `must_not_suspend` lint is unstable
11+
--> $DIR/gated.rs:2:1
12+
|
13+
LL | #![deny(must_not_suspend)]
14+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
15+
|
16+
= note: see issue #83310 <https://github.com/rust-lang/rust/issues/83310> for more information
17+
= help: add `#![feature(must_not_suspend)]` to the crate attributes to enable
18+
19+
error[E0658]: the `must_not_suspend` lint is unstable
20+
--> $DIR/gated.rs:2:1
21+
|
22+
LL | #![deny(must_not_suspend)]
23+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
24+
|
25+
= note: see issue #83310 <https://github.com/rust-lang/rust/issues/83310> for more information
26+
= help: add `#![feature(must_not_suspend)]` to the crate attributes to enable
27+
28+
error: `MutexGuard` held across a suspend point, but should not be
29+
--> $DIR/gated.rs:9:9
30+
|
31+
LL | let _guard = m.lock().unwrap();
32+
| ^^^^^^
33+
LL | other().await;
34+
| ------------- the value is held across this suspend point
35+
|
36+
note: the lint level is defined here
37+
--> $DIR/gated.rs:2:9
38+
|
39+
LL | #![deny(must_not_suspend)]
40+
| ^^^^^^^^^^^^^^^^
41+
note: holding a MutexGuard across suspend points can cause deadlocks, delays, and cause Futures to not implement `Send`
42+
--> $DIR/gated.rs:9:9
43+
|
44+
LL | let _guard = m.lock().unwrap();
45+
| ^^^^^^
46+
help: consider using a block (`{ ... }`) to shrink the value's scope, ending before the suspend point
47+
--> $DIR/gated.rs:9:9
48+
|
49+
LL | let _guard = m.lock().unwrap();
50+
| ^^^^^^
51+
52+
error: aborting due to 4 previous errors
53+
54+
For more information about this error, try `rustc --explain E0658`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// edition:2018
2+
// run-pass
3+
4+
use std::sync::Mutex;
5+
6+
// Copied from the issue. Allow-by-default for now, so run-pass
7+
pub async fn foo() {
8+
let foo = Mutex::new(1);
9+
let lock = foo.lock().unwrap();
10+
11+
// Prevent mutex lock being held across `.await` point.
12+
drop(lock);
13+
14+
bar().await;
15+
}
16+
17+
async fn bar() {}
18+
19+
fn main() {}

src/test/ui/lint/must_not_suspend/mutex.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
// edition:2018
2+
#![feature(must_not_suspend)]
23
#![deny(must_not_suspend)]
34

45
async fn other() {}

src/test/ui/lint/must_not_suspend/mutex.stderr

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,23 @@
11
error: `MutexGuard` held across a suspend point, but should not be
2-
--> $DIR/mutex.rs:7:9
2+
--> $DIR/mutex.rs:8:9
33
|
44
LL | let _guard = m.lock().unwrap();
55
| ^^^^^^
66
LL | other().await;
77
| ------------- the value is held across this suspend point
88
|
99
note: the lint level is defined here
10-
--> $DIR/mutex.rs:2:9
10+
--> $DIR/mutex.rs:3:9
1111
|
1212
LL | #![deny(must_not_suspend)]
1313
| ^^^^^^^^^^^^^^^^
1414
note: holding a MutexGuard across suspend points can cause deadlocks, delays, and cause Futures to not implement `Send`
15-
--> $DIR/mutex.rs:7:9
15+
--> $DIR/mutex.rs:8:9
1616
|
1717
LL | let _guard = m.lock().unwrap();
1818
| ^^^^^^
1919
help: consider using a block (`{ ... }`) to shrink the value's scope, ending before the suspend point
20-
--> $DIR/mutex.rs:7:9
20+
--> $DIR/mutex.rs:8:9
2121
|
2222
LL | let _guard = m.lock().unwrap();
2323
| ^^^^^^

src/test/ui/lint/must_not_suspend/warn.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// edition:2018
22
// run-pass
33
#![feature(must_not_suspend)]
4+
#![warn(must_not_suspend)]
45

56
#[must_not_suspend = "You gotta use Umm's, ya know?"]
67
struct Umm {

src/test/ui/lint/must_not_suspend/warn.stderr

+8-4
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,23 @@
11
warning: `Umm` held across a suspend point, but should not be
2-
--> $DIR/warn.rs:20:9
2+
--> $DIR/warn.rs:21:9
33
|
44
LL | let _guard = bar();
55
| ^^^^^^
66
LL | other().await;
77
| ------------- the value is held across this suspend point
88
|
9-
= note: `#[warn(must_not_suspend)]` on by default
9+
note: the lint level is defined here
10+
--> $DIR/warn.rs:4:9
11+
|
12+
LL | #![warn(must_not_suspend)]
13+
| ^^^^^^^^^^^^^^^^
1014
note: You gotta use Umm's, ya know?
11-
--> $DIR/warn.rs:20:9
15+
--> $DIR/warn.rs:21:9
1216
|
1317
LL | let _guard = bar();
1418
| ^^^^^^
1519
help: consider using a block (`{ ... }`) to shrink the value's scope, ending before the suspend point
16-
--> $DIR/warn.rs:20:9
20+
--> $DIR/warn.rs:21:9
1721
|
1822
LL | let _guard = bar();
1923
| ^^^^^^

0 commit comments

Comments
 (0)