-
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
Add new lints: manual_and
and manual_or
#12832
base: master
Are you sure you want to change the base?
Add new lints: manual_and
and manual_or
#12832
Conversation
9d0b00d
to
4165cd5
Compare
clippy_lints/src/manual_and.rs
Outdated
/// ```no_run | ||
/// if a { | ||
/// b |
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.
doc test is failling, maybe you meant to use /// ```ignore
?. Or assign values to a
and b
using:
/// ```no_run
/// # let a = true;
/// # let b = false;
/// if a {
/// b
something like that~
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.
Since manual_and.rs
and manual_or.rs
shares a lot same code, could you merge them into a single file?
Similar to the structures inside of src/booleans.rs
.
clippy_lints/src/manual_or.rs
Outdated
if let ExprKind::If(cond, then, Some(else_expr)) = expr.kind { | ||
if contains_let(cond) { | ||
return; | ||
} |
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.
I think clippy_utils::higher::If should achieve the same result here.
you could try replacing it with:
use clippy_utils::higher;
if let Some(higher::If { cond, then, r#else: Some(else_expr) }) = higher::If::hir(expr) {
// ...
using visitor might seems a bit of overkill
4165cd5
to
66758bc
Compare
We made the requested changes |
clippy_lints/src/manual_and_or.rs
Outdated
if contains_let(cond) { | ||
return; | ||
} |
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.
I think this is not needed anymore? yes?
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.
That's true, it's fixed now!
(Jarcho has too many PR assigned, I hope this make sense...) r? clippy |
66758bc
to
0b884ca
Compare
☔ The latest upstream changes (presumably #12849) made this pull request unmergeable. Please resolve the merge conflicts. |
0b884ca
to
32b35e7
Compare
There are merge commits (commits with multiple parents) in your changes. We have a no merge policy so these commits will need to be removed for this pull request to be merged. You can start a rebase with the following commands:
The following commits are merge commits: |
Suggests replacing if-else expressions where one branch is a boolean literal with && / || operators. Co-authored-by: Francisco Salgueiro <[email protected]>
7b68c50
to
3658ef6
Compare
fn extract_final_expression_snippet<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>) -> Option<String> { | ||
if let ExprKind::Block(block, _) = expr.kind { | ||
if let Some(final_expr) = block.expr { | ||
return cx.sess().source_map().span_to_snippet(final_expr.span).ok(); |
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.
Can use snippet_opt
here & elsewhere
if contains_or(cond) || contains_or(then) || fetch_bool_expr(then).is_some() { | ||
return; | ||
} |
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.
The precedence of the context the if
appears in is also significant:
let _ = c == if a { b } else { false };
// becomes
let _ = c == a && b;
// AKA
let _ = (c == a) && b;
return; | ||
} | ||
if match then.kind { | ||
ExprKind::Block(block, _) => !block.stmts.is_empty(), |
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.
We should check that the type of block.expr
isn't !
(never), to exclude things like
if a {
return
} else {
false
}
The lint isn't semantically incorrect here but a && return
is unusual
.unwrap_or_else(|_| "..".to_string()); | ||
|
||
let then_snippet = extract_final_expression_snippet(cx, then).unwrap_or_else(|| "..".to_string()); | ||
let suggestion = format!("{cond_snippet} && {then_snippet}"); |
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.
We'll want to handle when the if
contains comments -
if a {
// Comment
b
} else {
false
}
Preserving them is an option but it might be better to not lint here, if the comment is large it would be weird to have in the middle of an &&
/||
There's span_contains_comment
to help with this
☔ The latest upstream changes (presumably #12873) made this pull request unmergeable. Please resolve the merge conflicts. |
Hey @mira-eanda , this is a ping from triage, since there hasn't been any activity in some time. Are you still planning to continue this implementation? If you have any questions, you're always welcome to ask them in this PR or on Zulip. @rustbot author |
Fixes #12434
Added two new lints:
manual_and
that suggests replacing if-else expressions where one branch is a boolean literal with&&
andmanual_or
which does the same but for the||
operator.changelog: new lint: [
manual_and
]changelog: new lint: [
manual_or
]