Skip to content
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

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

mira-eanda
Copy link
Contributor

Fixes #12434

Added two new lints: manual_and that suggests replacing if-else expressions where one branch is a boolean literal with && and
manual_or which does the same but for the || operator.


changelog: new lint: [manual_and]
changelog: new lint: [manual_or]

@rustbot
Copy link
Collaborator

rustbot commented May 22, 2024

r? @Jarcho

rustbot has assigned @Jarcho.
They will have a look at your PR within the next two weeks and either review your PR or reassign to another reviewer.

Use r? to explicitly pick a reviewer

@rustbot rustbot added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties label May 22, 2024
Comment on lines 20 to 22
/// ```no_run
/// if a {
/// b
Copy link
Member

@J-ZhengLi J-ZhengLi May 23, 2024

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~

Copy link
Member

@J-ZhengLi J-ZhengLi left a 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.

Comment on lines 69 to 72
if let ExprKind::If(cond, then, Some(else_expr)) = expr.kind {
if contains_let(cond) {
return;
}
Copy link
Member

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

@mira-eanda
Copy link
Contributor Author

We made the requested changes

Comment on lines 183 to 185
if contains_let(cond) {
return;
}
Copy link
Member

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?

Copy link
Contributor Author

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!

@J-ZhengLi
Copy link
Member

J-ZhengLi commented May 31, 2024

(Jarcho has too many PR assigned, I hope this make sense...)

r? clippy

@bors
Copy link
Collaborator

bors commented Jun 11, 2024

☔ The latest upstream changes (presumably #12849) made this pull request unmergeable. Please resolve the merge conflicts.

@rustbot rustbot added has-merge-commits PR has merge commits, merge with caution. S-waiting-on-author Status: This is awaiting some action from the author. (Use `@rustbot ready` to update this status) labels Jun 17, 2024
@rustbot
Copy link
Collaborator

rustbot commented Jun 17, 2024

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:

$ # rebase
$ git pull --rebase https://github.com/rust-lang/rust-clippy.git master
$ git push --force-with-lease

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 <francisco.salgueiro@tecnico.ulisboa.pt>
@rustbot rustbot removed has-merge-commits PR has merge commits, merge with caution. S-waiting-on-author Status: This is awaiting some action from the author. (Use `@rustbot ready` to update this status) labels Jun 17, 2024
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();
Copy link
Member

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

Comment on lines +103 to +105
if contains_or(cond) || contains_or(then) || fetch_bool_expr(then).is_some() {
return;
}
Copy link
Member

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(),
Copy link
Member

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}");
Copy link
Member

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

@bors
Copy link
Collaborator

bors commented Jul 4, 2024

☔ The latest upstream changes (presumably #12873) made this pull request unmergeable. Please resolve the merge conflicts.

@Alexendoo Alexendoo added S-waiting-on-author Status: This is awaiting some action from the author. (Use `@rustbot ready` to update this status) and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties labels Jul 4, 2024
@xFrednet
Copy link
Member

xFrednet commented Aug 3, 2024

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-author Status: This is awaiting some action from the author. (Use `@rustbot ready` to update this status)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Manual && or ||
7 participants