Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork14.5k
Comments
Reduce precedence of expressions that have an outer attr#134661
Reduce precedence of expressions that have an outer attr#134661bors merged 2 commits intorust-lang:masterfrom
Conversation
rustbot commentedDec 22, 2024
rustbot has assigned@fee1-dead. Use |
This comment has been minimized.
This comment has been minimized.
rustbot commentedDec 22, 2024
Some changes occurred in src/tools/clippy cc @rust-lang/clippy |
fee1-dead commentedDec 23, 2024
r? compiler |
bors commentedDec 26, 2024
☔ The latest upstream changes (presumably#134788) made this pull request unmergeable. Pleaseresolve the merge conflicts. |
dtolnay commentedDec 26, 2024
Rebased to resolve conflict. |
fmease commentedDec 28, 2024
I'm going to look at this in a few hours. |
| fn prefix_attrs_precedence(attrs: &AttrVec) -> ExprPrecedence { | ||
| for attr in attrs { | ||
| if let AttrStyle::Outer = attr.style { | ||
| return ExprPrecedence::Prefix; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
I thinkExprPrecedence::Prefix isn't low enough. Consider the following cases involving binops:
#![feature(stmt_expr_attributes)]macro_rules! group{($e:expr) =>{ $e}}macro_rules! extra{($e:expr) =>{ #[allow()] $e}}fnmain(){// `-Zunpretty=expanded` on master & prefixattr:let _ = #[allow()]1 +1;// let _ = #[allow()] 1 + 1;let _ =group!(#[allow()]1) +1;// let _ = #[allow()] 1 + 1;let _ =1 +group!(#[allow()]1);// let _ = 1 + #[allow()] 1;let _ =extra!({0}) +1;// let _ = #[allow()] { 0 } + 1;let _ =extra!({0} +1);// let _ = #[allow()] { 0 } + 1;}
I haven't given it that much thought yet, so I don't know which specific precedence level(s) would make sense instead.
And indeed, this example is heavily inspired by the ones found in#15701 /#127436. So maybe answering this pretty-printing question is partially blocked by the open design question (meaning we can ignore it for now).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
I think that bug is orthogonal to this one.
The bug fixed by this PR is about when an outer expression A contains a subexpression B where B contains an attribute, and in the prettyprinter-produced code the attribute ended up applying to parts of A instead of only to B. This is fixed by having A observe a different effective precedence for its subexpression B, making A generate parentheses around the subexpression containing the attribute, i.e. the attribute will end upinside the parentheses.
In contrast, the bug you have identified is about an outer expression A that has an attribute, and a subexpression B that has no attribute. In this case when parentheses are inserted, the attribute will end upoutside the parentheses.
I will fix that as well but I expect it will involve unrelated code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Fix:#142476
bors commentedFeb 19, 2025
☔ The latest upstream changes (presumably#137235) made this pull request unmergeable. Pleaseresolve the merge conflicts. |
wesleywiser commentedJun 12, 2025
Hi@fmease, it looks like you marked this as waiting on review recently. Is this actually waiting on review or for the author to respond to your previous review comment? |
dtolnay commentedJun 13, 2025
dtolnay commentedJun 14, 2025
@bors r=fmease |
bors commentedJun 14, 2025
Reduce precedence of expressions that have an outer attrPreviously, `-Zunpretty=expanded` would expand this program as follows:```rust#![feature(stmt_expr_attributes)]macro_rules! repro { ($e:expr) => { #[allow(deprecated)] $e };}#[derive(Default)]struct Thing { #[deprecated] field: i32,}fn main() { let thing = Thing::default(); let _ = repro!(thing).field;}``````rs#![feature(prelude_import)]#![feature(stmt_expr_attributes)]#[prelude_import]use std::prelude::rust_2021::*;#[macro_use]extern crate std;struct Thing { #[deprecated] field: i32,}#[automatically_derived]impl ::core::default::Default for Thing { #[inline] fn default() -> Thing { Thing { field: ::core::default::Default::default() } }}fn main() { let thing = Thing::default(); let _ = #[allow(deprecated)] thing.field;}```This is not the correct expansion. The correct output would have `(#[allow(deprecated)] thing).field` with the attribute applying only to `thing`, not to `thing.field`.Rollup of 10 pull requestsSuccessful merges: -#133952 (Remove wasm legacy abi) -#134661 (Reduce precedence of expressions that have an outer attr) -#141769 (Move metadata object generation for dylibs to the linker code ) -#141864 (Handle win32 separator for cygwin paths) -#142347 (Async drop - fix for StorageLive/StorageDead codegen for pinned future) -#142377 (Try unremapping compiler sources) -#142389 (Apply ABI attributes on return types in `rustc_codegen_cranelift`) -#142470 (Add some missing mailmap entries) -#142481 (Add `f16` inline asm support for LoongArch) -#142509 (bump std libc dependency)r? `@ghost``@rustbot` modify labels: rollup
matthiaskrgr commentedJun 15, 2025
dtolnay commentedJun 15, 2025
bors commentedJun 15, 2025
Reduce precedence of expressions that have an outer attrPreviously, `-Zunpretty=expanded` would expand this program as follows:```rust#![feature(stmt_expr_attributes)]macro_rules! repro { ($e:expr) => { #[allow(deprecated)] $e };}#[derive(Default)]struct Thing { #[deprecated] field: i32,}fn main() { let thing = Thing::default(); let _ = repro!(thing).field;}``````rs#![feature(prelude_import)]#![feature(stmt_expr_attributes)]#[prelude_import]use std::prelude::rust_2021::*;#[macro_use]extern crate std;struct Thing { #[deprecated] field: i32,}#[automatically_derived]impl ::core::default::Default for Thing { #[inline] fn default() -> Thing { Thing { field: ::core::default::Default::default() } }}fn main() { let thing = Thing::default(); let _ = #[allow(deprecated)] thing.field;}```This is not the correct expansion. The correct output would have `(#[allow(deprecated)] thing).field` with the attribute applying only to `thing`, not to `thing.field`.Rollup of 9 pull requestsSuccessful merges: -#133952 (Remove wasm legacy abi) -#134661 (Reduce precedence of expressions that have an outer attr) -#141769 (Move metadata object generation for dylibs to the linker code ) -#141864 (Handle win32 separator for cygwin paths) -#141937 (Report never type lints in dependencies) -#142347 (Async drop - fix for StorageLive/StorageDead codegen for pinned future) -#142389 (Apply ABI attributes on return types in `rustc_codegen_cranelift`) -#142470 (Add some missing mailmap entries) -#142481 (Add `f16` inline asm support for LoongArch)r? `@ghost``@rustbot` modify labels: rollup
Rollup of 10 pull requestsSuccessful merges: -#133952 (Remove wasm legacy abi) -#134661 (Reduce precedence of expressions that have an outer attr) -#141769 (Move metadata object generation for dylibs to the linker code ) -#141937 (Report never type lints in dependencies) -#142347 (Async drop - fix for StorageLive/StorageDead codegen for pinned future) -#142389 (Apply ABI attributes on return types in `rustc_codegen_cranelift`) -#142470 (Add some missing mailmap entries) -#142481 (Add `f16` inline asm support for LoongArch) -#142499 (Remove check run bootstrap) -#142543 (Suggest adding semicolon in user code rather than macro impl details)r? `@ghost``@rustbot` modify labels: rollup
b79d3b1 intorust-lang:masterUh oh!
There was an error while loading.Please reload this page.
Rollup merge of#134661 - dtolnay:prefixattr, r=fmeaseReduce precedence of expressions that have an outer attrPreviously, `-Zunpretty=expanded` would expand this program as follows:```rust#![feature(stmt_expr_attributes)]macro_rules! repro { ($e:expr) => { #[allow(deprecated)] $e };}#[derive(Default)]struct Thing { #[deprecated] field: i32,}fn main() { let thing = Thing::default(); let _ = repro!(thing).field;}``````rs#![feature(prelude_import)]#![feature(stmt_expr_attributes)]#[prelude_import]use std::prelude::rust_2021::*;#[macro_use]extern crate std;struct Thing { #[deprecated] field: i32,}#[automatically_derived]impl ::core::default::Default for Thing { #[inline] fn default() -> Thing { Thing { field: ::core::default::Default::default() } }}fn main() { let thing = Thing::default(); let _ = #[allow(deprecated)] thing.field;}```This is not the correct expansion. The correct output would have `(#[allow(deprecated)] thing).field` with the attribute applying only to `thing`, not to `thing.field`.
Insert parentheses around binary operation with attributeFixes the bug found by `@fmease` inrust-lang#134661 (review).Previously, `-Zunpretty=expanded` would expand this program as follows:```rust#![feature(stmt_expr_attributes)]#![allow(unused_attributes)]macro_rules! group { ($e:expr) => { $e };}macro_rules! extra { ($e:expr) => { #[allow()] $e };}fn main() { let _ = #[allow()] 1 + 1; let _ = group!(#[allow()] 1) + 1; let _ = 1 + group!(#[allow()] 1); let _ = extra!({ 0 }) + 1; let _ = extra!({ 0 } + 1);}``````consolelet _ = #[allow()] 1 + 1;let _ = #[allow()] 1 + 1;let _ = 1 + #[allow()] 1;let _ = #[allow()] { 0 } + 1;let _ = #[allow()] { 0 } + 1;```The first 4 statements are the correct expansion, but the last one is not. The attribute is supposed to apply to the entire binary operation, not only to the left operand.After this PR, the 5th statement will expand to:```consolelet _ = #[allow()] ({ 0 } + 1);```In the future, as some subset of `stmt_expr_attributes` approaches stabilization, it is possible that we will need to do parenthesization for a number of additional cases depending on the outcome ofrust-lang#127436. But for now, at least this PR makes the pretty-printer align with the current behavior of the parser.r? fmease
Rollup merge of#142476 - dtolnay:attrbinop, r=fmeaseInsert parentheses around binary operation with attributeFixes the bug found by `@fmease` in#134661 (review).Previously, `-Zunpretty=expanded` would expand this program as follows:```rust#![feature(stmt_expr_attributes)]#![allow(unused_attributes)]macro_rules! group { ($e:expr) => { $e };}macro_rules! extra { ($e:expr) => { #[allow()] $e };}fn main() { let _ = #[allow()] 1 + 1; let _ = group!(#[allow()] 1) + 1; let _ = 1 + group!(#[allow()] 1); let _ = extra!({ 0 }) + 1; let _ = extra!({ 0 } + 1);}``````consolelet _ = #[allow()] 1 + 1;let _ = #[allow()] 1 + 1;let _ = 1 + #[allow()] 1;let _ = #[allow()] { 0 } + 1;let _ = #[allow()] { 0 } + 1;```The first 4 statements are the correct expansion, but the last one is not. The attribute is supposed to apply to the entire binary operation, not only to the left operand.After this PR, the 5th statement will expand to:```consolelet _ = #[allow()] ({ 0 } + 1);```In the future, as some subset of `stmt_expr_attributes` approaches stabilization, it is possible that we will need to do parenthesization for a number of additional cases depending on the outcome of#127436. But for now, at least this PR makes the pretty-printer align with the current behavior of the parser.r? fmease
Reduce precedence of expressions that have an outer attrPreviously, `-Zunpretty=expanded` would expand this program as follows:```rust#![feature(stmt_expr_attributes)]macro_rules! repro { ($e:expr) => { #[allow(deprecated)] $e };}#[derive(Default)]struct Thing { #[deprecated] field: i32,}fn main() { let thing = Thing::default(); let _ = repro!(thing).field;}``````rs#![feature(prelude_import)]#![feature(stmt_expr_attributes)]#[prelude_import]use std::prelude::rust_2021::*;#[macro_use]extern crate std;struct Thing { #[deprecated] field: i32,}#[automatically_derived]impl ::core::default::Default for Thing { #[inline] fn default() -> Thing { Thing { field: ::core::default::Default::default() } }}fn main() { let thing = Thing::default(); let _ = #[allow(deprecated)] thing.field;}```This is not the correct expansion. The correct output would have `(#[allow(deprecated)] thing).field` with the attribute applying only to `thing`, not to `thing.field`.Rollup of 10 pull requestsSuccessful merges: -rust-lang/rust#133952 (Remove wasm legacy abi) -rust-lang/rust#134661 (Reduce precedence of expressions that have an outer attr) -rust-lang/rust#141769 (Move metadata object generation for dylibs to the linker code ) -rust-lang/rust#141937 (Report never type lints in dependencies) -rust-lang/rust#142347 (Async drop - fix for StorageLive/StorageDead codegen for pinned future) -rust-lang/rust#142389 (Apply ABI attributes on return types in `rustc_codegen_cranelift`) -rust-lang/rust#142470 (Add some missing mailmap entries) -rust-lang/rust#142481 (Add `f16` inline asm support for LoongArch) -rust-lang/rust#142499 (Remove check run bootstrap) -rust-lang/rust#142543 (Suggest adding semicolon in user code rather than macro impl details)r? `@ghost``@rustbot` modify labels: rollup
Rollup of 10 pull requestsSuccessful merges: -rust-lang/rust#133952 (Remove wasm legacy abi) -rust-lang/rust#134661 (Reduce precedence of expressions that have an outer attr) -rust-lang/rust#141769 (Move metadata object generation for dylibs to the linker code ) -rust-lang/rust#141937 (Report never type lints in dependencies) -rust-lang/rust#142347 (Async drop - fix for StorageLive/StorageDead codegen for pinned future) -rust-lang/rust#142389 (Apply ABI attributes on return types in `rustc_codegen_cranelift`) -rust-lang/rust#142470 (Add some missing mailmap entries) -rust-lang/rust#142481 (Add `f16` inline asm support for LoongArch) -rust-lang/rust#142499 (Remove check run bootstrap) -rust-lang/rust#142543 (Suggest adding semicolon in user code rather than macro impl details)r? `@ghost``@rustbot` modify labels: rollup
Uh oh!
There was an error while loading.Please reload this page.
Previously,
-Zunpretty=expandedwould expand this program as follows:This is not the correct expansion. The correct output would have
(#[allow(deprecated)] thing).fieldwith the attribute applying only tothing, not tothing.field.