-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
Fix sign-handling bugs and false negatives in cast_sign_loss
#12126
Conversation
Thanks for the pull request, and welcome! The Rust team is excited to review your changes, and you should hear from @llogiq (or someone else) soon. 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 (
|
I've finished working on the code and the existing tests should pass. I still need to add new tests. |
cast_sign_loss
cast_sign_loss
Ok, the tests should be finished now too! |
@rustbot review |
Anyone should feel free to move this PR forward, I might not see notifications from reviewers. |
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: |
☔ The latest upstream changes (presumably #12306) made this pull request unmergeable. Please resolve the merge conflicts. |
7f330da
to
6bc7c96
Compare
I re-blessed the tests. |
/// Returns the sign of the list of peeled expressions. | ||
fn expr_muldiv_sign(cx: &LateContext<'_>, expr: &Expr<'_>) -> Sign { | ||
let mut negative_count = 0; | ||
let mut uncertain_count = 0; |
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.
We don't need an uncertain count. In fact, whenever we encounter any uncertain sign, we can return Uncertain
right away in this method.
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.
Thanks, I removed this and the uncertain_count in the add method in commit 1e3c55e
Apart from a small nit in the code, this makes sense to me. r=me with the nit fixed. |
@rustbot review The nit is fixed, r=llogiq |
Thank you! @bors r+ |
☀️ Test successful - checks-action_dev_test, checks-action_remark_test, checks-action_test |
Note: anyone should feel free to move this PR forward, I might not see notifications from reviewers.
changelog: [
cast_sign_loss
]: Fix sign-handling bugs and false negativesThis PR fixes some arithmetic bugs and false negatives in PR #11883 (and maybe earlier PRs).
Cc @J-ZhengLi
I haven't updated the tests yet. I was hoping for some initial feedback before adding tests to cover the cases listed below.
Here are the issues I've attempted to fix:
abs()
can return a negative value in release buildsExample:
https://play.rust-lang.org/?version=stable&mode=release&edition=2021&gist=022d200f9ef6ee72f629c0c9c1af11b8
Docs: https://doc.rust-lang.org/std/primitive.i32.html#method.abs
Other overflows that produce negative values could cause false negatives (and underflows could produce false positives), but they're harder to detect.
Values with uncertain signs can be positive or negative
Any number of values with uncertain signs cause the whole expression to have an uncertain sign, because an uncertain sign can be positive or negative.
Example (from UI tests):
https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=165d2e2676ee8343b1b9fe60db32aadd
Handle
expect()
the same way asunwrap()
Since we're ignoring
unwrap()
we might as well do the same withexpect()
.This doesn't seem to have tests but I'm happy to add some like
Some(existing_test).unwrap() as u32
.A negative base to an odd exponent is guaranteed to be negative
An integer
pow()
's sign is only uncertain when its operants are uncertain. (Ignoring overflow.)Example:
This offsets some of the false positives created by one or more uncertain signs producing an uncertain sign. (Rather than just an odd number of uncertain signs.)
Both sides of a multiply or divide should be peeled recursively
I'm not sure why the lhs was peeled recursively, and the rhs was left intact. But the sign of any sequence of multiplies and divides is determined by the signs of its operands. (Ignoring overflow.)
I'm not sure what to use as an example here, because most expressions I want to use are const-evaluable.
But if
p()
is a non-const function that returns a positive value, and if the lint handles unary negation, these should all lint:The right hand side of a Rem doesn't change the sign
Unlike Mul and Div,
I'm not sure what to use as an example here, because most expressions I want to use are const-evaluable.
But if
p()
is a non-const function that returns a positive value, and if the lint handles unary negation, only the first six expressions should lint.The expressions that start with a constant should lint (or not lint) regardless of whether the lint supports
p()
or unary negation, because only the dividend's sign matters.Example:
There's no need to bail on other expressions
When peeling, any other operators or expressions can be left intact and sent to the constant evaluator.
If these expressions can be evaluated, this offsets some of the false positives created by one or more uncertain signs producing an uncertain sign. If not, they end up marked as having uncertain sign.