-
Notifications
You must be signed in to change notification settings - Fork 13.2k
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
Suggest i += 1
when we see i++
or ++i
#83536
Conversation
(rust-highfive has picked a reviewer for you, use r? to override) |
r? @estebank |
help: try using `+= 1` instead | ||
| | ||
LL | i += 1; | ||
| ^^^^ |
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.
One issue with using a structured suggestion is that we will suggest invalid code in the case of
fn main() {
let mut i = 0;
while i++ < 5 { /* ... */ }
We suggest
fn main() {
let mut i = 0;
while i += 1 < 5 { /* ... */ }
}
Errors:
Compiling playground v0.0.1 (/playground)
error[E0308]: mismatched types
--> src/main.rs:3:11
|
3 | while i += 1 < 5 { /* ... */ }
| ^^^^^^^^^^ expected `bool`, found `()`
error[E0277]: cannot add-assign `bool` to `{integer}`
--> src/main.rs:3:13
|
3 | while i += 1 < 5 { /* ... */ }
| ^^ no implementation for `{integer} += bool`
|
= help: the trait `AddAssign<bool>` is not implemented for `{integer}`
error: aborting due to 2 previous errors
Some errors have detailed explanations: E0277, E0308.
For more information about an error, try `rustc --explain E0277`.
error: could not compile `playground`
To learn more, run the command again with --verbose.
And adding parentheses doesn't fix it:
fn main() {
let mut i = 0;
while (i += 1) < 5 { /* ... */ }
}
Errors:
Compiling playground v0.0.1 (/playground)
error[E0308]: mismatched types
--> src/main.rs:3:22
|
3 | while (i += 1) < 5 { /* ... */ }
| ^ expected `()`, found integer
error: aborting due to previous error
For more information about this error, try `rustc --explain E0308`.
error: could not compile `playground`
To learn more, run the command again with --verbose.
So maybe it would be better to just skip the structured suggestion?
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'm thinking whether it would make sense to try to suggest while { i += 1; i } < 5
?
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.
That's interesting! The advantage of that is that it will preserve the behavior of i++
in other languages. Would we always suggest { i += 1; i }
or would we sometimes suggest just i += 1
? I think it would probably be pretty hard to have conditional logic in this case, so I vote for unconditionally using { i += 1; i }
, unless there's a simple way to encode the logic.
Also, what should we suggest in the ++i
case? In that case, { i += 1; i }
is not the correct behavior; rather, the equivalent in Rust is { let temp = i; i += 1; temp }
. The problem with suggesting that is that the user may have code like:
++temp;
and then we would suggest
{ let temp = temp; temp += 1; temp }
which is incorrect.
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.
So, thinking about it more, maybe simply suggesting i += 1
in all cases is good enough? Or, alternatively, would it be better to just include a note
and skip the structured suggestion?
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.
You wrote that backwards: preincrement ++i
is { i += 1; i }
, and postincrement i++
is { let temp = i; i += 1; temp }
.
++i; //~ ERROR | ||
} | ||
|
||
fn main() {} |
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.
Probably should add tests for while i++ < 5
etc.
This comment has been minimized.
This comment has been minimized.
&& self.look_ahead(2, |t| !t.is_lit()) | ||
{ | ||
err.note("Rust has no dedicated increment and decrement operators"); | ||
err.help("try using `+= 1` instead"); |
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.
err.help("try using `+= 1` instead"); | |
let lo = self.token.span; // `+` | |
self.bump(); // `+` | |
let pre_sp = lo.to(self.token.span); | |
err.multipart_suggestion( | |
"try using `+= 1` instead" | |
vec![ | |
(pre_sp, String::new()), | |
(self.token.span.shrink_to_hi(), " += 1".to_string()), | |
], | |
Applicability::MachineApplicable, | |
); | |
self.bump(); // ident |
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.
Won't this turn ++i
into += 1i
?
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.
Yes, good catch. You'll need to account for ++i
and i++
specifically.
closing this due to inactivity |
Suggest `i += 1` when we see `i++` or `++i` Closes rust-lang#83502 (for `i++` and `++i`; `--i` should be covered by rust-lang#82987, and `i--` is tricky to handle). This is a continuation of rust-lang#83536. r? `@estebank`
Closes #83502 (for
i++
and++i
;--i
should be covered by #82987 andi--
is tricky to handle).