about summary refs log tree commit diff
path: root/compiler/rustc_parse/src/parser/expr.rs
diff options
context:
space:
mode:
authorNicholas Nethercote <n.nethercote@gmail.com>2024-12-19 18:24:07 +1100
committerNicholas Nethercote <n.nethercote@gmail.com>2025-02-27 09:53:17 +1100
commitceafbad81fcf71423d4dc7a90fe962bc5895b108 (patch)
tree263d73b402ee77cdfcfea0adbaf1dec5e2a45433 /compiler/rustc_parse/src/parser/expr.rs
parenta8364f3b2ad63c19037bdf060e49ad9ca07e16b6 (diff)
downloadrust-ceafbad81fcf71423d4dc7a90fe962bc5895b108.tar.gz
rust-ceafbad81fcf71423d4dc7a90fe962bc5895b108.zip
Introduce `AssocOp::Binary`.
It mirrors `ExprKind::Binary`, and contains a `BinOpKind`. This makes
`AssocOp` more like `ExprKind`. Note that the variants removed from
`AssocOp` are all named differently to `BinOpToken`, e.g. `Multiply`
instead of `Mul`, so that's an inconsistency removed.

The commit adds `precedence` and `fixity` methods to `BinOpKind`, and
calls them from the corresponding methods in `AssocOp`. This avoids the
need to create an `AssocOp` from a `BinOpKind` in a bunch of places, and
`AssocOp::from_ast_binop` is removed.

`AssocOp::to_ast_binop` is also no longer needed.

Overall things are shorter and nicer.
Diffstat (limited to 'compiler/rustc_parse/src/parser/expr.rs')
-rw-r--r--compiler/rustc_parse/src/parser/expr.rs61
1 files changed, 19 insertions, 42 deletions
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index 935e13cedef..00a5f2fa28f 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -188,17 +188,12 @@ impl<'a> Parser<'a> {
             }
 
             // Look for JS' `===` and `!==` and recover
-            if (op.node == AssocOp::Equal || op.node == AssocOp::NotEqual)
+            if let AssocOp::Binary(bop @ BinOpKind::Eq | bop @ BinOpKind::Ne) = op.node
                 && self.token == token::Eq
                 && self.prev_token.span.hi() == self.token.span.lo()
             {
                 let sp = op.span.to(self.token.span);
-                let sugg = match op.node {
-                    AssocOp::Equal => "==",
-                    AssocOp::NotEqual => "!=",
-                    _ => unreachable!(),
-                }
-                .into();
+                let sugg = bop.as_str().into();
                 let invalid = format!("{sugg}=");
                 self.dcx().emit_err(errors::InvalidComparisonOperator {
                     span: sp,
@@ -213,7 +208,7 @@ impl<'a> Parser<'a> {
             }
 
             // Look for PHP's `<>` and recover
-            if op.node == AssocOp::Less
+            if op.node == AssocOp::Binary(BinOpKind::Lt)
                 && self.token == token::Gt
                 && self.prev_token.span.hi() == self.token.span.lo()
             {
@@ -231,7 +226,7 @@ impl<'a> Parser<'a> {
             }
 
             // Look for C++'s `<=>` and recover
-            if op.node == AssocOp::LessEqual
+            if op.node == AssocOp::Binary(BinOpKind::Le)
                 && self.token == token::Gt
                 && self.prev_token.span.hi() == self.token.span.lo()
             {
@@ -290,25 +285,7 @@ impl<'a> Parser<'a> {
 
             let span = self.mk_expr_sp(&lhs, lhs_span, rhs.span);
             lhs = match op {
-                AssocOp::Add
-                | AssocOp::Subtract
-                | AssocOp::Multiply
-                | AssocOp::Divide
-                | AssocOp::Modulus
-                | AssocOp::LAnd
-                | AssocOp::LOr
-                | AssocOp::BitXor
-                | AssocOp::BitAnd
-                | AssocOp::BitOr
-                | AssocOp::ShiftLeft
-                | AssocOp::ShiftRight
-                | AssocOp::Equal
-                | AssocOp::Less
-                | AssocOp::LessEqual
-                | AssocOp::NotEqual
-                | AssocOp::Greater
-                | AssocOp::GreaterEqual => {
-                    let ast_op = op.to_ast_binop().unwrap();
+                AssocOp::Binary(ast_op) => {
                     let binary = self.mk_binary(source_map::respan(cur_op_span, ast_op), lhs, rhs);
                     self.mk_expr(span, binary)
                 }
@@ -335,13 +312,14 @@ impl<'a> Parser<'a> {
             // An exhaustive check is done in the following block, but these are checked first
             // because they *are* ambiguous but also reasonable looking incorrect syntax, so we
             // 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::Add)) | // `{ 42 } + 42` (unary plus)
-            (true, Some(AssocOp::LAnd)) | // `{ 42 } &&x` (#61475) or `{ 42 } && if x { 1 } else { 0 }`
-            (true, Some(AssocOp::LOr)) | // `{ 42 } || 42` ("logical or" or closure)
-            (true, Some(AssocOp::BitOr)) // `{ 42 } | 42` or `{ 42 } |x| 42`
-            => {
+            (true, Some(AssocOp::Binary(
+                BinOpKind::Mul | // `{ 42 } *foo = bar;` or `{ 42 } * 3`
+                BinOpKind::Sub | // `{ 42 } -5`
+                BinOpKind::Add | // `{ 42 } + 42` (unary plus)
+                BinOpKind::And | // `{ 42 } &&x` (#61475) or `{ 42 } && if x { 1 } else { 0 }`
+                BinOpKind::Or | // `{ 42 } || 42` ("logical or" or closure)
+                BinOpKind::BitOr // `{ 42 } | 42` or `{ 42 } |x| 42`
+            ))) => {
                 // These cases are ambiguous and can't be identified in the parser alone.
                 //
                 // Bitwise AND is left out because guessing intent is hard. We can make
@@ -380,21 +358,20 @@ impl<'a> Parser<'a> {
             // When parsing const expressions, stop parsing when encountering `>`.
             (
                 Some(
-                    AssocOp::ShiftRight
-                    | AssocOp::Greater
-                    | AssocOp::GreaterEqual
+                    AssocOp::Binary(BinOpKind::Shr | BinOpKind::Gt | BinOpKind::Ge)
                     | AssocOp::AssignOp(BinOpKind::Shr),
                 ),
                 _,
             ) if self.restrictions.contains(Restrictions::CONST_EXPR) => {
                 return None;
             }
-            // When recovering patterns as expressions, stop parsing when encountering an assignment `=`, an alternative `|`, or a range `..`.
+            // When recovering patterns as expressions, stop parsing when encountering an
+            // assignment `=`, an alternative `|`, or a range `..`.
             (
                 Some(
                     AssocOp::Assign
                     | AssocOp::AssignOp(_)
-                    | AssocOp::BitOr
+                    | AssocOp::Binary(BinOpKind::BitOr)
                     | AssocOp::DotDot
                     | AssocOp::DotDotEq,
                 ),
@@ -411,7 +388,7 @@ impl<'a> Parser<'a> {
                     incorrect: "and".into(),
                     sub: errors::InvalidLogicalOperatorSub::Conjunction(self.token.span),
                 });
-                (AssocOp::LAnd, span)
+                (AssocOp::Binary(BinOpKind::And), span)
             }
             (None, Some((Ident { name: sym::or, span }, IdentIsRaw::No))) if self.may_recover() => {
                 self.dcx().emit_err(errors::InvalidLogicalOperator {
@@ -419,7 +396,7 @@ impl<'a> Parser<'a> {
                     incorrect: "or".into(),
                     sub: errors::InvalidLogicalOperatorSub::Disjunction(self.token.span),
                 });
-                (AssocOp::LOr, span)
+                (AssocOp::Binary(BinOpKind::Or), span)
             }
             _ => return None,
         };