1
Fork 0

In AssocOp::AssignOp, use BinOpKind instead of BinOpToken

`AssocOp::AssignOp` contains a `BinOpToken`. `ExprKind::AssignOp`
contains a `BinOpKind`. Given that `AssocOp` is basically a cut-down
version of `ExprKind`, it makes sense to make `AssocOp` more like
`ExprKind`. Especially given that `AssocOp` and `BinOpKind` use semantic
operation names (e.g. `Mul`, `Div`), but `BinOpToken` uses syntactic
names (e.g. `Star`, `Slash`).

This results in more concise code, and removes the need for various
conversions. (Note that the removed functions `hirbinop2assignop` and
`astbinop2assignop` are semantically identical, because `hir::BinOp` is
just a synonum for `ast::BinOp`!)

The only downside to this is that it allows the possibility of some
nonsensical combinations, such as `AssocOp::AssignOp(BinOpKind::Lt)`.
But `ExprKind::AssignOp` already has that problem. The problem can be
fixed for both types in the future with some effort, by introducing an
`AssignOpKind` type.
This commit is contained in:
Nicholas Nethercote 2024-12-19 16:24:06 +11:00
parent ac91805f31
commit a8364f3b2a
4 changed files with 23 additions and 77 deletions

View file

@ -46,8 +46,8 @@ pub enum AssocOp {
GreaterEqual, GreaterEqual,
/// `=` /// `=`
Assign, Assign,
/// `?=` where ? is one of the BinOpToken /// `?=` where ? is one of the assignable BinOps
AssignOp(BinOpToken), AssignOp(BinOpKind),
/// `as` /// `as`
As, As,
/// `..` range /// `..` range
@ -71,18 +71,27 @@ impl AssocOp {
pub fn from_token(t: &Token) -> Option<AssocOp> { pub fn from_token(t: &Token) -> Option<AssocOp> {
use AssocOp::*; use AssocOp::*;
match t.kind { match t.kind {
token::BinOpEq(k) => Some(AssignOp(k)),
token::Eq => Some(Assign), token::Eq => Some(Assign),
token::BinOpEq(BinOpToken::Plus) => Some(AssignOp(BinOpKind::Add)),
token::BinOpEq(BinOpToken::Minus) => Some(AssignOp(BinOpKind::Sub)),
token::BinOpEq(BinOpToken::Star) => Some(AssignOp(BinOpKind::Mul)),
token::BinOpEq(BinOpToken::Slash) => Some(AssignOp(BinOpKind::Div)),
token::BinOpEq(BinOpToken::Percent) => Some(AssignOp(BinOpKind::Rem)),
token::BinOpEq(BinOpToken::Caret) => Some(AssignOp(BinOpKind::BitXor)),
token::BinOpEq(BinOpToken::And) => Some(AssignOp(BinOpKind::BitAnd)),
token::BinOpEq(BinOpToken::Or) => Some(AssignOp(BinOpKind::BitOr)),
token::BinOpEq(BinOpToken::Shl) => Some(AssignOp(BinOpKind::Shl)),
token::BinOpEq(BinOpToken::Shr) => Some(AssignOp(BinOpKind::Shr)),
token::BinOp(BinOpToken::Plus) => Some(Add),
token::BinOp(BinOpToken::Minus) => Some(Subtract),
token::BinOp(BinOpToken::Star) => Some(Multiply), token::BinOp(BinOpToken::Star) => Some(Multiply),
token::BinOp(BinOpToken::Slash) => Some(Divide), token::BinOp(BinOpToken::Slash) => Some(Divide),
token::BinOp(BinOpToken::Percent) => Some(Modulus), token::BinOp(BinOpToken::Percent) => Some(Modulus),
token::BinOp(BinOpToken::Plus) => Some(Add), token::BinOp(BinOpToken::Caret) => Some(BitXor),
token::BinOp(BinOpToken::Minus) => Some(Subtract), token::BinOp(BinOpToken::And) => Some(BitAnd),
token::BinOp(BinOpToken::Or) => Some(BitOr),
token::BinOp(BinOpToken::Shl) => Some(ShiftLeft), token::BinOp(BinOpToken::Shl) => Some(ShiftLeft),
token::BinOp(BinOpToken::Shr) => Some(ShiftRight), token::BinOp(BinOpToken::Shr) => Some(ShiftRight),
token::BinOp(BinOpToken::And) => Some(BitAnd),
token::BinOp(BinOpToken::Caret) => Some(BitXor),
token::BinOp(BinOpToken::Or) => Some(BitOr),
token::Lt => Some(Less), token::Lt => Some(Less),
token::Le => Some(LessEqual), token::Le => Some(LessEqual),
token::Ge => Some(GreaterEqual), token::Ge => Some(GreaterEqual),

View file

@ -313,19 +313,7 @@ impl<'a> Parser<'a> {
self.mk_expr(span, binary) self.mk_expr(span, binary)
} }
AssocOp::Assign => self.mk_expr(span, ExprKind::Assign(lhs, rhs, cur_op_span)), AssocOp::Assign => self.mk_expr(span, ExprKind::Assign(lhs, rhs, cur_op_span)),
AssocOp::AssignOp(k) => { AssocOp::AssignOp(aop) => {
let aop = match k {
token::Plus => BinOpKind::Add,
token::Minus => BinOpKind::Sub,
token::Star => BinOpKind::Mul,
token::Slash => BinOpKind::Div,
token::Percent => BinOpKind::Rem,
token::Caret => BinOpKind::BitXor,
token::And => BinOpKind::BitAnd,
token::Or => BinOpKind::BitOr,
token::Shl => BinOpKind::Shl,
token::Shr => BinOpKind::Shr,
};
let aopexpr = self.mk_assign_op(source_map::respan(cur_op_span, aop), lhs, rhs); let aopexpr = self.mk_assign_op(source_map::respan(cur_op_span, aop), lhs, rhs);
self.mk_expr(span, aopexpr) self.mk_expr(span, aopexpr)
} }
@ -395,7 +383,7 @@ impl<'a> Parser<'a> {
AssocOp::ShiftRight AssocOp::ShiftRight
| AssocOp::Greater | AssocOp::Greater
| AssocOp::GreaterEqual | AssocOp::GreaterEqual
| AssocOp::AssignOp(token::BinOpToken::Shr), | AssocOp::AssignOp(BinOpKind::Shr),
), ),
_, _,
) if self.restrictions.contains(Restrictions::CONST_EXPR) => { ) if self.restrictions.contains(Restrictions::CONST_EXPR) => {

View file

@ -31,7 +31,6 @@
// (Currently there is no way to opt into sysroot crates without `extern crate`.) // (Currently there is no way to opt into sysroot crates without `extern crate`.)
extern crate rustc_abi; extern crate rustc_abi;
extern crate rustc_ast; extern crate rustc_ast;
extern crate rustc_ast_pretty;
extern crate rustc_attr_parsing; extern crate rustc_attr_parsing;
extern crate rustc_const_eval; extern crate rustc_const_eval;
extern crate rustc_data_structures; extern crate rustc_data_structures;

View file

@ -5,8 +5,7 @@ use crate::source::{snippet, snippet_opt, snippet_with_applicability, snippet_wi
use crate::ty::expr_sig; use crate::ty::expr_sig;
use crate::{get_parent_expr_for_hir, higher}; use crate::{get_parent_expr_for_hir, higher};
use rustc_ast::util::parser::AssocOp; use rustc_ast::util::parser::AssocOp;
use rustc_ast::{ast, token}; use rustc_ast::ast;
use rustc_ast_pretty::pprust::token_kind_to_string;
use rustc_errors::Applicability; use rustc_errors::Applicability;
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::{Closure, ExprKind, HirId, MutTy, TyKind}; use rustc_hir::{Closure, ExprKind, HirId, MutTy, TyKind};
@ -158,7 +157,7 @@ impl<'a> Sugg<'a> {
Sugg::BinOp(AssocOp::Assign, get_snippet(lhs.span), get_snippet(rhs.span)) Sugg::BinOp(AssocOp::Assign, get_snippet(lhs.span), get_snippet(rhs.span))
}, },
ExprKind::AssignOp(op, lhs, rhs) => { ExprKind::AssignOp(op, lhs, rhs) => {
Sugg::BinOp(hirbinop2assignop(op), get_snippet(lhs.span), get_snippet(rhs.span)) Sugg::BinOp(AssocOp::AssignOp(op.node), get_snippet(lhs.span), get_snippet(rhs.span))
}, },
ExprKind::Binary(op, lhs, rhs) => Sugg::BinOp( ExprKind::Binary(op, lhs, rhs) => Sugg::BinOp(
AssocOp::from_ast_binop(op.node), AssocOp::from_ast_binop(op.node),
@ -245,7 +244,7 @@ impl<'a> Sugg<'a> {
snippet(rhs.span), snippet(rhs.span),
), ),
ast::ExprKind::AssignOp(op, ref lhs, ref rhs) => Sugg::BinOp( ast::ExprKind::AssignOp(op, ref lhs, ref rhs) => Sugg::BinOp(
astbinop2assignop(op), AssocOp::AssignOp(op.node),
snippet(lhs.span), snippet(lhs.span),
snippet(rhs.span), snippet(rhs.span),
), ),
@ -389,7 +388,7 @@ fn binop_to_string(op: AssocOp, lhs: &str, rhs: &str) -> String {
}, },
AssocOp::Assign => format!("{lhs} = {rhs}"), AssocOp::Assign => format!("{lhs} = {rhs}"),
AssocOp::AssignOp(op) => { AssocOp::AssignOp(op) => {
format!("{lhs} {}= {rhs}", token_kind_to_string(&token::BinOp(op))) format!("{lhs} {}= {rhs}", op.as_str())
}, },
AssocOp::As => format!("{lhs} as {rhs}"), AssocOp::As => format!("{lhs} as {rhs}"),
AssocOp::DotDot => format!("{lhs}..{rhs}"), AssocOp::DotDot => format!("{lhs}..{rhs}"),
@ -619,55 +618,6 @@ fn associativity(op: AssocOp) -> Associativity {
} }
} }
/// Converts a `hir::BinOp` to the corresponding assigning binary operator.
fn hirbinop2assignop(op: hir::BinOp) -> AssocOp {
use rustc_ast::token::BinOpToken::{And, Caret, Minus, Or, Percent, Plus, Shl, Shr, Slash, Star};
AssocOp::AssignOp(match op.node {
hir::BinOpKind::Add => Plus,
hir::BinOpKind::BitAnd => And,
hir::BinOpKind::BitOr => Or,
hir::BinOpKind::BitXor => Caret,
hir::BinOpKind::Div => Slash,
hir::BinOpKind::Mul => Star,
hir::BinOpKind::Rem => Percent,
hir::BinOpKind::Shl => Shl,
hir::BinOpKind::Shr => Shr,
hir::BinOpKind::Sub => Minus,
hir::BinOpKind::And
| hir::BinOpKind::Eq
| hir::BinOpKind::Ge
| hir::BinOpKind::Gt
| hir::BinOpKind::Le
| hir::BinOpKind::Lt
| hir::BinOpKind::Ne
| hir::BinOpKind::Or => panic!("This operator does not exist"),
})
}
/// Converts an `ast::BinOp` to the corresponding assigning binary operator.
fn astbinop2assignop(op: ast::BinOp) -> AssocOp {
use rustc_ast::ast::BinOpKind::{
Add, And, BitAnd, BitOr, BitXor, Div, Eq, Ge, Gt, Le, Lt, Mul, Ne, Or, Rem, Shl, Shr, Sub,
};
use rustc_ast::token::BinOpToken;
AssocOp::AssignOp(match op.node {
Add => BinOpToken::Plus,
BitAnd => BinOpToken::And,
BitOr => BinOpToken::Or,
BitXor => BinOpToken::Caret,
Div => BinOpToken::Slash,
Mul => BinOpToken::Star,
Rem => BinOpToken::Percent,
Shl => BinOpToken::Shl,
Shr => BinOpToken::Shr,
Sub => BinOpToken::Minus,
And | Eq | Ge | Gt | Le | Lt | Ne | Or => panic!("This operator does not exist"),
})
}
/// Returns the indentation before `span` if there are nothing but `[ \t]` /// Returns the indentation before `span` if there are nothing but `[ \t]`
/// before it on its line. /// before it on its line.
fn indentation<T: LintContext>(cx: &T, span: Span) -> Option<String> { fn indentation<T: LintContext>(cx: &T, span: Span) -> Option<String> {