add start_stmt to handle postfix increment

This commit is contained in:
yukang 2022-11-26 05:33:13 +08:00
parent 7c11a53f9c
commit dee85a391f
10 changed files with 203 additions and 38 deletions

View file

@ -1259,10 +1259,9 @@ impl<'a> Parser<'a> {
&mut self, &mut self,
operand_expr: P<Expr>, operand_expr: P<Expr>,
op_span: Span, op_span: Span,
prev_is_semi: bool, start_stmt: bool,
) -> PResult<'a, P<Expr>> { ) -> PResult<'a, P<Expr>> {
let standalone = let standalone = if start_stmt { IsStandalone::Standalone } else { IsStandalone::Subexpr };
if prev_is_semi { IsStandalone::Standalone } else { IsStandalone::Subexpr };
let kind = IncDecRecovery { standalone, op: IncOrDec::Inc, fixity: UnaryFixity::Pre }; let kind = IncDecRecovery { standalone, op: IncOrDec::Inc, fixity: UnaryFixity::Pre };
self.recover_from_inc_dec(operand_expr, kind, op_span) self.recover_from_inc_dec(operand_expr, kind, op_span)
} }
@ -1271,10 +1270,10 @@ impl<'a> Parser<'a> {
&mut self, &mut self,
operand_expr: P<Expr>, operand_expr: P<Expr>,
op_span: Span, op_span: Span,
prev_is_semi: bool, start_stmt: bool,
) -> PResult<'a, P<Expr>> { ) -> PResult<'a, P<Expr>> {
let kind = IncDecRecovery { 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, op: IncOrDec::Inc,
fixity: UnaryFixity::Post, fixity: UnaryFixity::Post,
}; };
@ -1305,20 +1304,22 @@ impl<'a> Parser<'a> {
UnaryFixity::Post => (base.span.shrink_to_lo(), op_span), 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 { match kind.standalone {
IsStandalone::Standalone => { IsStandalone::Standalone => {
self.inc_dec_standalone_suggest(kind, spans).emit_verbose(&mut err) self.inc_dec_standalone_suggest(kind, spans).emit_verbose(&mut err)
} }
IsStandalone::Subexpr => match kind.fixity { IsStandalone::Subexpr => {
UnaryFixity::Pre => { let Ok(base_src) = self.span_to_snippet(base.span)
self.prefix_inc_dec_suggest(base_src, kind, spans).emit(&mut err) 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)
}
} }
UnaryFixity::Post => { }
self.postfix_inc_dec_suggest(base_src, kind, spans).emit(&mut err)
}
},
} }
Err(err) Err(err)
} }

View file

@ -83,7 +83,7 @@ macro_rules! maybe_whole_expr {
pub(super) enum LhsExpr { pub(super) enum LhsExpr {
NotYetParsed, NotYetParsed,
AttributesParsed(AttrWrapper), AttributesParsed(AttrWrapper),
AlreadyParsed(P<Expr>), AlreadyParsed(P<Expr>, bool), // (expr, starts_statement)
} }
impl From<Option<AttrWrapper>> for LhsExpr { impl From<Option<AttrWrapper>> for LhsExpr {
@ -101,7 +101,7 @@ impl From<P<Expr>> for LhsExpr {
/// ///
/// This conversion does not allocate. /// This conversion does not allocate.
fn from(expr: P<Expr>) -> Self { fn from(expr: P<Expr>) -> Self {
LhsExpr::AlreadyParsed(expr) LhsExpr::AlreadyParsed(expr, false)
} }
} }
@ -173,7 +173,9 @@ impl<'a> Parser<'a> {
min_prec: usize, min_prec: usize,
lhs: LhsExpr, lhs: LhsExpr,
) -> PResult<'a, P<Expr>> { ) -> PResult<'a, P<Expr>> {
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 expr
} else { } else {
let attrs = match lhs { let attrs = match lhs {
@ -292,15 +294,7 @@ impl<'a> Parser<'a> {
let op_span = self.prev_token.span.to(self.token.span); let op_span = self.prev_token.span.to(self.token.span);
// Eat the second `+` // Eat the second `+`
self.bump(); self.bump();
let prev_is_semi = { lhs = self.recover_from_postfix_increment(lhs, op_span, starts_stmt)?;
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; continue;
} }
@ -607,14 +601,15 @@ impl<'a> Parser<'a> {
token::BinOp(token::Plus) token::BinOp(token::Plus)
if this.look_ahead(1, |t| *t == 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)); let pre_span = this.token.span.to(this.look_ahead(1, |t| t.span));
// Eat both `+`s. // Eat both `+`s.
this.bump(); this.bump();
this.bump(); this.bump();
let operand_expr = this.parse_dot_or_call_expr(Default::default())?; 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) => { token::Ident(..) if this.token.is_keyword(kw::Box) => {
make_it!(this, attrs, |this, _| this.parse_box_expr(lo)) make_it!(this, attrs, |this, _| this.parse_box_expr(lo))

View file

@ -156,7 +156,7 @@ impl<'a> Parser<'a> {
// Perform this outside of the `collect_tokens_trailing_token` closure, // Perform this outside of the `collect_tokens_trailing_token` closure,
// since our outer attributes do not apply to this part of the expression // since our outer attributes do not apply to this part of the expression
let expr = self.with_res(Restrictions::STMT_EXPR, |this| { 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))) Ok(self.mk_stmt(lo.to(self.prev_token.span), StmtKind::Expr(expr)))
} else { } else {
@ -190,7 +190,7 @@ impl<'a> Parser<'a> {
let e = self.mk_expr(lo.to(hi), ExprKind::MacCall(mac)); let e = self.mk_expr(lo.to(hi), ExprKind::MacCall(mac));
let e = self.maybe_recover_from_bad_qpath(e)?; 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_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) StmtKind::Expr(e)
}; };
Ok(self.mk_stmt(lo.to(hi), kind)) Ok(self.mk_stmt(lo.to(hi), kind))

View file

@ -1,5 +1,5 @@
error: Rust has no postfix increment operator error: Rust has no postfix increment operator
--> $DIR/increment-notfixed.rs:13:6 --> $DIR/increment-autofix-2.rs:13:6
| |
LL | i++; LL | i++;
| ^^ not a valid postfix operator | ^^ not a valid postfix operator
@ -10,7 +10,7 @@ LL | i += 1;
| ~~~~ | ~~~~
error: Rust has no postfix increment operator error: Rust has no postfix increment operator
--> $DIR/increment-notfixed.rs:19:12 --> $DIR/increment-autofix-2.rs:19:12
| |
LL | while i++ < 5 { LL | while i++ < 5 {
| ----- ^^ not a valid postfix operator | ----- ^^ 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 error: Rust has no postfix increment operator
--> $DIR/increment-notfixed.rs:27:8 --> $DIR/increment-autofix-2.rs:27:8
| |
LL | tmp++; LL | tmp++;
| ^^ not a valid postfix operator | ^^ not a valid postfix operator
@ -34,7 +34,7 @@ LL | tmp += 1;
| ~~~~ | ~~~~
error: Rust has no postfix increment operator error: Rust has no postfix increment operator
--> $DIR/increment-notfixed.rs:33:14 --> $DIR/increment-autofix-2.rs:33:14
| |
LL | while tmp++ < 5 { LL | while tmp++ < 5 {
| ----- ^^ not a valid postfix operator | ----- ^^ 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 error: Rust has no postfix increment operator
--> $DIR/increment-notfixed.rs:41:16 --> $DIR/increment-autofix-2.rs:41:16
| |
LL | foo.bar.qux++; LL | foo.bar.qux++;
| ^^ not a valid postfix operator | ^^ not a valid postfix operator
@ -58,7 +58,7 @@ LL | foo.bar.qux += 1;
| ~~~~ | ~~~~
error: Rust has no postfix increment operator error: Rust has no postfix increment operator
--> $DIR/increment-notfixed.rs:51:10 --> $DIR/increment-autofix-2.rs:51:10
| |
LL | s.tmp++; LL | s.tmp++;
| ^^ not a valid postfix operator | ^^ not a valid postfix operator
@ -69,7 +69,7 @@ LL | s.tmp += 1;
| ~~~~ | ~~~~
error: Rust has no prefix increment operator error: Rust has no prefix increment operator
--> $DIR/increment-notfixed.rs:58:5 --> $DIR/increment-autofix-2.rs:58:5
| |
LL | ++foo.bar.qux; LL | ++foo.bar.qux;
| ^^ not a valid prefix operator | ^^ not a valid prefix operator

View file

@ -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() { }

View file

@ -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

View file

@ -27,4 +27,19 @@ fn test5() {
if ++i == 1 { } //~ ERROR Rust has no prefix increment operator 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() {} fn main() {}

View file

@ -54,5 +54,28 @@ help: use `+= 1` instead
LL | if { i += 1; i } == 1 { } 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