From 7c11a53f9ccb4040995b9e054b093a47fef29cc1 Mon Sep 17 00:00:00 2001 From: yukang Date: Fri, 25 Nov 2022 17:11:47 +0800 Subject: [PATCH 1/3] fix #104867, Properly handle postfix inc/dec in standalone and subexpr scenarios --- .../rustc_parse/src/parser/diagnostics.rs | 57 +++++------------ compiler/rustc_parse/src/parser/expr.rs | 10 ++- src/test/ui/parser/increment-notfixed.fixed | 63 +++++++++++++++++++ src/test/ui/parser/increment-notfixed.rs | 8 ++- src/test/ui/parser/increment-notfixed.stderr | 26 +++----- src/test/ui/parser/issue-104867-inc-dec.rs | 30 +++++++++ .../ui/parser/issue-104867-inc-dec.stderr | 58 +++++++++++++++++ 7 files changed, 188 insertions(+), 64 deletions(-) create mode 100644 src/test/ui/parser/increment-notfixed.fixed create mode 100644 src/test/ui/parser/issue-104867-inc-dec.rs create mode 100644 src/test/ui/parser/issue-104867-inc-dec.stderr diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index 3f5baf343c9b7..eba0f22f37f34 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -159,8 +159,6 @@ enum IsStandalone { Standalone, /// It's a subexpression, i.e., *not* standalone. Subexpr, - /// It's maybe standalone; we're not sure. - Maybe, } #[derive(Debug, Copy, Clone, PartialEq, Eq)] @@ -213,14 +211,8 @@ impl MultiSugg { err.multipart_suggestion(&self.msg, self.patches, self.applicability); } - /// Overrides individual messages and applicabilities. - fn emit_many( - err: &mut Diagnostic, - msg: &str, - applicability: Applicability, - suggestions: impl Iterator, - ) { - err.multipart_suggestions(msg, suggestions.map(|s| s.patches), applicability); + fn emit_verbose(self, err: &mut Diagnostic) { + err.multipart_suggestion_verbose(&self.msg, self.patches, self.applicability); } } @@ -1272,7 +1264,6 @@ impl<'a> Parser<'a> { let standalone = if prev_is_semi { IsStandalone::Standalone } else { IsStandalone::Subexpr }; let kind = IncDecRecovery { standalone, op: IncOrDec::Inc, fixity: UnaryFixity::Pre }; - self.recover_from_inc_dec(operand_expr, kind, op_span) } @@ -1280,13 +1271,13 @@ impl<'a> Parser<'a> { &mut self, operand_expr: P, op_span: Span, + prev_is_semi: bool, ) -> PResult<'a, P> { let kind = IncDecRecovery { - standalone: IsStandalone::Maybe, + standalone: if prev_is_semi { IsStandalone::Standalone } else { IsStandalone::Subexpr }, op: IncOrDec::Inc, fixity: UnaryFixity::Post, }; - self.recover_from_inc_dec(operand_expr, kind, op_span) } @@ -1314,35 +1305,20 @@ impl<'a> Parser<'a> { UnaryFixity::Post => (base.span.shrink_to_lo(), op_span), }; + let Ok(base_src) = self.span_to_snippet(base.span) + else { return help_base_case(err, base) }; match kind.standalone { - IsStandalone::Standalone => self.inc_dec_standalone_suggest(kind, spans).emit(&mut err), - IsStandalone::Subexpr => { - let Ok(base_src) = self.span_to_snippet(base.span) - else { return help_base_case(err, base) }; - match kind.fixity { - UnaryFixity::Pre => { - self.prefix_inc_dec_suggest(base_src, kind, spans).emit(&mut err) - } - UnaryFixity::Post => { - self.postfix_inc_dec_suggest(base_src, kind, spans).emit(&mut err) - } - } - } - IsStandalone::Maybe => { - let Ok(base_src) = self.span_to_snippet(base.span) - else { return help_base_case(err, base) }; - let sugg1 = match kind.fixity { - UnaryFixity::Pre => self.prefix_inc_dec_suggest(base_src, kind, spans), - UnaryFixity::Post => self.postfix_inc_dec_suggest(base_src, kind, spans), - }; - let sugg2 = self.inc_dec_standalone_suggest(kind, spans); - MultiSugg::emit_many( - &mut err, - "use `+= 1` instead", - Applicability::Unspecified, - [sugg1, sugg2].into_iter(), - ) + IsStandalone::Standalone => { + self.inc_dec_standalone_suggest(kind, spans).emit_verbose(&mut err) } + IsStandalone::Subexpr => match kind.fixity { + UnaryFixity::Pre => { + self.prefix_inc_dec_suggest(base_src, kind, spans).emit(&mut err) + } + UnaryFixity::Post => { + self.postfix_inc_dec_suggest(base_src, kind, spans).emit(&mut err) + } + }, } Err(err) } @@ -1392,7 +1368,6 @@ impl<'a> Parser<'a> { } patches.push((post_span, format!(" {}= 1", kind.op.chr()))); - MultiSugg { msg: format!("use `{}= 1` instead", kind.op.chr()), patches, diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 9f2267efb8287..b98372d0f28c1 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -292,7 +292,15 @@ impl<'a> Parser<'a> { let op_span = self.prev_token.span.to(self.token.span); // Eat the second `+` self.bump(); - lhs = self.recover_from_postfix_increment(lhs, op_span)?; + let prev_is_semi = { + if let Ok(prev_code) = self.sess.source_map().span_to_prev_source(lhs.span) && + prev_code.trim_end().ends_with(";") { + true + } else { + false + } + }; + lhs = self.recover_from_postfix_increment(lhs, op_span, prev_is_semi)?; continue; } diff --git a/src/test/ui/parser/increment-notfixed.fixed b/src/test/ui/parser/increment-notfixed.fixed new file mode 100644 index 0000000000000..580ebaf5dbb13 --- /dev/null +++ b/src/test/ui/parser/increment-notfixed.fixed @@ -0,0 +1,63 @@ +// run-rustfix + +struct Foo { + bar: Bar, +} + +struct Bar { + qux: i32, +} + +pub fn post_regular() { + let mut i = 0; + i += 1; //~ ERROR Rust has no postfix increment operator + println!("{}", i); +} + +pub fn post_while() { + let mut i = 0; + while { let tmp = i; i += 1; tmp } < 5 { + //~^ ERROR Rust has no postfix increment operator + println!("{}", i); + } +} + +pub fn post_regular_tmp() { + let mut tmp = 0; + tmp += 1; //~ ERROR Rust has no postfix increment operator + println!("{}", tmp); +} + +pub fn post_while_tmp() { + let mut tmp = 0; + while { let tmp_ = tmp; tmp += 1; tmp_ } < 5 { + //~^ ERROR Rust has no postfix increment operator + println!("{}", tmp); + } +} + +pub fn post_field() { + let mut foo = Foo { bar: Bar { qux: 0 } }; + foo.bar.qux += 1; + //~^ ERROR Rust has no postfix increment operator + println!("{}", foo.bar.qux); +} + +pub fn post_field_tmp() { + struct S { + tmp: i32 + } + let mut s = S { tmp: 0 }; + s.tmp += 1; + //~^ ERROR Rust has no postfix increment operator + println!("{}", s.tmp); +} + +pub fn pre_field() { + let mut foo = Foo { bar: Bar { qux: 0 } }; + foo.bar.qux += 1; + //~^ ERROR Rust has no prefix increment operator + println!("{}", foo.bar.qux); +} + +fn main() {} diff --git a/src/test/ui/parser/increment-notfixed.rs b/src/test/ui/parser/increment-notfixed.rs index 15f159e53d294..ebe5fa6ca1e76 100644 --- a/src/test/ui/parser/increment-notfixed.rs +++ b/src/test/ui/parser/increment-notfixed.rs @@ -1,3 +1,5 @@ +// run-rustfix + struct Foo { bar: Bar, } @@ -35,7 +37,7 @@ pub fn post_while_tmp() { } pub fn post_field() { - let foo = Foo { bar: Bar { qux: 0 } }; + let mut foo = Foo { bar: Bar { qux: 0 } }; foo.bar.qux++; //~^ ERROR Rust has no postfix increment operator println!("{}", foo.bar.qux); @@ -45,14 +47,14 @@ pub fn post_field_tmp() { struct S { tmp: i32 } - let s = S { tmp: 0 }; + let mut s = S { tmp: 0 }; s.tmp++; //~^ ERROR Rust has no postfix increment operator println!("{}", s.tmp); } pub fn pre_field() { - let foo = Foo { bar: Bar { qux: 0 } }; + let mut foo = Foo { bar: Bar { qux: 0 } }; ++foo.bar.qux; //~^ ERROR Rust has no prefix increment operator println!("{}", foo.bar.qux); diff --git a/src/test/ui/parser/increment-notfixed.stderr b/src/test/ui/parser/increment-notfixed.stderr index ae55ae0671431..ffee8b64637c9 100644 --- a/src/test/ui/parser/increment-notfixed.stderr +++ b/src/test/ui/parser/increment-notfixed.stderr @@ -1,18 +1,16 @@ error: Rust has no postfix increment operator - --> $DIR/increment-notfixed.rs:11:6 + --> $DIR/increment-notfixed.rs:13:6 | LL | i++; | ^^ not a valid postfix operator | help: use `+= 1` instead | -LL | { let tmp = i; i += 1; tmp }; - | +++++++++++ ~~~~~~~~~~~~~~~ LL | i += 1; | ~~~~ error: Rust has no postfix increment operator - --> $DIR/increment-notfixed.rs:17:12 + --> $DIR/increment-notfixed.rs:19:12 | LL | while i++ < 5 { | ----- ^^ not a valid postfix operator @@ -23,24 +21,20 @@ help: use `+= 1` instead | LL | while { let tmp = i; i += 1; tmp } < 5 { | +++++++++++ ~~~~~~~~~~~~~~~ -LL | while i += 1 < 5 { - | ~~~~ error: Rust has no postfix increment operator - --> $DIR/increment-notfixed.rs:25:8 + --> $DIR/increment-notfixed.rs:27:8 | LL | tmp++; | ^^ not a valid postfix operator | help: use `+= 1` instead | -LL | { let tmp_ = tmp; tmp += 1; tmp_ }; - | ++++++++++++ ~~~~~~~~~~~~~~~~~~ LL | tmp += 1; | ~~~~ error: Rust has no postfix increment operator - --> $DIR/increment-notfixed.rs:31:14 + --> $DIR/increment-notfixed.rs:33:14 | LL | while tmp++ < 5 { | ----- ^^ not a valid postfix operator @@ -51,37 +45,31 @@ help: use `+= 1` instead | LL | while { let tmp_ = tmp; tmp += 1; tmp_ } < 5 { | ++++++++++++ ~~~~~~~~~~~~~~~~~~ -LL | while tmp += 1 < 5 { - | ~~~~ error: Rust has no postfix increment operator - --> $DIR/increment-notfixed.rs:39:16 + --> $DIR/increment-notfixed.rs:41:16 | LL | foo.bar.qux++; | ^^ not a valid postfix operator | help: use `+= 1` instead | -LL | { let tmp = foo.bar.qux; foo.bar.qux += 1; tmp }; - | +++++++++++ ~~~~~~~~~~~~~~~~~~~~~~~~~ LL | foo.bar.qux += 1; | ~~~~ error: Rust has no postfix increment operator - --> $DIR/increment-notfixed.rs:49:10 + --> $DIR/increment-notfixed.rs:51:10 | LL | s.tmp++; | ^^ not a valid postfix operator | help: use `+= 1` instead | -LL | { let tmp = s.tmp; s.tmp += 1; tmp }; - | +++++++++++ ~~~~~~~~~~~~~~~~~~~ LL | s.tmp += 1; | ~~~~ error: Rust has no prefix increment operator - --> $DIR/increment-notfixed.rs:56:5 + --> $DIR/increment-notfixed.rs:58:5 | LL | ++foo.bar.qux; | ^^ not a valid prefix operator diff --git a/src/test/ui/parser/issue-104867-inc-dec.rs b/src/test/ui/parser/issue-104867-inc-dec.rs new file mode 100644 index 0000000000000..d08d74ec1f911 --- /dev/null +++ b/src/test/ui/parser/issue-104867-inc-dec.rs @@ -0,0 +1,30 @@ +struct S { + x: i32, +} + +fn test1() { + let mut i = 0; + i++; //~ ERROR Rust has no postfix increment operator +} + +fn test2() { + let s = S { x: 0 }; + s.x++; //~ ERROR Rust has no postfix increment operator +} + +fn test3() { + let mut i = 0; + if i++ == 1 {} //~ ERROR Rust has no postfix increment operator +} + +fn test4() { + let mut i = 0; + ++i; //~ ERROR Rust has no prefix increment operator +} + +fn test5() { + let mut i = 0; + if ++i == 1 { } //~ ERROR Rust has no prefix increment operator +} + +fn main() {} diff --git a/src/test/ui/parser/issue-104867-inc-dec.stderr b/src/test/ui/parser/issue-104867-inc-dec.stderr new file mode 100644 index 0000000000000..d45b92bf89904 --- /dev/null +++ b/src/test/ui/parser/issue-104867-inc-dec.stderr @@ -0,0 +1,58 @@ +error: Rust has no postfix increment operator + --> $DIR/issue-104867-inc-dec.rs:7:6 + | +LL | i++; + | ^^ not a valid postfix operator + | +help: use `+= 1` instead + | +LL | i += 1; + | ~~~~ + +error: Rust has no postfix increment operator + --> $DIR/issue-104867-inc-dec.rs:12:8 + | +LL | s.x++; + | ^^ not a valid postfix operator + | +help: use `+= 1` instead + | +LL | s.x += 1; + | ~~~~ + +error: Rust has no postfix increment operator + --> $DIR/issue-104867-inc-dec.rs:17:9 + | +LL | if i++ == 1 {} + | ^^ not a valid postfix operator + | +help: use `+= 1` instead + | +LL | if { let tmp = i; i += 1; tmp } == 1 {} + | +++++++++++ ~~~~~~~~~~~~~~~ + +error: Rust has no prefix increment operator + --> $DIR/issue-104867-inc-dec.rs:22:5 + | +LL | ++i; + | ^^ not a valid prefix operator + | +help: use `+= 1` instead + | +LL - ++i; +LL + i += 1; + | + +error: Rust has no prefix increment operator + --> $DIR/issue-104867-inc-dec.rs:27:8 + | +LL | if ++i == 1 { } + | ^^ not a valid prefix operator + | +help: use `+= 1` instead + | +LL | if { i += 1; i } == 1 { } + | ~ +++++++++ + +error: aborting due to 5 previous errors + From dee85a391f091f314a24fb5a090f2e528f4eb81c Mon Sep 17 00:00:00 2001 From: yukang Date: Sat, 26 Nov 2022 05:33:13 +0800 Subject: [PATCH 2/3] add start_stmt to handle postfix increment --- .../rustc_parse/src/parser/diagnostics.rs | 29 +++--- compiler/rustc_parse/src/parser/expr.rs | 23 ++--- compiler/rustc_parse/src/parser/stmt.rs | 4 +- ...tfixed.fixed => increment-autofix-2.fixed} | 0 ...ent-notfixed.rs => increment-autofix-2.rs} | 0 ...ixed.stderr => increment-autofix-2.stderr} | 14 +-- src/test/ui/parser/issue-104867-inc-dec-2.rs | 41 +++++++++ .../ui/parser/issue-104867-inc-dec-2.stderr | 90 +++++++++++++++++++ src/test/ui/parser/issue-104867-inc-dec.rs | 15 ++++ .../ui/parser/issue-104867-inc-dec.stderr | 25 +++++- 10 files changed, 203 insertions(+), 38 deletions(-) rename src/test/ui/parser/{increment-notfixed.fixed => increment-autofix-2.fixed} (100%) rename src/test/ui/parser/{increment-notfixed.rs => increment-autofix-2.rs} (100%) rename src/test/ui/parser/{increment-notfixed.stderr => increment-autofix-2.stderr} (85%) create mode 100644 src/test/ui/parser/issue-104867-inc-dec-2.rs create mode 100644 src/test/ui/parser/issue-104867-inc-dec-2.stderr diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index eba0f22f37f34..f8c6ff994c4a0 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -1259,10 +1259,9 @@ impl<'a> Parser<'a> { &mut self, operand_expr: P, op_span: Span, - prev_is_semi: bool, + start_stmt: bool, ) -> PResult<'a, P> { - let standalone = - if prev_is_semi { IsStandalone::Standalone } else { IsStandalone::Subexpr }; + let standalone = if start_stmt { IsStandalone::Standalone } else { IsStandalone::Subexpr }; let kind = IncDecRecovery { standalone, op: IncOrDec::Inc, fixity: UnaryFixity::Pre }; self.recover_from_inc_dec(operand_expr, kind, op_span) } @@ -1271,10 +1270,10 @@ impl<'a> Parser<'a> { &mut self, operand_expr: P, op_span: Span, - prev_is_semi: bool, + start_stmt: bool, ) -> PResult<'a, P> { let kind = IncDecRecovery { - standalone: if prev_is_semi { IsStandalone::Standalone } else { IsStandalone::Subexpr }, + standalone: if start_stmt { IsStandalone::Standalone } else { IsStandalone::Subexpr }, op: IncOrDec::Inc, fixity: UnaryFixity::Post, }; @@ -1305,20 +1304,22 @@ impl<'a> Parser<'a> { UnaryFixity::Post => (base.span.shrink_to_lo(), op_span), }; - let Ok(base_src) = self.span_to_snippet(base.span) - else { return help_base_case(err, base) }; match kind.standalone { IsStandalone::Standalone => { self.inc_dec_standalone_suggest(kind, spans).emit_verbose(&mut err) } - IsStandalone::Subexpr => match kind.fixity { - UnaryFixity::Pre => { - self.prefix_inc_dec_suggest(base_src, kind, spans).emit(&mut err) - } - UnaryFixity::Post => { - self.postfix_inc_dec_suggest(base_src, kind, spans).emit(&mut err) + IsStandalone::Subexpr => { + let Ok(base_src) = self.span_to_snippet(base.span) + else { return help_base_case(err, base) }; + match kind.fixity { + UnaryFixity::Pre => { + self.prefix_inc_dec_suggest(base_src, kind, spans).emit(&mut err) + } + UnaryFixity::Post => { + self.postfix_inc_dec_suggest(base_src, kind, spans).emit(&mut err) + } } - }, + } } Err(err) } diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index b98372d0f28c1..36fe328cb193d 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -83,7 +83,7 @@ macro_rules! maybe_whole_expr { pub(super) enum LhsExpr { NotYetParsed, AttributesParsed(AttrWrapper), - AlreadyParsed(P), + AlreadyParsed(P, bool), // (expr, starts_statement) } impl From> for LhsExpr { @@ -101,7 +101,7 @@ impl From> for LhsExpr { /// /// This conversion does not allocate. fn from(expr: P) -> Self { - LhsExpr::AlreadyParsed(expr) + LhsExpr::AlreadyParsed(expr, false) } } @@ -173,7 +173,9 @@ impl<'a> Parser<'a> { min_prec: usize, lhs: LhsExpr, ) -> PResult<'a, P> { - let mut lhs = if let LhsExpr::AlreadyParsed(expr) = lhs { + let mut starts_stmt = false; + let mut lhs = if let LhsExpr::AlreadyParsed(expr, starts_statement) = lhs { + starts_stmt = starts_statement; expr } else { let attrs = match lhs { @@ -292,15 +294,7 @@ impl<'a> Parser<'a> { let op_span = self.prev_token.span.to(self.token.span); // Eat the second `+` self.bump(); - let prev_is_semi = { - if let Ok(prev_code) = self.sess.source_map().span_to_prev_source(lhs.span) && - prev_code.trim_end().ends_with(";") { - true - } else { - false - } - }; - lhs = self.recover_from_postfix_increment(lhs, op_span, prev_is_semi)?; + lhs = self.recover_from_postfix_increment(lhs, op_span, starts_stmt)?; continue; } @@ -607,14 +601,15 @@ impl<'a> Parser<'a> { token::BinOp(token::Plus) if this.look_ahead(1, |t| *t == token::BinOp(token::Plus)) => { - let prev_is_semi = this.prev_token == token::Semi; + let starts_stmt = this.prev_token == token::Semi + || this.prev_token == token::CloseDelim(Delimiter::Brace); let pre_span = this.token.span.to(this.look_ahead(1, |t| t.span)); // Eat both `+`s. this.bump(); this.bump(); let operand_expr = this.parse_dot_or_call_expr(Default::default())?; - this.recover_from_prefix_increment(operand_expr, pre_span, prev_is_semi) + this.recover_from_prefix_increment(operand_expr, pre_span, starts_stmt) } token::Ident(..) if this.token.is_keyword(kw::Box) => { make_it!(this, attrs, |this, _| this.parse_box_expr(lo)) diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index 1b56cd72db079..53aa0315151c4 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -156,7 +156,7 @@ impl<'a> Parser<'a> { // Perform this outside of the `collect_tokens_trailing_token` closure, // since our outer attributes do not apply to this part of the expression let expr = self.with_res(Restrictions::STMT_EXPR, |this| { - this.parse_assoc_expr_with(0, LhsExpr::AlreadyParsed(expr)) + this.parse_assoc_expr_with(0, LhsExpr::AlreadyParsed(expr, true)) })?; Ok(self.mk_stmt(lo.to(self.prev_token.span), StmtKind::Expr(expr))) } else { @@ -190,7 +190,7 @@ impl<'a> Parser<'a> { let e = self.mk_expr(lo.to(hi), ExprKind::MacCall(mac)); let e = self.maybe_recover_from_bad_qpath(e)?; let e = self.parse_dot_or_call_expr_with(e, lo, attrs)?; - let e = self.parse_assoc_expr_with(0, LhsExpr::AlreadyParsed(e))?; + let e = self.parse_assoc_expr_with(0, LhsExpr::AlreadyParsed(e, false))?; StmtKind::Expr(e) }; Ok(self.mk_stmt(lo.to(hi), kind)) diff --git a/src/test/ui/parser/increment-notfixed.fixed b/src/test/ui/parser/increment-autofix-2.fixed similarity index 100% rename from src/test/ui/parser/increment-notfixed.fixed rename to src/test/ui/parser/increment-autofix-2.fixed diff --git a/src/test/ui/parser/increment-notfixed.rs b/src/test/ui/parser/increment-autofix-2.rs similarity index 100% rename from src/test/ui/parser/increment-notfixed.rs rename to src/test/ui/parser/increment-autofix-2.rs diff --git a/src/test/ui/parser/increment-notfixed.stderr b/src/test/ui/parser/increment-autofix-2.stderr similarity index 85% rename from src/test/ui/parser/increment-notfixed.stderr rename to src/test/ui/parser/increment-autofix-2.stderr index ffee8b64637c9..11e985480d697 100644 --- a/src/test/ui/parser/increment-notfixed.stderr +++ b/src/test/ui/parser/increment-autofix-2.stderr @@ -1,5 +1,5 @@ error: Rust has no postfix increment operator - --> $DIR/increment-notfixed.rs:13:6 + --> $DIR/increment-autofix-2.rs:13:6 | LL | i++; | ^^ not a valid postfix operator @@ -10,7 +10,7 @@ LL | i += 1; | ~~~~ error: Rust has no postfix increment operator - --> $DIR/increment-notfixed.rs:19:12 + --> $DIR/increment-autofix-2.rs:19:12 | LL | while i++ < 5 { | ----- ^^ not a valid postfix operator @@ -23,7 +23,7 @@ LL | while { let tmp = i; i += 1; tmp } < 5 { | +++++++++++ ~~~~~~~~~~~~~~~ error: Rust has no postfix increment operator - --> $DIR/increment-notfixed.rs:27:8 + --> $DIR/increment-autofix-2.rs:27:8 | LL | tmp++; | ^^ not a valid postfix operator @@ -34,7 +34,7 @@ LL | tmp += 1; | ~~~~ error: Rust has no postfix increment operator - --> $DIR/increment-notfixed.rs:33:14 + --> $DIR/increment-autofix-2.rs:33:14 | LL | while tmp++ < 5 { | ----- ^^ not a valid postfix operator @@ -47,7 +47,7 @@ LL | while { let tmp_ = tmp; tmp += 1; tmp_ } < 5 { | ++++++++++++ ~~~~~~~~~~~~~~~~~~ error: Rust has no postfix increment operator - --> $DIR/increment-notfixed.rs:41:16 + --> $DIR/increment-autofix-2.rs:41:16 | LL | foo.bar.qux++; | ^^ not a valid postfix operator @@ -58,7 +58,7 @@ LL | foo.bar.qux += 1; | ~~~~ error: Rust has no postfix increment operator - --> $DIR/increment-notfixed.rs:51:10 + --> $DIR/increment-autofix-2.rs:51:10 | LL | s.tmp++; | ^^ not a valid postfix operator @@ -69,7 +69,7 @@ LL | s.tmp += 1; | ~~~~ error: Rust has no prefix increment operator - --> $DIR/increment-notfixed.rs:58:5 + --> $DIR/increment-autofix-2.rs:58:5 | LL | ++foo.bar.qux; | ^^ not a valid prefix operator diff --git a/src/test/ui/parser/issue-104867-inc-dec-2.rs b/src/test/ui/parser/issue-104867-inc-dec-2.rs new file mode 100644 index 0000000000000..e64dfbcdc287a --- /dev/null +++ b/src/test/ui/parser/issue-104867-inc-dec-2.rs @@ -0,0 +1,41 @@ +fn test1() { + let mut i = 0; + let _ = i + ++i; //~ ERROR Rust has no prefix increment operator +} + +fn test2() { + let mut i = 0; + let _ = ++i + i; //~ ERROR Rust has no prefix increment operator +} + +fn test3() { + let mut i = 0; + let _ = ++i + ++i; //~ ERROR Rust has no prefix increment operator +} + +fn test4() { + let mut i = 0; + let _ = i + i++; //~ ERROR Rust has no postfix increment operator +} + +fn test5() { + let mut i = 0; + let _ = i++ + i; //~ ERROR Rust has no postfix increment operator +} + +fn test6() { + let mut i = 0; + let _ = i++ + i++; //~ ERROR Rust has no postfix increment operator +} + +fn test7() { + let mut i = 0; + let _ = ++i + i++; //~ ERROR Rust has no prefix increment operator +} + +fn test8() { + let mut i = 0; + let _ = i++ + ++i; //~ ERROR Rust has no postfix increment operator +} + +fn main() { } diff --git a/src/test/ui/parser/issue-104867-inc-dec-2.stderr b/src/test/ui/parser/issue-104867-inc-dec-2.stderr new file mode 100644 index 0000000000000..21cfa4e8b78bf --- /dev/null +++ b/src/test/ui/parser/issue-104867-inc-dec-2.stderr @@ -0,0 +1,90 @@ +error: Rust has no prefix increment operator + --> $DIR/issue-104867-inc-dec-2.rs:3:17 + | +LL | let _ = i + ++i; + | ^^ not a valid prefix operator + | +help: use `+= 1` instead + | +LL | let _ = i + { i += 1; i }; + | ~ +++++++++ + +error: Rust has no prefix increment operator + --> $DIR/issue-104867-inc-dec-2.rs:8:13 + | +LL | let _ = ++i + i; + | ^^ not a valid prefix operator + | +help: use `+= 1` instead + | +LL | let _ = { i += 1; i } + i; + | ~ +++++++++ + +error: Rust has no prefix increment operator + --> $DIR/issue-104867-inc-dec-2.rs:13:13 + | +LL | let _ = ++i + ++i; + | ^^ not a valid prefix operator + | +help: use `+= 1` instead + | +LL | let _ = { i += 1; i } + ++i; + | ~ +++++++++ + +error: Rust has no postfix increment operator + --> $DIR/issue-104867-inc-dec-2.rs:18:18 + | +LL | let _ = i + i++; + | ^^ not a valid postfix operator + | +help: use `+= 1` instead + | +LL | let _ = { let tmp = i + i; i + i += 1; tmp }; + | +++++++++++ ~~~~~~~~~~~~~~~~~~~ + +error: Rust has no postfix increment operator + --> $DIR/issue-104867-inc-dec-2.rs:23:14 + | +LL | let _ = i++ + i; + | ^^ not a valid postfix operator + | +help: use `+= 1` instead + | +LL | let _ = { let tmp = i; i += 1; tmp } + i; + | +++++++++++ ~~~~~~~~~~~~~~~ + +error: Rust has no postfix increment operator + --> $DIR/issue-104867-inc-dec-2.rs:28:14 + | +LL | let _ = i++ + i++; + | ^^ not a valid postfix operator + | +help: use `+= 1` instead + | +LL | let _ = { let tmp = i; i += 1; tmp } + i++; + | +++++++++++ ~~~~~~~~~~~~~~~ + +error: Rust has no prefix increment operator + --> $DIR/issue-104867-inc-dec-2.rs:33:13 + | +LL | let _ = ++i + i++; + | ^^ not a valid prefix operator + | +help: use `+= 1` instead + | +LL | let _ = { i += 1; i } + i++; + | ~ +++++++++ + +error: Rust has no postfix increment operator + --> $DIR/issue-104867-inc-dec-2.rs:38:14 + | +LL | let _ = i++ + ++i; + | ^^ not a valid postfix operator + | +help: use `+= 1` instead + | +LL | let _ = { let tmp = i; i += 1; tmp } + ++i; + | +++++++++++ ~~~~~~~~~~~~~~~ + +error: aborting due to 8 previous errors + diff --git a/src/test/ui/parser/issue-104867-inc-dec.rs b/src/test/ui/parser/issue-104867-inc-dec.rs index d08d74ec1f911..760c67b4bed70 100644 --- a/src/test/ui/parser/issue-104867-inc-dec.rs +++ b/src/test/ui/parser/issue-104867-inc-dec.rs @@ -27,4 +27,19 @@ fn test5() { if ++i == 1 { } //~ ERROR Rust has no prefix increment operator } +fn test6() { + let mut i = 0; + loop { break; } + i++; //~ ERROR Rust has no postfix increment operator + loop { break; } + ++i; +} + +fn test7() { + let mut i = 0; + loop { break; } + ++i; //~ ERROR Rust has no prefix increment operator +} + + fn main() {} diff --git a/src/test/ui/parser/issue-104867-inc-dec.stderr b/src/test/ui/parser/issue-104867-inc-dec.stderr index d45b92bf89904..78bfd3e82f0de 100644 --- a/src/test/ui/parser/issue-104867-inc-dec.stderr +++ b/src/test/ui/parser/issue-104867-inc-dec.stderr @@ -54,5 +54,28 @@ help: use `+= 1` instead LL | if { i += 1; i } == 1 { } | ~ +++++++++ -error: aborting due to 5 previous errors +error: Rust has no postfix increment operator + --> $DIR/issue-104867-inc-dec.rs:33:6 + | +LL | i++; + | ^^ not a valid postfix operator + | +help: use `+= 1` instead + | +LL | i += 1; + | ~~~~ + +error: Rust has no prefix increment operator + --> $DIR/issue-104867-inc-dec.rs:41:5 + | +LL | ++i; + | ^^ not a valid prefix operator + | +help: use `+= 1` instead + | +LL - ++i; +LL + i += 1; + | + +error: aborting due to 7 previous errors From ded10a13d2a0ccb4475cb7a330179a1f39e2b4ff Mon Sep 17 00:00:00 2001 From: yukang Date: Sat, 26 Nov 2022 07:10:04 +0800 Subject: [PATCH 3/3] will not suggest for postfix operator when can not handle precedences well --- .../rustc_parse/src/parser/diagnostics.rs | 6 ++- src/test/ui/parser/issue-104867-inc-dec-2.rs | 11 ++++++ .../ui/parser/issue-104867-inc-dec-2.stderr | 37 ++++++++++++++----- 3 files changed, 43 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index f8c6ff994c4a0..a9555cddb1b43 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -1316,7 +1316,11 @@ impl<'a> Parser<'a> { self.prefix_inc_dec_suggest(base_src, kind, spans).emit(&mut err) } UnaryFixity::Post => { - self.postfix_inc_dec_suggest(base_src, kind, spans).emit(&mut err) + // won't suggest since we can not handle the precedences + // for example: `a + b++` has been parsed (a + b)++ and we can not suggest here + if !matches!(base.kind, ExprKind::Binary(_, _, _)) { + self.postfix_inc_dec_suggest(base_src, kind, spans).emit(&mut err) + } } } } diff --git a/src/test/ui/parser/issue-104867-inc-dec-2.rs b/src/test/ui/parser/issue-104867-inc-dec-2.rs index e64dfbcdc287a..a006421a975d9 100644 --- a/src/test/ui/parser/issue-104867-inc-dec-2.rs +++ b/src/test/ui/parser/issue-104867-inc-dec-2.rs @@ -16,6 +16,7 @@ fn test3() { fn test4() { let mut i = 0; let _ = i + i++; //~ ERROR Rust has no postfix increment operator + // won't suggest since we can not handle the precedences } fn test5() { @@ -38,4 +39,14 @@ fn test8() { let _ = i++ + ++i; //~ ERROR Rust has no postfix increment operator } +fn test9() { + let mut i = 0; + let _ = (1 + 2 + i)++; //~ ERROR Rust has no postfix increment operator +} + +fn test10() { + let mut i = 0; + let _ = (i++ + 1) + 2; //~ ERROR Rust has no postfix increment operator +} + fn main() { } diff --git a/src/test/ui/parser/issue-104867-inc-dec-2.stderr b/src/test/ui/parser/issue-104867-inc-dec-2.stderr index 21cfa4e8b78bf..4e2d0546851e3 100644 --- a/src/test/ui/parser/issue-104867-inc-dec-2.stderr +++ b/src/test/ui/parser/issue-104867-inc-dec-2.stderr @@ -36,14 +36,9 @@ error: Rust has no postfix increment operator | LL | let _ = i + i++; | ^^ not a valid postfix operator - | -help: use `+= 1` instead - | -LL | let _ = { let tmp = i + i; i + i += 1; tmp }; - | +++++++++++ ~~~~~~~~~~~~~~~~~~~ error: Rust has no postfix increment operator - --> $DIR/issue-104867-inc-dec-2.rs:23:14 + --> $DIR/issue-104867-inc-dec-2.rs:24:14 | LL | let _ = i++ + i; | ^^ not a valid postfix operator @@ -54,7 +49,7 @@ LL | let _ = { let tmp = i; i += 1; tmp } + i; | +++++++++++ ~~~~~~~~~~~~~~~ error: Rust has no postfix increment operator - --> $DIR/issue-104867-inc-dec-2.rs:28:14 + --> $DIR/issue-104867-inc-dec-2.rs:29:14 | LL | let _ = i++ + i++; | ^^ not a valid postfix operator @@ -65,7 +60,7 @@ LL | let _ = { let tmp = i; i += 1; tmp } + i++; | +++++++++++ ~~~~~~~~~~~~~~~ error: Rust has no prefix increment operator - --> $DIR/issue-104867-inc-dec-2.rs:33:13 + --> $DIR/issue-104867-inc-dec-2.rs:34:13 | LL | let _ = ++i + i++; | ^^ not a valid prefix operator @@ -76,7 +71,7 @@ LL | let _ = { i += 1; i } + i++; | ~ +++++++++ error: Rust has no postfix increment operator - --> $DIR/issue-104867-inc-dec-2.rs:38:14 + --> $DIR/issue-104867-inc-dec-2.rs:39:14 | LL | let _ = i++ + ++i; | ^^ not a valid postfix operator @@ -86,5 +81,27 @@ help: use `+= 1` instead LL | let _ = { let tmp = i; i += 1; tmp } + ++i; | +++++++++++ ~~~~~~~~~~~~~~~ -error: aborting due to 8 previous errors +error: Rust has no postfix increment operator + --> $DIR/issue-104867-inc-dec-2.rs:44:24 + | +LL | let _ = (1 + 2 + i)++; + | ^^ not a valid postfix operator + | +help: use `+= 1` instead + | +LL | let _ = { let tmp = (1 + 2 + i); (1 + 2 + i) += 1; tmp }; + | +++++++++++ ~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: Rust has no postfix increment operator + --> $DIR/issue-104867-inc-dec-2.rs:49:15 + | +LL | let _ = (i++ + 1) + 2; + | ^^ not a valid postfix operator + | +help: use `+= 1` instead + | +LL | let _ = ({ let tmp = i; i += 1; tmp } + 1) + 2; + | +++++++++++ ~~~~~~~~~~~~~~~ + +error: aborting due to 10 previous errors