-
Notifications
You must be signed in to change notification settings - Fork 13.8k
Not linting irrefutable_let_patterns on let chains #146832
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
base: master
Are you sure you want to change the base?
Not linting irrefutable_let_patterns on let chains #146832
Conversation
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment has been minimized.
This comment has been minimized.
11d320a
to
450d0a3
Compare
This comment has been minimized.
This comment has been minimized.
450d0a3
to
0aae158
Compare
This comment has been minimized.
This comment has been minimized.
ce66065
to
e77a3c4
Compare
Some changes occurred in match checking cc @Nadrieril The Miri subtree was changed cc @rust-lang/miri |
It seems that only modifying |
// for let chains, don't emit IRREFUTABLE_LET_PATTERNS | ||
if chain_refutabilities.len() > 1 { | ||
return; | ||
} | ||
|
||
if chain_refutabilities.iter().all(|r| matches!(*r, Some((_, Irrefutable)))) { | ||
// The entire chain is made up of irrefutable `let` statements | ||
report_irrefutable_let_patterns( |
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.
It seems the check you're adding should cause a reworking of the logic that follows.
All the lints seem to be removed in that test, but you'll want to ensure there are tests that cover the edges of what is still linted here. @rustbot author |
Reminder, once the PR becomes ready for a review, use |
e77a3c4
to
6425c06
Compare
// For let chains, don't lint. | ||
if let [Some((_, refutability))] = chain_refutabilities[..] { | ||
self.check_single_let(refutability, ex.span); |
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.
but you'll want to ensure there are tests that cover the edges of what is still linted here.
match chain_refutabilities.len() {
0 => "`assert!(self.let_source != LetSource::None)` ensure this case doesn't exist"
2.. => "`if let [Some((_, refutability))] = chain_refutabilities[..]` ensure not checked" // The purpose of this PR: don't check let chains
1 if chain_refutabilities[0].is_none()
=> "A boolean expression at the start of `while let` | `if let` | `else if let`, this case cannot pass syntax analysis"
1 if chain_refutabilities[0].is_some()
=> "There is exactly one let binding in `while let` | `if let` | `else if let` statement, proceed to check"
}
Some changes occurred to MIR optimizations cc @rust-lang/wg-mir-opt |
This comment has been minimized.
This comment has been minimized.
282a823
to
075e491
Compare
I tried adding a new test file, but I don't know why edit: adding |
This comment has been minimized.
This comment has been minimized.
075e491
to
b284c6b
Compare
@rustbot ready |
//@ edition: 2024 | ||
//@ check-pass | ||
|
||
#![feature(if_let_guard)] | ||
|
||
use std::ops::Range; | ||
|
||
fn main() { | ||
let opt = Some(None..Some(1)); | ||
|
||
if let first = &opt {} | ||
//~^ WARN irrefutable `if let` pattern | ||
|
||
if let first = &opt | ||
&& let Some(second) = first | ||
{} |
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.
Please add a comment at the top of this test describing the purpose of this test overall and comments throughout describing the nature of the cases that we're testing.
// If at least one of the operands is a `let ... = ...`. | ||
if chain_refutabilities.iter().any(|x| x.is_some()) { | ||
self.check_let_chain(chain_refutabilities, ex.span); | ||
// For let chains, don't lint. |
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.
This isn't a good comment in this position. What follows is something that will lint in some cases, and that's what should be described.
@rustbot author |
7200237
to
fddc34f
Compare
fddc34f
to
07a68e3
Compare
@rustbot ready |
This will need an FCP by the lang team. For that, this needs a description of what we'll be stabilizing exactly and the reasons for it. Have a look at other PRs that are labeled @rustbot author |
Is there anything I can do to move this forward? |
Yes, you can write such a description. :) |
I have updated the top comment of this PR. Does it now have the proper format for a FCP? If so, what are the next steps to get it started? |
Description
this PR makes the lint
irrefutable_let_patterns
not check forlet chains
,only check for single
if let
,while let
, andif let guard
.Motivation
Since
let chains
were stabilized, the following code has become common:This code naturally expresses "please call that function and then do something if the return value satisfies a condition".
Putting the let binding outside the if would be bad as then it remains in scope after the if, which is not the intent.
Current Output:
Another common case is progressively destructuring a struct with enum fields, or an enum with struct variants:
Current Output:
To avoid the warning, the readability would be much worse:
related issue
possible questions
Moving the irrefutable pattern at the head of the chain out of it would cause a variable that was intended to be temporary to remain in scope, so we remove it.
However, should we keep the check for moving the irrefutable pattern at the tail into the body?
Should we still lint
entire chain is made up of irrefutable let
?This is my first time contributing non-documentation code to Rust. If there are any irregularities, please feel free to point them out.
: )