Skip to content

Commit ee83773

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`. 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 74180ab commit ee83773

File tree

10 files changed

+146
-254
lines changed

10 files changed

+146
-254
lines changed

compiler/rustc_ast/src/ast.rs

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ pub use crate::format::*;
3838
use crate::ptr::P;
3939
use crate::token::{self, CommentKind, Delimiter};
4040
use crate::tokenstream::{DelimSpan, LazyAttrTokenStream, TokenStream};
41-
use crate::util::parser::{AssocOp, ExprPrecedence};
41+
use crate::util::parser::{ExprPrecedence, Fixity};
4242

4343
/// A "Label" is an identifier of some point in sources,
4444
/// e.g. in the following code:
@@ -948,8 +948,32 @@ impl BinOpKind {
948948
matches!(self, BinOpKind::And | BinOpKind::Or)
949949
}
950950

951+
pub fn precedence(&self) -> ExprPrecedence {
952+
use BinOpKind::*;
953+
match *self {
954+
Mul | Div | Rem => ExprPrecedence::Product,
955+
Add | Sub => ExprPrecedence::Sum,
956+
Shl | Shr => ExprPrecedence::Shift,
957+
BitAnd => ExprPrecedence::BitAnd,
958+
BitXor => ExprPrecedence::BitXor,
959+
BitOr => ExprPrecedence::BitOr,
960+
Lt | Gt | Le | Ge | Eq | Ne => ExprPrecedence::Compare,
961+
And => ExprPrecedence::LAnd,
962+
Or => ExprPrecedence::LOr,
963+
}
964+
}
965+
966+
pub fn fixity(&self) -> Fixity {
967+
// All binary operators have the same fixity.
968+
Fixity::Left
969+
}
970+
951971
pub fn is_comparison(self) -> bool {
952-
crate::util::parser::AssocOp::from_ast_binop(self).is_comparison()
972+
use BinOpKind::*;
973+
match self {
974+
Eq | Ne | Lt | Le | Gt | Ge => true,
975+
Add | Sub | Mul | Div | Rem | And | Or | BitXor | BitAnd | BitOr | Shl | Shr => false,
976+
}
953977
}
954978

955979
/// Returns `true` if the binary operator takes its arguments by value.
@@ -1339,7 +1363,7 @@ impl Expr {
13391363
ExprKind::Range(..) => ExprPrecedence::Range,
13401364

13411365
// Binop-like expr kinds, handled by `AssocOp`.
1342-
ExprKind::Binary(op, ..) => AssocOp::from_ast_binop(op.node).precedence(),
1366+
ExprKind::Binary(op, ..) => op.node.precedence(),
13431367
ExprKind::Cast(..) => ExprPrecedence::Cast,
13441368

13451369
ExprKind::Assign(..) |

compiler/rustc_ast/src/util/parser.rs

Lines changed: 40 additions & 138 deletions
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,56 +92,24 @@ 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 | Less | Greater | LessEqual | GreaterEqual | Equal | NotEqual
166-
| LAnd | LOr => Fixity::Left,
95+
As | Binary(_) => Fixity::Left,
16796
DotDot | DotDotEq => Fixity::None,
16897
}
16998
}
17099

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

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

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

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

Lines changed: 3 additions & 4 deletions
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,
@@ -275,12 +275,11 @@ impl<'a> State<'a> {
275275
rhs: &ast::Expr,
276276
fixup: FixupContext,
277277
) {
278-
let assoc_op = AssocOp::from_ast_binop(op.node);
279-
let binop_prec = assoc_op.precedence();
278+
let binop_prec = op.node.precedence();
280279
let left_prec = lhs.precedence();
281280
let right_prec = rhs.precedence();
282281

283-
let (mut left_needs_paren, right_needs_paren) = match assoc_op.fixity() {
282+
let (mut left_needs_paren, right_needs_paren) = match op.node.fixity() {
284283
Fixity::Left => (left_prec < binop_prec, right_prec <= binop_prec),
285284
Fixity::Right => (left_prec <= binop_prec, right_prec < binop_prec),
286285
Fixity::None => (left_prec <= binop_prec, right_prec <= binop_prec),

compiler/rustc_hir/src/hir.rs

Lines changed: 2 additions & 2 deletions
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, LitKind, MetaItemInner, MetaItemLit, TraitObjectSyntax, UintTy,
@@ -1953,7 +1953,7 @@ impl Expr<'_> {
19531953
| ExprKind::Become(..) => ExprPrecedence::Jump,
19541954

19551955
// Binop-like expr kinds, handled by `AssocOp`.
1956-
ExprKind::Binary(op, ..) => AssocOp::from_ast_binop(op.node).precedence(),
1956+
ExprKind::Binary(op, ..) => op.node.precedence(),
19571957
ExprKind::Cast(..) => ExprPrecedence::Cast,
19581958

19591959
ExprKind::Assign(..) |

compiler/rustc_hir_pretty/src/lib.rs

Lines changed: 3 additions & 4 deletions
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};
@@ -1287,12 +1287,11 @@ impl<'a> State<'a> {
12871287
}
12881288

12891289
fn print_expr_binary(&mut self, op: hir::BinOp, lhs: &hir::Expr<'_>, rhs: &hir::Expr<'_>) {
1290-
let assoc_op = AssocOp::from_ast_binop(op.node);
1291-
let binop_prec = assoc_op.precedence();
1290+
let binop_prec = op.node.precedence();
12921291
let left_prec = lhs.precedence();
12931292
let right_prec = rhs.precedence();
12941293

1295-
let (mut left_needs_paren, right_needs_paren) = match assoc_op.fixity() {
1294+
let (mut left_needs_paren, right_needs_paren) = match op.node.fixity() {
12961295
Fixity::Left => (left_prec < binop_prec, right_prec <= binop_prec),
12971296
Fixity::Right => (left_prec <= binop_prec, right_prec < binop_prec),
12981297
Fixity::None => (left_prec <= binop_prec, right_prec <= binop_prec),

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

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1493,10 +1493,8 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
14931493
ty::ExprKind::Binop(op) => {
14941494
let (_, _, c1, c2) = expr.binop_args();
14951495

1496-
let precedence = |binop: rustc_middle::mir::BinOp| {
1497-
use rustc_ast::util::parser::AssocOp;
1498-
AssocOp::from_ast_binop(binop.to_hir_binop()).precedence()
1499-
};
1496+
let precedence =
1497+
|binop: rustc_middle::mir::BinOp| binop.to_hir_binop().precedence();
15001498
let op_precedence = precedence(op);
15011499
let formatted_op = op.to_hir_binop().as_str();
15021500
let (lhs_parenthesized, rhs_parenthesized) = match (c1.kind(), c2.kind()) {

0 commit comments

Comments
 (0)