-
Notifications
You must be signed in to change notification settings - Fork 1.5k
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 lint which checks that duration conversion aren't losing precision #12539
base: master
Are you sure you want to change the base?
Conversation
Thanks for the pull request, and welcome! The Rust team is excited to review your changes, and you should hear from @blyxyas (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 (
|
0ef98ae
to
98bbb37
Compare
I've ran lintcheck with your patch applied on the top 500 crates:
So it looks like this lint could be useful. |
let time = (elapsed.as_secs() as f64) * 1e3 +
(elapsed.subsec_nanos() as f64) / 1e6;
d.as_secs() as f64 + f64::from(d.subsec_nanos()) / 1_000_000_000f64
(dur.as_secs() as f64) + (dur.subsec_nanos() as f64) / (NANOS_PER_SEC as f64)
let mut secs = source.sign.apply(source.duration.as_secs() as f64); The source code of pub const fn as_secs_f64(&self) -> f64 {
(self.secs as f64) + (self.nanos.0 as f64) / (NANOS_PER_SEC as f64)
} In order, the code from the linted crates appears to be calculating:
I think the lint application is probably okay advice for 2-4, but the advice it will give in the 1st case may be a bit confusing. Maybe it would be worthwhile to try to recognize the case where someone is doing the |
☔ The latest upstream changes (presumably #12312) made this pull request unmergeable. Please resolve the merge conflicts. |
98bbb37
to
092b40d
Compare
Honestly @declanvk, this is some of the best-written code, comments and PR description I've ever read. Congrats on making the code so understandable! Normally, 500+ lines diffs are quite painful to read, but this one is quite nice ❤️ |
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.
Great for a first iteration. Meow meow 😸
Thank you @blyxyas for reviewing! I'll address your comments in my next attempt. I wanted to get your opinion on the lint category versus the number of false positives. I placed the lint in the Also, based on the data @samueltardieu gathered (thank you!), are you worried about any of the cases from #12539 (comment)? Arguable, cases 1-3 have slightly off suggestions from the lint. |
0749e19
to
056ed4a
Compare
I pushed a new revision addressing 3/4 comments, let me know your thoughts on the last comment I left unresolved. Thanks again! |
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.
Sorry for the delay, some nits, some comments. Still very good for a first contribution. I really like your use of useful comments.
I forgot to ask, are you planning to implement #12539 (comment) or is this good enough? This is up to you. |
Oh sorry! I added the commit just because it was the easiest way to apply your suggestions, I'm still planning to work on the other comments/open that issue possibly |
☔ The latest upstream changes (presumably #12107) made this pull request unmergeable. Please resolve the merge conflicts. |
57fe0ef
to
effce8a
Compare
I added the rest of the requested changes to the commit, and I'm planning to cut that issue about recognizing |
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.
Just a nit, and this should be ready! (We don't want to lint proc macros)
**Description** Add a lint which checks for a binop or cast where the expression is converting a Duration to a floating point number, and losing precision along the way. The lint won't fire for most cases involving `as_nanos()` since converting that to floating point already gives the max precision. The lint is also restricted to an MSRV of 1.38.0, since that is when the `as_secs_{f32,f64}()` methods were stabilized. **Motivation** This change is motivated by [a rust stdlib ACP which proposed `as_millis_{f64,f32}`][ACP-link]. As part of that I did some code searches on github (see ACP for links) that showed a lot of code which converted Duration values to floating point using methods other than `as_secs_{f32,64}()`, and were losing precision because of that. This lint seems like a good way to raise awareness and prompt using the existing methods. [ACP-link]: rust-lang/libs-team#349 **Testing Done** Added UI tests, ran `cargo test`, followed the Clippy manual
- I applied about half of these from the UI - Made more parts of the example code visible - Added test on duration ref - Rebased over conflict - Moved to the `style` lint group Co-authored-by: Alejandra González <[email protected]>
91ead2d
to
475f28e
Compare
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.
Just a version update, and this should be ready! I've already opened the FCP thread on our Zulip :)
If everything goes as planned, this should be merged in about a week! Thanks for your contribution, and welcome to the project! ❤️
Co-authored-by: Alejandra González <[email protected]>
Thanks for all your work in this code review! And sorry about the mini-hiatus I took in the middle 😁 . I'm looking forward to merging this in! I'm still planning to create that followup issue about the alternate forms of duration conversion too. |
Also, should I respond to questions/comments on the Zulip thread? Or is that mostly for core contributors? |
} | ||
|
||
fn emit_lint(&self, cx: &LateContext<'_>) { | ||
let mut applicability = Applicability::MachineApplicable; |
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.
Would be good to use MaybeIncorrect
since there's a behaviour change. A note making it clear that the suggestion would include fractional e.g. milliseconds would also be good
Rust's Zulip is open to anyone and everyone, in fact, it's better that you yourself (as the PR author) respond these questions. |
☔ The latest upstream changes (presumably #12937) made this pull request unmergeable. Please resolve the merge conflicts. |
Hey @xFrednet, I am planning to continue, but it might take me a second to get back to this. Thanks for checking in! |
Description
Add a lint which checks for a binop or cast where the expression is converting a Duration to a floating point number, and losing precision along the way.
The lint won't fire for most cases involving
as_nanos()
since converting that to floating point already gives the max precision.The lint is also restricted to an MSRV of 1.38.0, since that is when the
as_secs_{f32,f64}()
methods were stabilized.Motivation
This change is motivated by a rust stdlib ACP which proposed
as_millis_{f64,f32}
. As part of that I did some code searches on github (see ACP for links) that showed a lot of code which converted Duration values to floating point using methods other thanas_secs_{f32,64}()
, and were losing precision because of that.This lint seems like a good way to raise awareness and prompt using the existing methods.
Testing Done
Added UI tests, ran
cargo test
, followed the Clippy manualchangelog: [
duration_to_float_precision_loss
]: Add new lint which checks for precision loss in duration to float conversions