-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
#[must_use = false] #3737
Open
lolbinarycat
wants to merge
4
commits into
rust-lang:master
Choose a base branch
from
lolbinarycat:must_use-false
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
#[must_use = false] #3737
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
- Feature Name: `must_use_false` | ||
- Start Date: 2024-12-07 | ||
- RFC PR: [rust-lang/rfcs#3737](https://github.com/rust-lang/rfcs/pull/3737) | ||
- Rust Issue: [rust-lang/rust#0000](https://github.com/rust-lang/rust/issues/0000) | ||
|
||
# Summary | ||
[summary]: #summary | ||
|
||
Allow annotating functions with `#[must_use = false]` to suppress any warning generated due to its return type being marked as `#[must_use]`. | ||
|
||
# Motivation | ||
[motivation]: #motivation | ||
|
||
The primary motivation is that there are some situations where a function is technically fallible, but it is almost always correct to not check its result. | ||
|
||
example: | ||
```rust | ||
/// Try to open a file before it is required. | ||
/// | ||
/// This result can be safely ignored, | ||
/// as the file will be automatically opened again | ||
/// when it is actually needed. | ||
#[must_use = false] | ||
pub fn hint_premptive_open(&mut self) -> io::Result<()> { | ||
/* ... */ | ||
} | ||
``` | ||
|
||
Another example is closing files and similar operations, where the only possible error recovery is to just ignoring the error. | ||
|
||
# Guide-level explanation | ||
[guide-level-explanation]: #guide-level-explanation | ||
|
||
The `#[must_use]` attribute can also take a boolean value instead of a string value. | ||
|
||
When a function is annotated with `#[must_use = false]`, its result can be ignored without triggering the `unused_must_use` lint, even if its return type is marked as `must_use`. | ||
|
||
`#[must_use = true]` is equivelent to `#[must_use]`. | ||
|
||
When used on a type, `#[must_use = false]` is equivelent to not having any `#[must_use]` attribute. | ||
|
||
# Reference-level explanation | ||
[reference-level-explanation]: #reference-level-explanation | ||
|
||
The `must_use` attribute is used to control when the `unused_must_use` lint is emitted. | ||
|
||
It has three forms: | ||
1. the plain `#[must_use]` form, equivalent to `#[must_use = true]`. | ||
2. the boolean form, `#[must_use = BOOLEAN]`, where `BOOLEAN` is either `true` or `false`. | ||
3. the string form, `#[must_use = "MESSAGE"]`, where `MESSAGE` is a help message to emmitted alongside the `unused_must_use` lint. | ||
|
||
For the purposes of calculating whether to emit `unused_must_use` for an expression, every function and type item is in one of the following `must_use` states: | ||
1. a positive state, corresponding to any `must_use` attribute besides `must_use = false`. | ||
2. a neutral state, corresponding to no `must_use` attribute | ||
3. a negative state, corresponding to `must_use = false`. | ||
|
||
For each | ||
[expression statement](https://doc.rust-lang.org/reference/statements.html#expression-statements), | ||
the following process is used to calculate a positive (emit the lint) or negative (do not emit the lint) result: | ||
1. if the expression of the expression statement is a function call, check the `must_use` state of that function, otherwise skip to step 3 | ||
2. if the function has a neutral state, continue to step 3, otherwise the result is positive/negative according the the state | ||
3. if the type of the expression has a positive `must_use` state, the result is positive, otherwise, the result is negative. | ||
|
||
|
||
# Drawbacks | ||
[drawbacks]: #drawbacks | ||
|
||
Yet another "opt-in/opt-out" dance, similar to `#[non_exhaustive]`. | ||
|
||
The usecase is fairly niche. | ||
|
||
Implementation complexity. | ||
|
||
Passing the result of a `#[must_use = false]` function through an identity function will cause the lint to trigger. | ||
|
||
# Rationale and alternatives | ||
[rationale-and-alternatives]: #rationale-and-alternatives | ||
|
||
An `=` style attribute is used since this is already used for `must_use`, and it intuativly evokes the idea of "overwriting" a variable. | ||
|
||
`#[must_use = true]` is provided for symmetry. | ||
|
||
# Prior art | ||
[prior-art]: #prior-art | ||
|
||
* [Pre-RFC on IRLO](https://internals.rust-lang.org/t/pre-rfc-must-use-false/21861) | ||
* Scala's `@CanIgnoreResult` annotation | ||
|
||
# Unresolved questions | ||
[unresolved-questions]: #unresolved-questions | ||
|
||
- Is this the best way we can handle this, or is there a more elegant/general solution that doesn't involve marking every single function? | ||
|
||
# Future possibilities | ||
[future-possibilities]: #future-possibilities | ||
|
||
* A future edition making `#[must_use]` the default for functions that return something other than `()`. | ||
* Allow annotating a module/crate with `#[must_use]` to make all its functions and methods default to `must_use`. | ||
|
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.