Skip to content

Conversation

@mdgaziur
Copy link
Contributor

@mdgaziur mdgaziur commented Nov 26, 2022

This PR fixes #9958. In order to fix the issue, the lint will now peel reference operators and enclose the expression with parentheses when necessary.

changelog: [comparison_to_empty]: Peel deref operators in suggestions when necessary

@rust-highfive
Copy link

Thanks for the pull request, and welcome! The Rust team is excited to review your changes, and you should hear from @dswij (or someone else) soon.

Please see the contribution instructions for more information.

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties label Nov 26, 2022
Copy link
Member

@dswij dswij left a comment

Choose a reason for hiding this comment

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

Thanks for the PR, and welcome to Clippy!

Note that for the changelog, it's user-facing changelog. So we'd expect a short explanation of the change itself, rather than pointing it to an issue number/link. Could you help to change that?

Other than that, it's just a small comment on the change itself, and it should be good to go

Comment on lines 430 to 440
if let ExprKind::Unary(UnOp::Deref, expr) = lit1.kind {
lit1 = expr;
}
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 only covers 1 deref, so 2 derefs or more wouldn't be covered, i.e.

    let s = "Hello, world!";
    let s1 = &&s;
    println!("{}", **s1 == "");

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 think getting the expression that is deref'd in a loop can be a solution

Copy link
Member

Choose a reason for hiding this comment

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

That's one way to do it, but we have a util function that derefs expr

/// Removes `AddrOf` operators (`&`) or deref operators (`*`), but only if a reference type is
/// dereferenced. An overloaded deref such as `Vec` to slice would not be removed.
pub fn peel_ref_operators<'hir>(cx: &LateContext<'_>, mut expr: &'hir Expr<'hir>) -> &'hir Expr<'hir> {
loop {
match expr.kind {
ExprKind::AddrOf(_, _, e) => expr = e,
ExprKind::Unary(UnOp::Deref, e) if cx.typeck_results().expr_ty(e).is_ref() => expr = e,
_ => break,
}
}
expr
}

Maybe we can use that instead

Copy link
Contributor Author

@mdgaziur mdgaziur Nov 30, 2022

Choose a reason for hiding this comment

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

Another thing I noticed is that, parentheses aren't removed. So, something like the following code:

**(s1) == ""

will become:

(s1).is_empty()

Is there any way to remove these redundant parentheses?

Copy link
Member

Choose a reason for hiding this comment

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

We have another util to build suggestions, but it needs a little bit more digging:

https://github.com/rust-lang/rust-clippy/blob/78589ffad2c973f7863fdabc2df6e8ab2b54110f/clippy_utils/src/sugg.rs

IIRC, you can remove parentheses with this.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Can you tell me what default parameter in Sugg::hir_with_applicability does?

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 found out that other lints don't remove the parentheses. Is this ok if I ignore parentheses?
AFAIK, the util you've suggested directly takes snippet from source code and has no method to remove unnecessary parentheses.

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 it depends on the lint whether it will suggest removing the parentheses or not. Ideally, we'd have the parentheses removed.

But it's fine if we merge it without removing it in this PR, since the change is already an improvement as it is.

Let me know if you decide not to include the parentheses change in this PR.

Copy link
Contributor Author

@mdgaziur mdgaziur Dec 1, 2022

Choose a reason for hiding this comment

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

I think we can ignore parentheses for now.

let s = "Hello, world!";
let s1 = &s;
println!("{}", *s1 == "");

Copy link
Member

Choose a reason for hiding this comment

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

Let's also add a case for multiple derefs in the test.

@mdgaziur mdgaziur force-pushed the master branch 3 times, most recently from 7b4ca31 to 5b42720 Compare November 30, 2022 13:02
@dswij
Copy link
Member

dswij commented Dec 2, 2022

Thanks for this! @bors r+

@bors
Copy link
Contributor

bors commented Dec 2, 2022

📌 Commit 7a0f0c0 has been approved by dswij

It is now in the queue for this repository.

@bors
Copy link
Contributor

bors commented Dec 2, 2022

⌛ Testing commit 7a0f0c0 with merge 56d5657...

@dswij dswij changed the title Fix #9958 comparison_to_empty: peel deref operators in suggestions Dec 2, 2022
@dswij dswij changed the title comparison_to_empty: peel deref operators in suggestions comparison_to_empty: peel derefs in suggestions Dec 2, 2022
@bors
Copy link
Contributor

bors commented Dec 2, 2022

☀️ Test successful - checks-action_dev_test, checks-action_remark_test, checks-action_test
Approved by: dswij
Pushing 56d5657 to master...

@bors bors merged commit 56d5657 into rust-lang:master Dec 2, 2022
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.

Clippy lint "comparison to empty" fails to apply fix when reference is used

4 participants