Eliminate magic numbers from expression precedence
This commit is contained in:
parent
539c863eaf
commit
7ced18f329
18 changed files with 162 additions and 138 deletions
|
@ -39,9 +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::{
|
use crate::util::parser::{AssocOp, ExprPrecedence};
|
||||||
AssocOp, PREC_CLOSURE, PREC_JUMP, PREC_PREFIX, PREC_RANGE, PREC_UNAMBIGUOUS,
|
|
||||||
};
|
|
||||||
|
|
||||||
/// 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:
|
||||||
|
@ -1317,29 +1315,29 @@ impl Expr {
|
||||||
Some(P(Ty { kind, id: self.id, span: self.span, tokens: None }))
|
Some(P(Ty { kind, id: self.id, span: self.span, tokens: None }))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn precedence(&self) -> i8 {
|
pub fn precedence(&self) -> ExprPrecedence {
|
||||||
match self.kind {
|
match self.kind {
|
||||||
ExprKind::Closure(..) => PREC_CLOSURE,
|
ExprKind::Closure(..) => ExprPrecedence::Closure,
|
||||||
|
|
||||||
ExprKind::Break(..)
|
ExprKind::Break(..)
|
||||||
| ExprKind::Continue(..)
|
| ExprKind::Continue(..)
|
||||||
| ExprKind::Ret(..)
|
| ExprKind::Ret(..)
|
||||||
| ExprKind::Yield(..)
|
| ExprKind::Yield(..)
|
||||||
| ExprKind::Yeet(..)
|
| ExprKind::Yeet(..)
|
||||||
| ExprKind::Become(..) => PREC_JUMP,
|
| ExprKind::Become(..) => ExprPrecedence::Jump,
|
||||||
|
|
||||||
// `Range` claims to have higher precedence than `Assign`, but `x .. x = x` fails to
|
// `Range` claims to have higher precedence than `Assign`, but `x .. x = x` fails to
|
||||||
// parse, instead of parsing as `(x .. x) = x`. Giving `Range` a lower precedence
|
// parse, instead of parsing as `(x .. x) = x`. Giving `Range` a lower precedence
|
||||||
// ensures that `pprust` will add parentheses in the right places to get the desired
|
// ensures that `pprust` will add parentheses in the right places to get the desired
|
||||||
// parse.
|
// parse.
|
||||||
ExprKind::Range(..) => PREC_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() as i8,
|
ExprKind::Binary(op, ..) => AssocOp::from_ast_binop(op.node).precedence(),
|
||||||
ExprKind::Cast(..) => AssocOp::As.precedence() as i8,
|
ExprKind::Cast(..) => ExprPrecedence::Cast,
|
||||||
|
|
||||||
ExprKind::Assign(..) |
|
ExprKind::Assign(..) |
|
||||||
ExprKind::AssignOp(..) => AssocOp::Assign.precedence() as i8,
|
ExprKind::AssignOp(..) => ExprPrecedence::Assign,
|
||||||
|
|
||||||
// Unary, prefix
|
// Unary, prefix
|
||||||
ExprKind::AddrOf(..)
|
ExprKind::AddrOf(..)
|
||||||
|
@ -1348,7 +1346,7 @@ impl Expr {
|
||||||
// need parens sometimes. E.g. we can print `(let _ = a) && b` as `let _ = a && b`
|
// need parens sometimes. E.g. we can print `(let _ = a) && b` as `let _ = a && b`
|
||||||
// but we need to print `(let _ = a) < b` as-is with parens.
|
// but we need to print `(let _ = a) < b` as-is with parens.
|
||||||
| ExprKind::Let(..)
|
| ExprKind::Let(..)
|
||||||
| ExprKind::Unary(..) => PREC_PREFIX,
|
| ExprKind::Unary(..) => ExprPrecedence::Prefix,
|
||||||
|
|
||||||
// Never need parens
|
// Never need parens
|
||||||
ExprKind::Array(_)
|
ExprKind::Array(_)
|
||||||
|
@ -1381,7 +1379,7 @@ impl Expr {
|
||||||
| ExprKind::Underscore
|
| ExprKind::Underscore
|
||||||
| ExprKind::While(..)
|
| ExprKind::While(..)
|
||||||
| ExprKind::Err(_)
|
| ExprKind::Err(_)
|
||||||
| ExprKind::Dummy => PREC_UNAMBIGUOUS,
|
| ExprKind::Dummy => ExprPrecedence::Unambiguous,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -128,21 +128,21 @@ impl AssocOp {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets the precedence of this operator
|
/// Gets the precedence of this operator
|
||||||
pub fn precedence(&self) -> usize {
|
pub fn precedence(&self) -> ExprPrecedence {
|
||||||
use AssocOp::*;
|
use AssocOp::*;
|
||||||
match *self {
|
match *self {
|
||||||
As => 14,
|
As => ExprPrecedence::Cast,
|
||||||
Multiply | Divide | Modulus => 13,
|
Multiply | Divide | Modulus => ExprPrecedence::Product,
|
||||||
Add | Subtract => 12,
|
Add | Subtract => ExprPrecedence::Sum,
|
||||||
ShiftLeft | ShiftRight => 11,
|
ShiftLeft | ShiftRight => ExprPrecedence::Shift,
|
||||||
BitAnd => 10,
|
BitAnd => ExprPrecedence::BitAnd,
|
||||||
BitXor => 9,
|
BitXor => ExprPrecedence::BitXor,
|
||||||
BitOr => 8,
|
BitOr => ExprPrecedence::BitOr,
|
||||||
Less | Greater | LessEqual | GreaterEqual | Equal | NotEqual => 7,
|
Less | Greater | LessEqual | GreaterEqual | Equal | NotEqual => ExprPrecedence::Compare,
|
||||||
LAnd => 6,
|
LAnd => ExprPrecedence::LAnd,
|
||||||
LOr => 5,
|
LOr => ExprPrecedence::LOr,
|
||||||
DotDot | DotDotEq => 4,
|
DotDot | DotDotEq => ExprPrecedence::Range,
|
||||||
Assign | AssignOp(_) => 2,
|
Assign | AssignOp(_) => ExprPrecedence::Assign,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -229,16 +229,44 @@ impl AssocOp {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const PREC_CLOSURE: i8 = -40;
|
#[derive(Clone, Copy, PartialEq, PartialOrd)]
|
||||||
pub const PREC_JUMP: i8 = -30;
|
pub enum ExprPrecedence {
|
||||||
pub const PREC_RANGE: i8 = -10;
|
Closure,
|
||||||
// The range 2..=14 is reserved for AssocOp binary operator precedences.
|
// return, break, yield
|
||||||
pub const PREC_PREFIX: i8 = 50;
|
Jump,
|
||||||
pub const PREC_UNAMBIGUOUS: i8 = 60;
|
// = += -= *= /= %= &= |= ^= <<= >>=
|
||||||
|
Assign,
|
||||||
|
// .. ..=
|
||||||
|
Range,
|
||||||
|
// ||
|
||||||
|
LOr,
|
||||||
|
// &&
|
||||||
|
LAnd,
|
||||||
|
// == != < > <= >=
|
||||||
|
Compare,
|
||||||
|
// |
|
||||||
|
BitOr,
|
||||||
|
// ^
|
||||||
|
BitXor,
|
||||||
|
// &
|
||||||
|
BitAnd,
|
||||||
|
// << >>
|
||||||
|
Shift,
|
||||||
|
// + -
|
||||||
|
Sum,
|
||||||
|
// * / %
|
||||||
|
Product,
|
||||||
|
// as
|
||||||
|
Cast,
|
||||||
|
// unary - * ! & &mut
|
||||||
|
Prefix,
|
||||||
|
// paths, loops, function calls, array indexing, field expressions, method calls
|
||||||
|
Unambiguous,
|
||||||
|
}
|
||||||
|
|
||||||
/// In `let p = e`, operators with precedence `<=` this one requires parentheses in `e`.
|
/// In `let p = e`, operators with precedence `<=` this one requires parentheses in `e`.
|
||||||
pub fn prec_let_scrutinee_needs_par() -> usize {
|
pub fn prec_let_scrutinee_needs_par() -> ExprPrecedence {
|
||||||
AssocOp::LAnd.precedence()
|
ExprPrecedence::LAnd
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Suppose we have `let _ = e` and the `order` of `e`.
|
/// Suppose we have `let _ = e` and the `order` of `e`.
|
||||||
|
@ -246,8 +274,8 @@ pub fn prec_let_scrutinee_needs_par() -> usize {
|
||||||
///
|
///
|
||||||
/// Conversely, suppose that we have `(let _ = a) OP b` and `order` is that of `OP`.
|
/// Conversely, suppose that we have `(let _ = a) OP b` and `order` is that of `OP`.
|
||||||
/// Can we print this as `let _ = a OP b`?
|
/// Can we print this as `let _ = a OP b`?
|
||||||
pub fn needs_par_as_let_scrutinee(order: i8) -> bool {
|
pub fn needs_par_as_let_scrutinee(order: ExprPrecedence) -> bool {
|
||||||
order <= prec_let_scrutinee_needs_par() as i8
|
order <= prec_let_scrutinee_needs_par()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Expressions that syntactically contain an "exterior" struct literal i.e., not surrounded by any
|
/// Expressions that syntactically contain an "exterior" struct literal i.e., not surrounded by any
|
||||||
|
|
|
@ -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, Fixity};
|
use rustc_ast::util::parser::{self, AssocOp, 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,
|
||||||
|
@ -214,7 +214,7 @@ impl<'a> State<'a> {
|
||||||
fn print_expr_call(&mut self, func: &ast::Expr, args: &[P<ast::Expr>], fixup: FixupContext) {
|
fn print_expr_call(&mut self, func: &ast::Expr, args: &[P<ast::Expr>], fixup: FixupContext) {
|
||||||
let needs_paren = match func.kind {
|
let needs_paren = match func.kind {
|
||||||
ast::ExprKind::Field(..) => true,
|
ast::ExprKind::Field(..) => true,
|
||||||
_ => func.precedence() < parser::PREC_UNAMBIGUOUS,
|
_ => func.precedence() < ExprPrecedence::Unambiguous,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Independent of parenthesization related to precedence, we must
|
// Independent of parenthesization related to precedence, we must
|
||||||
|
@ -256,7 +256,7 @@ impl<'a> State<'a> {
|
||||||
// a statement containing an expression.
|
// a statement containing an expression.
|
||||||
self.print_expr_cond_paren(
|
self.print_expr_cond_paren(
|
||||||
receiver,
|
receiver,
|
||||||
receiver.precedence() < parser::PREC_UNAMBIGUOUS,
|
receiver.precedence() < ExprPrecedence::Unambiguous,
|
||||||
fixup,
|
fixup,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -276,7 +276,7 @@ impl<'a> State<'a> {
|
||||||
fixup: FixupContext,
|
fixup: FixupContext,
|
||||||
) {
|
) {
|
||||||
let assoc_op = AssocOp::from_ast_binop(op.node);
|
let assoc_op = AssocOp::from_ast_binop(op.node);
|
||||||
let binop_prec = assoc_op.precedence() as i8;
|
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();
|
||||||
|
|
||||||
|
@ -317,7 +317,7 @@ impl<'a> State<'a> {
|
||||||
self.word(op.as_str());
|
self.word(op.as_str());
|
||||||
self.print_expr_cond_paren(
|
self.print_expr_cond_paren(
|
||||||
expr,
|
expr,
|
||||||
expr.precedence() < parser::PREC_PREFIX,
|
expr.precedence() < ExprPrecedence::Prefix,
|
||||||
fixup.subsequent_subexpression(),
|
fixup.subsequent_subexpression(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -339,7 +339,7 @@ impl<'a> State<'a> {
|
||||||
}
|
}
|
||||||
self.print_expr_cond_paren(
|
self.print_expr_cond_paren(
|
||||||
expr,
|
expr,
|
||||||
expr.precedence() < parser::PREC_PREFIX,
|
expr.precedence() < ExprPrecedence::Prefix,
|
||||||
fixup.subsequent_subexpression(),
|
fixup.subsequent_subexpression(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -423,10 +423,9 @@ impl<'a> State<'a> {
|
||||||
self.print_token_literal(lit, expr.span)
|
self.print_token_literal(lit, expr.span)
|
||||||
}
|
}
|
||||||
ast::ExprKind::Cast(expr, ty) => {
|
ast::ExprKind::Cast(expr, ty) => {
|
||||||
let prec = AssocOp::As.precedence() as i8;
|
|
||||||
self.print_expr_cond_paren(
|
self.print_expr_cond_paren(
|
||||||
expr,
|
expr,
|
||||||
expr.precedence() < prec,
|
expr.precedence() < ExprPrecedence::Cast,
|
||||||
fixup.leftmost_subexpression(),
|
fixup.leftmost_subexpression(),
|
||||||
);
|
);
|
||||||
self.space();
|
self.space();
|
||||||
|
@ -503,7 +502,7 @@ impl<'a> State<'a> {
|
||||||
MatchKind::Postfix => {
|
MatchKind::Postfix => {
|
||||||
self.print_expr_cond_paren(
|
self.print_expr_cond_paren(
|
||||||
expr,
|
expr,
|
||||||
expr.precedence() < parser::PREC_UNAMBIGUOUS,
|
expr.precedence() < ExprPrecedence::Unambiguous,
|
||||||
fixup,
|
fixup,
|
||||||
);
|
);
|
||||||
self.word_nbsp(".match");
|
self.word_nbsp(".match");
|
||||||
|
@ -567,31 +566,31 @@ impl<'a> State<'a> {
|
||||||
ast::ExprKind::Await(expr, _) => {
|
ast::ExprKind::Await(expr, _) => {
|
||||||
self.print_expr_cond_paren(
|
self.print_expr_cond_paren(
|
||||||
expr,
|
expr,
|
||||||
expr.precedence() < parser::PREC_UNAMBIGUOUS,
|
expr.precedence() < ExprPrecedence::Unambiguous,
|
||||||
fixup,
|
fixup,
|
||||||
);
|
);
|
||||||
self.word(".await");
|
self.word(".await");
|
||||||
}
|
}
|
||||||
ast::ExprKind::Assign(lhs, rhs, _) => {
|
ast::ExprKind::Assign(lhs, rhs, _) => {
|
||||||
let prec = AssocOp::Assign.precedence() as i8;
|
|
||||||
self.print_expr_cond_paren(
|
self.print_expr_cond_paren(
|
||||||
lhs,
|
lhs,
|
||||||
lhs.precedence() <= prec,
|
// Ranges are allowed on the right-hand side of assignment,
|
||||||
|
// but not the left. `(a..b) = c` needs parentheses.
|
||||||
|
lhs.precedence() <= ExprPrecedence::Range,
|
||||||
fixup.leftmost_subexpression(),
|
fixup.leftmost_subexpression(),
|
||||||
);
|
);
|
||||||
self.space();
|
self.space();
|
||||||
self.word_space("=");
|
self.word_space("=");
|
||||||
self.print_expr_cond_paren(
|
self.print_expr_cond_paren(
|
||||||
rhs,
|
rhs,
|
||||||
rhs.precedence() < prec,
|
rhs.precedence() < ExprPrecedence::Assign,
|
||||||
fixup.subsequent_subexpression(),
|
fixup.subsequent_subexpression(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
ast::ExprKind::AssignOp(op, lhs, rhs) => {
|
ast::ExprKind::AssignOp(op, lhs, rhs) => {
|
||||||
let prec = AssocOp::Assign.precedence() as i8;
|
|
||||||
self.print_expr_cond_paren(
|
self.print_expr_cond_paren(
|
||||||
lhs,
|
lhs,
|
||||||
lhs.precedence() <= prec,
|
lhs.precedence() <= ExprPrecedence::Range,
|
||||||
fixup.leftmost_subexpression(),
|
fixup.leftmost_subexpression(),
|
||||||
);
|
);
|
||||||
self.space();
|
self.space();
|
||||||
|
@ -599,14 +598,14 @@ impl<'a> State<'a> {
|
||||||
self.word_space("=");
|
self.word_space("=");
|
||||||
self.print_expr_cond_paren(
|
self.print_expr_cond_paren(
|
||||||
rhs,
|
rhs,
|
||||||
rhs.precedence() < prec,
|
rhs.precedence() < ExprPrecedence::Assign,
|
||||||
fixup.subsequent_subexpression(),
|
fixup.subsequent_subexpression(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
ast::ExprKind::Field(expr, ident) => {
|
ast::ExprKind::Field(expr, ident) => {
|
||||||
self.print_expr_cond_paren(
|
self.print_expr_cond_paren(
|
||||||
expr,
|
expr,
|
||||||
expr.precedence() < parser::PREC_UNAMBIGUOUS,
|
expr.precedence() < ExprPrecedence::Unambiguous,
|
||||||
fixup,
|
fixup,
|
||||||
);
|
);
|
||||||
self.word(".");
|
self.word(".");
|
||||||
|
@ -615,7 +614,7 @@ impl<'a> State<'a> {
|
||||||
ast::ExprKind::Index(expr, index, _) => {
|
ast::ExprKind::Index(expr, index, _) => {
|
||||||
self.print_expr_cond_paren(
|
self.print_expr_cond_paren(
|
||||||
expr,
|
expr,
|
||||||
expr.precedence() < parser::PREC_UNAMBIGUOUS,
|
expr.precedence() < ExprPrecedence::Unambiguous,
|
||||||
fixup.leftmost_subexpression(),
|
fixup.leftmost_subexpression(),
|
||||||
);
|
);
|
||||||
self.word("[");
|
self.word("[");
|
||||||
|
@ -627,7 +626,7 @@ impl<'a> State<'a> {
|
||||||
// than `Assign`, but `x .. x = x` gives a parse error instead of `x .. (x = x)`.
|
// than `Assign`, but `x .. x = x` gives a parse error instead of `x .. (x = x)`.
|
||||||
// Here we use a fake precedence value so that any child with lower precedence than
|
// Here we use a fake precedence value so that any child with lower precedence than
|
||||||
// a "normal" binop gets parenthesized. (`LOr` is the lowest-precedence binop.)
|
// a "normal" binop gets parenthesized. (`LOr` is the lowest-precedence binop.)
|
||||||
let fake_prec = AssocOp::LOr.precedence() as i8;
|
let fake_prec = ExprPrecedence::LOr;
|
||||||
if let Some(e) = start {
|
if let Some(e) = start {
|
||||||
self.print_expr_cond_paren(
|
self.print_expr_cond_paren(
|
||||||
e,
|
e,
|
||||||
|
@ -662,7 +661,7 @@ impl<'a> State<'a> {
|
||||||
expr,
|
expr,
|
||||||
// Parenthesize if required by precedence, or in the
|
// Parenthesize if required by precedence, or in the
|
||||||
// case of `break 'inner: loop { break 'inner 1 } + 1`
|
// case of `break 'inner: loop { break 'inner 1 } + 1`
|
||||||
expr.precedence() < parser::PREC_JUMP
|
expr.precedence() < ExprPrecedence::Jump
|
||||||
|| (opt_label.is_none() && classify::leading_labeled_expr(expr)),
|
|| (opt_label.is_none() && classify::leading_labeled_expr(expr)),
|
||||||
fixup.subsequent_subexpression(),
|
fixup.subsequent_subexpression(),
|
||||||
);
|
);
|
||||||
|
@ -681,7 +680,7 @@ impl<'a> State<'a> {
|
||||||
self.word(" ");
|
self.word(" ");
|
||||||
self.print_expr_cond_paren(
|
self.print_expr_cond_paren(
|
||||||
expr,
|
expr,
|
||||||
expr.precedence() < parser::PREC_JUMP,
|
expr.precedence() < ExprPrecedence::Jump,
|
||||||
fixup.subsequent_subexpression(),
|
fixup.subsequent_subexpression(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -694,7 +693,7 @@ impl<'a> State<'a> {
|
||||||
self.word(" ");
|
self.word(" ");
|
||||||
self.print_expr_cond_paren(
|
self.print_expr_cond_paren(
|
||||||
expr,
|
expr,
|
||||||
expr.precedence() < parser::PREC_JUMP,
|
expr.precedence() < ExprPrecedence::Jump,
|
||||||
fixup.subsequent_subexpression(),
|
fixup.subsequent_subexpression(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -704,7 +703,7 @@ impl<'a> State<'a> {
|
||||||
self.word(" ");
|
self.word(" ");
|
||||||
self.print_expr_cond_paren(
|
self.print_expr_cond_paren(
|
||||||
result,
|
result,
|
||||||
result.precedence() < parser::PREC_JUMP,
|
result.precedence() < ExprPrecedence::Jump,
|
||||||
fixup.subsequent_subexpression(),
|
fixup.subsequent_subexpression(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -758,13 +757,13 @@ impl<'a> State<'a> {
|
||||||
self.space();
|
self.space();
|
||||||
self.print_expr_cond_paren(
|
self.print_expr_cond_paren(
|
||||||
expr,
|
expr,
|
||||||
expr.precedence() < parser::PREC_JUMP,
|
expr.precedence() < ExprPrecedence::Jump,
|
||||||
fixup.subsequent_subexpression(),
|
fixup.subsequent_subexpression(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast::ExprKind::Try(e) => {
|
ast::ExprKind::Try(e) => {
|
||||||
self.print_expr_cond_paren(e, e.precedence() < parser::PREC_UNAMBIGUOUS, fixup);
|
self.print_expr_cond_paren(e, e.precedence() < ExprPrecedence::Unambiguous, fixup);
|
||||||
self.word("?")
|
self.word("?")
|
||||||
}
|
}
|
||||||
ast::ExprKind::TryBlock(blk) => {
|
ast::ExprKind::TryBlock(blk) => {
|
||||||
|
|
|
@ -6,6 +6,7 @@ use std::path::{Path, PathBuf};
|
||||||
use std::process::ExitStatus;
|
use std::process::ExitStatus;
|
||||||
|
|
||||||
use rustc_abi::TargetDataLayoutErrors;
|
use rustc_abi::TargetDataLayoutErrors;
|
||||||
|
use rustc_ast::util::parser::ExprPrecedence;
|
||||||
use rustc_ast_pretty::pprust;
|
use rustc_ast_pretty::pprust;
|
||||||
use rustc_macros::Subdiagnostic;
|
use rustc_macros::Subdiagnostic;
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
|
@ -298,6 +299,12 @@ impl IntoDiagArg for hir::def::Namespace {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl IntoDiagArg for ExprPrecedence {
|
||||||
|
fn into_diag_arg(self) -> DiagArgValue {
|
||||||
|
DiagArgValue::Number(self as i32)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct DiagSymbolList<S = Symbol>(Vec<S>);
|
pub struct DiagSymbolList<S = Symbol>(Vec<S>);
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
use rustc_abi::ExternAbi;
|
use rustc_abi::ExternAbi;
|
||||||
use rustc_ast::util::parser::{AssocOp, PREC_CLOSURE, PREC_JUMP, PREC_PREFIX, PREC_UNAMBIGUOUS};
|
use rustc_ast::util::parser::{AssocOp, ExprPrecedence};
|
||||||
use rustc_ast::{
|
use rustc_ast::{
|
||||||
self as ast, Attribute, FloatTy, InlineAsmOptions, InlineAsmTemplatePiece, IntTy, Label,
|
self as ast, Attribute, FloatTy, InlineAsmOptions, InlineAsmTemplatePiece, IntTy, Label,
|
||||||
LitKind, TraitObjectSyntax, UintTy,
|
LitKind, TraitObjectSyntax, UintTy,
|
||||||
|
@ -1708,22 +1708,22 @@ pub struct Expr<'hir> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Expr<'_> {
|
impl Expr<'_> {
|
||||||
pub fn precedence(&self) -> i8 {
|
pub fn precedence(&self) -> ExprPrecedence {
|
||||||
match self.kind {
|
match self.kind {
|
||||||
ExprKind::Closure { .. } => PREC_CLOSURE,
|
ExprKind::Closure { .. } => ExprPrecedence::Closure,
|
||||||
|
|
||||||
ExprKind::Break(..)
|
ExprKind::Break(..)
|
||||||
| ExprKind::Continue(..)
|
| ExprKind::Continue(..)
|
||||||
| ExprKind::Ret(..)
|
| ExprKind::Ret(..)
|
||||||
| ExprKind::Yield(..)
|
| ExprKind::Yield(..)
|
||||||
| ExprKind::Become(..) => PREC_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() as i8,
|
ExprKind::Binary(op, ..) => AssocOp::from_ast_binop(op.node).precedence(),
|
||||||
ExprKind::Cast(..) => AssocOp::As.precedence() as i8,
|
ExprKind::Cast(..) => ExprPrecedence::Cast,
|
||||||
|
|
||||||
ExprKind::Assign(..) |
|
ExprKind::Assign(..) |
|
||||||
ExprKind::AssignOp(..) => AssocOp::Assign.precedence() as i8,
|
ExprKind::AssignOp(..) => ExprPrecedence::Assign,
|
||||||
|
|
||||||
// Unary, prefix
|
// Unary, prefix
|
||||||
ExprKind::AddrOf(..)
|
ExprKind::AddrOf(..)
|
||||||
|
@ -1732,7 +1732,7 @@ impl Expr<'_> {
|
||||||
// need parens sometimes. E.g. we can print `(let _ = a) && b` as `let _ = a && b`
|
// need parens sometimes. E.g. we can print `(let _ = a) && b` as `let _ = a && b`
|
||||||
// but we need to print `(let _ = a) < b` as-is with parens.
|
// but we need to print `(let _ = a) < b` as-is with parens.
|
||||||
| ExprKind::Let(..)
|
| ExprKind::Let(..)
|
||||||
| ExprKind::Unary(..) => PREC_PREFIX,
|
| ExprKind::Unary(..) => ExprPrecedence::Prefix,
|
||||||
|
|
||||||
// Never need parens
|
// Never need parens
|
||||||
ExprKind::Array(_)
|
ExprKind::Array(_)
|
||||||
|
@ -1753,7 +1753,7 @@ impl Expr<'_> {
|
||||||
| ExprKind::Struct(..)
|
| ExprKind::Struct(..)
|
||||||
| ExprKind::Tup(_)
|
| ExprKind::Tup(_)
|
||||||
| ExprKind::Type(..)
|
| ExprKind::Type(..)
|
||||||
| ExprKind::Err(_) => PREC_UNAMBIGUOUS,
|
| ExprKind::Err(_) => ExprPrecedence::Unambiguous,
|
||||||
|
|
||||||
ExprKind::DropTemps(ref expr, ..) => expr.precedence(),
|
ExprKind::DropTemps(ref expr, ..) => expr.precedence(),
|
||||||
}
|
}
|
||||||
|
|
|
@ -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, Fixity};
|
use rustc_ast::util::parser::{self, AssocOp, ExprPrecedence, Fixity};
|
||||||
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};
|
||||||
use rustc_ast_pretty::pprust::{Comments, PrintState};
|
use rustc_ast_pretty::pprust::{Comments, PrintState};
|
||||||
|
@ -1134,7 +1134,7 @@ impl<'a> State<'a> {
|
||||||
fn print_expr_call(&mut self, func: &hir::Expr<'_>, args: &[hir::Expr<'_>]) {
|
fn print_expr_call(&mut self, func: &hir::Expr<'_>, args: &[hir::Expr<'_>]) {
|
||||||
let needs_paren = match func.kind {
|
let needs_paren = match func.kind {
|
||||||
hir::ExprKind::Field(..) => true,
|
hir::ExprKind::Field(..) => true,
|
||||||
_ => func.precedence() < parser::PREC_UNAMBIGUOUS,
|
_ => func.precedence() < ExprPrecedence::Unambiguous,
|
||||||
};
|
};
|
||||||
|
|
||||||
self.print_expr_cond_paren(func, needs_paren);
|
self.print_expr_cond_paren(func, needs_paren);
|
||||||
|
@ -1148,7 +1148,7 @@ impl<'a> State<'a> {
|
||||||
args: &[hir::Expr<'_>],
|
args: &[hir::Expr<'_>],
|
||||||
) {
|
) {
|
||||||
let base_args = args;
|
let base_args = args;
|
||||||
self.print_expr_cond_paren(receiver, receiver.precedence() < parser::PREC_UNAMBIGUOUS);
|
self.print_expr_cond_paren(receiver, receiver.precedence() < ExprPrecedence::Unambiguous);
|
||||||
self.word(".");
|
self.word(".");
|
||||||
self.print_ident(segment.ident);
|
self.print_ident(segment.ident);
|
||||||
|
|
||||||
|
@ -1162,7 +1162,7 @@ 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 assoc_op = AssocOp::from_ast_binop(op.node);
|
||||||
let binop_prec = assoc_op.precedence() as i8;
|
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();
|
||||||
|
|
||||||
|
@ -1193,7 +1193,7 @@ impl<'a> State<'a> {
|
||||||
|
|
||||||
fn print_expr_unary(&mut self, op: hir::UnOp, expr: &hir::Expr<'_>) {
|
fn print_expr_unary(&mut self, op: hir::UnOp, expr: &hir::Expr<'_>) {
|
||||||
self.word(op.as_str());
|
self.word(op.as_str());
|
||||||
self.print_expr_cond_paren(expr, expr.precedence() < parser::PREC_PREFIX)
|
self.print_expr_cond_paren(expr, expr.precedence() < ExprPrecedence::Prefix);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn print_expr_addr_of(
|
fn print_expr_addr_of(
|
||||||
|
@ -1210,7 +1210,7 @@ impl<'a> State<'a> {
|
||||||
self.print_mutability(mutability, true);
|
self.print_mutability(mutability, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.print_expr_cond_paren(expr, expr.precedence() < parser::PREC_PREFIX)
|
self.print_expr_cond_paren(expr, expr.precedence() < ExprPrecedence::Prefix);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn print_literal(&mut self, lit: &hir::Lit) {
|
fn print_literal(&mut self, lit: &hir::Lit) {
|
||||||
|
@ -1348,8 +1348,7 @@ impl<'a> State<'a> {
|
||||||
self.print_literal(lit);
|
self.print_literal(lit);
|
||||||
}
|
}
|
||||||
hir::ExprKind::Cast(expr, ty) => {
|
hir::ExprKind::Cast(expr, ty) => {
|
||||||
let prec = AssocOp::As.precedence() as i8;
|
self.print_expr_cond_paren(expr, expr.precedence() < ExprPrecedence::Cast);
|
||||||
self.print_expr_cond_paren(expr, expr.precedence() < prec);
|
|
||||||
self.space();
|
self.space();
|
||||||
self.word_space("as");
|
self.word_space("as");
|
||||||
self.print_type(ty);
|
self.print_type(ty);
|
||||||
|
@ -1450,27 +1449,25 @@ impl<'a> State<'a> {
|
||||||
self.print_block(blk);
|
self.print_block(blk);
|
||||||
}
|
}
|
||||||
hir::ExprKind::Assign(lhs, rhs, _) => {
|
hir::ExprKind::Assign(lhs, rhs, _) => {
|
||||||
let prec = AssocOp::Assign.precedence() as i8;
|
self.print_expr_cond_paren(lhs, lhs.precedence() <= ExprPrecedence::Assign);
|
||||||
self.print_expr_cond_paren(lhs, lhs.precedence() <= prec);
|
|
||||||
self.space();
|
self.space();
|
||||||
self.word_space("=");
|
self.word_space("=");
|
||||||
self.print_expr_cond_paren(rhs, rhs.precedence() < prec);
|
self.print_expr_cond_paren(rhs, rhs.precedence() < ExprPrecedence::Assign);
|
||||||
}
|
}
|
||||||
hir::ExprKind::AssignOp(op, lhs, rhs) => {
|
hir::ExprKind::AssignOp(op, lhs, rhs) => {
|
||||||
let prec = AssocOp::Assign.precedence() as i8;
|
self.print_expr_cond_paren(lhs, lhs.precedence() <= ExprPrecedence::Assign);
|
||||||
self.print_expr_cond_paren(lhs, lhs.precedence() <= prec);
|
|
||||||
self.space();
|
self.space();
|
||||||
self.word(op.node.as_str());
|
self.word(op.node.as_str());
|
||||||
self.word_space("=");
|
self.word_space("=");
|
||||||
self.print_expr_cond_paren(rhs, rhs.precedence() < prec);
|
self.print_expr_cond_paren(rhs, rhs.precedence() < ExprPrecedence::Assign);
|
||||||
}
|
}
|
||||||
hir::ExprKind::Field(expr, ident) => {
|
hir::ExprKind::Field(expr, ident) => {
|
||||||
self.print_expr_cond_paren(expr, expr.precedence() < parser::PREC_UNAMBIGUOUS);
|
self.print_expr_cond_paren(expr, expr.precedence() < ExprPrecedence::Unambiguous);
|
||||||
self.word(".");
|
self.word(".");
|
||||||
self.print_ident(ident);
|
self.print_ident(ident);
|
||||||
}
|
}
|
||||||
hir::ExprKind::Index(expr, index, _) => {
|
hir::ExprKind::Index(expr, index, _) => {
|
||||||
self.print_expr_cond_paren(expr, expr.precedence() < parser::PREC_UNAMBIGUOUS);
|
self.print_expr_cond_paren(expr, expr.precedence() < ExprPrecedence::Unambiguous);
|
||||||
self.word("[");
|
self.word("[");
|
||||||
self.print_expr(index);
|
self.print_expr(index);
|
||||||
self.word("]");
|
self.word("]");
|
||||||
|
@ -1484,7 +1481,7 @@ impl<'a> State<'a> {
|
||||||
}
|
}
|
||||||
if let Some(expr) = opt_expr {
|
if let Some(expr) = opt_expr {
|
||||||
self.space();
|
self.space();
|
||||||
self.print_expr_cond_paren(expr, expr.precedence() < parser::PREC_JUMP);
|
self.print_expr_cond_paren(expr, expr.precedence() < ExprPrecedence::Jump);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
hir::ExprKind::Continue(destination) => {
|
hir::ExprKind::Continue(destination) => {
|
||||||
|
@ -1498,13 +1495,13 @@ impl<'a> State<'a> {
|
||||||
self.word("return");
|
self.word("return");
|
||||||
if let Some(expr) = result {
|
if let Some(expr) = result {
|
||||||
self.word(" ");
|
self.word(" ");
|
||||||
self.print_expr_cond_paren(expr, expr.precedence() < parser::PREC_JUMP);
|
self.print_expr_cond_paren(expr, expr.precedence() < ExprPrecedence::Jump);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
hir::ExprKind::Become(result) => {
|
hir::ExprKind::Become(result) => {
|
||||||
self.word("become");
|
self.word("become");
|
||||||
self.word(" ");
|
self.word(" ");
|
||||||
self.print_expr_cond_paren(result, result.precedence() < parser::PREC_JUMP);
|
self.print_expr_cond_paren(result, result.precedence() < ExprPrecedence::Jump);
|
||||||
}
|
}
|
||||||
hir::ExprKind::InlineAsm(asm) => {
|
hir::ExprKind::InlineAsm(asm) => {
|
||||||
self.word("asm!");
|
self.word("asm!");
|
||||||
|
@ -1529,7 +1526,7 @@ impl<'a> State<'a> {
|
||||||
}
|
}
|
||||||
hir::ExprKind::Yield(expr, _) => {
|
hir::ExprKind::Yield(expr, _) => {
|
||||||
self.word_space("yield");
|
self.word_space("yield");
|
||||||
self.print_expr_cond_paren(expr, expr.precedence() < parser::PREC_JUMP);
|
self.print_expr_cond_paren(expr, expr.precedence() < ExprPrecedence::Jump);
|
||||||
}
|
}
|
||||||
hir::ExprKind::Err(_) => {
|
hir::ExprKind::Err(_) => {
|
||||||
self.popen();
|
self.popen();
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use std::iter;
|
use std::iter;
|
||||||
|
|
||||||
use rustc_ast::util::parser::PREC_UNAMBIGUOUS;
|
use rustc_ast::util::parser::ExprPrecedence;
|
||||||
use rustc_errors::{Applicability, Diag, ErrorGuaranteed, StashKey};
|
use rustc_errors::{Applicability, Diag, ErrorGuaranteed, StashKey};
|
||||||
use rustc_hir::def::{self, CtorKind, Namespace, Res};
|
use rustc_hir::def::{self, CtorKind, Namespace, Res};
|
||||||
use rustc_hir::def_id::DefId;
|
use rustc_hir::def_id::DefId;
|
||||||
|
@ -606,7 +606,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Ok(rest_snippet) = rest_snippet {
|
if let Ok(rest_snippet) = rest_snippet {
|
||||||
let sugg = if callee_expr.precedence() >= PREC_UNAMBIGUOUS {
|
let sugg = if callee_expr.precedence() >= ExprPrecedence::Unambiguous {
|
||||||
vec![
|
vec![
|
||||||
(up_to_rcvr_span, "".to_string()),
|
(up_to_rcvr_span, "".to_string()),
|
||||||
(rest_span, format!(".{}({rest_snippet}", segment.ident)),
|
(rest_span, format!(".{}({rest_snippet}", segment.ident)),
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
//! expression, `e as U2` is not necessarily so (in fact it will only be valid if
|
//! expression, `e as U2` is not necessarily so (in fact it will only be valid if
|
||||||
//! `U1` coerces to `U2`).
|
//! `U1` coerces to `U2`).
|
||||||
|
|
||||||
|
use rustc_ast::util::parser::ExprPrecedence;
|
||||||
use rustc_data_structures::fx::FxHashSet;
|
use rustc_data_structures::fx::FxHashSet;
|
||||||
use rustc_errors::codes::*;
|
use rustc_errors::codes::*;
|
||||||
use rustc_errors::{Applicability, Diag, ErrorGuaranteed};
|
use rustc_errors::{Applicability, Diag, ErrorGuaranteed};
|
||||||
|
@ -1108,7 +1109,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
|
||||||
|
|
||||||
fn lossy_provenance_ptr2int_lint(&self, fcx: &FnCtxt<'a, 'tcx>, t_c: ty::cast::IntTy) {
|
fn lossy_provenance_ptr2int_lint(&self, fcx: &FnCtxt<'a, 'tcx>, t_c: ty::cast::IntTy) {
|
||||||
let expr_prec = self.expr.precedence();
|
let expr_prec = self.expr.precedence();
|
||||||
let needs_parens = expr_prec < rustc_ast::util::parser::PREC_UNAMBIGUOUS;
|
let needs_parens = expr_prec < ExprPrecedence::Unambiguous;
|
||||||
|
|
||||||
let needs_cast = !matches!(t_c, ty::cast::IntTy::U(ty::UintTy::Usize));
|
let needs_cast = !matches!(t_c, ty::cast::IntTy::U(ty::UintTy::Usize));
|
||||||
let cast_span = self.expr_span.shrink_to_hi().to(self.cast_span);
|
let cast_span = self.expr_span.shrink_to_hi().to(self.cast_span);
|
||||||
|
|
|
@ -2,7 +2,7 @@ use core::cmp::min;
|
||||||
use core::iter;
|
use core::iter;
|
||||||
|
|
||||||
use hir::def_id::LocalDefId;
|
use hir::def_id::LocalDefId;
|
||||||
use rustc_ast::util::parser::PREC_UNAMBIGUOUS;
|
use rustc_ast::util::parser::ExprPrecedence;
|
||||||
use rustc_data_structures::packed::Pu128;
|
use rustc_data_structures::packed::Pu128;
|
||||||
use rustc_errors::{Applicability, Diag, MultiSpan};
|
use rustc_errors::{Applicability, Diag, MultiSpan};
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
|
@ -398,7 +398,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
// so we remove the user's `clone` call.
|
// so we remove the user's `clone` call.
|
||||||
{
|
{
|
||||||
vec![(receiver_method.ident.span, conversion_method.name.to_string())]
|
vec![(receiver_method.ident.span, conversion_method.name.to_string())]
|
||||||
} else if expr.precedence() < PREC_UNAMBIGUOUS {
|
} else if expr.precedence() < ExprPrecedence::Unambiguous {
|
||||||
vec![
|
vec![
|
||||||
(expr.span.shrink_to_lo(), "(".to_string()),
|
(expr.span.shrink_to_lo(), "(".to_string()),
|
||||||
(expr.span.shrink_to_hi(), format!(").{}()", conversion_method.name)),
|
(expr.span.shrink_to_hi(), format!(").{}()", conversion_method.name)),
|
||||||
|
@ -1376,7 +1376,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
{
|
{
|
||||||
let span = expr.span.find_oldest_ancestor_in_same_ctxt();
|
let span = expr.span.find_oldest_ancestor_in_same_ctxt();
|
||||||
|
|
||||||
let mut sugg = if expr.precedence() >= PREC_UNAMBIGUOUS {
|
let mut sugg = if expr.precedence() >= ExprPrecedence::Unambiguous {
|
||||||
vec![(span.shrink_to_hi(), ".into()".to_owned())]
|
vec![(span.shrink_to_hi(), ".into()".to_owned())]
|
||||||
} else {
|
} else {
|
||||||
vec![
|
vec![
|
||||||
|
@ -3000,7 +3000,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
"change the type of the numeric literal from `{checked_ty}` to `{expected_ty}`",
|
"change the type of the numeric literal from `{checked_ty}` to `{expected_ty}`",
|
||||||
);
|
);
|
||||||
|
|
||||||
let close_paren = if expr.precedence() < PREC_UNAMBIGUOUS {
|
let close_paren = if expr.precedence() < ExprPrecedence::Unambiguous {
|
||||||
sugg.push((expr.span.shrink_to_lo(), "(".to_string()));
|
sugg.push((expr.span.shrink_to_lo(), "(".to_string()));
|
||||||
")"
|
")"
|
||||||
} else {
|
} else {
|
||||||
|
@ -3025,7 +3025,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
let len = src.trim_end_matches(&checked_ty.to_string()).len();
|
let len = src.trim_end_matches(&checked_ty.to_string()).len();
|
||||||
expr.span.with_lo(expr.span.lo() + BytePos(len as u32))
|
expr.span.with_lo(expr.span.lo() + BytePos(len as u32))
|
||||||
},
|
},
|
||||||
if expr.precedence() < PREC_UNAMBIGUOUS {
|
if expr.precedence() < ExprPrecedence::Unambiguous {
|
||||||
// Readd `)`
|
// Readd `)`
|
||||||
format!("{expected_ty})")
|
format!("{expected_ty})")
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
|
||||||
use rustc_ast::token::Token;
|
use rustc_ast::token::Token;
|
||||||
|
use rustc_ast::util::parser::ExprPrecedence;
|
||||||
use rustc_ast::{Path, Visibility};
|
use rustc_ast::{Path, Visibility};
|
||||||
use rustc_errors::codes::*;
|
use rustc_errors::codes::*;
|
||||||
use rustc_errors::{
|
use rustc_errors::{
|
||||||
|
@ -2686,7 +2687,7 @@ pub(crate) struct UnexpectedExpressionInPattern {
|
||||||
/// Was a `RangePatternBound` expected?
|
/// Was a `RangePatternBound` expected?
|
||||||
pub is_bound: bool,
|
pub is_bound: bool,
|
||||||
/// The unexpected expr's precedence (used in match arm guard suggestions).
|
/// The unexpected expr's precedence (used in match arm guard suggestions).
|
||||||
pub expr_precedence: i8,
|
pub expr_precedence: ExprPrecedence,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Subdiagnostic)]
|
#[derive(Subdiagnostic)]
|
||||||
|
|
|
@ -10,7 +10,7 @@ use rustc_ast::ptr::P;
|
||||||
use rustc_ast::token::{self, Delimiter, Token, TokenKind};
|
use rustc_ast::token::{self, Delimiter, Token, TokenKind};
|
||||||
use rustc_ast::util::case::Case;
|
use rustc_ast::util::case::Case;
|
||||||
use rustc_ast::util::classify;
|
use rustc_ast::util::classify;
|
||||||
use rustc_ast::util::parser::{AssocOp, Fixity, prec_let_scrutinee_needs_par};
|
use rustc_ast::util::parser::{AssocOp, ExprPrecedence, Fixity, prec_let_scrutinee_needs_par};
|
||||||
use rustc_ast::visit::{Visitor, walk_expr};
|
use rustc_ast::visit::{Visitor, walk_expr};
|
||||||
use rustc_ast::{
|
use rustc_ast::{
|
||||||
self as ast, AnonConst, Arm, AttrStyle, AttrVec, BinOp, BinOpKind, BlockCheckMode, CaptureBy,
|
self as ast, AnonConst, Arm, AttrStyle, AttrVec, BinOp, BinOpKind, BlockCheckMode, CaptureBy,
|
||||||
|
@ -128,7 +128,7 @@ impl<'a> Parser<'a> {
|
||||||
/// followed by a subexpression (e.g. `1 + 2`).
|
/// followed by a subexpression (e.g. `1 + 2`).
|
||||||
pub(super) fn parse_expr_assoc_with(
|
pub(super) fn parse_expr_assoc_with(
|
||||||
&mut self,
|
&mut self,
|
||||||
min_prec: Bound<usize>,
|
min_prec: Bound<ExprPrecedence>,
|
||||||
attrs: AttrWrapper,
|
attrs: AttrWrapper,
|
||||||
) -> PResult<'a, (P<Expr>, bool)> {
|
) -> PResult<'a, (P<Expr>, bool)> {
|
||||||
let lhs = if self.token.is_range_separator() {
|
let lhs = if self.token.is_range_separator() {
|
||||||
|
@ -144,7 +144,7 @@ impl<'a> Parser<'a> {
|
||||||
/// was actually parsed.
|
/// was actually parsed.
|
||||||
pub(super) fn parse_expr_assoc_rest_with(
|
pub(super) fn parse_expr_assoc_rest_with(
|
||||||
&mut self,
|
&mut self,
|
||||||
min_prec: Bound<usize>,
|
min_prec: Bound<ExprPrecedence>,
|
||||||
starts_stmt: bool,
|
starts_stmt: bool,
|
||||||
mut lhs: P<Expr>,
|
mut lhs: P<Expr>,
|
||||||
) -> PResult<'a, (P<Expr>, bool)> {
|
) -> PResult<'a, (P<Expr>, bool)> {
|
||||||
|
@ -455,7 +455,7 @@ impl<'a> Parser<'a> {
|
||||||
/// The other two variants are handled in `parse_prefix_range_expr` below.
|
/// The other two variants are handled in `parse_prefix_range_expr` below.
|
||||||
fn parse_expr_range(
|
fn parse_expr_range(
|
||||||
&mut self,
|
&mut self,
|
||||||
prec: usize,
|
prec: ExprPrecedence,
|
||||||
lhs: P<Expr>,
|
lhs: P<Expr>,
|
||||||
op: AssocOp,
|
op: AssocOp,
|
||||||
cur_op_span: Span,
|
cur_op_span: Span,
|
||||||
|
|
|
@ -3,12 +3,11 @@ use std::ops::Bound;
|
||||||
use rustc_ast::mut_visit::{self, MutVisitor};
|
use rustc_ast::mut_visit::{self, MutVisitor};
|
||||||
use rustc_ast::ptr::P;
|
use rustc_ast::ptr::P;
|
||||||
use rustc_ast::token::{self, BinOpToken, Delimiter, IdentIsRaw, Token};
|
use rustc_ast::token::{self, BinOpToken, Delimiter, IdentIsRaw, Token};
|
||||||
use rustc_ast::util::parser::AssocOp;
|
use rustc_ast::util::parser::ExprPrecedence;
|
||||||
use rustc_ast::visit::{self, Visitor};
|
use rustc_ast::visit::{self, Visitor};
|
||||||
use rustc_ast::{
|
use rustc_ast::{
|
||||||
self as ast, Arm, AttrVec, BinOpKind, BindingMode, ByRef, Expr, ExprKind, LocalKind, MacCall,
|
self as ast, Arm, AttrVec, BindingMode, ByRef, Expr, ExprKind, LocalKind, MacCall, Mutability,
|
||||||
Mutability, Pat, PatField, PatFieldsRest, PatKind, Path, QSelf, RangeEnd, RangeSyntax, Stmt,
|
Pat, PatField, PatFieldsRest, PatKind, Path, QSelf, RangeEnd, RangeSyntax, Stmt, StmtKind,
|
||||||
StmtKind,
|
|
||||||
};
|
};
|
||||||
use rustc_ast_pretty::pprust;
|
use rustc_ast_pretty::pprust;
|
||||||
use rustc_errors::{Applicability, Diag, DiagArgValue, PResult, StashKey};
|
use rustc_errors::{Applicability, Diag, DiagArgValue, PResult, StashKey};
|
||||||
|
@ -548,10 +547,7 @@ impl<'a> Parser<'a> {
|
||||||
// HACK: a neater way would be preferable.
|
// HACK: a neater way would be preferable.
|
||||||
let expr = match &err.args["expr_precedence"] {
|
let expr = match &err.args["expr_precedence"] {
|
||||||
DiagArgValue::Number(expr_precedence) => {
|
DiagArgValue::Number(expr_precedence) => {
|
||||||
if *expr_precedence
|
if *expr_precedence <= ExprPrecedence::Compare as i32 {
|
||||||
<= AssocOp::from_ast_binop(BinOpKind::Eq).precedence()
|
|
||||||
as i32
|
|
||||||
{
|
|
||||||
format!("({expr})")
|
format!("({expr})")
|
||||||
} else {
|
} else {
|
||||||
format!("{expr}")
|
format!("{expr}")
|
||||||
|
@ -573,9 +569,7 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
Some(guard) => {
|
Some(guard) => {
|
||||||
// Are parentheses required around the old guard?
|
// Are parentheses required around the old guard?
|
||||||
let wrap_guard = guard.precedence()
|
let wrap_guard = guard.precedence() <= ExprPrecedence::LAnd;
|
||||||
<= AssocOp::from_ast_binop(BinOpKind::And).precedence()
|
|
||||||
as i8;
|
|
||||||
|
|
||||||
err.subdiagnostic(
|
err.subdiagnostic(
|
||||||
UnexpectedExpressionInPatternSugg::UpdateGuard {
|
UnexpectedExpressionInPatternSugg::UpdateGuard {
|
||||||
|
|
|
@ -7,7 +7,7 @@ use clippy_utils::{
|
||||||
peel_middle_ty_refs,
|
peel_middle_ty_refs,
|
||||||
};
|
};
|
||||||
use core::mem;
|
use core::mem;
|
||||||
use rustc_ast::util::parser::{PREC_PREFIX, PREC_UNAMBIGUOUS};
|
use rustc_ast::util::parser::ExprPrecedence;
|
||||||
use rustc_data_structures::fx::FxIndexMap;
|
use rustc_data_structures::fx::FxIndexMap;
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
use rustc_hir::def_id::DefId;
|
use rustc_hir::def_id::DefId;
|
||||||
|
@ -963,7 +963,7 @@ fn report<'tcx>(
|
||||||
// expr_str (the suggestion) is never shown if is_final_ufcs is true, since it's
|
// expr_str (the suggestion) is never shown if is_final_ufcs is true, since it's
|
||||||
// `expr.kind == ExprKind::Call`. Therefore, this is, afaik, always unnecessary.
|
// `expr.kind == ExprKind::Call`. Therefore, this is, afaik, always unnecessary.
|
||||||
/*
|
/*
|
||||||
expr_str = if !expr_is_macro_call && is_final_ufcs && expr.precedence() < PREC_PREFIX {
|
expr_str = if !expr_is_macro_call && is_final_ufcs && expr.precedence() < ExprPrecedence::Prefix {
|
||||||
Cow::Owned(format!("({expr_str})"))
|
Cow::Owned(format!("({expr_str})"))
|
||||||
} else {
|
} else {
|
||||||
expr_str
|
expr_str
|
||||||
|
@ -999,13 +999,13 @@ fn report<'tcx>(
|
||||||
data.first_expr.span,
|
data.first_expr.span,
|
||||||
state.msg,
|
state.msg,
|
||||||
|diag| {
|
|diag| {
|
||||||
let (precedence, calls_field) = match cx.tcx.parent_hir_node(data.first_expr.hir_id) {
|
let needs_paren = match cx.tcx.parent_hir_node(data.first_expr.hir_id) {
|
||||||
Node::Expr(e) => match e.kind {
|
Node::Expr(e) => match e.kind {
|
||||||
ExprKind::Call(callee, _) if callee.hir_id != data.first_expr.hir_id => (0, false),
|
ExprKind::Call(callee, _) if callee.hir_id != data.first_expr.hir_id => false,
|
||||||
ExprKind::Call(..) => (PREC_UNAMBIGUOUS, matches!(expr.kind, ExprKind::Field(..))),
|
ExprKind::Call(..) => expr.precedence() < ExprPrecedence::Unambiguous || matches!(expr.kind, ExprKind::Field(..)),
|
||||||
_ => (e.precedence(), false),
|
_ => expr.precedence() < e.precedence(),
|
||||||
},
|
},
|
||||||
_ => (0, false),
|
_ => false,
|
||||||
};
|
};
|
||||||
let is_in_tuple = matches!(
|
let is_in_tuple = matches!(
|
||||||
get_parent_expr(cx, data.first_expr),
|
get_parent_expr(cx, data.first_expr),
|
||||||
|
@ -1016,7 +1016,7 @@ fn report<'tcx>(
|
||||||
);
|
);
|
||||||
|
|
||||||
let sugg = if !snip_is_macro
|
let sugg = if !snip_is_macro
|
||||||
&& (calls_field || expr.precedence() < precedence)
|
&& needs_paren
|
||||||
&& !has_enclosing_paren(&snip)
|
&& !has_enclosing_paren(&snip)
|
||||||
&& !is_in_tuple
|
&& !is_in_tuple
|
||||||
{
|
{
|
||||||
|
@ -1049,16 +1049,16 @@ fn report<'tcx>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let (prefix, precedence) = match mutability {
|
let (prefix, needs_paren) = match mutability {
|
||||||
Some(mutability) if !ty.is_ref() => {
|
Some(mutability) if !ty.is_ref() => {
|
||||||
let prefix = match mutability {
|
let prefix = match mutability {
|
||||||
Mutability::Not => "&",
|
Mutability::Not => "&",
|
||||||
Mutability::Mut => "&mut ",
|
Mutability::Mut => "&mut ",
|
||||||
};
|
};
|
||||||
(prefix, PREC_PREFIX)
|
(prefix, expr.precedence() < ExprPrecedence::Prefix)
|
||||||
},
|
},
|
||||||
None if !ty.is_ref() && data.adjusted_ty.is_ref() => ("&", 0),
|
None if !ty.is_ref() && data.adjusted_ty.is_ref() => ("&", false),
|
||||||
_ => ("", 0),
|
_ => ("", false),
|
||||||
};
|
};
|
||||||
span_lint_hir_and_then(
|
span_lint_hir_and_then(
|
||||||
cx,
|
cx,
|
||||||
|
@ -1070,7 +1070,7 @@ fn report<'tcx>(
|
||||||
let mut app = Applicability::MachineApplicable;
|
let mut app = Applicability::MachineApplicable;
|
||||||
let (snip, snip_is_macro) =
|
let (snip, snip_is_macro) =
|
||||||
snippet_with_context(cx, expr.span, data.first_expr.span.ctxt(), "..", &mut app);
|
snippet_with_context(cx, expr.span, data.first_expr.span.ctxt(), "..", &mut app);
|
||||||
let sugg = if !snip_is_macro && expr.precedence() < precedence && !has_enclosing_paren(&snip) {
|
let sugg = if !snip_is_macro && needs_paren && !has_enclosing_paren(&snip) {
|
||||||
format!("{prefix}({snip})")
|
format!("{prefix}({snip})")
|
||||||
} else {
|
} else {
|
||||||
format!("{prefix}{snip}")
|
format!("{prefix}{snip}")
|
||||||
|
@ -1157,7 +1157,7 @@ impl<'tcx> Dereferencing<'tcx> {
|
||||||
},
|
},
|
||||||
Some(parent) if !parent.span.from_expansion() => {
|
Some(parent) if !parent.span.from_expansion() => {
|
||||||
// Double reference might be needed at this point.
|
// Double reference might be needed at this point.
|
||||||
if parent.precedence() == PREC_UNAMBIGUOUS {
|
if parent.precedence() == ExprPrecedence::Unambiguous {
|
||||||
// Parentheses would be needed here, don't lint.
|
// Parentheses would be needed here, don't lint.
|
||||||
*outer_pat = None;
|
*outer_pat = None;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -3,7 +3,7 @@ use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||||
use clippy_utils::source::{indent_of, snippet, snippet_with_applicability};
|
use clippy_utils::source::{indent_of, snippet, snippet_with_applicability};
|
||||||
use clippy_utils::visitors::contains_break_or_continue;
|
use clippy_utils::visitors::contains_break_or_continue;
|
||||||
use rustc_ast::Mutability;
|
use rustc_ast::Mutability;
|
||||||
use rustc_ast::util::parser::PREC_PREFIX;
|
use rustc_ast::util::parser::ExprPrecedence;
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
use rustc_hir::{BorrowKind, Expr, ExprKind, Pat, PatKind, is_range_literal};
|
use rustc_hir::{BorrowKind, Expr, ExprKind, Pat, PatKind, is_range_literal};
|
||||||
use rustc_lint::LateContext;
|
use rustc_lint::LateContext;
|
||||||
|
@ -84,7 +84,7 @@ pub(super) fn check<'tcx>(
|
||||||
if !prefix.is_empty()
|
if !prefix.is_empty()
|
||||||
&& (
|
&& (
|
||||||
// Precedence of internal expression is less than or equal to precedence of `&expr`.
|
// Precedence of internal expression is less than or equal to precedence of `&expr`.
|
||||||
arg_expression.precedence() <= PREC_PREFIX || is_range_literal(arg_expression)
|
arg_expression.precedence() <= ExprPrecedence::Prefix || is_range_literal(arg_expression)
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
arg_snip = format!("({arg_snip})").into();
|
arg_snip = format!("({arg_snip})").into();
|
||||||
|
|
|
@ -7,7 +7,7 @@ use clippy_utils::{
|
||||||
CaptureKind, can_move_expr_to_closure, is_else_clause, is_lint_allowed, is_res_lang_ctor, path_res,
|
CaptureKind, can_move_expr_to_closure, is_else_clause, is_lint_allowed, is_res_lang_ctor, path_res,
|
||||||
path_to_local_id, peel_blocks, peel_hir_expr_refs, peel_hir_expr_while,
|
path_to_local_id, peel_blocks, peel_hir_expr_refs, peel_hir_expr_while,
|
||||||
};
|
};
|
||||||
use rustc_ast::util::parser::PREC_UNAMBIGUOUS;
|
use rustc_ast::util::parser::ExprPrecedence;
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
use rustc_hir::LangItem::{OptionNone, OptionSome};
|
use rustc_hir::LangItem::{OptionNone, OptionSome};
|
||||||
use rustc_hir::def::Res;
|
use rustc_hir::def::Res;
|
||||||
|
@ -117,7 +117,7 @@ where
|
||||||
// it's being passed by value.
|
// it's being passed by value.
|
||||||
let scrutinee = peel_hir_expr_refs(scrutinee).0;
|
let scrutinee = peel_hir_expr_refs(scrutinee).0;
|
||||||
let (scrutinee_str, _) = snippet_with_context(cx, scrutinee.span, expr_ctxt, "..", &mut app);
|
let (scrutinee_str, _) = snippet_with_context(cx, scrutinee.span, expr_ctxt, "..", &mut app);
|
||||||
let scrutinee_str = if scrutinee.span.eq_ctxt(expr.span) && scrutinee.precedence() < PREC_UNAMBIGUOUS {
|
let scrutinee_str = if scrutinee.span.eq_ctxt(expr.span) && scrutinee.precedence() < ExprPrecedence::Unambiguous {
|
||||||
format!("({scrutinee_str})")
|
format!("({scrutinee_str})")
|
||||||
} else {
|
} else {
|
||||||
scrutinee_str.into()
|
scrutinee_str.into()
|
||||||
|
|
|
@ -2,7 +2,7 @@ use clippy_utils::consts::{self, Constant};
|
||||||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||||
use clippy_utils::source::snippet_with_context;
|
use clippy_utils::source::snippet_with_context;
|
||||||
use clippy_utils::sugg::has_enclosing_paren;
|
use clippy_utils::sugg::has_enclosing_paren;
|
||||||
use rustc_ast::util::parser::PREC_PREFIX;
|
use rustc_ast::util::parser::ExprPrecedence;
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
use rustc_hir::{BinOpKind, Expr, ExprKind, UnOp};
|
use rustc_hir::{BinOpKind, Expr, ExprKind, UnOp};
|
||||||
use rustc_lint::{LateContext, LateLintPass};
|
use rustc_lint::{LateContext, LateLintPass};
|
||||||
|
@ -58,7 +58,7 @@ fn check_mul(cx: &LateContext<'_>, span: Span, lit: &Expr<'_>, exp: &Expr<'_>) {
|
||||||
{
|
{
|
||||||
let mut applicability = Applicability::MachineApplicable;
|
let mut applicability = Applicability::MachineApplicable;
|
||||||
let (snip, from_macro) = snippet_with_context(cx, exp.span, span.ctxt(), "..", &mut applicability);
|
let (snip, from_macro) = snippet_with_context(cx, exp.span, span.ctxt(), "..", &mut applicability);
|
||||||
let suggestion = if !from_macro && exp.precedence() < PREC_PREFIX && !has_enclosing_paren(&snip) {
|
let suggestion = if !from_macro && exp.precedence() < ExprPrecedence::Prefix && !has_enclosing_paren(&snip) {
|
||||||
format!("-({snip})")
|
format!("-({snip})")
|
||||||
} else {
|
} else {
|
||||||
format!("-{snip}")
|
format!("-{snip}")
|
||||||
|
|
|
@ -2,7 +2,7 @@ use clippy_utils::diagnostics::span_lint_and_then;
|
||||||
use clippy_utils::source::snippet_with_context;
|
use clippy_utils::source::snippet_with_context;
|
||||||
use clippy_utils::ty::is_type_lang_item;
|
use clippy_utils::ty::is_type_lang_item;
|
||||||
use clippy_utils::{get_parent_expr, peel_middle_ty_refs};
|
use clippy_utils::{get_parent_expr, peel_middle_ty_refs};
|
||||||
use rustc_ast::util::parser::PREC_PREFIX;
|
use rustc_ast::util::parser::ExprPrecedence;
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
use rustc_hir::{BorrowKind, Expr, ExprKind, LangItem, Mutability};
|
use rustc_hir::{BorrowKind, Expr, ExprKind, LangItem, Mutability};
|
||||||
use rustc_lint::{LateContext, LateLintPass, Lint};
|
use rustc_lint::{LateContext, LateLintPass, Lint};
|
||||||
|
@ -85,7 +85,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantSlicing {
|
||||||
let (expr_ty, expr_ref_count) = peel_middle_ty_refs(cx.typeck_results().expr_ty(expr));
|
let (expr_ty, expr_ref_count) = peel_middle_ty_refs(cx.typeck_results().expr_ty(expr));
|
||||||
let (indexed_ty, indexed_ref_count) = peel_middle_ty_refs(cx.typeck_results().expr_ty(indexed));
|
let (indexed_ty, indexed_ref_count) = peel_middle_ty_refs(cx.typeck_results().expr_ty(indexed));
|
||||||
let parent_expr = get_parent_expr(cx, expr);
|
let parent_expr = get_parent_expr(cx, expr);
|
||||||
let needs_parens_for_prefix = parent_expr.is_some_and(|parent| parent.precedence() > PREC_PREFIX);
|
let needs_parens_for_prefix = parent_expr.is_some_and(|parent| parent.precedence() > ExprPrecedence::Prefix);
|
||||||
|
|
||||||
if expr_ty == indexed_ty {
|
if expr_ty == indexed_ty {
|
||||||
if expr_ref_count > indexed_ref_count {
|
if expr_ref_count > indexed_ref_count {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use super::TRANSMUTES_EXPRESSIBLE_AS_PTR_CASTS;
|
use super::TRANSMUTES_EXPRESSIBLE_AS_PTR_CASTS;
|
||||||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||||
use clippy_utils::sugg::Sugg;
|
use clippy_utils::sugg::Sugg;
|
||||||
use rustc_ast::util::parser::AssocOp;
|
use rustc_ast::util::parser::ExprPrecedence;
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
use rustc_hir::{Expr, Node};
|
use rustc_hir::{Expr, Node};
|
||||||
use rustc_hir_typeck::cast::check_cast;
|
use rustc_hir_typeck::cast::check_cast;
|
||||||
|
@ -44,8 +44,7 @@ pub(super) fn check<'tcx>(
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Node::Expr(parent) = cx.tcx.parent_hir_node(e.hir_id)
|
if let Node::Expr(parent) = cx.tcx.parent_hir_node(e.hir_id)
|
||||||
&& parent.precedence()
|
&& parent.precedence() > ExprPrecedence::Cast
|
||||||
> i8::try_from(AssocOp::As.precedence()).expect("AssocOp always returns a precedence < 128")
|
|
||||||
{
|
{
|
||||||
sugg = format!("({sugg})");
|
sugg = format!("({sugg})");
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue