Skip to content

Commit 6b14ce9

Browse files
Bhargav Voletinikomatsakis
authored andcommitted
Address more RFC review feedback
1 parent a5f176b commit 6b14ce9

File tree

1 file changed

+38
-4
lines changed

1 file changed

+38
-4
lines changed

text/0000-must-not-await-lint.md

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
- Feature Name: `must_not_await_lint`
22
- Start Date: 2020-11-09
3-
- RFC PR: [rust-lang/rfcs#0000](https://github.com/rust-lang/rfcs/pull/0000)
3+
- RFC PR: [rust-lang/rfcs#3014](https://github.com/rust-lang/rfcs/pull/3014)
44
- Rust Issue: [rust-lang/rust#0000](https://github.com/rust-lang/rust/issues/0000)
55

66
# Summary
@@ -13,7 +13,7 @@ Introduce a `#[must_not_await]` lint in the compiler that will warn the user whe
1313

1414
Enable users to fearlessly write concurrent async code without the need to understand the internals of runtimes and how their code will be affected. The goal is to provide a best effort warning that will let the user know of a possible side effect that is not visible by reading the code right away.
1515

16-
One example of these side effects is holding a `MutexGuard` across an await bound. This opens up the possibility of causing a deadlock since the future holding onto the lock did not relinquish it back before it yielded control. This is a problem for futures that run on single-threaded runtimes (`!Send`) where holding a local after a yield will result in a deadlock. Even on multi-threaded runtimes, it would be nice to provide a custom error message that explains why the user doesn't want to do this instead of only a generic message about their future not being `Send`. Any other kind of RAII guard which depends on behavior similar to that of a `MutexGuard` will have the same issue.
16+
One example of these side effects is holding a `MutexGuard` across an await bound. This opens up the possibility of causing a deadlock since the future holding onto the lock did not relinquish it back before it yielded control. This is a problem for futures that run on single-threaded runtimes (`!Send`) where holding a lock after a yield will result in a deadlock. Even on multi-threaded runtimes, it would be nice to provide a custom error message that explains why the user doesn't want to do this instead of only a generic message about their future not being `Send`. Any other kind of RAII guard which depends on behavior similar to that of a `MutexGuard` will have the same issue.
1717

1818
The big reason for including a lint like this is because under the hood the compiler will automatically transform async fn into a state machine which can store locals. This process is invisible to users and will produce code that is different than what is in the actual rust file. Due to this it is important to inform users that their code may not do what they expect.
1919

@@ -96,6 +96,26 @@ async fn foo() {
9696

9797
When used on a [trait declaration], if the value implementing that trait is held across an await point, the lint is violated.
9898

99+
```rust
100+
#[must_not_await]
101+
trait Lock {
102+
fn foo(&self) -> i32;
103+
}
104+
105+
fn get_lock() -> impl Lock {
106+
1i32
107+
}
108+
109+
async fn foo() {
110+
// violates the #[must_not_await] lint
111+
let bar = get_lock();
112+
my_async_op.await;
113+
println!("{:?}", bar);
114+
}
115+
```
116+
117+
When used on a function in a trait declaration, then the behavior also applies when the call expression is a function from the implementation of the trait.
118+
99119
```rust
100120
trait Trait {
101121
#[must_not_await]
@@ -113,6 +133,7 @@ async fn foo() {
113133
}
114134
```
115135

136+
116137
When used on a function in a trait implementation, the attribute does nothing.
117138

118139
[`MetaNameValueStr`]: https://doc.rust-lang.org/reference/attributes.html#meta-item-attribute-syntax
@@ -121,7 +142,9 @@ When used on a function in a trait implementation, the attribute does nothing.
121142
# Drawbacks
122143
[drawbacks]: #drawbacks
123144

124-
- There is a possibility it can produce a false positive warning and it could get noisy. But using the `allow` attribute would work similar to other `deny-by-default` lints.
145+
- There is a possibility it can produce a false positive warning and it could get noisy. But using the `allow` attribute would work similar to other [`warn-by-default`] lints. One thing to note, unlike the `#[must_use]` lint, users cannot silence this warning by using `let _ = bar()` where `bar()` returns a type which has a `#[must_use]` attribute. The `#[allow]` attribute will be the only way to silence the warning.
146+
147+
[`warn-by-default`]: https://doc.rust-lang.org/rustc/lints/listing/warn-by-default.html
125148

126149
# Rationale and alternatives
127150
[rationale-and-alternatives]: #rationale-and-alternatives
@@ -149,4 +172,15 @@ The `#[must_use]` attribute ensures that if a type or the result of a function i
149172
# Unresolved questions
150173
[unresolved-questions]: #unresolved-questions
151174

152-
- Propagate the lint in nested structs/enums. Similar to the use case for the `must_use` attribute. These likely should be solved together.
175+
176+
# Common behavior with `#[must_use]` lint
177+
178+
Both `#[must_use]` and `#[must_not_await]` are [`warn-by-default`] lints, and are applied to types decorated with the attribute. Currently the `#[must_use]` lint does not automatically propagate the lint in nested structures/enums due to the additional complexity that it adds on top of the possible breaking changes introduced in the wider ecosystem
179+
180+
Automatically propagating the lint for types containing a type marked by one of these attributes would make for a more ergonomic user experience, and would reduce syntactic noise.
181+
182+
While tradeoffs exist for both approaches, in either case, both lints should exhibit the same behavior.
183+
184+
The `#[must_use]` lint is being used in stable rust for a long time now(The earliest reference I could find was in the release notes for [1.27]) with existing behavior.
185+
186+
[1.27]: https://github.com/rust-lang/rust/blob/master/RELEASES.md#version-1270-2018-06-21

0 commit comments

Comments
 (0)