-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Add ifs_as_logical_ops lint #14904
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?
Add ifs_as_logical_ops lint #14904
Conversation
☔ The latest upstream changes (possibly d7b27ec) made this pull request unmergeable. Please resolve the merge conflicts. |
ed0c921
to
a277b18
Compare
Hm, it doesn't look like my rebase really worked, let me have another go... |
a277b18
to
ed0c921
Compare
I'll take a look at merge conflicts once I've got a review, I think |
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.
Did a first pass over this. You'll need a late pass to avoid an annoying false positive.
impl EarlyLintPass for IfsAsLogicalOps { | ||
fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &Expr) { | ||
if let ExprKind::If(cond, cond_inner, Some(els)) = &e.kind | ||
&& let Some(inner_if_stmt) = cond_inner.stmts.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.
This needs to be exactly one statement.
You'll also want to make this a late lint to check if it diverges. e.g. todo!()
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.
Just for my own understanding, by diverge you mean the case where we have an intentional panic of some sort here instead of a boolean, in which case we shouldn'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.
or are there other possible divergences?
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.
Ah I looked at zulip and also found https://en.wikipedia.org/wiki/Divergence_(computer_science) and I think I understand sufficiently now
if let ExprKind::If(cond, cond_inner, Some(els)) = &e.kind | ||
&& let Some(inner_if_stmt) = cond_inner.stmts.first() | ||
&& let ExprKind::Block(inner_block, _label) = &els.kind | ||
&& let Some(stmt) = inner_block.stmts.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.
This needs to be exactly one statement.
let if_cond_snippet = snippet(cx, cond.span, ".."); | ||
let conjunction_snippet = " && "; | ||
let inner_snippet = snippet(cx, inner_if_stmt.span, ".."); | ||
let final_snippet = if_cond_snippet + conjunction_snippet + inner_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.
Should just be format!("{x} && {y}")
&& let LitKind::Bool = &lit.kind | ||
&& lit.symbol == kw::False | ||
{ | ||
let if_cond_snippet = snippet(cx, cond.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.
Use clippy_utils::source::SpanRangeExt::get_source_text
instead.
Fixes #14865 by adding the ifs_as_logical_ops lint.
Only adds the conjunctive version (transform if x else y => x && y) for now.
Opening WIP PR to get feedback.
Please write a short comment explaining your change (or "none" for internal only changes)
changelog: [
ifs_as_logical_ops
] : "WIP"