Conversation
906f3bd to
1561476
Compare
Urgau
left a comment
There was a problem hiding this comment.
❤️ Thanks for working on it, appreciate it.
Left a few remarks/nits.
| cx, | ||
| MANUAL_MIDPOINT, | ||
| expr.span, | ||
| "manual implementation of `midpoint`", |
There was a problem hiding this comment.
| "manual implementation of `midpoint`", | |
| "manual implementation of `midpoint` which can overflow", |
There was a problem hiding this comment.
I'm reluctant to add this on the lint message, because this particular use may well never overflow depending on the context. This is appropriate for the lint short description though, I'll add it there. What do you think?
There was a problem hiding this comment.
We should add it to the lint short description, but I still think we should mention it in the main message as it's the main issue (not the fact that it's a manual implementation). We could reduce the assertion by saying "which may overflow" (instead of "can").
There was a problem hiding this comment.
Any addition may overflow, and we do not suggest using .checked_add(). I'll let other weigh in, but I'm not comfortable saying "which may overflow" on (a + b) / 2 if a and b are indices in a vector for example, they will never overflow as they will be nowhere near usize::MAX/2 for any realistic vector.
There was a problem hiding this comment.
(a + b) / 2ifaandbare indices in a vector for example
u8::MAX = 255, u16::MAX = 65536 are fairly realistic numbers to me (which could be indices of custom containers).
they will never overflow as they will be nowhere near
usize::MAX/2for any realistic vector.
There was a problem hiding this comment.
I was specifically talking about the usize case which is used to index a vector. And let's not confuse the issue: I'm not trying to argue that we should not lint, we will, only that I am not comfortable saying that a particular computation may overflow.
I couldn't find lints that warn about the potential risk when linting an expression if the risk is remote or non-existing for this particular expression, even though they still lint to make it clearer and safer should this code be changed later.
There was a problem hiding this comment.
I think I agree that it's a good idea to mention this even in the message. IMO it doesn't particularly hurt to mention even if the user knows it could never overflow, but it can definitely help in cases where that's an edge case the user hadn't considered, and I could see how the lint could otherwise be dismissed as 'just a nit like the other manual_* lints, not that important'.
The fact that it's an incorrect implementation due to overflow is the reason why it's deny-by-default/correctness in the first place, right? The current primary message makes this sound more like a complexity or style lint
tests/ui/manual_midpoint.stderr
Outdated
| --> tests/ui/manual_midpoint.rs:12:13 | ||
| | | ||
| LL | let _ = (f + 5.0) / 2.0; | ||
| | ^^^^^^^^^^^^^^^ help: use instead: `f32::midpoint(f, 5.0)` |
There was a problem hiding this comment.
I don't if it's in Clippy customs but would be possible to add a help linking to the documentation, something like this (which rustc does to further guide the user):
help: for more information visit <https://doc.rust-lang.org/nightly/std/primitive.u32.html#method.midpoint>
There was a problem hiding this comment.
This is done only for niche or complex situations in the existing codebase, such as implementing a local trait for a foreign type (orphan rule).
There was a problem hiding this comment.
There's a first time for everything. :-)
More seriously, I'm fine if the link it's not included.
| let mut app = Applicability::MachineApplicable; | ||
| let left_sugg = Sugg::hir_with_applicability(cx, ll_expr, "..", &mut app); | ||
| let right_sugg = Sugg::hir_with_applicability(cx, lr_expr, "..", &mut app); | ||
| let sugg = format!("{left_ty}::midpoint({left_sugg}, {right_sugg})"); |
There was a problem hiding this comment.
Interesting choice of form, I would have probably use the method syntax (ie. .midpoint(..)) instead, as to not have to much shifts from the original code, but that works as well.
There was a problem hiding this comment.
I feel that linting (a + b) / 2 as a.midpoint(b) introduces an asymmetry between a and b while u32::midpoint(a, b) doesn't. But I'm not opposed to this change.
What do others think? Please upvote if you prefer a.midpoint(b) and downvote if you prefer u32::midpoint(a, b).
There was a problem hiding this comment.
I can't pick between the 2 because the first one is more convenirnt but the second one is more readable...
Well, by writing this comment I realized I prefer more readable code so let's go for 2.
There was a problem hiding this comment.
I initially preferred a.midpoint(b) but having thought more about it, the latter has some other advantages: u32::midpoint(a, b) doesn't require parentheses in some cases where the LHS is an expression with low precedence like (a + b + c) / 2, and it also sidesteps type inference issues in cases like
let c: u64 = (10 + 5) / 2;where 10.midpoint(5) would not compile. So the current suggestion LGTM
6e01b0d to
8fc52b4
Compare
|
r? @y21 |
| let mut app = Applicability::MachineApplicable; | ||
| let left_sugg = Sugg::hir_with_applicability(cx, ll_expr, "..", &mut app); | ||
| let right_sugg = Sugg::hir_with_applicability(cx, lr_expr, "..", &mut app); | ||
| let sugg = format!("{left_ty}::midpoint({left_sugg}, {right_sugg})"); |
There was a problem hiding this comment.
I initially preferred a.midpoint(b) but having thought more about it, the latter has some other advantages: u32::midpoint(a, b) doesn't require parentheses in some cases where the LHS is an expression with low precedence like (a + b + c) / 2, and it also sidesteps type inference issues in cases like
let c: u64 = (10 + 5) / 2;where 10.midpoint(5) would not compile. So the current suggestion LGTM
| cx, | ||
| MANUAL_MIDPOINT, | ||
| expr.span, | ||
| "manual implementation of `midpoint`", |
There was a problem hiding this comment.
I think I agree that it's a good idea to mention this even in the message. IMO it doesn't particularly hurt to mention even if the user knows it could never overflow, but it can definitely help in cases where that's an edge case the user hadn't considered, and I could see how the lint could otherwise be dismissed as 'just a nit like the other manual_* lints, not that important'.
The fact that it's an incorrect implementation due to overflow is the reason why it's deny-by-default/correctness in the first place, right? The current primary message makes this sound more like a complexity or style lint
8fc52b4 to
dee2bc8
Compare
dee2bc8 to
d879aba
Compare
|
I have eliminated the lint on additions with more than 2 operands, as there is no reason to suggest |
d879aba to
f28fbf1
Compare
|
I opened a thread on Zulip to discuss how to handle |
b14c9fc to
7cd170d
Compare
a0c770e to
de46175
Compare
|
Rebasing because of a new conflict in |
y21
left a comment
There was a problem hiding this comment.
Looks good, going to start the FCP in a bit
52d6d79 to
3c13085
Compare
|
Rebased |
3c13085 to
71b6776
Compare
|
Rebased |
71b6776 to
28fd9ba
Compare
|
Thanks, I'll add this.
@rustbot author
|
I'll have to wait until the next rustup until the stabilization of @rustbot review |
28fd9ba to
d8e4023
Compare
|
Updated to set the lint version to 1.87. |
d8e4023 to
baadee8
Compare
|
Rebased, category changed to |
changelog: [
manual_midpoint]: new lintCloses #13849