Skip to content

Commit 7c11a53

Browse files
committed
fix #104867, Properly handle postfix inc/dec in standalone and subexpr scenarios
1 parent 1dda298 commit 7c11a53

File tree

7 files changed

+188
-64
lines changed

7 files changed

+188
-64
lines changed

compiler/rustc_parse/src/parser/diagnostics.rs

+16-41
Original file line numberDiff line numberDiff line change
@@ -159,8 +159,6 @@ enum IsStandalone {
159159
Standalone,
160160
/// It's a subexpression, i.e., *not* standalone.
161161
Subexpr,
162-
/// It's maybe standalone; we're not sure.
163-
Maybe,
164162
}
165163

166164
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
@@ -213,14 +211,8 @@ impl MultiSugg {
213211
err.multipart_suggestion(&self.msg, self.patches, self.applicability);
214212
}
215213

216-
/// Overrides individual messages and applicabilities.
217-
fn emit_many(
218-
err: &mut Diagnostic,
219-
msg: &str,
220-
applicability: Applicability,
221-
suggestions: impl Iterator<Item = Self>,
222-
) {
223-
err.multipart_suggestions(msg, suggestions.map(|s| s.patches), applicability);
214+
fn emit_verbose(self, err: &mut Diagnostic) {
215+
err.multipart_suggestion_verbose(&self.msg, self.patches, self.applicability);
224216
}
225217
}
226218

@@ -1272,21 +1264,20 @@ impl<'a> Parser<'a> {
12721264
let standalone =
12731265
if prev_is_semi { IsStandalone::Standalone } else { IsStandalone::Subexpr };
12741266
let kind = IncDecRecovery { standalone, op: IncOrDec::Inc, fixity: UnaryFixity::Pre };
1275-
12761267
self.recover_from_inc_dec(operand_expr, kind, op_span)
12771268
}
12781269

12791270
pub(super) fn recover_from_postfix_increment(
12801271
&mut self,
12811272
operand_expr: P<Expr>,
12821273
op_span: Span,
1274+
prev_is_semi: bool,
12831275
) -> PResult<'a, P<Expr>> {
12841276
let kind = IncDecRecovery {
1285-
standalone: IsStandalone::Maybe,
1277+
standalone: if prev_is_semi { IsStandalone::Standalone } else { IsStandalone::Subexpr },
12861278
op: IncOrDec::Inc,
12871279
fixity: UnaryFixity::Post,
12881280
};
1289-
12901281
self.recover_from_inc_dec(operand_expr, kind, op_span)
12911282
}
12921283

@@ -1314,35 +1305,20 @@ impl<'a> Parser<'a> {
13141305
UnaryFixity::Post => (base.span.shrink_to_lo(), op_span),
13151306
};
13161307

1308+
let Ok(base_src) = self.span_to_snippet(base.span)
1309+
else { return help_base_case(err, base) };
13171310
match kind.standalone {
1318-
IsStandalone::Standalone => self.inc_dec_standalone_suggest(kind, spans).emit(&mut err),
1319-
IsStandalone::Subexpr => {
1320-
let Ok(base_src) = self.span_to_snippet(base.span)
1321-
else { return help_base_case(err, base) };
1322-
match kind.fixity {
1323-
UnaryFixity::Pre => {
1324-
self.prefix_inc_dec_suggest(base_src, kind, spans).emit(&mut err)
1325-
}
1326-
UnaryFixity::Post => {
1327-
self.postfix_inc_dec_suggest(base_src, kind, spans).emit(&mut err)
1328-
}
1329-
}
1330-
}
1331-
IsStandalone::Maybe => {
1332-
let Ok(base_src) = self.span_to_snippet(base.span)
1333-
else { return help_base_case(err, base) };
1334-
let sugg1 = match kind.fixity {
1335-
UnaryFixity::Pre => self.prefix_inc_dec_suggest(base_src, kind, spans),
1336-
UnaryFixity::Post => self.postfix_inc_dec_suggest(base_src, kind, spans),
1337-
};
1338-
let sugg2 = self.inc_dec_standalone_suggest(kind, spans);
1339-
MultiSugg::emit_many(
1340-
&mut err,
1341-
"use `+= 1` instead",
1342-
Applicability::Unspecified,
1343-
[sugg1, sugg2].into_iter(),
1344-
)
1311+
IsStandalone::Standalone => {
1312+
self.inc_dec_standalone_suggest(kind, spans).emit_verbose(&mut err)
13451313
}
1314+
IsStandalone::Subexpr => match kind.fixity {
1315+
UnaryFixity::Pre => {
1316+
self.prefix_inc_dec_suggest(base_src, kind, spans).emit(&mut err)
1317+
}
1318+
UnaryFixity::Post => {
1319+
self.postfix_inc_dec_suggest(base_src, kind, spans).emit(&mut err)
1320+
}
1321+
},
13461322
}
13471323
Err(err)
13481324
}
@@ -1392,7 +1368,6 @@ impl<'a> Parser<'a> {
13921368
}
13931369

13941370
patches.push((post_span, format!(" {}= 1", kind.op.chr())));
1395-
13961371
MultiSugg {
13971372
msg: format!("use `{}= 1` instead", kind.op.chr()),
13981373
patches,

compiler/rustc_parse/src/parser/expr.rs

+9-1
Original file line numberDiff line numberDiff line change
@@ -292,7 +292,15 @@ impl<'a> Parser<'a> {
292292
let op_span = self.prev_token.span.to(self.token.span);
293293
// Eat the second `+`
294294
self.bump();
295-
lhs = self.recover_from_postfix_increment(lhs, op_span)?;
295+
let prev_is_semi = {
296+
if let Ok(prev_code) = self.sess.source_map().span_to_prev_source(lhs.span) &&
297+
prev_code.trim_end().ends_with(";") {
298+
true
299+
} else {
300+
false
301+
}
302+
};
303+
lhs = self.recover_from_postfix_increment(lhs, op_span, prev_is_semi)?;
296304
continue;
297305
}
298306

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
// run-rustfix
2+
3+
struct Foo {
4+
bar: Bar,
5+
}
6+
7+
struct Bar {
8+
qux: i32,
9+
}
10+
11+
pub fn post_regular() {
12+
let mut i = 0;
13+
i += 1; //~ ERROR Rust has no postfix increment operator
14+
println!("{}", i);
15+
}
16+
17+
pub fn post_while() {
18+
let mut i = 0;
19+
while { let tmp = i; i += 1; tmp } < 5 {
20+
//~^ ERROR Rust has no postfix increment operator
21+
println!("{}", i);
22+
}
23+
}
24+
25+
pub fn post_regular_tmp() {
26+
let mut tmp = 0;
27+
tmp += 1; //~ ERROR Rust has no postfix increment operator
28+
println!("{}", tmp);
29+
}
30+
31+
pub fn post_while_tmp() {
32+
let mut tmp = 0;
33+
while { let tmp_ = tmp; tmp += 1; tmp_ } < 5 {
34+
//~^ ERROR Rust has no postfix increment operator
35+
println!("{}", tmp);
36+
}
37+
}
38+
39+
pub fn post_field() {
40+
let mut foo = Foo { bar: Bar { qux: 0 } };
41+
foo.bar.qux += 1;
42+
//~^ ERROR Rust has no postfix increment operator
43+
println!("{}", foo.bar.qux);
44+
}
45+
46+
pub fn post_field_tmp() {
47+
struct S {
48+
tmp: i32
49+
}
50+
let mut s = S { tmp: 0 };
51+
s.tmp += 1;
52+
//~^ ERROR Rust has no postfix increment operator
53+
println!("{}", s.tmp);
54+
}
55+
56+
pub fn pre_field() {
57+
let mut foo = Foo { bar: Bar { qux: 0 } };
58+
foo.bar.qux += 1;
59+
//~^ ERROR Rust has no prefix increment operator
60+
println!("{}", foo.bar.qux);
61+
}
62+
63+
fn main() {}

src/test/ui/parser/increment-notfixed.rs

+5-3
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
// run-rustfix
2+
13
struct Foo {
24
bar: Bar,
35
}
@@ -35,7 +37,7 @@ pub fn post_while_tmp() {
3537
}
3638

3739
pub fn post_field() {
38-
let foo = Foo { bar: Bar { qux: 0 } };
40+
let mut foo = Foo { bar: Bar { qux: 0 } };
3941
foo.bar.qux++;
4042
//~^ ERROR Rust has no postfix increment operator
4143
println!("{}", foo.bar.qux);
@@ -45,14 +47,14 @@ pub fn post_field_tmp() {
4547
struct S {
4648
tmp: i32
4749
}
48-
let s = S { tmp: 0 };
50+
let mut s = S { tmp: 0 };
4951
s.tmp++;
5052
//~^ ERROR Rust has no postfix increment operator
5153
println!("{}", s.tmp);
5254
}
5355

5456
pub fn pre_field() {
55-
let foo = Foo { bar: Bar { qux: 0 } };
57+
let mut foo = Foo { bar: Bar { qux: 0 } };
5658
++foo.bar.qux;
5759
//~^ ERROR Rust has no prefix increment operator
5860
println!("{}", foo.bar.qux);

src/test/ui/parser/increment-notfixed.stderr

+7-19
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,16 @@
11
error: Rust has no postfix increment operator
2-
--> $DIR/increment-notfixed.rs:11:6
2+
--> $DIR/increment-notfixed.rs:13:6
33
|
44
LL | i++;
55
| ^^ not a valid postfix operator
66
|
77
help: use `+= 1` instead
88
|
9-
LL | { let tmp = i; i += 1; tmp };
10-
| +++++++++++ ~~~~~~~~~~~~~~~
119
LL | i += 1;
1210
| ~~~~
1311

1412
error: Rust has no postfix increment operator
15-
--> $DIR/increment-notfixed.rs:17:12
13+
--> $DIR/increment-notfixed.rs:19:12
1614
|
1715
LL | while i++ < 5 {
1816
| ----- ^^ not a valid postfix operator
@@ -23,24 +21,20 @@ help: use `+= 1` instead
2321
|
2422
LL | while { let tmp = i; i += 1; tmp } < 5 {
2523
| +++++++++++ ~~~~~~~~~~~~~~~
26-
LL | while i += 1 < 5 {
27-
| ~~~~
2824

2925
error: Rust has no postfix increment operator
30-
--> $DIR/increment-notfixed.rs:25:8
26+
--> $DIR/increment-notfixed.rs:27:8
3127
|
3228
LL | tmp++;
3329
| ^^ not a valid postfix operator
3430
|
3531
help: use `+= 1` instead
3632
|
37-
LL | { let tmp_ = tmp; tmp += 1; tmp_ };
38-
| ++++++++++++ ~~~~~~~~~~~~~~~~~~
3933
LL | tmp += 1;
4034
| ~~~~
4135

4236
error: Rust has no postfix increment operator
43-
--> $DIR/increment-notfixed.rs:31:14
37+
--> $DIR/increment-notfixed.rs:33:14
4438
|
4539
LL | while tmp++ < 5 {
4640
| ----- ^^ not a valid postfix operator
@@ -51,37 +45,31 @@ help: use `+= 1` instead
5145
|
5246
LL | while { let tmp_ = tmp; tmp += 1; tmp_ } < 5 {
5347
| ++++++++++++ ~~~~~~~~~~~~~~~~~~
54-
LL | while tmp += 1 < 5 {
55-
| ~~~~
5648

5749
error: Rust has no postfix increment operator
58-
--> $DIR/increment-notfixed.rs:39:16
50+
--> $DIR/increment-notfixed.rs:41:16
5951
|
6052
LL | foo.bar.qux++;
6153
| ^^ not a valid postfix operator
6254
|
6355
help: use `+= 1` instead
6456
|
65-
LL | { let tmp = foo.bar.qux; foo.bar.qux += 1; tmp };
66-
| +++++++++++ ~~~~~~~~~~~~~~~~~~~~~~~~~
6757
LL | foo.bar.qux += 1;
6858
| ~~~~
6959

7060
error: Rust has no postfix increment operator
71-
--> $DIR/increment-notfixed.rs:49:10
61+
--> $DIR/increment-notfixed.rs:51:10
7262
|
7363
LL | s.tmp++;
7464
| ^^ not a valid postfix operator
7565
|
7666
help: use `+= 1` instead
7767
|
78-
LL | { let tmp = s.tmp; s.tmp += 1; tmp };
79-
| +++++++++++ ~~~~~~~~~~~~~~~~~~~
8068
LL | s.tmp += 1;
8169
| ~~~~
8270

8371
error: Rust has no prefix increment operator
84-
--> $DIR/increment-notfixed.rs:56:5
72+
--> $DIR/increment-notfixed.rs:58:5
8573
|
8674
LL | ++foo.bar.qux;
8775
| ^^ not a valid prefix operator
+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
struct S {
2+
x: i32,
3+
}
4+
5+
fn test1() {
6+
let mut i = 0;
7+
i++; //~ ERROR Rust has no postfix increment operator
8+
}
9+
10+
fn test2() {
11+
let s = S { x: 0 };
12+
s.x++; //~ ERROR Rust has no postfix increment operator
13+
}
14+
15+
fn test3() {
16+
let mut i = 0;
17+
if i++ == 1 {} //~ ERROR Rust has no postfix increment operator
18+
}
19+
20+
fn test4() {
21+
let mut i = 0;
22+
++i; //~ ERROR Rust has no prefix increment operator
23+
}
24+
25+
fn test5() {
26+
let mut i = 0;
27+
if ++i == 1 { } //~ ERROR Rust has no prefix increment operator
28+
}
29+
30+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
error: Rust has no postfix increment operator
2+
--> $DIR/issue-104867-inc-dec.rs:7:6
3+
|
4+
LL | i++;
5+
| ^^ not a valid postfix operator
6+
|
7+
help: use `+= 1` instead
8+
|
9+
LL | i += 1;
10+
| ~~~~
11+
12+
error: Rust has no postfix increment operator
13+
--> $DIR/issue-104867-inc-dec.rs:12:8
14+
|
15+
LL | s.x++;
16+
| ^^ not a valid postfix operator
17+
|
18+
help: use `+= 1` instead
19+
|
20+
LL | s.x += 1;
21+
| ~~~~
22+
23+
error: Rust has no postfix increment operator
24+
--> $DIR/issue-104867-inc-dec.rs:17:9
25+
|
26+
LL | if i++ == 1 {}
27+
| ^^ not a valid postfix operator
28+
|
29+
help: use `+= 1` instead
30+
|
31+
LL | if { let tmp = i; i += 1; tmp } == 1 {}
32+
| +++++++++++ ~~~~~~~~~~~~~~~
33+
34+
error: Rust has no prefix increment operator
35+
--> $DIR/issue-104867-inc-dec.rs:22:5
36+
|
37+
LL | ++i;
38+
| ^^ not a valid prefix operator
39+
|
40+
help: use `+= 1` instead
41+
|
42+
LL - ++i;
43+
LL + i += 1;
44+
|
45+
46+
error: Rust has no prefix increment operator
47+
--> $DIR/issue-104867-inc-dec.rs:27:8
48+
|
49+
LL | if ++i == 1 { }
50+
| ^^ not a valid prefix operator
51+
|
52+
help: use `+= 1` instead
53+
|
54+
LL | if { i += 1; i } == 1 { }
55+
| ~ +++++++++
56+
57+
error: aborting due to 5 previous errors
58+

0 commit comments

Comments
 (0)