about summary refs log tree commit diff
path: root/compiler/rustc_ast_pretty
diff options
context:
space:
mode:
authorDavid Tolnay <dtolnay@gmail.com>2025-06-13 13:00:46 -0700
committerDavid Tolnay <dtolnay@gmail.com>2025-06-20 13:49:12 -0700
commit12a855d2c8420032700c5e3df32d07e0e12d3647 (patch)
tree7f2e6a612739708b475dee6118e42ecc7ec24ca6 /compiler/rustc_ast_pretty
parentcbef8f6e0745e7ee5bcd91a482a3152a2b1dd23b (diff)
downloadrust-12a855d2c8420032700c5e3df32d07e0e12d3647.tar.gz
rust-12a855d2c8420032700c5e3df32d07e0e12d3647.zip
Insert parentheses around binary operation with attribute
Diffstat (limited to 'compiler/rustc_ast_pretty')
-rw-r--r--compiler/rustc_ast_pretty/src/pprust/state/expr.rs50
1 files changed, 38 insertions, 12 deletions
diff --git a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs
index ee49246a4bb..f6b5ff404db 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs
@@ -386,18 +386,44 @@ impl<'a> State<'a> {
 
         let ib = self.ibox(INDENT_UNIT);
 
-        // The Match subexpression in `match x {} - 1` must be parenthesized if
-        // it is the leftmost subexpression in a statement:
-        //
-        //     (match x {}) - 1;
-        //
-        // But not otherwise:
-        //
-        //     let _ = match x {} - 1;
-        //
-        // Same applies to a small set of other expression kinds which eagerly
-        // terminate a statement which opens with them.
-        let needs_par = fixup.would_cause_statement_boundary(expr);
+        let needs_par = {
+            // The Match subexpression in `match x {} - 1` must be parenthesized
+            // if it is the leftmost subexpression in a statement:
+            //
+            //     (match x {}) - 1;
+            //
+            // But not otherwise:
+            //
+            //     let _ = match x {} - 1;
+            //
+            // Same applies to a small set of other expression kinds which
+            // eagerly terminate a statement which opens with them.
+            fixup.would_cause_statement_boundary(expr)
+        } || {
+            // If a binary operation ends up with an attribute, such as
+            // resulting from the following macro expansion, then parentheses
+            // are required so that the attribute encompasses the right
+            // subexpression and not just the left one.
+            //
+            //     #![feature(stmt_expr_attributes)]
+            //
+            //     macro_rules! add_attr {
+            //         ($e:expr) => { #[attr] $e };
+            //     }
+            //
+            //     let _ = add_attr!(1 + 1);
+            //
+            // We must pretty-print `#[attr] (1 + 1)` not `#[attr] 1 + 1`.
+            !attrs.is_empty()
+                && matches!(
+                    expr.kind,
+                    ast::ExprKind::Binary(..)
+                        | ast::ExprKind::Cast(..)
+                        | ast::ExprKind::Assign(..)
+                        | ast::ExprKind::AssignOp(..)
+                        | ast::ExprKind::Range(..)
+                )
+        };
         if needs_par {
             self.popen();
             fixup = FixupContext::default();