Skip to content

Commit 01b3c24

Browse files
authored
Rollup merge of rust-lang#126893 - dtolnay:prec, r=compiler-errors
Eliminate the distinction between PREC_POSTFIX and PREC_PAREN precedence level I have been tangling with precedence as part of porting some pretty-printer improvements from syn back to rustc (related to parenthesization of closures, returns, and breaks by the AST pretty-printer). As far as I have been able to tell, there is no difference between the 2 different precedence levels that rustc identifies as `PREC_POSTFIX` (field access, square bracket index, question mark, method call) and `PREC_PAREN` (loops, if, paths, literals). There are a bunch of places that look at either `prec < PREC_POSTFIX` or `prec >= PREC_POSTFIX`. But there is nothing that needs to distinguish PREC_POSTFIX and PREC_PAREN from one another. https://github.com/rust-lang/rust/blob/d49994b060684af423339b55769439b2f444a7b9/compiler/rustc_ast/src/util/parser.rs#L236-L237 https://github.com/rust-lang/rust/blob/d49994b060684af423339b55769439b2f444a7b9/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs#L2829 https://github.com/rust-lang/rust/blob/d49994b060684af423339b55769439b2f444a7b9/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs#L1290 In the interest of eliminating a distinction without a difference, this PR collapses these 2 levels down to 1. There is exactly 1 case where an expression with PREC_POSTFIX precedence needs to be parenthesized in a location that an expression with PREC_PAREN would not, and that's when the receiver of ExprKind::MethodCall is ExprKind::Field. `x.f()` means a different thing than `(x.f)()`. But this does not justify having separate precedence levels because this special case in the grammar is not governed by precedence. Field access does not have "lower precedence than" method call syntax &mdash; you can tell because if it did, then `x.f[0].f()` wouldn't be able to have its unparenthesized field access in the receiver of a method call. Because this Field/MethodCall special case is not governed by precedence, it already requires special handling and is not affected by eliminating the PREC_POSTFIX precedence level. https://github.com/rust-lang/rust/blob/d49994b060684af423339b55769439b2f444a7b9/compiler/rustc_ast_pretty/src/pprust/state/expr.rs#L217-L221
2 parents dfaa53f + 35ec4eb commit 01b3c24

File tree

2 files changed

+5
-5
lines changed

2 files changed

+5
-5
lines changed

clippy_lints/src/dereference.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use clippy_utils::{
66
expr_use_ctxt, get_parent_expr, is_block_like, is_lint_allowed, path_to_local, DefinedTy, ExprUseNode,
77
};
88
use core::mem;
9-
use rustc_ast::util::parser::{PREC_POSTFIX, PREC_PREFIX};
9+
use rustc_ast::util::parser::{PREC_UNAMBIGUOUS, PREC_PREFIX};
1010
use rustc_data_structures::fx::FxIndexMap;
1111
use rustc_errors::Applicability;
1212
use rustc_hir::intravisit::{walk_ty, Visitor};
@@ -1013,7 +1013,7 @@ fn report<'tcx>(
10131013
let (precedence, calls_field) = match cx.tcx.parent_hir_node(data.first_expr.hir_id) {
10141014
Node::Expr(e) => match e.kind {
10151015
ExprKind::Call(callee, _) if callee.hir_id != data.first_expr.hir_id => (0, false),
1016-
ExprKind::Call(..) => (PREC_POSTFIX, matches!(expr.kind, ExprKind::Field(..))),
1016+
ExprKind::Call(..) => (PREC_UNAMBIGUOUS, matches!(expr.kind, ExprKind::Field(..))),
10171017
_ => (e.precedence().order(), false),
10181018
},
10191019
_ => (0, false),
@@ -1160,7 +1160,7 @@ impl<'tcx> Dereferencing<'tcx> {
11601160
},
11611161
Some(parent) if !parent.span.from_expansion() => {
11621162
// Double reference might be needed at this point.
1163-
if parent.precedence().order() == PREC_POSTFIX {
1163+
if parent.precedence().order() == PREC_UNAMBIGUOUS {
11641164
// Parentheses would be needed here, don't lint.
11651165
*outer_pat = None;
11661166
} else {

clippy_lints/src/matches/manual_utils.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use clippy_utils::{
77
can_move_expr_to_closure, is_else_clause, is_lint_allowed, is_res_lang_ctor, path_res, path_to_local_id,
88
peel_blocks, peel_hir_expr_refs, peel_hir_expr_while, CaptureKind,
99
};
10-
use rustc_ast::util::parser::PREC_POSTFIX;
10+
use rustc_ast::util::parser::PREC_UNAMBIGUOUS;
1111
use rustc_errors::Applicability;
1212
use rustc_hir::def::Res;
1313
use rustc_hir::LangItem::{OptionNone, OptionSome};
@@ -117,7 +117,7 @@ where
117117
// it's being passed by value.
118118
let scrutinee = peel_hir_expr_refs(scrutinee).0;
119119
let (scrutinee_str, _) = snippet_with_context(cx, scrutinee.span, expr_ctxt, "..", &mut app);
120-
let scrutinee_str = if scrutinee.span.eq_ctxt(expr.span) && scrutinee.precedence().order() < PREC_POSTFIX {
120+
let scrutinee_str = if scrutinee.span.eq_ctxt(expr.span) && scrutinee.precedence().order() < PREC_UNAMBIGUOUS {
121121
format!("({scrutinee_str})")
122122
} else {
123123
scrutinee_str.into()

0 commit comments

Comments
 (0)