-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Added new non_zero_suggestions
lint
#13167
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
Conversation
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) some time within the next two weeks. Please see the contribution instructions for more information. Namely, in order to ensure the minimum review times lag, PR authors and assigned reviewers should ensure that the review label (
|
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.
👋 welcome~
I'm just stopping by and left some comments.
(btw, I didn't go through the details, only pointing out something rather obvious~)
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) { | ||
if let ExprKind::Call(func, [arg]) = expr.kind { | ||
if let ExprKind::Path(qpath) = &func.kind { |
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.
maybe check if the expr is a binary expression first? Therefore the below example doesn't cause error after applying lint suggestion:
let x: u64 = u64::from(NonZeroU32::new(5).unwrap());
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.
First I thought like that only, based on the suggestion from the issue but then I thought do we need it?
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.
Do we need to check for binary expr?
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 yes? Notice that the tests are failing because the lint shouldn't suggestion a fix to a non-binary expr
:
error[E0308]: mismatched types
--> tests/ui/non_zero_suggestions.fixed:68:5
|
LL | fn no_bin_exp(x: u64, y: NonZeroU32) -> u64 {
| --- expected `u64` because of return type
LL | NonZeroU64::from(y)
| ^^^^^^^^^^^^^^^^^^^ expected `u64`, found `NonZero<u64>`
|
= note: expected type `u64`
found struct `std::num::NonZero<u64>`
help: call `Into::into` on this expression to convert `std::num::NonZero<u64>` into `u64`
|
LL | NonZeroU64::from(y).into()
| +++++++
In this case, you shouldn't give a MachineApplicable
suggestion at least, as it's telling rustfix
to apply that suggestion because it's "always correct", but that's not the case since there could be type difference. I think the original issue specifically limit the cases to binary expr
was because that they wanted to play safe, as the resulting type of an integer that add|sub|div|mul|...
another NonZero
type is still the integer type itself (example), so it can always being replaced to the NonZero
type directly.
I think you could try adjusting the applicability
base on whether the expr
is binary or not, if yes, you can continue to offer a MachineApplicable
suggestion as it is. But if not, you should state the applicability as MaybeIncorrect
, so when a user runs clippy with --fix
, it wouldn't cause any suggestion-cause-error
issue.
For example, you could try something like this:
let mut appllicability = Applicability::MaybeIncorrect;
if let ExprKind::Binary(_, _, rhs) = expr.kind {
applicability = Applicability::MachineApplicable;
check_for_fn(...);
} else {
check_for_fn(...);
}
If you decided to do this, you may split the test cases to non-fixable
and fixable
tests, because in clippy, the suggestion will always get applied no matter the applicability. (There are some lints that does this, search files that end with fixable
for hints)
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 guess you are right. Limiting the lint to binary expressions would be better. It avoids complex cases and aligns with the original intent of the issue. I'll focus on implementing this change and add relevant test cases. I'll update the PR soon with these changes.
Thank you very much for your thorough review and helpful suggestions, @J-ZhengLi ^^. Actually this is my first PR towards Open Source. 😅 |
❤️ Already doing pretty good then, keep it up~ |
All fixed! can you check? @J-ZhengLi |
r? clippy could someone have the time to take a look at this? |
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 already looks good, I merely have a suggestion for an optional extension. If you don't want to tackle that, too, that's alright, we can merge after a rebase and open an issue describing the extension so it doesn't get lost.
|
||
fn check_non_zero_conversion(cx: &LateContext<'_>, expr: &Expr<'_>, applicability: Applicability) { | ||
// Check if the expression is a function call with one argument | ||
if let ExprKind::Call(func, [arg]) = expr.kind |
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 catches NonZeroXX::from(x)
but would miss y.into::<NonZeroXX>()
. Do you want to tackle that case, too?
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 the into method of NonZero
does not take generic arguments. I am not sure of it. was it changed in the new update? Can you provide me with an example?
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 std::num::{NonZeroU32, NonZeroU64};
fn main() {
let x = NonZeroU32::try_from(1).unwrap();
let _y: NonZeroU64 = x.into();
}
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.
Oh, I see.. we can add that to the unfixable
test cases. It is a little tricky to tackle. That's why I added this one in the unfixable
test cases:
let x: u64 = u64::from(NonZeroU32::new(5).unwrap().get());
It can be added in the future optimizations.
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: |
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: |
@rustbot ready |
Can you remove the merge commit and instead rebase on current master? |
It's ready! |
☔ The latest upstream changes (presumably #12987) made this pull request unmergeable. Please resolve the merge conflicts. |
r=me after rebase. |
@bors r+ |
☀️ Test successful - checks-action_dev_test, checks-action_remark_test, checks-action_test |
Created lint based on the suggestions in #7291
.stderr
file)cargo test
passes locallycargo dev update_lints
cargo dev fmt
changelog: new [
non_zero_suggestions
] lint