Skip to content

Commit 49b43fe

Browse files
committed
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.
1 parent 57ef7aa commit 49b43fe

File tree

10 files changed

+153
-256
lines changed

10 files changed

+153
-256
lines changed

compiler/rustc_ast/src/ast.rs

+32-3
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ pub use crate::format::*;
3939
use crate::ptr::P;
4040
use crate::token::{self, CommentKind, Delimiter};
4141
use crate::tokenstream::{DelimSpan, LazyAttrTokenStream, TokenStream};
42-
use crate::util::parser::{AssocOp, ExprPrecedence};
42+
use crate::util::parser::{ExprPrecedence, Fixity};
4343

4444
/// A "Label" is an identifier of some point in sources,
4545
/// e.g. in the following code:
@@ -937,8 +937,37 @@ impl BinOpKind {
937937
matches!(self, BinOpKind::And | BinOpKind::Or)
938938
}
939939

940+
pub fn precedence(&self) -> ExprPrecedence {
941+
use BinOpKind::*;
942+
match *self {
943+
Mul | Div | Rem => ExprPrecedence::Product,
944+
Add | Sub => ExprPrecedence::Sum,
945+
Shl | Shr => ExprPrecedence::Shift,
946+
BitAnd => ExprPrecedence::BitAnd,
947+
BitXor => ExprPrecedence::BitXor,
948+
BitOr => ExprPrecedence::BitOr,
949+
Lt | Gt | Le | Ge | Eq | Ne => ExprPrecedence::Compare,
950+
And => ExprPrecedence::LAnd,
951+
Or => ExprPrecedence::LOr,
952+
}
953+
}
954+
955+
pub fn fixity(&self) -> Fixity {
956+
use BinOpKind::*;
957+
match self {
958+
Eq | Ne | Lt | Le | Gt | Ge => Fixity::None,
959+
Add | Sub | Mul | Div | Rem | And | Or | BitXor | BitAnd | BitOr | Shl | Shr => {
960+
Fixity::Left
961+
}
962+
}
963+
}
964+
940965
pub fn is_comparison(self) -> bool {
941-
crate::util::parser::AssocOp::from_ast_binop(self).is_comparison()
966+
use BinOpKind::*;
967+
match self {
968+
Eq | Ne | Lt | Le | Gt | Ge => true,
969+
Add | Sub | Mul | Div | Rem | And | Or | BitXor | BitAnd | BitOr | Shl | Shr => false,
970+
}
942971
}
943972

944973
/// Returns `true` if the binary operator takes its arguments by value.
@@ -1332,7 +1361,7 @@ impl Expr {
13321361
ExprKind::Range(..) => ExprPrecedence::Range,
13331362

13341363
// Binop-like expr kinds, handled by `AssocOp`.
1335-
ExprKind::Binary(op, ..) => AssocOp::from_ast_binop(op.node).precedence(),
1364+
ExprKind::Binary(op, ..) => op.node.precedence(),
13361365
ExprKind::Cast(..) => ExprPrecedence::Cast,
13371366

13381367
ExprKind::Assign(..) |

compiler/rustc_ast/src/util/parser.rs

+42-140
Original file line numberDiff line numberDiff line change
@@ -3,51 +3,15 @@ use rustc_span::kw;
33
use crate::ast::{self, BinOpKind};
44
use crate::token::{self, BinOpToken, Token};
55

6-
/// Associative operator with precedence.
7-
///
8-
/// This is the enum which specifies operator precedence and fixity to the parser.
6+
/// Associative operator.
97
#[derive(Copy, Clone, PartialEq, Debug)]
108
pub enum AssocOp {
11-
/// `+`
12-
Add,
13-
/// `-`
14-
Subtract,
15-
/// `*`
16-
Multiply,
17-
/// `/`
18-
Divide,
19-
/// `%`
20-
Modulus,
21-
/// `&&`
22-
LAnd,
23-
/// `||`
24-
LOr,
25-
/// `^`
26-
BitXor,
27-
/// `&`
28-
BitAnd,
29-
/// `|`
30-
BitOr,
31-
/// `<<`
32-
ShiftLeft,
33-
/// `>>`
34-
ShiftRight,
35-
/// `==`
36-
Equal,
37-
/// `<`
38-
Less,
39-
/// `<=`
40-
LessEqual,
41-
/// `!=`
42-
NotEqual,
43-
/// `>`
44-
Greater,
45-
/// `>=`
46-
GreaterEqual,
47-
/// `=`
48-
Assign,
9+
/// A binary op.
10+
Binary(BinOpKind),
4911
/// `?=` where ? is one of the assignable BinOps
5012
AssignOp(BinOpKind),
13+
/// `=`
14+
Assign,
5115
/// `as`
5216
As,
5317
/// `..` range
@@ -67,11 +31,21 @@ pub enum Fixity {
6731
}
6832

6933
impl AssocOp {
70-
/// Creates a new AssocOP from a token
34+
/// Creates a new AssocOp from a token.
7135
pub fn from_token(t: &Token) -> Option<AssocOp> {
7236
use AssocOp::*;
7337
match t.kind {
7438
token::Eq => Some(Assign),
39+
token::BinOp(BinOpToken::Plus) => Some(Binary(BinOpKind::Add)),
40+
token::BinOp(BinOpToken::Minus) => Some(Binary(BinOpKind::Sub)),
41+
token::BinOp(BinOpToken::Star) => Some(Binary(BinOpKind::Mul)),
42+
token::BinOp(BinOpToken::Slash) => Some(Binary(BinOpKind::Div)),
43+
token::BinOp(BinOpToken::Percent) => Some(Binary(BinOpKind::Rem)),
44+
token::BinOp(BinOpToken::Caret) => Some(Binary(BinOpKind::BitXor)),
45+
token::BinOp(BinOpToken::And) => Some(Binary(BinOpKind::BitAnd)),
46+
token::BinOp(BinOpToken::Or) => Some(Binary(BinOpKind::BitOr)),
47+
token::BinOp(BinOpToken::Shl) => Some(Binary(BinOpKind::Shl)),
48+
token::BinOp(BinOpToken::Shr) => Some(Binary(BinOpKind::Shr)),
7549
token::BinOpEq(BinOpToken::Plus) => Some(AssignOp(BinOpKind::Add)),
7650
token::BinOpEq(BinOpToken::Minus) => Some(AssignOp(BinOpKind::Sub)),
7751
token::BinOpEq(BinOpToken::Star) => Some(AssignOp(BinOpKind::Mul)),
@@ -82,74 +56,31 @@ impl AssocOp {
8256
token::BinOpEq(BinOpToken::Or) => Some(AssignOp(BinOpKind::BitOr)),
8357
token::BinOpEq(BinOpToken::Shl) => Some(AssignOp(BinOpKind::Shl)),
8458
token::BinOpEq(BinOpToken::Shr) => Some(AssignOp(BinOpKind::Shr)),
85-
token::BinOp(BinOpToken::Plus) => Some(Add),
86-
token::BinOp(BinOpToken::Minus) => Some(Subtract),
87-
token::BinOp(BinOpToken::Star) => Some(Multiply),
88-
token::BinOp(BinOpToken::Slash) => Some(Divide),
89-
token::BinOp(BinOpToken::Percent) => Some(Modulus),
90-
token::BinOp(BinOpToken::Caret) => Some(BitXor),
91-
token::BinOp(BinOpToken::And) => Some(BitAnd),
92-
token::BinOp(BinOpToken::Or) => Some(BitOr),
93-
token::BinOp(BinOpToken::Shl) => Some(ShiftLeft),
94-
token::BinOp(BinOpToken::Shr) => Some(ShiftRight),
95-
token::Lt => Some(Less),
96-
token::Le => Some(LessEqual),
97-
token::Ge => Some(GreaterEqual),
98-
token::Gt => Some(Greater),
99-
token::EqEq => Some(Equal),
100-
token::Ne => Some(NotEqual),
101-
token::AndAnd => Some(LAnd),
102-
token::OrOr => Some(LOr),
59+
token::Lt => Some(Binary(BinOpKind::Lt)),
60+
token::Le => Some(Binary(BinOpKind::Le)),
61+
token::Ge => Some(Binary(BinOpKind::Ge)),
62+
token::Gt => Some(Binary(BinOpKind::Gt)),
63+
token::EqEq => Some(Binary(BinOpKind::Eq)),
64+
token::Ne => Some(Binary(BinOpKind::Ne)),
65+
token::AndAnd => Some(Binary(BinOpKind::And)),
66+
token::OrOr => Some(Binary(BinOpKind::Or)),
10367
token::DotDot => Some(DotDot),
10468
token::DotDotEq => Some(DotDotEq),
10569
// DotDotDot is no longer supported, but we need some way to display the error
10670
token::DotDotDot => Some(DotDotEq),
10771
// `<-` should probably be `< -`
108-
token::LArrow => Some(Less),
72+
token::LArrow => Some(Binary(BinOpKind::Lt)),
10973
_ if t.is_keyword(kw::As) => Some(As),
11074
_ => None,
11175
}
11276
}
11377

114-
/// Creates a new AssocOp from ast::BinOpKind.
115-
pub fn from_ast_binop(op: BinOpKind) -> Self {
116-
use AssocOp::*;
117-
match op {
118-
BinOpKind::Lt => Less,
119-
BinOpKind::Gt => Greater,
120-
BinOpKind::Le => LessEqual,
121-
BinOpKind::Ge => GreaterEqual,
122-
BinOpKind::Eq => Equal,
123-
BinOpKind::Ne => NotEqual,
124-
BinOpKind::Mul => Multiply,
125-
BinOpKind::Div => Divide,
126-
BinOpKind::Rem => Modulus,
127-
BinOpKind::Add => Add,
128-
BinOpKind::Sub => Subtract,
129-
BinOpKind::Shl => ShiftLeft,
130-
BinOpKind::Shr => ShiftRight,
131-
BinOpKind::BitAnd => BitAnd,
132-
BinOpKind::BitXor => BitXor,
133-
BinOpKind::BitOr => BitOr,
134-
BinOpKind::And => LAnd,
135-
BinOpKind::Or => LOr,
136-
}
137-
}
138-
13978
/// Gets the precedence of this operator
14079
pub fn precedence(&self) -> ExprPrecedence {
14180
use AssocOp::*;
14281
match *self {
14382
As => ExprPrecedence::Cast,
144-
Multiply | Divide | Modulus => ExprPrecedence::Product,
145-
Add | Subtract => ExprPrecedence::Sum,
146-
ShiftLeft | ShiftRight => ExprPrecedence::Shift,
147-
BitAnd => ExprPrecedence::BitAnd,
148-
BitXor => ExprPrecedence::BitXor,
149-
BitOr => ExprPrecedence::BitOr,
150-
Less | Greater | LessEqual | GreaterEqual | Equal | NotEqual => ExprPrecedence::Compare,
151-
LAnd => ExprPrecedence::LAnd,
152-
LOr => ExprPrecedence::LOr,
83+
Binary(bin_op) => bin_op.precedence(),
15384
DotDot | DotDotEq => ExprPrecedence::Range,
15485
Assign | AssignOp(_) => ExprPrecedence::Assign,
15586
}
@@ -161,57 +92,25 @@ impl AssocOp {
16192
// NOTE: it is a bug to have an operators that has same precedence but different fixities!
16293
match *self {
16394
Assign | AssignOp(_) => Fixity::Right,
164-
As | Multiply | Divide | Modulus | Add | Subtract | ShiftLeft | ShiftRight | BitAnd
165-
| BitXor | BitOr | LAnd | LOr => Fixity::Left,
166-
Less | Greater | LessEqual | GreaterEqual | Equal | NotEqual | DotDot | DotDotEq => {
167-
Fixity::None
168-
}
95+
Binary(binop) => binop.fixity(),
96+
As => Fixity::Left,
97+
DotDot | DotDotEq => Fixity::None,
16998
}
17099
}
171100

172101
pub fn is_comparison(&self) -> bool {
173102
use AssocOp::*;
174103
match *self {
175-
Less | Greater | LessEqual | GreaterEqual | Equal | NotEqual => true,
176-
Assign | AssignOp(_) | As | Multiply | Divide | Modulus | Add | Subtract
177-
| ShiftLeft | ShiftRight | BitAnd | BitXor | BitOr | LAnd | LOr | DotDot | DotDotEq => {
178-
false
179-
}
104+
Binary(binop) => binop.is_comparison(),
105+
Assign | AssignOp(_) | As | DotDot | DotDotEq => false,
180106
}
181107
}
182108

183109
pub fn is_assign_like(&self) -> bool {
184110
use AssocOp::*;
185111
match *self {
186112
Assign | AssignOp(_) => true,
187-
Less | Greater | LessEqual | GreaterEqual | Equal | NotEqual | As | Multiply
188-
| Divide | Modulus | Add | Subtract | ShiftLeft | ShiftRight | BitAnd | BitXor
189-
| BitOr | LAnd | LOr | DotDot | DotDotEq => false,
190-
}
191-
}
192-
193-
pub fn to_ast_binop(&self) -> Option<BinOpKind> {
194-
use AssocOp::*;
195-
match *self {
196-
Less => Some(BinOpKind::Lt),
197-
Greater => Some(BinOpKind::Gt),
198-
LessEqual => Some(BinOpKind::Le),
199-
GreaterEqual => Some(BinOpKind::Ge),
200-
Equal => Some(BinOpKind::Eq),
201-
NotEqual => Some(BinOpKind::Ne),
202-
Multiply => Some(BinOpKind::Mul),
203-
Divide => Some(BinOpKind::Div),
204-
Modulus => Some(BinOpKind::Rem),
205-
Add => Some(BinOpKind::Add),
206-
Subtract => Some(BinOpKind::Sub),
207-
ShiftLeft => Some(BinOpKind::Shl),
208-
ShiftRight => Some(BinOpKind::Shr),
209-
BitAnd => Some(BinOpKind::BitAnd),
210-
BitXor => Some(BinOpKind::BitXor),
211-
BitOr => Some(BinOpKind::BitOr),
212-
LAnd => Some(BinOpKind::And),
213-
LOr => Some(BinOpKind::Or),
214-
Assign | AssignOp(_) | As | DotDot | DotDotEq => None,
113+
As | Binary(_) | DotDot | DotDotEq => false,
215114
}
216115
}
217116

@@ -221,16 +120,19 @@ impl AssocOp {
221120
/// parentheses while having a high degree of confidence on the correctness of the suggestion.
222121
pub fn can_continue_expr_unambiguously(&self) -> bool {
223122
use AssocOp::*;
123+
use BinOpKind::*;
224124
matches!(
225125
self,
226-
BitXor | // `{ 42 } ^ 3`
227126
Assign | // `{ 42 } = { 42 }`
228-
Divide | // `{ 42 } / 42`
229-
Modulus | // `{ 42 } % 2`
230-
ShiftRight | // `{ 42 } >> 2`
231-
LessEqual | // `{ 42 } <= 3`
232-
Greater | // `{ 42 } > 3`
233-
GreaterEqual | // `{ 42 } >= 3`
127+
Binary(
128+
BitXor | // `{ 42 } ^ 3`
129+
Div | // `{ 42 } / 42`
130+
Rem | // `{ 42 } % 2`
131+
Shr | // `{ 42 } >> 2`
132+
Le | // `{ 42 } <= 3`
133+
Gt | // `{ 42 } > 3`
134+
Ge // `{ 42 } >= 3`
135+
) |
234136
AssignOp(_) | // `{ 42 } +=`
235137
// Equal | // `{ 42 } == { 42 }` Accepting these here would regress incorrect
236138
// NotEqual | // `{ 42 } != { 42 } struct literals parser recovery.

compiler/rustc_ast_pretty/src/pprust/state/expr.rs

+3-4
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use itertools::{Itertools, Position};
55
use rustc_ast::ptr::P;
66
use rustc_ast::util::classify;
77
use rustc_ast::util::literal::escape_byte_str_symbol;
8-
use rustc_ast::util::parser::{self, AssocOp, ExprPrecedence, Fixity};
8+
use rustc_ast::util::parser::{self, ExprPrecedence, Fixity};
99
use rustc_ast::{
1010
self as ast, BlockCheckMode, FormatAlignment, FormatArgPosition, FormatArgsPiece, FormatCount,
1111
FormatDebugHex, FormatSign, FormatTrait, token,
@@ -279,12 +279,11 @@ impl<'a> State<'a> {
279279
rhs: &ast::Expr,
280280
fixup: FixupContext,
281281
) {
282-
let assoc_op = AssocOp::from_ast_binop(op.node);
283-
let binop_prec = assoc_op.precedence();
282+
let binop_prec = op.node.precedence();
284283
let left_prec = lhs.precedence();
285284
let right_prec = rhs.precedence();
286285

287-
let (mut left_needs_paren, right_needs_paren) = match assoc_op.fixity() {
286+
let (mut left_needs_paren, right_needs_paren) = match op.node.fixity() {
288287
Fixity::Left => (left_prec < binop_prec, right_prec <= binop_prec),
289288
Fixity::Right => (left_prec <= binop_prec, right_prec < binop_prec),
290289
Fixity::None => (left_prec <= binop_prec, right_prec <= binop_prec),

compiler/rustc_hir/src/hir.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use rustc_abi::ExternAbi;
44
// ignore-tidy-filelength
55
use rustc_ast::attr::AttributeExt;
66
use rustc_ast::token::CommentKind;
7-
use rustc_ast::util::parser::{AssocOp, ExprPrecedence};
7+
use rustc_ast::util::parser::ExprPrecedence;
88
use rustc_ast::{
99
self as ast, AttrId, AttrStyle, DelimArgs, FloatTy, InlineAsmOptions, InlineAsmTemplatePiece,
1010
IntTy, Label, LitIntType, LitKind, MetaItemInner, MetaItemLit, TraitObjectSyntax, UintTy,
@@ -2035,7 +2035,7 @@ impl Expr<'_> {
20352035
| ExprKind::Become(..) => ExprPrecedence::Jump,
20362036

20372037
// Binop-like expr kinds, handled by `AssocOp`.
2038-
ExprKind::Binary(op, ..) => AssocOp::from_ast_binop(op.node).precedence(),
2038+
ExprKind::Binary(op, ..) => op.node.precedence(),
20392039
ExprKind::Cast(..) => ExprPrecedence::Cast,
20402040

20412041
ExprKind::Assign(..) |

compiler/rustc_hir_pretty/src/lib.rs

+3-4
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use std::cell::Cell;
1010
use std::vec;
1111

1212
use rustc_abi::ExternAbi;
13-
use rustc_ast::util::parser::{self, AssocOp, ExprPrecedence, Fixity};
13+
use rustc_ast::util::parser::{self, ExprPrecedence, Fixity};
1414
use rustc_ast::{DUMMY_NODE_ID, DelimArgs};
1515
use rustc_ast_pretty::pp::Breaks::{Consistent, Inconsistent};
1616
use rustc_ast_pretty::pp::{self, Breaks};
@@ -1311,12 +1311,11 @@ impl<'a> State<'a> {
13111311
}
13121312

13131313
fn print_expr_binary(&mut self, op: hir::BinOp, lhs: &hir::Expr<'_>, rhs: &hir::Expr<'_>) {
1314-
let assoc_op = AssocOp::from_ast_binop(op.node);
1315-
let binop_prec = assoc_op.precedence();
1314+
let binop_prec = op.node.precedence();
13161315
let left_prec = lhs.precedence();
13171316
let right_prec = rhs.precedence();
13181317

1319-
let (mut left_needs_paren, right_needs_paren) = match assoc_op.fixity() {
1318+
let (mut left_needs_paren, right_needs_paren) = match op.node.fixity() {
13201319
Fixity::Left => (left_prec < binop_prec, right_prec <= binop_prec),
13211320
Fixity::Right => (left_prec <= binop_prec, right_prec < binop_prec),
13221321
Fixity::None => (left_prec <= binop_prec, right_prec <= binop_prec),

compiler/rustc_middle/src/ty/print/pretty.rs

+2-4
Original file line numberDiff line numberDiff line change
@@ -1512,10 +1512,8 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
15121512
ty::ExprKind::Binop(op) => {
15131513
let (_, _, c1, c2) = expr.binop_args();
15141514

1515-
let precedence = |binop: rustc_middle::mir::BinOp| {
1516-
use rustc_ast::util::parser::AssocOp;
1517-
AssocOp::from_ast_binop(binop.to_hir_binop()).precedence()
1518-
};
1515+
let precedence =
1516+
|binop: rustc_middle::mir::BinOp| binop.to_hir_binop().precedence();
15191517
let op_precedence = precedence(op);
15201518
let formatted_op = op.to_hir_binop().as_str();
15211519
let (lhs_parenthesized, rhs_parenthesized) = match (c1.kind(), c2.kind()) {

0 commit comments

Comments
 (0)