Fix #74233.
Greater | // `{ 42 } > 3`
GreaterEqual | // `{ 42 } >= 3`
AssignOp(_) | // `{ 42 } +=`
- LAnd | // `{ 42 } &&foo`
As | // `{ 42 } as usize`
// Equal | // `{ 42 } == { 42 }` Accepting these here would regress incorrect
// NotEqual | // `{ 42 } != { 42 } struct literals parser recovery.
// want to keep their span info to improve diagnostics in these cases in a later stage.
(true, Some(AssocOp::Multiply)) | // `{ 42 } *foo = bar;` or `{ 42 } * 3`
(true, Some(AssocOp::Subtract)) | // `{ 42 } -5`
- (true, Some(AssocOp::LAnd)) | // `{ 42 } &&x` (#61475)
(true, Some(AssocOp::Add)) // `{ 42 } + 42
// If the next token is a keyword, then the tokens above *are* unambiguously incorrect:
// `if x { a } else { b } && if y { c } else { d }`
- if !self.look_ahead(1, |t| t.is_reserved_ident()) => {
+ if !self.look_ahead(1, |t| t.is_used_keyword()) => {
+ // These cases are ambiguous and can't be identified in the parser alone.
+ let sp = self.sess.source_map().start_point(self.token.span);
+ self.sess.ambiguous_block_expr_parse.borrow_mut().insert(sp, lhs.span);
+ false
+ }
+ (true, Some(AssocOp::LAnd)) => {
+ // `{ 42 } &&x` (#61475) or `{ 42 } && if x { 1 } else { 0 }`. Separated from the
+ // above due to #74233.
// These cases are ambiguous and can't be identified in the parser alone.
let sp = self.sess.source_map().start_point(self.token.span);
self.sess.ambiguous_block_expr_parse.borrow_mut().insert(sp, lhs.span);
}
self.suggest_boxing_when_appropriate(err, expr, expected, expr_ty);
self.suggest_missing_await(err, expr, expected, expr_ty);
+ self.suggest_missing_parentheses(err, expr);
self.note_need_for_fn_pointer(err, expected, expr_ty);
}
}
}
+ fn suggest_missing_parentheses(&self, err: &mut DiagnosticBuilder<'_>, expr: &hir::Expr<'_>) {
+ let sp = self.tcx.sess.source_map().start_point(expr.span);
+ if let Some(sp) = self.tcx.sess.parse_sess.ambiguous_block_expr_parse.borrow().get(&sp) {
+ // `{ 42 } &&x` (#61475) or `{ 42 } && if x { 1 } else { 0 }`
+ self.tcx.sess.parse_sess.expr_parentheses_needed(err, *sp, None);
+ }
+ }
+
fn note_need_for_fn_pointer(
&self,
err: &mut DiagnosticBuilder<'_>,
--- /dev/null
+// This is not autofixable because we give extra suggestions to end the first expression with `;`.
+fn foo(a: Option<u32>, b: Option<u32>) -> bool {
+ if let Some(x) = a { true } else { false }
+ //~^ ERROR mismatched types
+ //~| ERROR mismatched types
+ && //~ ERROR mismatched types
+ if let Some(y) = a { true } else { false }
+}
+
+fn main() {}
--- /dev/null
+error[E0308]: mismatched types
+ --> $DIR/expr-as-stmt-2.rs:3:26
+ |
+LL | if let Some(x) = a { true } else { false }
+ | ---------------------^^^^------------------ help: consider using a semicolon here
+ | | |
+ | | expected `()`, found `bool`
+ | expected this to be `()`
+
+error[E0308]: mismatched types
+ --> $DIR/expr-as-stmt-2.rs:3:40
+ |
+LL | if let Some(x) = a { true } else { false }
+ | -----------------------------------^^^^^--- help: consider using a semicolon here
+ | | |
+ | | expected `()`, found `bool`
+ | expected this to be `()`
+
+error[E0308]: mismatched types
+ --> $DIR/expr-as-stmt-2.rs:6:5
+ |
+LL | fn foo(a: Option<u32>, b: Option<u32>) -> bool {
+ | ---- expected `bool` because of return type
+LL | if let Some(x) = a { true } else { false }
+ | ------------------------------------------ help: parentheses are required to parse this as an expression: `(if let Some(x) = a { true } else { false })`
+...
+LL | / &&
+LL | | if let Some(y) = a { true } else { false }
+ | |______________________________________________^ expected `bool`, found `&&bool`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
//~^ ERROR mismatched types
}
-fn qux(a: Option<u32>, b: Option<u32>) -> bool {
- (if let Some(x) = a { true } else { false })
- && //~ ERROR expected expression
- if let Some(y) = a { true } else { false }
-}
-
fn moo(x: u32) -> bool {
(match x {
_ => 1,
//~^ ERROR mismatched types
}
-fn qux(a: Option<u32>, b: Option<u32>) -> bool {
- if let Some(x) = a { true } else { false }
- && //~ ERROR expected expression
- if let Some(y) = a { true } else { false }
-}
-
fn moo(x: u32) -> bool {
match x {
_ => 1,
| |
| help: parentheses are required to parse this as an expression: `({ 42 })`
-error: expected expression, found `&&`
- --> $DIR/expr-as-stmt.rs:30:5
- |
-LL | if let Some(x) = a { true } else { false }
- | ------------------------------------------ help: parentheses are required to parse this as an expression: `(if let Some(x) = a { true } else { false })`
-LL | &&
- | ^^ expected expression
-
error: expected expression, found `>`
- --> $DIR/expr-as-stmt.rs:37:7
+ --> $DIR/expr-as-stmt.rs:31:7
|
LL | } > 0
| ^ expected expression
| |
| help: parentheses are required to parse this as an expression: `({ 3 })`
-error: aborting due to 10 previous errors
+error: aborting due to 9 previous errors
Some errors have detailed explanations: E0308, E0614.
For more information about an error, try `rustc --explain E0308`.