Eliminate magic numbers from expression precedence

This commit is contained in:
David Tolnay 2024-11-28 12:47:18 -08:00
parent 539c863eaf
commit 7ced18f329
No known key found for this signature in database
GPG Key ID: F9BA143B95FF6D82
18 changed files with 162 additions and 138 deletions

View File

@ -39,9 +39,7 @@ pub use crate::format::*;
use crate::ptr::P;
use crate::token::{self, CommentKind, Delimiter};
use crate::tokenstream::{DelimSpan, LazyAttrTokenStream, TokenStream};
use crate::util::parser::{
AssocOp, PREC_CLOSURE, PREC_JUMP, PREC_PREFIX, PREC_RANGE, PREC_UNAMBIGUOUS,
};
use crate::util::parser::{AssocOp, ExprPrecedence};
/// A "Label" is an identifier of some point in sources,
/// e.g. in the following code:
@ -1317,29 +1315,29 @@ impl Expr {
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 {
ExprKind::Closure(..) => PREC_CLOSURE,
ExprKind::Closure(..) => ExprPrecedence::Closure,
ExprKind::Break(..)
| ExprKind::Continue(..)
| ExprKind::Ret(..)
| ExprKind::Yield(..)
| ExprKind::Yeet(..)
| ExprKind::Become(..) => PREC_JUMP,
| ExprKind::Become(..) => ExprPrecedence::Jump,
// `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
// ensures that `pprust` will add parentheses in the right places to get the desired
// parse.
ExprKind::Range(..) => PREC_RANGE,
ExprKind::Range(..) => ExprPrecedence::Range,
// Binop-like expr kinds, handled by `AssocOp`.
ExprKind::Binary(op, ..) => AssocOp::from_ast_binop(op.node).precedence() as i8,
ExprKind::Cast(..) => AssocOp::As.precedence() as i8,
ExprKind::Binary(op, ..) => AssocOp::from_ast_binop(op.node).precedence(),
ExprKind::Cast(..) => ExprPrecedence::Cast,
ExprKind::Assign(..) |
ExprKind::AssignOp(..) => AssocOp::Assign.precedence() as i8,
ExprKind::AssignOp(..) => ExprPrecedence::Assign,
// Unary, prefix
ExprKind::AddrOf(..)
@ -1348,7 +1346,7 @@ impl Expr {
// 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.
| ExprKind::Let(..)
| ExprKind::Unary(..) => PREC_PREFIX,
| ExprKind::Unary(..) => ExprPrecedence::Prefix,
// Never need parens
ExprKind::Array(_)
@ -1381,7 +1379,7 @@ impl Expr {
| ExprKind::Underscore
| ExprKind::While(..)
| ExprKind::Err(_)
| ExprKind::Dummy => PREC_UNAMBIGUOUS,
| ExprKind::Dummy => ExprPrecedence::Unambiguous,
}
}

View File

@ -128,21 +128,21 @@ impl AssocOp {
}
/// Gets the precedence of this operator
pub fn precedence(&self) -> usize {
pub fn precedence(&self) -> ExprPrecedence {
use AssocOp::*;
match *self {
As => 14,
Multiply | Divide | Modulus => 13,
Add | Subtract => 12,
ShiftLeft | ShiftRight => 11,
BitAnd => 10,
BitXor => 9,
BitOr => 8,
Less | Greater | LessEqual | GreaterEqual | Equal | NotEqual => 7,
LAnd => 6,
LOr => 5,
DotDot | DotDotEq => 4,
Assign | AssignOp(_) => 2,
As => ExprPrecedence::Cast,
Multiply | Divide | Modulus => ExprPrecedence::Product,
Add | Subtract => ExprPrecedence::Sum,
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,
}
}
@ -229,16 +229,44 @@ impl AssocOp {
}
}
pub const PREC_CLOSURE: i8 = -40;
pub const PREC_JUMP: i8 = -30;
pub const PREC_RANGE: i8 = -10;
// The range 2..=14 is reserved for AssocOp binary operator precedences.
pub const PREC_PREFIX: i8 = 50;
pub const PREC_UNAMBIGUOUS: i8 = 60;
#[derive(Clone, Copy, PartialEq, PartialOrd)]
pub enum ExprPrecedence {
Closure,
// return, break, yield
Jump,
// = += -= *= /= %= &= |= ^= <<= >>=
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`.
pub fn prec_let_scrutinee_needs_par() -> usize {
AssocOp::LAnd.precedence()
pub fn prec_let_scrutinee_needs_par() -> ExprPrecedence {
ExprPrecedence::LAnd
}
/// 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`.
/// Can we print this as `let _ = a OP b`?
pub fn needs_par_as_let_scrutinee(order: i8) -> bool {
order <= prec_let_scrutinee_needs_par() as i8
pub fn needs_par_as_let_scrutinee(order: ExprPrecedence) -> bool {
order <= prec_let_scrutinee_needs_par()
}
/// Expressions that syntactically contain an "exterior" struct literal i.e., not surrounded by any

View File

@ -5,7 +5,7 @@ use itertools::{Itertools, Position};
use rustc_ast::ptr::P;
use rustc_ast::util::classify;
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::{
self as ast, BlockCheckMode, FormatAlignment, FormatArgPosition, FormatArgsPiece, FormatCount,
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) {
let needs_paren = match func.kind {
ast::ExprKind::Field(..) => true,
_ => func.precedence() < parser::PREC_UNAMBIGUOUS,
_ => func.precedence() < ExprPrecedence::Unambiguous,
};
// Independent of parenthesization related to precedence, we must
@ -256,7 +256,7 @@ impl<'a> State<'a> {
// a statement containing an expression.
self.print_expr_cond_paren(
receiver,
receiver.precedence() < parser::PREC_UNAMBIGUOUS,
receiver.precedence() < ExprPrecedence::Unambiguous,
fixup,
);
@ -276,7 +276,7 @@ impl<'a> State<'a> {
fixup: FixupContext,
) {
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 right_prec = rhs.precedence();
@ -317,7 +317,7 @@ impl<'a> State<'a> {
self.word(op.as_str());
self.print_expr_cond_paren(
expr,
expr.precedence() < parser::PREC_PREFIX,
expr.precedence() < ExprPrecedence::Prefix,
fixup.subsequent_subexpression(),
);
}
@ -339,7 +339,7 @@ impl<'a> State<'a> {
}
self.print_expr_cond_paren(
expr,
expr.precedence() < parser::PREC_PREFIX,
expr.precedence() < ExprPrecedence::Prefix,
fixup.subsequent_subexpression(),
);
}
@ -423,10 +423,9 @@ impl<'a> State<'a> {
self.print_token_literal(lit, expr.span)
}
ast::ExprKind::Cast(expr, ty) => {
let prec = AssocOp::As.precedence() as i8;
self.print_expr_cond_paren(
expr,
expr.precedence() < prec,
expr.precedence() < ExprPrecedence::Cast,
fixup.leftmost_subexpression(),
);
self.space();
@ -503,7 +502,7 @@ impl<'a> State<'a> {
MatchKind::Postfix => {
self.print_expr_cond_paren(
expr,
expr.precedence() < parser::PREC_UNAMBIGUOUS,
expr.precedence() < ExprPrecedence::Unambiguous,
fixup,
);
self.word_nbsp(".match");
@ -567,31 +566,31 @@ impl<'a> State<'a> {
ast::ExprKind::Await(expr, _) => {
self.print_expr_cond_paren(
expr,
expr.precedence() < parser::PREC_UNAMBIGUOUS,
expr.precedence() < ExprPrecedence::Unambiguous,
fixup,
);
self.word(".await");
}
ast::ExprKind::Assign(lhs, rhs, _) => {
let prec = AssocOp::Assign.precedence() as i8;
self.print_expr_cond_paren(
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(),
);
self.space();
self.word_space("=");
self.print_expr_cond_paren(
rhs,
rhs.precedence() < prec,
rhs.precedence() < ExprPrecedence::Assign,
fixup.subsequent_subexpression(),
);
}
ast::ExprKind::AssignOp(op, lhs, rhs) => {
let prec = AssocOp::Assign.precedence() as i8;
self.print_expr_cond_paren(
lhs,
lhs.precedence() <= prec,
lhs.precedence() <= ExprPrecedence::Range,
fixup.leftmost_subexpression(),
);
self.space();
@ -599,14 +598,14 @@ impl<'a> State<'a> {
self.word_space("=");
self.print_expr_cond_paren(
rhs,
rhs.precedence() < prec,
rhs.precedence() < ExprPrecedence::Assign,
fixup.subsequent_subexpression(),
);
}
ast::ExprKind::Field(expr, ident) => {
self.print_expr_cond_paren(
expr,
expr.precedence() < parser::PREC_UNAMBIGUOUS,
expr.precedence() < ExprPrecedence::Unambiguous,
fixup,
);
self.word(".");
@ -615,7 +614,7 @@ impl<'a> State<'a> {
ast::ExprKind::Index(expr, index, _) => {
self.print_expr_cond_paren(
expr,
expr.precedence() < parser::PREC_UNAMBIGUOUS,
expr.precedence() < ExprPrecedence::Unambiguous,
fixup.leftmost_subexpression(),
);
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)`.
// 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.)
let fake_prec = AssocOp::LOr.precedence() as i8;
let fake_prec = ExprPrecedence::LOr;
if let Some(e) = start {
self.print_expr_cond_paren(
e,
@ -662,7 +661,7 @@ impl<'a> State<'a> {
expr,
// Parenthesize if required by precedence, or in the
// 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)),
fixup.subsequent_subexpression(),
);
@ -681,7 +680,7 @@ impl<'a> State<'a> {
self.word(" ");
self.print_expr_cond_paren(
expr,
expr.precedence() < parser::PREC_JUMP,
expr.precedence() < ExprPrecedence::Jump,
fixup.subsequent_subexpression(),
);
}
@ -694,7 +693,7 @@ impl<'a> State<'a> {
self.word(" ");
self.print_expr_cond_paren(
expr,
expr.precedence() < parser::PREC_JUMP,
expr.precedence() < ExprPrecedence::Jump,
fixup.subsequent_subexpression(),
);
}
@ -704,7 +703,7 @@ impl<'a> State<'a> {
self.word(" ");
self.print_expr_cond_paren(
result,
result.precedence() < parser::PREC_JUMP,
result.precedence() < ExprPrecedence::Jump,
fixup.subsequent_subexpression(),
);
}
@ -758,13 +757,13 @@ impl<'a> State<'a> {
self.space();
self.print_expr_cond_paren(
expr,
expr.precedence() < parser::PREC_JUMP,
expr.precedence() < ExprPrecedence::Jump,
fixup.subsequent_subexpression(),
);
}
}
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("?")
}
ast::ExprKind::TryBlock(blk) => {

View File

@ -6,6 +6,7 @@ use std::path::{Path, PathBuf};
use std::process::ExitStatus;
use rustc_abi::TargetDataLayoutErrors;
use rustc_ast::util::parser::ExprPrecedence;
use rustc_ast_pretty::pprust;
use rustc_macros::Subdiagnostic;
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)]
pub struct DiagSymbolList<S = Symbol>(Vec<S>);

View File

@ -1,7 +1,7 @@
use std::fmt;
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::{
self as ast, Attribute, FloatTy, InlineAsmOptions, InlineAsmTemplatePiece, IntTy, Label,
LitKind, TraitObjectSyntax, UintTy,
@ -1708,22 +1708,22 @@ pub struct Expr<'hir> {
}
impl Expr<'_> {
pub fn precedence(&self) -> i8 {
pub fn precedence(&self) -> ExprPrecedence {
match self.kind {
ExprKind::Closure { .. } => PREC_CLOSURE,
ExprKind::Closure { .. } => ExprPrecedence::Closure,
ExprKind::Break(..)
| ExprKind::Continue(..)
| ExprKind::Ret(..)
| ExprKind::Yield(..)
| ExprKind::Become(..) => PREC_JUMP,
| ExprKind::Become(..) => ExprPrecedence::Jump,
// Binop-like expr kinds, handled by `AssocOp`.
ExprKind::Binary(op, ..) => AssocOp::from_ast_binop(op.node).precedence() as i8,
ExprKind::Cast(..) => AssocOp::As.precedence() as i8,
ExprKind::Binary(op, ..) => AssocOp::from_ast_binop(op.node).precedence(),
ExprKind::Cast(..) => ExprPrecedence::Cast,
ExprKind::Assign(..) |
ExprKind::AssignOp(..) => AssocOp::Assign.precedence() as i8,
ExprKind::AssignOp(..) => ExprPrecedence::Assign,
// Unary, prefix
ExprKind::AddrOf(..)
@ -1732,7 +1732,7 @@ impl Expr<'_> {
// 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.
| ExprKind::Let(..)
| ExprKind::Unary(..) => PREC_PREFIX,
| ExprKind::Unary(..) => ExprPrecedence::Prefix,
// Never need parens
ExprKind::Array(_)
@ -1753,7 +1753,7 @@ impl Expr<'_> {
| ExprKind::Struct(..)
| ExprKind::Tup(_)
| ExprKind::Type(..)
| ExprKind::Err(_) => PREC_UNAMBIGUOUS,
| ExprKind::Err(_) => ExprPrecedence::Unambiguous,
ExprKind::DropTemps(ref expr, ..) => expr.precedence(),
}

View File

@ -10,7 +10,7 @@ use std::cell::Cell;
use std::vec;
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::{self, Breaks};
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<'_>]) {
let needs_paren = match func.kind {
hir::ExprKind::Field(..) => true,
_ => func.precedence() < parser::PREC_UNAMBIGUOUS,
_ => func.precedence() < ExprPrecedence::Unambiguous,
};
self.print_expr_cond_paren(func, needs_paren);
@ -1148,7 +1148,7 @@ impl<'a> State<'a> {
args: &[hir::Expr<'_>],
) {
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.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<'_>) {
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 right_prec = rhs.precedence();
@ -1193,7 +1193,7 @@ impl<'a> State<'a> {
fn print_expr_unary(&mut self, op: hir::UnOp, expr: &hir::Expr<'_>) {
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(
@ -1210,7 +1210,7 @@ impl<'a> State<'a> {
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) {
@ -1348,8 +1348,7 @@ impl<'a> State<'a> {
self.print_literal(lit);
}
hir::ExprKind::Cast(expr, ty) => {
let prec = AssocOp::As.precedence() as i8;
self.print_expr_cond_paren(expr, expr.precedence() < prec);
self.print_expr_cond_paren(expr, expr.precedence() < ExprPrecedence::Cast);
self.space();
self.word_space("as");
self.print_type(ty);
@ -1450,27 +1449,25 @@ impl<'a> State<'a> {
self.print_block(blk);
}
hir::ExprKind::Assign(lhs, rhs, _) => {
let prec = AssocOp::Assign.precedence() as i8;
self.print_expr_cond_paren(lhs, lhs.precedence() <= prec);
self.print_expr_cond_paren(lhs, lhs.precedence() <= ExprPrecedence::Assign);
self.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) => {
let prec = AssocOp::Assign.precedence() as i8;
self.print_expr_cond_paren(lhs, lhs.precedence() <= prec);
self.print_expr_cond_paren(lhs, lhs.precedence() <= ExprPrecedence::Assign);
self.space();
self.word(op.node.as_str());
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) => {
self.print_expr_cond_paren(expr, expr.precedence() < parser::PREC_UNAMBIGUOUS);
self.print_expr_cond_paren(expr, expr.precedence() < ExprPrecedence::Unambiguous);
self.word(".");
self.print_ident(ident);
}
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.print_expr(index);
self.word("]");
@ -1484,7 +1481,7 @@ impl<'a> State<'a> {
}
if let Some(expr) = opt_expr {
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) => {
@ -1498,13 +1495,13 @@ impl<'a> State<'a> {
self.word("return");
if let Some(expr) = result {
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) => {
self.word("become");
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) => {
self.word("asm!");
@ -1529,7 +1526,7 @@ impl<'a> State<'a> {
}
hir::ExprKind::Yield(expr, _) => {
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(_) => {
self.popen();

View File

@ -1,6 +1,6 @@
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_hir::def::{self, CtorKind, Namespace, Res};
use rustc_hir::def_id::DefId;
@ -606,7 +606,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
};
if let Ok(rest_snippet) = rest_snippet {
let sugg = if callee_expr.precedence() >= PREC_UNAMBIGUOUS {
let sugg = if callee_expr.precedence() >= ExprPrecedence::Unambiguous {
vec![
(up_to_rcvr_span, "".to_string()),
(rest_span, format!(".{}({rest_snippet}", segment.ident)),

View File

@ -28,6 +28,7 @@
//! expression, `e as U2` is not necessarily so (in fact it will only be valid if
//! `U1` coerces to `U2`).
use rustc_ast::util::parser::ExprPrecedence;
use rustc_data_structures::fx::FxHashSet;
use rustc_errors::codes::*;
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) {
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 cast_span = self.expr_span.shrink_to_hi().to(self.cast_span);

View File

@ -2,7 +2,7 @@ use core::cmp::min;
use core::iter;
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_errors::{Applicability, Diag, MultiSpan};
use rustc_hir as hir;
@ -398,7 +398,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// so we remove the user's `clone` call.
{
vec![(receiver_method.ident.span, conversion_method.name.to_string())]
} else if expr.precedence() < PREC_UNAMBIGUOUS {
} else if expr.precedence() < ExprPrecedence::Unambiguous {
vec![
(expr.span.shrink_to_lo(), "(".to_string()),
(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 mut sugg = if expr.precedence() >= PREC_UNAMBIGUOUS {
let mut sugg = if expr.precedence() >= ExprPrecedence::Unambiguous {
vec![(span.shrink_to_hi(), ".into()".to_owned())]
} else {
vec![
@ -3000,7 +3000,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
"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()));
")"
} else {
@ -3025,7 +3025,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let len = src.trim_end_matches(&checked_ty.to_string()).len();
expr.span.with_lo(expr.span.lo() + BytePos(len as u32))
},
if expr.precedence() < PREC_UNAMBIGUOUS {
if expr.precedence() < ExprPrecedence::Unambiguous {
// Readd `)`
format!("{expected_ty})")
} else {

View File

@ -3,6 +3,7 @@
use std::borrow::Cow;
use rustc_ast::token::Token;
use rustc_ast::util::parser::ExprPrecedence;
use rustc_ast::{Path, Visibility};
use rustc_errors::codes::*;
use rustc_errors::{
@ -2686,7 +2687,7 @@ pub(crate) struct UnexpectedExpressionInPattern {
/// Was a `RangePatternBound` expected?
pub is_bound: bool,
/// The unexpected expr's precedence (used in match arm guard suggestions).
pub expr_precedence: i8,
pub expr_precedence: ExprPrecedence,
}
#[derive(Subdiagnostic)]

View File

@ -10,7 +10,7 @@ use rustc_ast::ptr::P;
use rustc_ast::token::{self, Delimiter, Token, TokenKind};
use rustc_ast::util::case::Case;
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::{
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`).
pub(super) fn parse_expr_assoc_with(
&mut self,
min_prec: Bound<usize>,
min_prec: Bound<ExprPrecedence>,
attrs: AttrWrapper,
) -> PResult<'a, (P<Expr>, bool)> {
let lhs = if self.token.is_range_separator() {
@ -144,7 +144,7 @@ impl<'a> Parser<'a> {
/// was actually parsed.
pub(super) fn parse_expr_assoc_rest_with(
&mut self,
min_prec: Bound<usize>,
min_prec: Bound<ExprPrecedence>,
starts_stmt: bool,
mut lhs: P<Expr>,
) -> 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.
fn parse_expr_range(
&mut self,
prec: usize,
prec: ExprPrecedence,
lhs: P<Expr>,
op: AssocOp,
cur_op_span: Span,

View File

@ -3,12 +3,11 @@ use std::ops::Bound;
use rustc_ast::mut_visit::{self, MutVisitor};
use rustc_ast::ptr::P;
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::{
self as ast, Arm, AttrVec, BinOpKind, BindingMode, ByRef, Expr, ExprKind, LocalKind, MacCall,
Mutability, Pat, PatField, PatFieldsRest, PatKind, Path, QSelf, RangeEnd, RangeSyntax, Stmt,
StmtKind,
self as ast, Arm, AttrVec, BindingMode, ByRef, Expr, ExprKind, LocalKind, MacCall, Mutability,
Pat, PatField, PatFieldsRest, PatKind, Path, QSelf, RangeEnd, RangeSyntax, Stmt, StmtKind,
};
use rustc_ast_pretty::pprust;
use rustc_errors::{Applicability, Diag, DiagArgValue, PResult, StashKey};
@ -548,10 +547,7 @@ impl<'a> Parser<'a> {
// HACK: a neater way would be preferable.
let expr = match &err.args["expr_precedence"] {
DiagArgValue::Number(expr_precedence) => {
if *expr_precedence
<= AssocOp::from_ast_binop(BinOpKind::Eq).precedence()
as i32
{
if *expr_precedence <= ExprPrecedence::Compare as i32 {
format!("({expr})")
} else {
format!("{expr}")
@ -573,9 +569,7 @@ impl<'a> Parser<'a> {
}
Some(guard) => {
// Are parentheses required around the old guard?
let wrap_guard = guard.precedence()
<= AssocOp::from_ast_binop(BinOpKind::And).precedence()
as i8;
let wrap_guard = guard.precedence() <= ExprPrecedence::LAnd;
err.subdiagnostic(
UnexpectedExpressionInPatternSugg::UpdateGuard {

View File

@ -7,7 +7,7 @@ use clippy_utils::{
peel_middle_ty_refs,
};
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_errors::Applicability;
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.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})"))
} else {
expr_str
@ -999,13 +999,13 @@ fn report<'tcx>(
data.first_expr.span,
state.msg,
|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 {
ExprKind::Call(callee, _) if callee.hir_id != data.first_expr.hir_id => (0, false),
ExprKind::Call(..) => (PREC_UNAMBIGUOUS, matches!(expr.kind, ExprKind::Field(..))),
_ => (e.precedence(), false),
ExprKind::Call(callee, _) if callee.hir_id != data.first_expr.hir_id => false,
ExprKind::Call(..) => expr.precedence() < ExprPrecedence::Unambiguous || matches!(expr.kind, ExprKind::Field(..)),
_ => expr.precedence() < e.precedence(),
},
_ => (0, false),
_ => false,
};
let is_in_tuple = matches!(
get_parent_expr(cx, data.first_expr),
@ -1016,7 +1016,7 @@ fn report<'tcx>(
);
let sugg = if !snip_is_macro
&& (calls_field || expr.precedence() < precedence)
&& needs_paren
&& !has_enclosing_paren(&snip)
&& !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() => {
let prefix = match mutability {
Mutability::Not => "&",
Mutability::Mut => "&mut ",
};
(prefix, PREC_PREFIX)
(prefix, expr.precedence() < ExprPrecedence::Prefix)
},
None if !ty.is_ref() && data.adjusted_ty.is_ref() => ("&", 0),
_ => ("", 0),
None if !ty.is_ref() && data.adjusted_ty.is_ref() => ("&", false),
_ => ("", false),
};
span_lint_hir_and_then(
cx,
@ -1070,7 +1070,7 @@ fn report<'tcx>(
let mut app = Applicability::MachineApplicable;
let (snip, snip_is_macro) =
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})")
} else {
format!("{prefix}{snip}")
@ -1157,7 +1157,7 @@ impl<'tcx> Dereferencing<'tcx> {
},
Some(parent) if !parent.span.from_expansion() => {
// 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.
*outer_pat = None;
} else {

View File

@ -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::visitors::contains_break_or_continue;
use rustc_ast::Mutability;
use rustc_ast::util::parser::PREC_PREFIX;
use rustc_ast::util::parser::ExprPrecedence;
use rustc_errors::Applicability;
use rustc_hir::{BorrowKind, Expr, ExprKind, Pat, PatKind, is_range_literal};
use rustc_lint::LateContext;
@ -84,7 +84,7 @@ pub(super) fn check<'tcx>(
if !prefix.is_empty()
&& (
// 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();

View File

@ -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,
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_hir::LangItem::{OptionNone, OptionSome};
use rustc_hir::def::Res;
@ -117,7 +117,7 @@ where
// it's being passed by value.
let scrutinee = peel_hir_expr_refs(scrutinee).0;
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})")
} else {
scrutinee_str.into()

View File

@ -2,7 +2,7 @@ use clippy_utils::consts::{self, Constant};
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::snippet_with_context;
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_hir::{BinOpKind, Expr, ExprKind, UnOp};
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 (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})")
} else {
format!("-{snip}")

View File

@ -2,7 +2,7 @@ use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::source::snippet_with_context;
use clippy_utils::ty::is_type_lang_item;
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_hir::{BorrowKind, Expr, ExprKind, LangItem, Mutability};
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 (indexed_ty, indexed_ref_count) = peel_middle_ty_refs(cx.typeck_results().expr_ty(indexed));
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_ref_count > indexed_ref_count {

View File

@ -1,7 +1,7 @@
use super::TRANSMUTES_EXPRESSIBLE_AS_PTR_CASTS;
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::sugg::Sugg;
use rustc_ast::util::parser::AssocOp;
use rustc_ast::util::parser::ExprPrecedence;
use rustc_errors::Applicability;
use rustc_hir::{Expr, Node};
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)
&& parent.precedence()
> i8::try_from(AssocOp::As.precedence()).expect("AssocOp always returns a precedence < 128")
&& parent.precedence() > ExprPrecedence::Cast
{
sugg = format!("({sugg})");
}