Rollup merge of #136846 - nnethercote:make-AssocOp-more-like-ExprKind, r=spastorino
Make `AssocOp` more like `ExprKind` This is step 1 of [MCP 831](https://github.com/rust-lang/compiler-team/issues/831). r? ``@estebank``
This commit is contained in:
commit
4ecca4c09c
11 changed files with 205 additions and 374 deletions
|
@ -39,7 +39,7 @@ pub use crate::format::*;
|
||||||
use crate::ptr::P;
|
use crate::ptr::P;
|
||||||
use crate::token::{self, CommentKind, Delimiter};
|
use crate::token::{self, CommentKind, Delimiter};
|
||||||
use crate::tokenstream::{DelimSpan, LazyAttrTokenStream, TokenStream};
|
use crate::tokenstream::{DelimSpan, LazyAttrTokenStream, TokenStream};
|
||||||
use crate::util::parser::{AssocOp, ExprPrecedence};
|
use crate::util::parser::{ExprPrecedence, Fixity};
|
||||||
|
|
||||||
/// A "Label" is an identifier of some point in sources,
|
/// A "Label" is an identifier of some point in sources,
|
||||||
/// e.g. in the following code:
|
/// e.g. in the following code:
|
||||||
|
@ -937,8 +937,37 @@ impl BinOpKind {
|
||||||
matches!(self, BinOpKind::And | BinOpKind::Or)
|
matches!(self, BinOpKind::And | BinOpKind::Or)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn precedence(&self) -> ExprPrecedence {
|
||||||
|
use BinOpKind::*;
|
||||||
|
match *self {
|
||||||
|
Mul | Div | Rem => ExprPrecedence::Product,
|
||||||
|
Add | Sub => ExprPrecedence::Sum,
|
||||||
|
Shl | Shr => ExprPrecedence::Shift,
|
||||||
|
BitAnd => ExprPrecedence::BitAnd,
|
||||||
|
BitXor => ExprPrecedence::BitXor,
|
||||||
|
BitOr => ExprPrecedence::BitOr,
|
||||||
|
Lt | Gt | Le | Ge | Eq | Ne => ExprPrecedence::Compare,
|
||||||
|
And => ExprPrecedence::LAnd,
|
||||||
|
Or => ExprPrecedence::LOr,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn fixity(&self) -> Fixity {
|
||||||
|
use BinOpKind::*;
|
||||||
|
match self {
|
||||||
|
Eq | Ne | Lt | Le | Gt | Ge => Fixity::None,
|
||||||
|
Add | Sub | Mul | Div | Rem | And | Or | BitXor | BitAnd | BitOr | Shl | Shr => {
|
||||||
|
Fixity::Left
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn is_comparison(self) -> bool {
|
pub fn is_comparison(self) -> bool {
|
||||||
crate::util::parser::AssocOp::from_ast_binop(self).is_comparison()
|
use BinOpKind::*;
|
||||||
|
match self {
|
||||||
|
Eq | Ne | Lt | Le | Gt | Ge => true,
|
||||||
|
Add | Sub | Mul | Div | Rem | And | Or | BitXor | BitAnd | BitOr | Shl | Shr => false,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns `true` if the binary operator takes its arguments by value.
|
/// Returns `true` if the binary operator takes its arguments by value.
|
||||||
|
@ -1332,7 +1361,7 @@ impl Expr {
|
||||||
ExprKind::Range(..) => ExprPrecedence::Range,
|
ExprKind::Range(..) => ExprPrecedence::Range,
|
||||||
|
|
||||||
// Binop-like expr kinds, handled by `AssocOp`.
|
// Binop-like expr kinds, handled by `AssocOp`.
|
||||||
ExprKind::Binary(op, ..) => AssocOp::from_ast_binop(op.node).precedence(),
|
ExprKind::Binary(op, ..) => op.node.precedence(),
|
||||||
ExprKind::Cast(..) => ExprPrecedence::Cast,
|
ExprKind::Cast(..) => ExprPrecedence::Cast,
|
||||||
|
|
||||||
ExprKind::Assign(..) |
|
ExprKind::Assign(..) |
|
||||||
|
@ -1424,6 +1453,15 @@ pub enum RangeLimits {
|
||||||
Closed,
|
Closed,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl RangeLimits {
|
||||||
|
pub fn as_str(&self) -> &'static str {
|
||||||
|
match self {
|
||||||
|
RangeLimits::HalfOpen => "..",
|
||||||
|
RangeLimits::Closed => "..=",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// A method call (e.g. `x.foo::<Bar, Baz>(a, b, c)`).
|
/// A method call (e.g. `x.foo::<Bar, Baz>(a, b, c)`).
|
||||||
#[derive(Clone, Encodable, Decodable, Debug)]
|
#[derive(Clone, Encodable, Decodable, Debug)]
|
||||||
pub struct MethodCall {
|
pub struct MethodCall {
|
||||||
|
|
|
@ -1,59 +1,21 @@
|
||||||
use rustc_span::kw;
|
use rustc_span::kw;
|
||||||
|
|
||||||
use crate::ast::{self, BinOpKind};
|
use crate::ast::{self, BinOpKind, RangeLimits};
|
||||||
use crate::token::{self, BinOpToken, Token};
|
use crate::token::{self, BinOpToken, Token};
|
||||||
|
|
||||||
/// Associative operator with precedence.
|
/// Associative operator.
|
||||||
///
|
|
||||||
/// This is the enum which specifies operator precedence and fixity to the parser.
|
|
||||||
#[derive(Copy, Clone, PartialEq, Debug)]
|
#[derive(Copy, Clone, PartialEq, Debug)]
|
||||||
pub enum AssocOp {
|
pub enum AssocOp {
|
||||||
/// `+`
|
/// A binary op.
|
||||||
Add,
|
Binary(BinOpKind),
|
||||||
/// `-`
|
/// `?=` where ? is one of the assignable BinOps
|
||||||
Subtract,
|
AssignOp(BinOpKind),
|
||||||
/// `*`
|
|
||||||
Multiply,
|
|
||||||
/// `/`
|
|
||||||
Divide,
|
|
||||||
/// `%`
|
|
||||||
Modulus,
|
|
||||||
/// `&&`
|
|
||||||
LAnd,
|
|
||||||
/// `||`
|
|
||||||
LOr,
|
|
||||||
/// `^`
|
|
||||||
BitXor,
|
|
||||||
/// `&`
|
|
||||||
BitAnd,
|
|
||||||
/// `|`
|
|
||||||
BitOr,
|
|
||||||
/// `<<`
|
|
||||||
ShiftLeft,
|
|
||||||
/// `>>`
|
|
||||||
ShiftRight,
|
|
||||||
/// `==`
|
|
||||||
Equal,
|
|
||||||
/// `<`
|
|
||||||
Less,
|
|
||||||
/// `<=`
|
|
||||||
LessEqual,
|
|
||||||
/// `!=`
|
|
||||||
NotEqual,
|
|
||||||
/// `>`
|
|
||||||
Greater,
|
|
||||||
/// `>=`
|
|
||||||
GreaterEqual,
|
|
||||||
/// `=`
|
/// `=`
|
||||||
Assign,
|
Assign,
|
||||||
/// `?=` where ? is one of the BinOpToken
|
|
||||||
AssignOp(BinOpToken),
|
|
||||||
/// `as`
|
/// `as`
|
||||||
As,
|
Cast,
|
||||||
/// `..` range
|
/// `..` or `..=` range
|
||||||
DotDot,
|
Range(RangeLimits),
|
||||||
/// `..=` range
|
|
||||||
DotDotEq,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Debug)]
|
#[derive(PartialEq, Debug)]
|
||||||
|
@ -67,81 +29,56 @@ pub enum Fixity {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AssocOp {
|
impl AssocOp {
|
||||||
/// Creates a new AssocOP from a token
|
/// Creates a new AssocOp from a token.
|
||||||
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::BinOp(BinOpToken::Star) => Some(Multiply),
|
token::BinOp(BinOpToken::Plus) => Some(Binary(BinOpKind::Add)),
|
||||||
token::BinOp(BinOpToken::Slash) => Some(Divide),
|
token::BinOp(BinOpToken::Minus) => Some(Binary(BinOpKind::Sub)),
|
||||||
token::BinOp(BinOpToken::Percent) => Some(Modulus),
|
token::BinOp(BinOpToken::Star) => Some(Binary(BinOpKind::Mul)),
|
||||||
token::BinOp(BinOpToken::Plus) => Some(Add),
|
token::BinOp(BinOpToken::Slash) => Some(Binary(BinOpKind::Div)),
|
||||||
token::BinOp(BinOpToken::Minus) => Some(Subtract),
|
token::BinOp(BinOpToken::Percent) => Some(Binary(BinOpKind::Rem)),
|
||||||
token::BinOp(BinOpToken::Shl) => Some(ShiftLeft),
|
token::BinOp(BinOpToken::Caret) => Some(Binary(BinOpKind::BitXor)),
|
||||||
token::BinOp(BinOpToken::Shr) => Some(ShiftRight),
|
token::BinOp(BinOpToken::And) => Some(Binary(BinOpKind::BitAnd)),
|
||||||
token::BinOp(BinOpToken::And) => Some(BitAnd),
|
token::BinOp(BinOpToken::Or) => Some(Binary(BinOpKind::BitOr)),
|
||||||
token::BinOp(BinOpToken::Caret) => Some(BitXor),
|
token::BinOp(BinOpToken::Shl) => Some(Binary(BinOpKind::Shl)),
|
||||||
token::BinOp(BinOpToken::Or) => Some(BitOr),
|
token::BinOp(BinOpToken::Shr) => Some(Binary(BinOpKind::Shr)),
|
||||||
token::Lt => Some(Less),
|
token::BinOpEq(BinOpToken::Plus) => Some(AssignOp(BinOpKind::Add)),
|
||||||
token::Le => Some(LessEqual),
|
token::BinOpEq(BinOpToken::Minus) => Some(AssignOp(BinOpKind::Sub)),
|
||||||
token::Ge => Some(GreaterEqual),
|
token::BinOpEq(BinOpToken::Star) => Some(AssignOp(BinOpKind::Mul)),
|
||||||
token::Gt => Some(Greater),
|
token::BinOpEq(BinOpToken::Slash) => Some(AssignOp(BinOpKind::Div)),
|
||||||
token::EqEq => Some(Equal),
|
token::BinOpEq(BinOpToken::Percent) => Some(AssignOp(BinOpKind::Rem)),
|
||||||
token::Ne => Some(NotEqual),
|
token::BinOpEq(BinOpToken::Caret) => Some(AssignOp(BinOpKind::BitXor)),
|
||||||
token::AndAnd => Some(LAnd),
|
token::BinOpEq(BinOpToken::And) => Some(AssignOp(BinOpKind::BitAnd)),
|
||||||
token::OrOr => Some(LOr),
|
token::BinOpEq(BinOpToken::Or) => Some(AssignOp(BinOpKind::BitOr)),
|
||||||
token::DotDot => Some(DotDot),
|
token::BinOpEq(BinOpToken::Shl) => Some(AssignOp(BinOpKind::Shl)),
|
||||||
token::DotDotEq => Some(DotDotEq),
|
token::BinOpEq(BinOpToken::Shr) => Some(AssignOp(BinOpKind::Shr)),
|
||||||
|
token::Lt => Some(Binary(BinOpKind::Lt)),
|
||||||
|
token::Le => Some(Binary(BinOpKind::Le)),
|
||||||
|
token::Ge => Some(Binary(BinOpKind::Ge)),
|
||||||
|
token::Gt => Some(Binary(BinOpKind::Gt)),
|
||||||
|
token::EqEq => Some(Binary(BinOpKind::Eq)),
|
||||||
|
token::Ne => Some(Binary(BinOpKind::Ne)),
|
||||||
|
token::AndAnd => Some(Binary(BinOpKind::And)),
|
||||||
|
token::OrOr => Some(Binary(BinOpKind::Or)),
|
||||||
|
token::DotDot => Some(Range(RangeLimits::HalfOpen)),
|
||||||
// DotDotDot is no longer supported, but we need some way to display the error
|
// DotDotDot is no longer supported, but we need some way to display the error
|
||||||
token::DotDotDot => Some(DotDotEq),
|
token::DotDotEq | token::DotDotDot => Some(Range(RangeLimits::Closed)),
|
||||||
// `<-` should probably be `< -`
|
// `<-` should probably be `< -`
|
||||||
token::LArrow => Some(Less),
|
token::LArrow => Some(Binary(BinOpKind::Lt)),
|
||||||
_ if t.is_keyword(kw::As) => Some(As),
|
_ if t.is_keyword(kw::As) => Some(Cast),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a new AssocOp from ast::BinOpKind.
|
|
||||||
pub fn from_ast_binop(op: BinOpKind) -> Self {
|
|
||||||
use AssocOp::*;
|
|
||||||
match op {
|
|
||||||
BinOpKind::Lt => Less,
|
|
||||||
BinOpKind::Gt => Greater,
|
|
||||||
BinOpKind::Le => LessEqual,
|
|
||||||
BinOpKind::Ge => GreaterEqual,
|
|
||||||
BinOpKind::Eq => Equal,
|
|
||||||
BinOpKind::Ne => NotEqual,
|
|
||||||
BinOpKind::Mul => Multiply,
|
|
||||||
BinOpKind::Div => Divide,
|
|
||||||
BinOpKind::Rem => Modulus,
|
|
||||||
BinOpKind::Add => Add,
|
|
||||||
BinOpKind::Sub => Subtract,
|
|
||||||
BinOpKind::Shl => ShiftLeft,
|
|
||||||
BinOpKind::Shr => ShiftRight,
|
|
||||||
BinOpKind::BitAnd => BitAnd,
|
|
||||||
BinOpKind::BitXor => BitXor,
|
|
||||||
BinOpKind::BitOr => BitOr,
|
|
||||||
BinOpKind::And => LAnd,
|
|
||||||
BinOpKind::Or => LOr,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Gets the precedence of this operator
|
/// Gets the precedence of this operator
|
||||||
pub fn precedence(&self) -> ExprPrecedence {
|
pub fn precedence(&self) -> ExprPrecedence {
|
||||||
use AssocOp::*;
|
use AssocOp::*;
|
||||||
match *self {
|
match *self {
|
||||||
As => ExprPrecedence::Cast,
|
Cast => ExprPrecedence::Cast,
|
||||||
Multiply | Divide | Modulus => ExprPrecedence::Product,
|
Binary(bin_op) => bin_op.precedence(),
|
||||||
Add | Subtract => ExprPrecedence::Sum,
|
Range(_) => ExprPrecedence::Range,
|
||||||
ShiftLeft | ShiftRight => ExprPrecedence::Shift,
|
|
||||||
BitAnd => ExprPrecedence::BitAnd,
|
|
||||||
BitXor => ExprPrecedence::BitXor,
|
|
||||||
BitOr => ExprPrecedence::BitOr,
|
|
||||||
Less | Greater | LessEqual | GreaterEqual | Equal | NotEqual => ExprPrecedence::Compare,
|
|
||||||
LAnd => ExprPrecedence::LAnd,
|
|
||||||
LOr => ExprPrecedence::LOr,
|
|
||||||
DotDot | DotDotEq => ExprPrecedence::Range,
|
|
||||||
Assign | AssignOp(_) => ExprPrecedence::Assign,
|
Assign | AssignOp(_) => ExprPrecedence::Assign,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -152,22 +89,17 @@ impl AssocOp {
|
||||||
// NOTE: it is a bug to have an operators that has same precedence but different fixities!
|
// NOTE: it is a bug to have an operators that has same precedence but different fixities!
|
||||||
match *self {
|
match *self {
|
||||||
Assign | AssignOp(_) => Fixity::Right,
|
Assign | AssignOp(_) => Fixity::Right,
|
||||||
As | Multiply | Divide | Modulus | Add | Subtract | ShiftLeft | ShiftRight | BitAnd
|
Binary(binop) => binop.fixity(),
|
||||||
| BitXor | BitOr | LAnd | LOr => Fixity::Left,
|
Cast => Fixity::Left,
|
||||||
Less | Greater | LessEqual | GreaterEqual | Equal | NotEqual | DotDot | DotDotEq => {
|
Range(_) => Fixity::None,
|
||||||
Fixity::None
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_comparison(&self) -> bool {
|
pub fn is_comparison(&self) -> bool {
|
||||||
use AssocOp::*;
|
use AssocOp::*;
|
||||||
match *self {
|
match *self {
|
||||||
Less | Greater | LessEqual | GreaterEqual | Equal | NotEqual => true,
|
Binary(binop) => binop.is_comparison(),
|
||||||
Assign | AssignOp(_) | As | Multiply | Divide | Modulus | Add | Subtract
|
Assign | AssignOp(_) | Cast | Range(_) => false,
|
||||||
| ShiftLeft | ShiftRight | BitAnd | BitXor | BitOr | LAnd | LOr | DotDot | DotDotEq => {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -175,34 +107,7 @@ impl AssocOp {
|
||||||
use AssocOp::*;
|
use AssocOp::*;
|
||||||
match *self {
|
match *self {
|
||||||
Assign | AssignOp(_) => true,
|
Assign | AssignOp(_) => true,
|
||||||
Less | Greater | LessEqual | GreaterEqual | Equal | NotEqual | As | Multiply
|
Cast | Binary(_) | Range(_) => false,
|
||||||
| Divide | Modulus | Add | Subtract | ShiftLeft | ShiftRight | BitAnd | BitXor
|
|
||||||
| BitOr | LAnd | LOr | DotDot | DotDotEq => false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn to_ast_binop(&self) -> Option<BinOpKind> {
|
|
||||||
use AssocOp::*;
|
|
||||||
match *self {
|
|
||||||
Less => Some(BinOpKind::Lt),
|
|
||||||
Greater => Some(BinOpKind::Gt),
|
|
||||||
LessEqual => Some(BinOpKind::Le),
|
|
||||||
GreaterEqual => Some(BinOpKind::Ge),
|
|
||||||
Equal => Some(BinOpKind::Eq),
|
|
||||||
NotEqual => Some(BinOpKind::Ne),
|
|
||||||
Multiply => Some(BinOpKind::Mul),
|
|
||||||
Divide => Some(BinOpKind::Div),
|
|
||||||
Modulus => Some(BinOpKind::Rem),
|
|
||||||
Add => Some(BinOpKind::Add),
|
|
||||||
Subtract => Some(BinOpKind::Sub),
|
|
||||||
ShiftLeft => Some(BinOpKind::Shl),
|
|
||||||
ShiftRight => Some(BinOpKind::Shr),
|
|
||||||
BitAnd => Some(BinOpKind::BitAnd),
|
|
||||||
BitXor => Some(BinOpKind::BitXor),
|
|
||||||
BitOr => Some(BinOpKind::BitOr),
|
|
||||||
LAnd => Some(BinOpKind::And),
|
|
||||||
LOr => Some(BinOpKind::Or),
|
|
||||||
Assign | AssignOp(_) | As | DotDot | DotDotEq => None,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -212,20 +117,23 @@ impl AssocOp {
|
||||||
/// parentheses while having a high degree of confidence on the correctness of the suggestion.
|
/// parentheses while having a high degree of confidence on the correctness of the suggestion.
|
||||||
pub fn can_continue_expr_unambiguously(&self) -> bool {
|
pub fn can_continue_expr_unambiguously(&self) -> bool {
|
||||||
use AssocOp::*;
|
use AssocOp::*;
|
||||||
|
use BinOpKind::*;
|
||||||
matches!(
|
matches!(
|
||||||
self,
|
self,
|
||||||
BitXor | // `{ 42 } ^ 3`
|
|
||||||
Assign | // `{ 42 } = { 42 }`
|
Assign | // `{ 42 } = { 42 }`
|
||||||
Divide | // `{ 42 } / 42`
|
Binary(
|
||||||
Modulus | // `{ 42 } % 2`
|
BitXor | // `{ 42 } ^ 3`
|
||||||
ShiftRight | // `{ 42 } >> 2`
|
Div | // `{ 42 } / 42`
|
||||||
LessEqual | // `{ 42 } <= 3`
|
Rem | // `{ 42 } % 2`
|
||||||
Greater | // `{ 42 } > 3`
|
Shr | // `{ 42 } >> 2`
|
||||||
GreaterEqual | // `{ 42 } >= 3`
|
Le | // `{ 42 } <= 3`
|
||||||
|
Gt | // `{ 42 } > 3`
|
||||||
|
Ge // `{ 42 } >= 3`
|
||||||
|
) |
|
||||||
AssignOp(_) | // `{ 42 } +=`
|
AssignOp(_) | // `{ 42 } +=`
|
||||||
// Equal | // `{ 42 } == { 42 }` Accepting these here would regress incorrect
|
// Equal | // `{ 42 } == { 42 }` Accepting these here would regress incorrect
|
||||||
// NotEqual | // `{ 42 } != { 42 } struct literals parser recovery.
|
// NotEqual | // `{ 42 } != { 42 } struct literals parser recovery.
|
||||||
As // `{ 42 } as usize`
|
Cast // `{ 42 } as usize`
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@ use itertools::{Itertools, Position};
|
||||||
use rustc_ast::ptr::P;
|
use rustc_ast::ptr::P;
|
||||||
use rustc_ast::util::classify;
|
use rustc_ast::util::classify;
|
||||||
use rustc_ast::util::literal::escape_byte_str_symbol;
|
use rustc_ast::util::literal::escape_byte_str_symbol;
|
||||||
use rustc_ast::util::parser::{self, AssocOp, ExprPrecedence, Fixity};
|
use rustc_ast::util::parser::{self, ExprPrecedence, Fixity};
|
||||||
use rustc_ast::{
|
use rustc_ast::{
|
||||||
self as ast, BlockCheckMode, FormatAlignment, FormatArgPosition, FormatArgsPiece, FormatCount,
|
self as ast, BlockCheckMode, FormatAlignment, FormatArgPosition, FormatArgsPiece, FormatCount,
|
||||||
FormatDebugHex, FormatSign, FormatTrait, token,
|
FormatDebugHex, FormatSign, FormatTrait, token,
|
||||||
|
@ -279,12 +279,11 @@ impl<'a> State<'a> {
|
||||||
rhs: &ast::Expr,
|
rhs: &ast::Expr,
|
||||||
fixup: FixupContext,
|
fixup: FixupContext,
|
||||||
) {
|
) {
|
||||||
let assoc_op = AssocOp::from_ast_binop(op.node);
|
let binop_prec = op.node.precedence();
|
||||||
let binop_prec = assoc_op.precedence();
|
|
||||||
let left_prec = lhs.precedence();
|
let left_prec = lhs.precedence();
|
||||||
let right_prec = rhs.precedence();
|
let right_prec = rhs.precedence();
|
||||||
|
|
||||||
let (mut left_needs_paren, right_needs_paren) = match assoc_op.fixity() {
|
let (mut left_needs_paren, right_needs_paren) = match op.node.fixity() {
|
||||||
Fixity::Left => (left_prec < binop_prec, right_prec <= binop_prec),
|
Fixity::Left => (left_prec < binop_prec, right_prec <= binop_prec),
|
||||||
Fixity::Right => (left_prec <= binop_prec, right_prec < binop_prec),
|
Fixity::Right => (left_prec <= binop_prec, right_prec < binop_prec),
|
||||||
Fixity::None => (left_prec <= binop_prec, right_prec <= binop_prec),
|
Fixity::None => (left_prec <= binop_prec, right_prec <= binop_prec),
|
||||||
|
|
|
@ -4,7 +4,7 @@ use std::fmt;
|
||||||
use rustc_abi::ExternAbi;
|
use rustc_abi::ExternAbi;
|
||||||
use rustc_ast::attr::AttributeExt;
|
use rustc_ast::attr::AttributeExt;
|
||||||
use rustc_ast::token::CommentKind;
|
use rustc_ast::token::CommentKind;
|
||||||
use rustc_ast::util::parser::{AssocOp, ExprPrecedence};
|
use rustc_ast::util::parser::ExprPrecedence;
|
||||||
use rustc_ast::{
|
use rustc_ast::{
|
||||||
self as ast, FloatTy, InlineAsmOptions, InlineAsmTemplatePiece, IntTy, Label, LitIntType,
|
self as ast, FloatTy, InlineAsmOptions, InlineAsmTemplatePiece, IntTy, Label, LitIntType,
|
||||||
LitKind, TraitObjectSyntax, UintTy, UnsafeBinderCastKind,
|
LitKind, TraitObjectSyntax, UintTy, UnsafeBinderCastKind,
|
||||||
|
@ -2124,7 +2124,7 @@ impl Expr<'_> {
|
||||||
| ExprKind::Become(..) => ExprPrecedence::Jump,
|
| ExprKind::Become(..) => ExprPrecedence::Jump,
|
||||||
|
|
||||||
// Binop-like expr kinds, handled by `AssocOp`.
|
// Binop-like expr kinds, handled by `AssocOp`.
|
||||||
ExprKind::Binary(op, ..) => AssocOp::from_ast_binop(op.node).precedence(),
|
ExprKind::Binary(op, ..) => op.node.precedence(),
|
||||||
ExprKind::Cast(..) => ExprPrecedence::Cast,
|
ExprKind::Cast(..) => ExprPrecedence::Cast,
|
||||||
|
|
||||||
ExprKind::Assign(..) |
|
ExprKind::Assign(..) |
|
||||||
|
|
|
@ -10,7 +10,7 @@ use std::cell::Cell;
|
||||||
use std::vec;
|
use std::vec;
|
||||||
|
|
||||||
use rustc_abi::ExternAbi;
|
use rustc_abi::ExternAbi;
|
||||||
use rustc_ast::util::parser::{self, AssocOp, ExprPrecedence, Fixity};
|
use rustc_ast::util::parser::{self, ExprPrecedence, Fixity};
|
||||||
use rustc_ast::{AttrStyle, DUMMY_NODE_ID, DelimArgs};
|
use rustc_ast::{AttrStyle, DUMMY_NODE_ID, DelimArgs};
|
||||||
use rustc_ast_pretty::pp::Breaks::{Consistent, Inconsistent};
|
use rustc_ast_pretty::pp::Breaks::{Consistent, Inconsistent};
|
||||||
use rustc_ast_pretty::pp::{self, Breaks};
|
use rustc_ast_pretty::pp::{self, Breaks};
|
||||||
|
@ -1296,12 +1296,11 @@ impl<'a> State<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn print_expr_binary(&mut self, op: hir::BinOp, lhs: &hir::Expr<'_>, rhs: &hir::Expr<'_>) {
|
fn print_expr_binary(&mut self, op: hir::BinOp, lhs: &hir::Expr<'_>, rhs: &hir::Expr<'_>) {
|
||||||
let assoc_op = AssocOp::from_ast_binop(op.node);
|
let binop_prec = op.node.precedence();
|
||||||
let binop_prec = assoc_op.precedence();
|
|
||||||
let left_prec = lhs.precedence();
|
let left_prec = lhs.precedence();
|
||||||
let right_prec = rhs.precedence();
|
let right_prec = rhs.precedence();
|
||||||
|
|
||||||
let (mut left_needs_paren, right_needs_paren) = match assoc_op.fixity() {
|
let (mut left_needs_paren, right_needs_paren) = match op.node.fixity() {
|
||||||
Fixity::Left => (left_prec < binop_prec, right_prec <= binop_prec),
|
Fixity::Left => (left_prec < binop_prec, right_prec <= binop_prec),
|
||||||
Fixity::Right => (left_prec <= binop_prec, right_prec < binop_prec),
|
Fixity::Right => (left_prec <= binop_prec, right_prec < binop_prec),
|
||||||
Fixity::None => (left_prec <= binop_prec, right_prec <= binop_prec),
|
Fixity::None => (left_prec <= binop_prec, right_prec <= binop_prec),
|
||||||
|
|
|
@ -1516,10 +1516,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
|
||||||
ty::ExprKind::Binop(op) => {
|
ty::ExprKind::Binop(op) => {
|
||||||
let (_, _, c1, c2) = expr.binop_args();
|
let (_, _, c1, c2) = expr.binop_args();
|
||||||
|
|
||||||
let precedence = |binop: crate::mir::BinOp| {
|
let precedence = |binop: crate::mir::BinOp| binop.to_hir_binop().precedence();
|
||||||
use rustc_ast::util::parser::AssocOp;
|
|
||||||
AssocOp::from_ast_binop(binop.to_hir_binop()).precedence()
|
|
||||||
};
|
|
||||||
let op_precedence = precedence(op);
|
let op_precedence = precedence(op);
|
||||||
let formatted_op = op.to_hir_binop().as_str();
|
let formatted_op = op.to_hir_binop().as_str();
|
||||||
let (lhs_parenthesized, rhs_parenthesized) = match (c1.kind(), c2.kind()) {
|
let (lhs_parenthesized, rhs_parenthesized) = match (c1.kind(), c2.kind()) {
|
||||||
|
|
|
@ -1350,13 +1350,13 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
return match (op.node, &outer_op.node) {
|
return match (op.node, &outer_op.node) {
|
||||||
// `x == y == z`
|
// `x == y == z`
|
||||||
(BinOpKind::Eq, AssocOp::Equal) |
|
(BinOpKind::Eq, AssocOp::Binary(BinOpKind::Eq)) |
|
||||||
// `x < y < z` and friends.
|
// `x < y < z` and friends.
|
||||||
(BinOpKind::Lt, AssocOp::Less | AssocOp::LessEqual) |
|
(BinOpKind::Lt, AssocOp::Binary(BinOpKind::Lt | BinOpKind::Le)) |
|
||||||
(BinOpKind::Le, AssocOp::LessEqual | AssocOp::Less) |
|
(BinOpKind::Le, AssocOp::Binary(BinOpKind::Lt | BinOpKind::Le)) |
|
||||||
// `x > y > z` and friends.
|
// `x > y > z` and friends.
|
||||||
(BinOpKind::Gt, AssocOp::Greater | AssocOp::GreaterEqual) |
|
(BinOpKind::Gt, AssocOp::Binary(BinOpKind::Gt | BinOpKind::Ge)) |
|
||||||
(BinOpKind::Ge, AssocOp::GreaterEqual | AssocOp::Greater) => {
|
(BinOpKind::Ge, AssocOp::Binary(BinOpKind::Gt | BinOpKind::Ge)) => {
|
||||||
let expr_to_str = |e: &Expr| {
|
let expr_to_str = |e: &Expr| {
|
||||||
self.span_to_snippet(e.span)
|
self.span_to_snippet(e.span)
|
||||||
.unwrap_or_else(|_| pprust::expr_to_string(e))
|
.unwrap_or_else(|_| pprust::expr_to_string(e))
|
||||||
|
@ -1368,7 +1368,10 @@ impl<'a> Parser<'a> {
|
||||||
false // Keep the current parse behavior, where the AST is `(x < y) < z`.
|
false // Keep the current parse behavior, where the AST is `(x < y) < z`.
|
||||||
}
|
}
|
||||||
// `x == y < z`
|
// `x == y < z`
|
||||||
(BinOpKind::Eq, AssocOp::Less | AssocOp::LessEqual | AssocOp::Greater | AssocOp::GreaterEqual) => {
|
(
|
||||||
|
BinOpKind::Eq,
|
||||||
|
AssocOp::Binary(BinOpKind::Lt | BinOpKind::Le | BinOpKind::Gt | BinOpKind::Ge)
|
||||||
|
) => {
|
||||||
// Consume `z`/outer-op-rhs.
|
// Consume `z`/outer-op-rhs.
|
||||||
let snapshot = self.create_snapshot_for_diagnostic();
|
let snapshot = self.create_snapshot_for_diagnostic();
|
||||||
match self.parse_expr() {
|
match self.parse_expr() {
|
||||||
|
@ -1389,7 +1392,10 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// `x > y == z`
|
// `x > y == z`
|
||||||
(BinOpKind::Lt | BinOpKind::Le | BinOpKind::Gt | BinOpKind::Ge, AssocOp::Equal) => {
|
(
|
||||||
|
BinOpKind::Lt | BinOpKind::Le | BinOpKind::Gt | BinOpKind::Ge,
|
||||||
|
AssocOp::Binary(BinOpKind::Eq)
|
||||||
|
) => {
|
||||||
let snapshot = self.create_snapshot_for_diagnostic();
|
let snapshot = self.create_snapshot_for_diagnostic();
|
||||||
// At this point it is always valid to enclose the lhs in parentheses, no
|
// At this point it is always valid to enclose the lhs in parentheses, no
|
||||||
// further checks are necessary.
|
// further checks are necessary.
|
||||||
|
@ -1457,10 +1463,10 @@ impl<'a> Parser<'a> {
|
||||||
|
|
||||||
// Include `<` to provide this recommendation even in a case like
|
// Include `<` to provide this recommendation even in a case like
|
||||||
// `Foo<Bar<Baz<Qux, ()>>>`
|
// `Foo<Bar<Baz<Qux, ()>>>`
|
||||||
if op.node == BinOpKind::Lt && outer_op.node == AssocOp::Less
|
if op.node == BinOpKind::Lt && outer_op.node == AssocOp::Binary(BinOpKind::Lt)
|
||||||
|| outer_op.node == AssocOp::Greater
|
|| outer_op.node == AssocOp::Binary(BinOpKind::Gt)
|
||||||
{
|
{
|
||||||
if outer_op.node == AssocOp::Less {
|
if outer_op.node == AssocOp::Binary(BinOpKind::Lt) {
|
||||||
let snapshot = self.create_snapshot_for_diagnostic();
|
let snapshot = self.create_snapshot_for_diagnostic();
|
||||||
self.bump();
|
self.bump();
|
||||||
// So far we have parsed `foo<bar<`, consume the rest of the type args.
|
// So far we have parsed `foo<bar<`, consume the rest of the type args.
|
||||||
|
@ -2635,10 +2641,12 @@ impl<'a> Parser<'a> {
|
||||||
) -> PResult<'a, GenericArg> {
|
) -> PResult<'a, GenericArg> {
|
||||||
let is_op_or_dot = AssocOp::from_token(&self.token)
|
let is_op_or_dot = AssocOp::from_token(&self.token)
|
||||||
.and_then(|op| {
|
.and_then(|op| {
|
||||||
if let AssocOp::Greater
|
if let AssocOp::Binary(
|
||||||
| AssocOp::Less
|
BinOpKind::Gt
|
||||||
| AssocOp::ShiftRight
|
| BinOpKind::Lt
|
||||||
| AssocOp::GreaterEqual
|
| BinOpKind::Shr
|
||||||
|
| BinOpKind::Ge
|
||||||
|
)
|
||||||
// Don't recover from `foo::<bar = baz>`, because this could be an attempt to
|
// Don't recover from `foo::<bar = baz>`, because this could be an attempt to
|
||||||
// assign a value to a defaulted generic parameter.
|
// assign a value to a defaulted generic parameter.
|
||||||
| AssocOp::Assign
|
| AssocOp::Assign
|
||||||
|
|
|
@ -171,7 +171,7 @@ impl<'a> Parser<'a> {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// Check for deprecated `...` syntax
|
// Check for deprecated `...` syntax
|
||||||
if self.token == token::DotDotDot && op.node == AssocOp::DotDotEq {
|
if self.token == token::DotDotDot && op.node == AssocOp::Range(RangeLimits::Closed) {
|
||||||
self.err_dotdotdot_syntax(self.token.span);
|
self.err_dotdotdot_syntax(self.token.span);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -188,17 +188,12 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Look for JS' `===` and `!==` and recover
|
// 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.token == token::Eq
|
||||||
&& self.prev_token.span.hi() == self.token.span.lo()
|
&& self.prev_token.span.hi() == self.token.span.lo()
|
||||||
{
|
{
|
||||||
let sp = op.span.to(self.token.span);
|
let sp = op.span.to(self.token.span);
|
||||||
let sugg = match op.node {
|
let sugg = bop.as_str().into();
|
||||||
AssocOp::Equal => "==",
|
|
||||||
AssocOp::NotEqual => "!=",
|
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
|
||||||
.into();
|
|
||||||
let invalid = format!("{sugg}=");
|
let invalid = format!("{sugg}=");
|
||||||
self.dcx().emit_err(errors::InvalidComparisonOperator {
|
self.dcx().emit_err(errors::InvalidComparisonOperator {
|
||||||
span: sp,
|
span: sp,
|
||||||
|
@ -213,7 +208,7 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Look for PHP's `<>` and recover
|
// Look for PHP's `<>` and recover
|
||||||
if op.node == AssocOp::Less
|
if op.node == AssocOp::Binary(BinOpKind::Lt)
|
||||||
&& self.token == token::Gt
|
&& self.token == token::Gt
|
||||||
&& self.prev_token.span.hi() == self.token.span.lo()
|
&& self.prev_token.span.hi() == self.token.span.lo()
|
||||||
{
|
{
|
||||||
|
@ -231,7 +226,7 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Look for C++'s `<=>` and recover
|
// Look for C++'s `<=>` and recover
|
||||||
if op.node == AssocOp::LessEqual
|
if op.node == AssocOp::Binary(BinOpKind::Le)
|
||||||
&& self.token == token::Gt
|
&& self.token == token::Gt
|
||||||
&& self.prev_token.span.hi() == self.token.span.lo()
|
&& self.prev_token.span.hi() == self.token.span.lo()
|
||||||
{
|
{
|
||||||
|
@ -269,13 +264,13 @@ impl<'a> Parser<'a> {
|
||||||
|
|
||||||
let op = op.node;
|
let op = op.node;
|
||||||
// Special cases:
|
// Special cases:
|
||||||
if op == AssocOp::As {
|
if op == AssocOp::Cast {
|
||||||
lhs = self.parse_assoc_op_cast(lhs, lhs_span, ExprKind::Cast)?;
|
lhs = self.parse_assoc_op_cast(lhs, lhs_span, ExprKind::Cast)?;
|
||||||
continue;
|
continue;
|
||||||
} else if op == AssocOp::DotDot || op == AssocOp::DotDotEq {
|
} else if let AssocOp::Range(limits) = op {
|
||||||
// If we didn't have to handle `x..`/`x..=`, it would be pretty easy to
|
// If we didn't have to handle `x..`/`x..=`, it would be pretty easy to
|
||||||
// generalise it to the Fixity::None code.
|
// generalise it to the Fixity::None code.
|
||||||
lhs = self.parse_expr_range(prec, lhs, op, cur_op_span)?;
|
lhs = self.parse_expr_range(prec, lhs, limits, cur_op_span)?;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -290,46 +285,16 @@ impl<'a> Parser<'a> {
|
||||||
|
|
||||||
let span = self.mk_expr_sp(&lhs, lhs_span, rhs.span);
|
let span = self.mk_expr_sp(&lhs, lhs_span, rhs.span);
|
||||||
lhs = match op {
|
lhs = match op {
|
||||||
AssocOp::Add
|
AssocOp::Binary(ast_op) => {
|
||||||
| 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();
|
|
||||||
let binary = self.mk_binary(source_map::respan(cur_op_span, ast_op), lhs, rhs);
|
let binary = self.mk_binary(source_map::respan(cur_op_span, ast_op), lhs, rhs);
|
||||||
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)
|
||||||
}
|
}
|
||||||
AssocOp::As | AssocOp::DotDot | AssocOp::DotDotEq => {
|
AssocOp::Cast | AssocOp::Range(_) => {
|
||||||
self.dcx().span_bug(span, "AssocOp should have been handled by special case")
|
self.dcx().span_bug(span, "AssocOp should have been handled by special case")
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -347,13 +312,14 @@ impl<'a> Parser<'a> {
|
||||||
// An exhaustive check is done in the following block, but these are checked first
|
// 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
|
// 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.
|
// 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::Binary(
|
||||||
(true, Some(AssocOp::Subtract)) | // `{ 42 } -5`
|
BinOpKind::Mul | // `{ 42 } *foo = bar;` or `{ 42 } * 3`
|
||||||
(true, Some(AssocOp::Add)) | // `{ 42 } + 42` (unary plus)
|
BinOpKind::Sub | // `{ 42 } -5`
|
||||||
(true, Some(AssocOp::LAnd)) | // `{ 42 } &&x` (#61475) or `{ 42 } && if x { 1 } else { 0 }`
|
BinOpKind::Add | // `{ 42 } + 42` (unary plus)
|
||||||
(true, Some(AssocOp::LOr)) | // `{ 42 } || 42` ("logical or" or closure)
|
BinOpKind::And | // `{ 42 } &&x` (#61475) or `{ 42 } && if x { 1 } else { 0 }`
|
||||||
(true, Some(AssocOp::BitOr)) // `{ 42 } | 42` or `{ 42 } |x| 42`
|
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.
|
// 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
|
// Bitwise AND is left out because guessing intent is hard. We can make
|
||||||
|
@ -392,23 +358,21 @@ impl<'a> Parser<'a> {
|
||||||
// When parsing const expressions, stop parsing when encountering `>`.
|
// When parsing const expressions, stop parsing when encountering `>`.
|
||||||
(
|
(
|
||||||
Some(
|
Some(
|
||||||
AssocOp::ShiftRight
|
AssocOp::Binary(BinOpKind::Shr | BinOpKind::Gt | BinOpKind::Ge)
|
||||||
| AssocOp::Greater
|
| AssocOp::AssignOp(BinOpKind::Shr),
|
||||||
| AssocOp::GreaterEqual
|
|
||||||
| AssocOp::AssignOp(token::BinOpToken::Shr),
|
|
||||||
),
|
),
|
||||||
_,
|
_,
|
||||||
) if self.restrictions.contains(Restrictions::CONST_EXPR) => {
|
) if self.restrictions.contains(Restrictions::CONST_EXPR) => {
|
||||||
return None;
|
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(
|
Some(
|
||||||
AssocOp::Assign
|
AssocOp::Assign
|
||||||
| AssocOp::AssignOp(_)
|
| AssocOp::AssignOp(_)
|
||||||
| AssocOp::BitOr
|
| AssocOp::Binary(BinOpKind::BitOr)
|
||||||
| AssocOp::DotDot
|
| AssocOp::Range(_),
|
||||||
| AssocOp::DotDotEq,
|
|
||||||
),
|
),
|
||||||
_,
|
_,
|
||||||
) if self.restrictions.contains(Restrictions::IS_PAT) => {
|
) if self.restrictions.contains(Restrictions::IS_PAT) => {
|
||||||
|
@ -423,7 +387,7 @@ impl<'a> Parser<'a> {
|
||||||
incorrect: "and".into(),
|
incorrect: "and".into(),
|
||||||
sub: errors::InvalidLogicalOperatorSub::Conjunction(self.token.span),
|
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() => {
|
(None, Some((Ident { name: sym::or, span }, IdentIsRaw::No))) if self.may_recover() => {
|
||||||
self.dcx().emit_err(errors::InvalidLogicalOperator {
|
self.dcx().emit_err(errors::InvalidLogicalOperator {
|
||||||
|
@ -431,7 +395,7 @@ impl<'a> Parser<'a> {
|
||||||
incorrect: "or".into(),
|
incorrect: "or".into(),
|
||||||
sub: errors::InvalidLogicalOperatorSub::Disjunction(self.token.span),
|
sub: errors::InvalidLogicalOperatorSub::Disjunction(self.token.span),
|
||||||
});
|
});
|
||||||
(AssocOp::LOr, span)
|
(AssocOp::Binary(BinOpKind::Or), span)
|
||||||
}
|
}
|
||||||
_ => return None,
|
_ => return None,
|
||||||
};
|
};
|
||||||
|
@ -449,7 +413,7 @@ impl<'a> Parser<'a> {
|
||||||
&mut self,
|
&mut self,
|
||||||
prec: ExprPrecedence,
|
prec: ExprPrecedence,
|
||||||
lhs: P<Expr>,
|
lhs: P<Expr>,
|
||||||
op: AssocOp,
|
limits: RangeLimits,
|
||||||
cur_op_span: Span,
|
cur_op_span: Span,
|
||||||
) -> PResult<'a, P<Expr>> {
|
) -> PResult<'a, P<Expr>> {
|
||||||
let rhs = if self.is_at_start_of_range_notation_rhs() {
|
let rhs = if self.is_at_start_of_range_notation_rhs() {
|
||||||
|
@ -465,8 +429,6 @@ impl<'a> Parser<'a> {
|
||||||
};
|
};
|
||||||
let rhs_span = rhs.as_ref().map_or(cur_op_span, |x| x.span);
|
let rhs_span = rhs.as_ref().map_or(cur_op_span, |x| x.span);
|
||||||
let span = self.mk_expr_sp(&lhs, lhs.span, rhs_span);
|
let span = self.mk_expr_sp(&lhs, lhs.span, rhs_span);
|
||||||
let limits =
|
|
||||||
if op == AssocOp::DotDot { RangeLimits::HalfOpen } else { RangeLimits::Closed };
|
|
||||||
let range = self.mk_range(Some(lhs), rhs, limits);
|
let range = self.mk_range(Some(lhs), rhs, limits);
|
||||||
Ok(self.mk_expr(span, range))
|
Ok(self.mk_expr(span, range))
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,7 +50,7 @@ pub(crate) fn check<'tcx>(
|
||||||
// format the suggestion
|
// format the suggestion
|
||||||
let suggestion = format!(
|
let suggestion = format!(
|
||||||
"{}.abs()",
|
"{}.abs()",
|
||||||
sugg::make_assoc(AssocOp::Subtract, &sug_l, &sug_r).maybe_par()
|
sugg::make_assoc(AssocOp::Binary(BinOpKind::Sub), &sug_l, &sug_r).maybe_par()
|
||||||
);
|
);
|
||||||
// spans the lint
|
// spans the lint
|
||||||
span_lint_and_then(
|
span_lint_and_then(
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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};
|
||||||
|
@ -114,10 +113,7 @@ impl<'a> Sugg<'a> {
|
||||||
/// function variants of `Sugg`, since these use different snippet functions.
|
/// function variants of `Sugg`, since these use different snippet functions.
|
||||||
fn hir_from_snippet(expr: &hir::Expr<'_>, mut get_snippet: impl FnMut(Span) -> Cow<'a, str>) -> Self {
|
fn hir_from_snippet(expr: &hir::Expr<'_>, mut get_snippet: impl FnMut(Span) -> Cow<'a, str>) -> Self {
|
||||||
if let Some(range) = higher::Range::hir(expr) {
|
if let Some(range) = higher::Range::hir(expr) {
|
||||||
let op = match range.limits {
|
let op = AssocOp::Range(range.limits);
|
||||||
ast::RangeLimits::HalfOpen => AssocOp::DotDot,
|
|
||||||
ast::RangeLimits::Closed => AssocOp::DotDotEq,
|
|
||||||
};
|
|
||||||
let start = range.start.map_or("".into(), |expr| get_snippet(expr.span));
|
let start = range.start.map_or("".into(), |expr| get_snippet(expr.span));
|
||||||
let end = range.end.map_or("".into(), |expr| get_snippet(expr.span));
|
let end = range.end.map_or("".into(), |expr| get_snippet(expr.span));
|
||||||
|
|
||||||
|
@ -158,16 +154,16 @@ 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::Binary(op.node),
|
||||||
get_snippet(lhs.span),
|
get_snippet(lhs.span),
|
||||||
get_snippet(rhs.span),
|
get_snippet(rhs.span),
|
||||||
),
|
),
|
||||||
ExprKind::Cast(lhs, ty) |
|
ExprKind::Cast(lhs, ty) |
|
||||||
//FIXME(chenyukang), remove this after type ascription is removed from AST
|
//FIXME(chenyukang), remove this after type ascription is removed from AST
|
||||||
ExprKind::Type(lhs, ty) => Sugg::BinOp(AssocOp::As, get_snippet(lhs.span), get_snippet(ty.span)),
|
ExprKind::Type(lhs, ty) => Sugg::BinOp(AssocOp::Cast, get_snippet(lhs.span), get_snippet(ty.span)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -179,8 +175,6 @@ impl<'a> Sugg<'a> {
|
||||||
ctxt: SyntaxContext,
|
ctxt: SyntaxContext,
|
||||||
app: &mut Applicability,
|
app: &mut Applicability,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
use rustc_ast::ast::RangeLimits;
|
|
||||||
|
|
||||||
let mut snippet = |span: Span| snippet_with_context(cx, span, ctxt, default, app).0;
|
let mut snippet = |span: Span| snippet_with_context(cx, span, ctxt, default, app).0;
|
||||||
|
|
||||||
match expr.kind {
|
match expr.kind {
|
||||||
|
@ -229,13 +223,8 @@ impl<'a> Sugg<'a> {
|
||||||
| ast::ExprKind::Err(_)
|
| ast::ExprKind::Err(_)
|
||||||
| ast::ExprKind::Dummy
|
| ast::ExprKind::Dummy
|
||||||
| ast::ExprKind::UnsafeBinderCast(..) => Sugg::NonParen(snippet(expr.span)),
|
| ast::ExprKind::UnsafeBinderCast(..) => Sugg::NonParen(snippet(expr.span)),
|
||||||
ast::ExprKind::Range(ref lhs, ref rhs, RangeLimits::HalfOpen) => Sugg::BinOp(
|
ast::ExprKind::Range(ref lhs, ref rhs, limits) => Sugg::BinOp(
|
||||||
AssocOp::DotDot,
|
AssocOp::Range(limits),
|
||||||
lhs.as_ref().map_or("".into(), |lhs| snippet(lhs.span)),
|
|
||||||
rhs.as_ref().map_or("".into(), |rhs| snippet(rhs.span)),
|
|
||||||
),
|
|
||||||
ast::ExprKind::Range(ref lhs, ref rhs, RangeLimits::Closed) => Sugg::BinOp(
|
|
||||||
AssocOp::DotDotEq,
|
|
||||||
lhs.as_ref().map_or("".into(), |lhs| snippet(lhs.span)),
|
lhs.as_ref().map_or("".into(), |lhs| snippet(lhs.span)),
|
||||||
rhs.as_ref().map_or("".into(), |rhs| snippet(rhs.span)),
|
rhs.as_ref().map_or("".into(), |rhs| snippet(rhs.span)),
|
||||||
),
|
),
|
||||||
|
@ -245,19 +234,19 @@ 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),
|
||||||
),
|
),
|
||||||
ast::ExprKind::Binary(op, ref lhs, ref rhs) => Sugg::BinOp(
|
ast::ExprKind::Binary(op, ref lhs, ref rhs) => Sugg::BinOp(
|
||||||
AssocOp::from_ast_binop(op.node),
|
AssocOp::Binary(op.node),
|
||||||
snippet(lhs.span),
|
snippet(lhs.span),
|
||||||
snippet(rhs.span),
|
snippet(rhs.span),
|
||||||
),
|
),
|
||||||
ast::ExprKind::Cast(ref lhs, ref ty) |
|
ast::ExprKind::Cast(ref lhs, ref ty) |
|
||||||
//FIXME(chenyukang), remove this after type ascription is removed from AST
|
//FIXME(chenyukang), remove this after type ascription is removed from AST
|
||||||
ast::ExprKind::Type(ref lhs, ref ty) => Sugg::BinOp(
|
ast::ExprKind::Type(ref lhs, ref ty) => Sugg::BinOp(
|
||||||
AssocOp::As,
|
AssocOp::Cast,
|
||||||
snippet(lhs.span),
|
snippet(lhs.span),
|
||||||
snippet(ty.span),
|
snippet(ty.span),
|
||||||
),
|
),
|
||||||
|
@ -276,7 +265,7 @@ impl<'a> Sugg<'a> {
|
||||||
|
|
||||||
/// Convenience method to create the `<lhs> as <rhs>` suggestion.
|
/// Convenience method to create the `<lhs> as <rhs>` suggestion.
|
||||||
pub fn as_ty<R: Display>(self, rhs: R) -> Sugg<'static> {
|
pub fn as_ty<R: Display>(self, rhs: R) -> Sugg<'static> {
|
||||||
make_assoc(AssocOp::As, &self, &Sugg::NonParen(rhs.to_string().into()))
|
make_assoc(AssocOp::Cast, &self, &Sugg::NonParen(rhs.to_string().into()))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convenience method to create the `&<expr>` suggestion.
|
/// Convenience method to create the `&<expr>` suggestion.
|
||||||
|
@ -327,11 +316,8 @@ impl<'a> Sugg<'a> {
|
||||||
|
|
||||||
/// Convenience method to create the `<lhs>..<rhs>` or `<lhs>...<rhs>`
|
/// Convenience method to create the `<lhs>..<rhs>` or `<lhs>...<rhs>`
|
||||||
/// suggestion.
|
/// suggestion.
|
||||||
pub fn range(self, end: &Self, limit: ast::RangeLimits) -> Sugg<'static> {
|
pub fn range(self, end: &Self, limits: ast::RangeLimits) -> Sugg<'static> {
|
||||||
match limit {
|
make_assoc(AssocOp::Range(limits), &self, end)
|
||||||
ast::RangeLimits::HalfOpen => make_assoc(AssocOp::DotDot, &self, end),
|
|
||||||
ast::RangeLimits::Closed => make_assoc(AssocOp::DotDotEq, &self, end),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Adds parentheses to any expression that might need them. Suitable to the
|
/// Adds parentheses to any expression that might need them. Suitable to the
|
||||||
|
@ -367,33 +353,11 @@ impl<'a> Sugg<'a> {
|
||||||
/// Generates a string from the operator and both sides.
|
/// Generates a string from the operator and both sides.
|
||||||
fn binop_to_string(op: AssocOp, lhs: &str, rhs: &str) -> String {
|
fn binop_to_string(op: AssocOp, lhs: &str, rhs: &str) -> String {
|
||||||
match op {
|
match op {
|
||||||
AssocOp::Add
|
AssocOp::Binary(op) => format!("{lhs} {} {rhs}", op.as_str()),
|
||||||
| 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 => {
|
|
||||||
format!("{lhs} {} {rhs}", op.to_ast_binop().expect("Those are AST ops").as_str())
|
|
||||||
},
|
|
||||||
AssocOp::Assign => format!("{lhs} = {rhs}"),
|
AssocOp::Assign => format!("{lhs} = {rhs}"),
|
||||||
AssocOp::AssignOp(op) => {
|
AssocOp::AssignOp(op) => format!("{lhs} {}= {rhs}", op.as_str()),
|
||||||
format!("{lhs} {}= {rhs}", token_kind_to_string(&token::BinOp(op)))
|
AssocOp::Cast => format!("{lhs} as {rhs}"),
|
||||||
},
|
AssocOp::Range(limits) => format!("{lhs}{}{rhs}", limits.as_str()),
|
||||||
AssocOp::As => format!("{lhs} as {rhs}"),
|
|
||||||
AssocOp::DotDot => format!("{lhs}..{rhs}"),
|
|
||||||
AssocOp::DotDotEq => format!("{lhs}..={rhs}"),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -468,7 +432,7 @@ impl Neg for Sugg<'_> {
|
||||||
type Output = Sugg<'static>;
|
type Output = Sugg<'static>;
|
||||||
fn neg(self) -> Sugg<'static> {
|
fn neg(self) -> Sugg<'static> {
|
||||||
match &self {
|
match &self {
|
||||||
Self::BinOp(AssocOp::As, ..) => Sugg::MaybeParen(format!("-({self})").into()),
|
Self::BinOp(AssocOp::Cast, ..) => Sugg::MaybeParen(format!("-({self})").into()),
|
||||||
_ => make_unop("-", self),
|
_ => make_unop("-", self),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -477,16 +441,17 @@ impl Neg for Sugg<'_> {
|
||||||
impl<'a> Not for Sugg<'a> {
|
impl<'a> Not for Sugg<'a> {
|
||||||
type Output = Sugg<'a>;
|
type Output = Sugg<'a>;
|
||||||
fn not(self) -> Sugg<'a> {
|
fn not(self) -> Sugg<'a> {
|
||||||
use AssocOp::{Equal, Greater, GreaterEqual, Less, LessEqual, NotEqual};
|
use AssocOp::Binary;
|
||||||
|
use ast::BinOpKind::{Eq, Gt, Ge, Lt, Le, Ne};
|
||||||
|
|
||||||
if let Sugg::BinOp(op, lhs, rhs) = self {
|
if let Sugg::BinOp(op, lhs, rhs) = self {
|
||||||
let to_op = match op {
|
let to_op = match op {
|
||||||
Equal => NotEqual,
|
Binary(Eq) => Binary(Ne),
|
||||||
NotEqual => Equal,
|
Binary(Ne) => Binary(Eq),
|
||||||
Less => GreaterEqual,
|
Binary(Lt) => Binary(Ge),
|
||||||
GreaterEqual => Less,
|
Binary(Ge) => Binary(Lt),
|
||||||
Greater => LessEqual,
|
Binary(Gt) => Binary(Le),
|
||||||
LessEqual => Greater,
|
Binary(Le) => Binary(Gt),
|
||||||
_ => return make_unop("!", Sugg::BinOp(op, lhs, rhs)),
|
_ => return make_unop("!", Sugg::BinOp(op, lhs, rhs)),
|
||||||
};
|
};
|
||||||
Sugg::BinOp(to_op, lhs, rhs)
|
Sugg::BinOp(to_op, lhs, rhs)
|
||||||
|
@ -538,7 +503,7 @@ pub fn make_unop(op: &str, expr: Sugg<'_>) -> Sugg<'static> {
|
||||||
pub fn make_assoc(op: AssocOp, lhs: &Sugg<'_>, rhs: &Sugg<'_>) -> Sugg<'static> {
|
pub fn make_assoc(op: AssocOp, lhs: &Sugg<'_>, rhs: &Sugg<'_>) -> Sugg<'static> {
|
||||||
/// Returns `true` if the operator is a shift operator `<<` or `>>`.
|
/// Returns `true` if the operator is a shift operator `<<` or `>>`.
|
||||||
fn is_shift(op: AssocOp) -> bool {
|
fn is_shift(op: AssocOp) -> bool {
|
||||||
matches!(op, AssocOp::ShiftLeft | AssocOp::ShiftRight)
|
matches!(op, AssocOp::Binary(ast::BinOpKind::Shl | ast::BinOpKind::Shr))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns `true` if the operator is an arithmetic operator
|
/// Returns `true` if the operator is an arithmetic operator
|
||||||
|
@ -546,7 +511,13 @@ pub fn make_assoc(op: AssocOp, lhs: &Sugg<'_>, rhs: &Sugg<'_>) -> Sugg<'static>
|
||||||
fn is_arith(op: AssocOp) -> bool {
|
fn is_arith(op: AssocOp) -> bool {
|
||||||
matches!(
|
matches!(
|
||||||
op,
|
op,
|
||||||
AssocOp::Add | AssocOp::Subtract | AssocOp::Multiply | AssocOp::Divide | AssocOp::Modulus
|
AssocOp::Binary(
|
||||||
|
ast::BinOpKind::Add
|
||||||
|
| ast::BinOpKind::Sub
|
||||||
|
| ast::BinOpKind::Mul
|
||||||
|
| ast::BinOpKind::Div
|
||||||
|
| ast::BinOpKind::Rem
|
||||||
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -578,9 +549,9 @@ pub fn make_assoc(op: AssocOp, lhs: &Sugg<'_>, rhs: &Sugg<'_>) -> Sugg<'static>
|
||||||
Sugg::BinOp(op, lhs.into(), rhs.into())
|
Sugg::BinOp(op, lhs.into(), rhs.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convenience wrapper around `make_assoc` and `AssocOp::from_ast_binop`.
|
/// Convenience wrapper around `make_assoc` and `AssocOp::Binary`.
|
||||||
pub fn make_binop(op: ast::BinOpKind, lhs: &Sugg<'_>, rhs: &Sugg<'_>) -> Sugg<'static> {
|
pub fn make_binop(op: ast::BinOpKind, lhs: &Sugg<'_>, rhs: &Sugg<'_>) -> Sugg<'static> {
|
||||||
make_assoc(AssocOp::from_ast_binop(op), lhs, rhs)
|
make_assoc(AssocOp::Binary(op), lhs, rhs)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Eq, Clone, Copy)]
|
#[derive(PartialEq, Eq, Clone, Copy)]
|
||||||
|
@ -605,69 +576,19 @@ enum Associativity {
|
||||||
/// associative.
|
/// associative.
|
||||||
#[must_use]
|
#[must_use]
|
||||||
fn associativity(op: AssocOp) -> Associativity {
|
fn associativity(op: AssocOp) -> Associativity {
|
||||||
use rustc_ast::util::parser::AssocOp::{
|
use rustc_ast::util::parser::AssocOp::{Assign, AssignOp, Binary, Cast, Range};
|
||||||
Add, As, Assign, AssignOp, BitAnd, BitOr, BitXor, Divide, DotDot, DotDotEq, Equal, Greater, GreaterEqual, LAnd,
|
use ast::BinOpKind::{
|
||||||
LOr, Less, LessEqual, Modulus, Multiply, NotEqual, ShiftLeft, ShiftRight, Subtract,
|
Add, BitAnd, BitOr, BitXor, Div, Eq, Gt, Ge, And, Or, Lt, Le, Rem, Mul, Ne, Shl, Shr, Sub,
|
||||||
};
|
};
|
||||||
|
|
||||||
match op {
|
match op {
|
||||||
Assign | AssignOp(_) => Associativity::Right,
|
Assign | AssignOp(_) => Associativity::Right,
|
||||||
Add | BitAnd | BitOr | BitXor | LAnd | LOr | Multiply | As => Associativity::Both,
|
Binary(Add | BitAnd | BitOr | BitXor | And | Or | Mul) | Cast => Associativity::Both,
|
||||||
Divide | Equal | Greater | GreaterEqual | Less | LessEqual | Modulus | NotEqual | ShiftLeft | ShiftRight
|
Binary(Div | Eq | Gt | Ge | Lt | Le | Rem | Ne | Shl | Shr | Sub) => Associativity::Left,
|
||||||
| Subtract => Associativity::Left,
|
Range(_) => Associativity::None,
|
||||||
DotDot | DotDotEq => Associativity::None,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 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> {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue