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::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,
} }
} }

View file

@ -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

View file

@ -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) => {

View file

@ -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>);

View file

@ -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(),
} }

View file

@ -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();

View file

@ -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)),

View file

@ -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);

View file

@ -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 {

View file

@ -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)]

View file

@ -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,

View file

@ -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 {

View file

@ -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 {

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::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();

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, 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()

View file

@ -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}")

View file

@ -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 {

View file

@ -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})");
} }