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

[FP] identity_op in front of if #8730

Merged
merged 1 commit into from
May 3, 2022
Merged

Conversation

tamaroning
Copy link
Contributor

@tamaroning tamaroning commented Apr 22, 2022

fix #8724

changelog: FP: [identity_op]: is now allowed in front of if statements, blocks and other expressions where the suggestion would be invalid.

Resolved simular problems with blocks, mathces, and loops.
identity_op always does NOT suggest reducing 0 + if b { 1 } else { 2 } + 3 into if b { 1 } else { 2 } + 3 even in the case that the expression is in f(expr) or let x = expr; for now.

@rust-highfive
Copy link

r? @Manishearth

(rust-highfive has picked a reviewer for you, use r? to override)

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties label Apr 22, 2022
// See #8724
let a = 0;
let b = true;
0 + if b { 1 } else { 2 };
Copy link
Contributor

Choose a reason for hiding this comment

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

I would like to see a testcase like let _c = 0 + if b { 1 } else { 2 };
Maybe also a function like I wrote in #8724:

pub fn decide(a: bool, b: bool) -> u32 {
    0 + if a { 1 } else { 2 } + if b { 3 } else { 5 }
}

@tamaroning
Copy link
Contributor Author

tamaroning commented Apr 22, 2022

Hmm, uitest somehow fails.
Despite of attribute #[allow(clippy::identity_op)], the warning of identity_op occurs.

...
---- compile_test stdout ----
diff of stderr:

+error: the operation is ineffective. Consider reducing it to `i`
error: test failed, to rerun pass '--test compile-test'
+  --> $DIR/without_loop_counters.rs:104:13
+   |
+LL |         dst[i - 0] = src[i];
+   |             ^^^^^
+   |
+   = note: `-D clippy::identity-op` implied by `-D warnings`
+
...

#[allow(clippy::identity_op)]
for i in 0..5 {
dst[i - 0] = src[i];
}

4/23
Updated without_loop_counters test

@tamaroning tamaroning marked this pull request as ready for review April 22, 2022 16:17
Comment on lines 59 to 77
fn reducible_to_right(&mut self, right: &'tcx Expr<'_>) -> bool {
if self.top_level_binop {
true
} else {
!if let ExprKind::If(..) | ExprKind::Match(..) = right.kind {
self.leftmost
} else {
false
}
match cmp.node {
BinOpKind::Add | BinOpKind::BitOr | BinOpKind::BitXor => {
check(cx, left, 0, e.span, right.span);
check(cx, right, 0, e.span, left.span);
},
BinOpKind::Shl | BinOpKind::Shr | BinOpKind::Sub => check(cx, right, 0, e.span, left.span),
BinOpKind::Mul => {
check(cx, left, 1, e.span, right.span);
check(cx, right, 1, e.span, left.span);
},
BinOpKind::Div => check(cx, right, 1, e.span, left.span),
BinOpKind::BitAnd => {
check(cx, left, -1, e.span, right.span);
check(cx, right, -1, e.span, left.span);
},
BinOpKind::Rem => check_remainder(cx, left, right, e.span, left.span),
_ => (),
}
}

This comment was marked as outdated.

@Manishearth
Copy link
Member

r? @Alexendoo

(I'm travelling rn and might not be able to do full reviews, can rubber-stamp after you've had a look at it)

Copy link
Member

@Alexendoo Alexendoo left a comment

Choose a reason for hiding this comment

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

👋

Comment on lines 48 to 52
struct ExprVisitor<'a, 'tcx> {
cx: &'a LateContext<'tcx>,
leftmost: bool,
top_level_binop: bool,
}
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 a visitor is too confusing here, e.g. leftmost is always true by the time it reaches the self.reducible_to_right calls

A simpler alternative would be to go back to using check_expr in the lint pass and checking if e's parent expr is an ExprKind::Binary to determine if it's top level or not

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks for your review. I fixed it.

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 the visitor can be removed entirely, at least for all the test cases leftmost is still always true in self.reducible_to_right because the order statements are visited in are

     a + b + c + d;
// 1 LLLLLLLLL   R
// 2 LLLLL   R
// 3 L   R

I believe just checking the ExprKind of right as you do in reducible_to_right + is_toplevel_binary is enough

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ohh I misunderstood what you meant. And it seems to work for test cases.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed it.

@giraffate giraffate assigned giraffate and unassigned Manishearth Apr 27, 2022
Comment on lines 75 to 78
// Checks if `left op ..right` can be actually reduced to `right`
// e.g. `0 + if b { 1 } + else { 2 } + if b { 3 } + else { 4 }`
// cannot be reduced to `if b { 1 } + else { 2 } + if b { 3 } + else { 4 }`
// See #8724
Copy link
Member

Choose a reason for hiding this comment

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

nit

Suggested change
// Checks if `left op ..right` can be actually reduced to `right`
// e.g. `0 + if b { 1 } + else { 2 } + if b { 3 } + else { 4 }`
// cannot be reduced to `if b { 1 } + else { 2 } + if b { 3 } + else { 4 }`
// See #8724
/// Checks if `left op ..right` can be actually reduced to `right`
/// e.g. `0 + if b { 1 } else { 2 } + if b { 3 } else { 4 }`
/// cannot be reduced to `if b { 1 } else { 2 } + if b { 3 } else { 4 }`
/// See #8724

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks. Fixed it.

Comment on lines +95 to +96
let _ = 0 + if 0 + 1 > 0 { 1 } else { 2 } + if 0 + 1 > 0 { 3 } else { 4 };
let _ = 0 + match 0 + 1 { 0 => 10, _ => 20 } + match 0 + 1 { 0 => 30, _ => 40 };
Copy link
Member

Choose a reason for hiding this comment

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

There's a false negative in here, in contexts where it's unambiguously an expression it is fine to reduce these, e.g.

let b = true;

f(0 + if b { 1 } else { 2 } + 3);
let _ = 0 + if b { 1 } else { 2 } + 3;
const _: i32 = 0 + if b { 1 } else { 2 } + 3;

Perhaps instead of get_parent_expr it should be a get_parent_node, checking the node's variant

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks.
But I think it seems to be enough to use get_parent_expr.
Is there need to check node variants, using get_parent_node?

Copy link
Member

Choose a reason for hiding this comment

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

Those cases don't lint currently but they could do is what I mean, as in

// doesn't trigger the lint
f(0 + if b { 1 } else { 2 } + 3);
// but it could, as the following is valid
f(if b { 1 } else { 2 } + 3);

It'd be also fine to leave it as is and make a note of that under a Known problems section in the lint description

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I didn't aware of this case. I will leave it as it is and add documents.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added documents

@@ -99,7 +100,6 @@ pub fn manual_copy(src: &[i32], dst: &mut [i32], dst2: &mut [i32]) {
dst[i] = src[i - from];
}

#[allow(clippy::identity_op)]
Copy link
Member

Choose a reason for hiding this comment

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

nit: can move this back now

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed it.

// cannot be reduced to `if b { 1 } + else { 2 } + if b { 3 } + else { 4 }`
// See #8724
fn reducible_to_right(cx: &LateContext<'_>, binary: &Expr<'_>, right: &Expr<'_>) -> bool {
if let ExprKind::If(..) | ExprKind::Match(..) = right.kind {
Copy link
Member

Choose a reason for hiding this comment

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

Can also include ExprKind::Block and ExprKind::Loop

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed it.

@Manishearth
Copy link
Member

@bors deletage=Alexendoo

@Manishearth
Copy link
Member

@bors delegate=Alexendoo

@bors
Copy link
Collaborator

bors commented Apr 29, 2022

✌️ @Alexendoo can now approve this pull request

@Alexendoo
Copy link
Member

Thanks @tamaroning!

Changes look good, please could you squash your commits into one with a descriptive message and then it'll be good to go

fix

Update identity_op.rs

ok

update without_loop_counters test

chore

fix

chore

remove visitor and leftmost

fix

add document
@Alexendoo
Copy link
Member

Thanks!

@bors r+

@bors
Copy link
Collaborator

bors commented May 2, 2022

📌 Commit 6ad810f has been approved by Alexendoo

bors added a commit that referenced this pull request May 2, 2022
[FP] identity_op in front of if

fix #8724

changelog:
@bors
Copy link
Collaborator

bors commented May 2, 2022

⌛ Testing commit 6ad810f with merge 59d7a90...

@bors
Copy link
Collaborator

bors commented May 2, 2022

💔 Test failed - checks-action_test

@xFrednet
Copy link
Member

xFrednet commented May 2, 2022

Hey, the changelog entry from the PR description is still missing. Could you add one? Then all tests should pass 🙃

@tamaroning
Copy link
Contributor Author

@xFrednet Sorry, could you rerun the test?

@xFrednet
Copy link
Member

xFrednet commented May 3, 2022

No problem @tamaroning, usually I would edit the changelog entry myself if it's the last thing, but here I wasn't sure anymore how it was exactly fixed. 🙃 Thank you for the changes 👍

@bors retry

@bors
Copy link
Collaborator

bors commented May 3, 2022

⌛ Testing commit 6ad810f with merge 0ceacbe...

@bors
Copy link
Collaborator

bors commented May 3, 2022

☀️ Test successful - checks-action_dev_test, checks-action_remark_test, checks-action_test
Approved by: Alexendoo
Pushing 0ceacbe to master...

@bors bors merged commit 0ceacbe into rust-lang:master May 3, 2022
bors added a commit that referenced this pull request May 24, 2022
…dnet

`identity_op`: add parenthesis to suggestions where required

changelog: [`identity_op`]: add parenthesis to suggestions where required

Follow up to #8730, wraps the cases we can't lint as-is in parenthesis rather than ignoring them

Catches a couple new FPs with mixed operator precedences and `as` casts

```rust
// such as
0 + { a } * 2;
0 + a as usize;
```

The suggestions are now applied using `span_lint_and_sugg` rather than appearing in just the message and have a `run-rustfix` test
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-review Status: Awaiting review from the assignee but also interested parties
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[FP] identity_op in front of if
8 participants