Lint bit width#16902
Conversation
|
r? @dswij rustbot has assigned @dswij. Use Why was this reviewer chosen?The reviewer was selected based on:
|
8b811db to
236b137
Compare
|
|
Good catch! I remove support |
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Sorry for the delay. Overall it looks good, just a small comment and waiting FCP.
@rustbot label lint-nominated
|
This lint has been nominated for inclusion. |
You could solve this by suggesting |
|
Reminder, once the PR becomes ready for a review, use |
966cd22 to
f2d90b9
Compare
This comment has been minimized.
This comment has been minimized.
@ada4a fair point, I will look into this over the week. In case this make sense I maybe put the changes on a separate PR, on top of this one. What do you think? :) |
Hm, I'm not fundamentally opposed to the idea – a smaller PR is easier to get merged – but given that the FCP usually takes ~2 weeks anyway, we might as well use the time to bring that new pattern in, as I don't think it's very controversial. I'd say try implementing the nonzero thing (at your own pace); if you see that that requires a large restructuring of the lint, then consider squashing that change into this PR – because it'd be silly to have a reviewer approve the code just for it to get changed right after; otherwise, feel free to leave it as a separate PR |
Ah! I was not aware of the FCP policy, so I went and followed @ada4a feedback and for NonZero the lint suggests |
| let type_invariant = match right_ty.kind() { | ||
| // int::BITS or uint::BITS | ||
| ty::Uint(_) => IntTypeVariant::UnsignedInt, | ||
| ty::Int(_) => IntTypeVariant::SignedInt, | ||
| // NonZero::<int/uint>::BITS | ||
| ty::Adt(adt, args) if cx.tcx.is_diagnostic_item(sym::NonZero, adt.did()) => { | ||
| match args.type_at(0).kind() { | ||
| ty::Uint(_) => IntTypeVariant::NonZeroUnsigned, | ||
| ty::Int(_) => IntTypeVariant::NonZeroSigned, | ||
| _ => return, | ||
| } | ||
| }, | ||
| _ => return, | ||
| }; | ||
|
|
||
| if let Some(left_width) = get_bit_width(cx, left_ty) | ||
| && let Some(right_width) = get_bit_width(cx, right_ty) | ||
| && left_width == right_width | ||
| { | ||
| // manual implementation of bit_width | ||
| emit_manual_bit_width(cx, recv, expr, type_invariant); | ||
| } else { | ||
| // mismatched calling types | ||
| emit_type_mismatch(cx, recv, expr, type_invariant, right_ty); | ||
| } | ||
| }, | ||
| _ => {}, | ||
| } | ||
| } | ||
| } | ||
|
|
||
| fn get_bit_width(cx: &LateContext<'_>, ty: Ty<'_>) -> Option<u64> { | ||
| // num.bit_width() return None for `usize` and `isize` so we need this wrapper | ||
| let size_safe_bit_width = |x: Option<u64>| x.or_else(|| Some(cx.tcx.data_layout.pointer_size().bits())); | ||
|
|
||
| match ty.kind() { | ||
| // int::BITS or uint::BITS | ||
| ty::Uint(num) => size_safe_bit_width(num.bit_width()), | ||
| ty::Int(num) => size_safe_bit_width(num.bit_width()), | ||
| // NonZero::<int/uint>::BITS | ||
| ty::Adt(adt, args) if cx.tcx.is_diagnostic_item(sym::NonZero, adt.did()) => { | ||
| let arg = args.type_at(0); | ||
| match arg.kind() { | ||
| ty::Uint(num) => size_safe_bit_width(num.bit_width()), | ||
| ty::Int(num) => size_safe_bit_width(num.bit_width()), | ||
| _ => None, | ||
| } | ||
| }, | ||
| _ => None, | ||
| } | ||
| } |
There was a problem hiding this comment.
The duplication is somewhat unfortunate, but oh well..
There was a problem hiding this comment.
Oh, I actually kind of liked the enum... but this is fine as well.
Could you please squash down the commits? Having multiple commits during development is fine, but since they all amount to iteration over one feature, it's preferable to have the final form to be one commit as well.
a15d758 to
62ceefb
Compare
Done :) |
|
Note: I changed the changelog entry to individually bracket each lint name, since that's how you make them valid Markdown links. Ideally, CI would've caught that... Thank you again for all your work! |
|
Hm, it looks like merging this to latest master causes test failures. Could you please rebase the PR onto master and fix the failures? |
62ceefb to
c2bf51a
Compare
|
This PR was rebased onto a different master commit. Here's a range-diff highlighting what actually changed. Rebasing is a normal part of keeping PRs up to date, so no action is needed—this note is just to help reviewers. |
Ah ok! interesting I updated the change log with Thanks for all the amazing feedback and patience :) was so much fun |
c2bf51a to
c5526c9
Compare
The failing test happens because the target |
c5526c9 to
3f51827
Compare
af827df to
202fe63
Compare
202fe63 to
9cd426c
Compare
9cd426c to
a35fed2
Compare
|
We did it 🎉 |
View all comments
Fixes #16876
Current state:
Uint::BITS - x.leading_zeros()tox.bit_width()Int::BITS - x.leading_zeros()tox.cast_unsigned().bit_width()NonZero::<Uint>::BITS - x.leading_zeros()tox.bit_width().get()NonZero::<Int>::BITS - x.leading_zeros()tox.cast_unsigned().bit_width().get()T::BITSdoes not align with value (x) callingleading_zeros()the lint will raise this mismatch and suggest to replace the whole line withx.bit_width()Description
rust 1.97 introduces the method
bit_width()for uints and NonZero (docs), this will make the manual computation redundant and unnecessary.Example 1
Can be replaced with:
Example 2
Can be replaced with:
Example 3
Can be replaced with:
Example 4
Can be replaced with:
Example 5
Can be replaced with:
changelog: [
manual_bit_width], [mismatched_bit_width_type]: Added a lint to detect bit_width implementations.I have
.stderrfile)cargo testpasses locallycargo dev update_lintscargo dev fmt