1
Fork 0

Rollup merge of #133603 - dtolnay:precedence, r=lcnr

Eliminate magic numbers from expression precedence

Context: see https://github.com/rust-lang/rust/pull/133140.

This PR continues on backporting Syn's expression precedence design into rustc. Rustc's design used mysterious integer quantities represented variously as `i8` or `usize` (e.g. `PREC_CLOSURE = -40i8`), a special significance around `0` that is never named, and an extra `PREC_FORCE_PAREN` precedence level that does not correspond to any expression. Syn's design uses a C-like enum with variants that clearly correspond to specific sets of expression kinds.

This PR is a refactoring that has no intended behavior change on its own, but it unblocks other precedence work that rustc's precedence design was poorly suited to accommodate.

- Asymmetrical precedence, so that a pretty-printer can tell `(return 1) + 1` needs parens but `1 + return 1` does not.

- Squashing the `Closure` and `Jump` cases into a single precedence level.

- Numerous remaining false positives and false negatives in rustc pretty-printer's parenthesization of macro metavariables, for example in `$e < rhs` where $e is `lhs as Thing<T>`.

FYI `@fmease` &mdash; you don't need to review if rustbot picks someone else, but you mentioned being interested in the followup PRs.
This commit is contained in:
Guillaume Gomez 2024-12-02 17:36:03 +01:00 committed by GitHub
commit 7dd0c8314d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
19 changed files with 220 additions and 196 deletions

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,
@ -1695,22 +1695,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(..)
@ -1719,7 +1719,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(_)
@ -1740,7 +1740,7 @@ impl Expr<'_> {
| ExprKind::Struct(..)
| ExprKind::Tup(_)
| ExprKind::Type(..)
| ExprKind::Err(_) => PREC_UNAMBIGUOUS,
| ExprKind::Err(_) => ExprPrecedence::Unambiguous,
ExprKind::DropTemps(ref expr, ..) => expr.precedence(),
}