Skip to content

Warn by default when encountering a statement which only consists of an equality comparison #1812

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

Closed
wants to merge 5 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
102 changes: 102 additions & 0 deletions text/0000-eq-statement-warning.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
- Feature Name: eq_statement_warning
- Start Date: 2016-12-07
- RFC PR: (leave this empty)
- Rust Issue: (leave this empty)

# Summary
[summary]: #summary

Warn by default when encountering a statement which only consists of an equality comparison.

# Motivation
[motivation]: #motivation

It is easy to accidentally write `==` when one actually meant `=`.

Consider the following code:

```rust
fn main() {
let mut a = 10;
println!("A is {}", a);
if 1 == 2 {
a = 20;
} else {
a == 30; // Oops, meant assignment
}
println!("A is now {}", a); // Still 10
}
```

At the time of this RFC, no warning is produced for this code,
making it easy not to notice this mistake.
This can result in wasted time trying to debug a simple mistake.

We can rectify this by giving a warning to the user.

I'd like to quote @mbrubeck to provide additional motivation
for why this is a good candidate for an on-by-default builtin lint:

- It catches a typo that is easy to make and difficult to spot,
and that won't be caught by type checking.

- It can be very narrowly targeted, only matching statements of the form `EXPR == EXPR;`.

- False positives are unlikely, because `==` should rarely if ever have side effects,
so it almost never makes sense to discard its result.

# Detailed design
[design]: #detailed-design

Add a new lint called `eq_statement`, which checks for statements that are
of the form `lhs == rhs;`. This lint should warn by default.

The message should tell the user that the result of the equality comparison is not used.
It should also hint that the user probably intended `lhs = rhs`.
Optionally, it can also tell the user that they if they only want the side effects, they
can explicitly express that with `let _ = lhs == rhs;`.

# Drawbacks
[drawbacks]: #drawbacks

This adds an additional lint to maintain.

False positives shouldn't be an issue, as `let _ = rhs == rhs;` expresses the same thing
more explicitly.

# Alternatives
[alternatives]: #alternatives

## [RFC 886](https://github.com/rust-lang/rfcs/pull/886)

[RFC 886](https://github.com/rust-lang/rfcs/pull/886) proposes allowing the `must_use` attribute
on functions. With this, `PartialEq::eq` could be marked `must_use`.

This RFC was closed, but it should be reconsidered with this use case serving as
additional motivation.

## Clippy

Clippy already has a lint that warns about this, called `no_effect`.

It looks like this:
```
warning: statement with no effect, #[warn(no_effect)] on by default
--> src/main.rs:7:9
|
7 | a == 30; // Oops, meant assignment
| ^^^^^^^^
```

However, not everyone uses clippy, and I believe this is a common enough mistake
to justify including a lint for it in rustc itself.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isn't the solution to simply move the lint from clippy to rustc? Together with the unnecessary_operation lint for maximal effect

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The no_effect lint in clippy has a larger scope than this one, making it more prone to false positives, and less likely to be accepted into rustc. But I'll add merging this lint into rustc as a possible alternative.

Since unnecessary_operation is not required to solve the problem described in the motivation, it should probably belong in a separate RFC.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

an intermediate solution is to name the rustc lint no_effect, only implement your suggested a == b; check, and thus ensure that the lint's name will never become obsolete, since it can be extended to more complex situations.


The `no_effect` lint itself could also be considered for inclusion into rustc
and enabled by default. Note however that `no_effect` is larger in scope than
`eq_statement`, so it is more likely to _potentially_ have false positives, though
none have been found to date.

# Unresolved questions
[unresolved]: #unresolved-questions

None.