diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs index 710a592e258b4..3a65ffe41ae87 100644 --- a/compiler/rustc_ast/src/token.rs +++ b/compiler/rustc_ast/src/token.rs @@ -586,6 +586,13 @@ impl Token { self.is_non_raw_ident_where(|id| id.name.is_bool_lit()) } + pub fn is_numeric_lit(&self) -> bool { + matches!( + self.kind, + Literal(Lit { kind: LitKind::Integer, .. }) | Literal(Lit { kind: LitKind::Float, .. }) + ) + } + /// Returns `true` if the token is a non-raw identifier for which `pred` holds. pub fn is_non_raw_ident_where(&self, pred: impl FnOnce(Ident) -> bool) -> bool { match self.ident() { diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 326c8f81ffbf9..83e1c5ff753a8 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -516,6 +516,26 @@ impl<'a> Parser<'a> { token::BinOp(token::And) | token::AndAnd => { make_it!(this, attrs, |this, _| this.parse_borrow_expr(lo)) } + token::BinOp(token::Plus) if this.look_ahead(1, |tok| tok.is_numeric_lit()) => { + let mut err = this.struct_span_err(lo, "leading `+` is not supported"); + err.span_label(lo, "unexpected `+`"); + + // a block on the LHS might have been intended to be an expression instead + if let Some(sp) = this.sess.ambiguous_block_expr_parse.borrow().get(&lo) { + this.sess.expr_parentheses_needed(&mut err, *sp); + } else { + err.span_suggestion_verbose( + lo, + "try removing the `+`", + "".to_string(), + Applicability::MachineApplicable, + ); + } + err.emit(); + + this.bump(); + this.parse_prefix_expr(None) + } // `+expr` token::Ident(..) if this.token.is_keyword(kw::Box) => { make_it!(this, attrs, |this, _| this.parse_box_expr(lo)) } diff --git a/src/test/ui/associated-types/issue-36499.stderr b/src/test/ui/associated-types/issue-36499.stderr index ff450f60acc68..610798d880f0a 100644 --- a/src/test/ui/associated-types/issue-36499.stderr +++ b/src/test/ui/associated-types/issue-36499.stderr @@ -1,8 +1,14 @@ -error: expected expression, found `+` +error: leading `+` is not supported --> $DIR/issue-36499.rs:4:9 | LL | 2 + +2; - | ^ expected expression + | ^ unexpected `+` + | +help: try removing the `+` + | +LL - 2 + +2; +LL + 2 + 2; + | error: aborting due to previous error diff --git a/src/test/ui/parser/expr-as-stmt.fixed b/src/test/ui/parser/expr-as-stmt.fixed index c217ab9774fd2..5f5e25991e0cc 100644 --- a/src/test/ui/parser/expr-as-stmt.fixed +++ b/src/test/ui/parser/expr-as-stmt.fixed @@ -10,7 +10,7 @@ fn foo() -> i32 { } fn bar() -> i32 { - ({2}) + 2 //~ ERROR expected expression, found `+` + ({2}) + 2 //~ ERROR leading `+` is not supported //~^ ERROR mismatched types } diff --git a/src/test/ui/parser/expr-as-stmt.rs b/src/test/ui/parser/expr-as-stmt.rs index b04025faaec63..5428e1c32fed3 100644 --- a/src/test/ui/parser/expr-as-stmt.rs +++ b/src/test/ui/parser/expr-as-stmt.rs @@ -10,7 +10,7 @@ fn foo() -> i32 { } fn bar() -> i32 { - {2} + 2 //~ ERROR expected expression, found `+` + {2} + 2 //~ ERROR leading `+` is not supported //~^ ERROR mismatched types } diff --git a/src/test/ui/parser/expr-as-stmt.stderr b/src/test/ui/parser/expr-as-stmt.stderr index ba5cd01abfcc7..d99e9be0000c3 100644 --- a/src/test/ui/parser/expr-as-stmt.stderr +++ b/src/test/ui/parser/expr-as-stmt.stderr @@ -9,11 +9,11 @@ help: parentheses are required to parse this as an expression LL | ({2}) + {2} | + + -error: expected expression, found `+` +error: leading `+` is not supported --> $DIR/expr-as-stmt.rs:13:9 | LL | {2} + 2 - | ^ expected expression + | ^ unexpected `+` | help: parentheses are required to parse this as an expression | diff --git a/src/test/ui/parser/issue-88276-unary-plus.fixed b/src/test/ui/parser/issue-88276-unary-plus.fixed new file mode 100644 index 0000000000000..25b7c340f600d --- /dev/null +++ b/src/test/ui/parser/issue-88276-unary-plus.fixed @@ -0,0 +1,8 @@ +// run-rustfix +#[allow(unused_parens)] +fn main() { + let _ = 1; //~ ERROR leading `+` is not supported + let _ = (1.0 + 2.0) * 3.0; //~ ERROR leading `+` is not supported + //~| ERROR leading `+` is not supported + let _ = [3, 4+6]; //~ ERROR leading `+` is not supported +} diff --git a/src/test/ui/parser/issue-88276-unary-plus.rs b/src/test/ui/parser/issue-88276-unary-plus.rs new file mode 100644 index 0000000000000..11b2e9d601653 --- /dev/null +++ b/src/test/ui/parser/issue-88276-unary-plus.rs @@ -0,0 +1,8 @@ +// run-rustfix +#[allow(unused_parens)] +fn main() { + let _ = +1; //~ ERROR leading `+` is not supported + let _ = (1.0 + +2.0) * +3.0; //~ ERROR leading `+` is not supported + //~| ERROR leading `+` is not supported + let _ = [+3, 4+6]; //~ ERROR leading `+` is not supported +} diff --git a/src/test/ui/parser/issue-88276-unary-plus.stderr b/src/test/ui/parser/issue-88276-unary-plus.stderr new file mode 100644 index 0000000000000..b26761729a837 --- /dev/null +++ b/src/test/ui/parser/issue-88276-unary-plus.stderr @@ -0,0 +1,50 @@ +error: leading `+` is not supported + --> $DIR/issue-88276-unary-plus.rs:4:13 + | +LL | let _ = +1; + | ^ unexpected `+` + | +help: try removing the `+` + | +LL - let _ = +1; +LL + let _ = 1; + | + +error: leading `+` is not supported + --> $DIR/issue-88276-unary-plus.rs:5:20 + | +LL | let _ = (1.0 + +2.0) * +3.0; + | ^ unexpected `+` + | +help: try removing the `+` + | +LL - let _ = (1.0 + +2.0) * +3.0; +LL + let _ = (1.0 + 2.0) * +3.0; + | + +error: leading `+` is not supported + --> $DIR/issue-88276-unary-plus.rs:5:28 + | +LL | let _ = (1.0 + +2.0) * +3.0; + | ^ unexpected `+` + | +help: try removing the `+` + | +LL - let _ = (1.0 + +2.0) * +3.0; +LL + let _ = (1.0 + +2.0) * 3.0; + | + +error: leading `+` is not supported + --> $DIR/issue-88276-unary-plus.rs:7:14 + | +LL | let _ = [+3, 4+6]; + | ^ unexpected `+` + | +help: try removing the `+` + | +LL - let _ = [+3, 4+6]; +LL + let _ = [3, 4+6]; + | + +error: aborting due to 4 previous errors +