rust-lang / rustfmt

Format Rust code
https://rust-lang.github.io/rustfmt/
Apache License 2.0
6.06k stars 892 forks source link

presence of lint attributes changes const block formatting #6341

Open eric-seppanen opened 2 months ago

eric-seppanen commented 2 months ago

If I ask cargo fmt from 1.81.0 to format this code, I get:

const COUNT: u8 = 5;

pub struct Thing;

impl Thing {
    pub fn set() {
        #[allow(clippy::assertions_on_constants)]
        const {
            assert!(COUNT == 5)
        };
    }
}

Under 1.80.0 I get:

const COUNT: u8 = 5;

pub struct Thing;

impl Thing {
    pub fn set() {
        #[allow(clippy::assertions_on_constants)]
        const { assert!(COUNT == 5) };
    }
}

Weirdly, if I remove the lint attribute, then both 1.81.0 and 1.80.0 format the const block on a single line.

I'm on Ubuntu 22.04, with no rustfmt.toml and the rustfmt versions are:

$ .rustup/toolchains/1.80.0-x86_64-unknown-linux-gnu/bin/rustfmt -V
rustfmt 1.7.0-stable (0514789 2024-07-21)
$ .rustup/toolchains/1.81.0-x86_64-unknown-linux-gnu/bin/rustfmt -V
rustfmt 1.7.1-stable (eeb90cd 2024-09-04)
ytmimi commented 2 months ago

const block formatting was updated in the 1.7.1 release to address a different bug: https://github.com/rust-lang/rustfmt/pull/6173. It's unfortunate that the formatting for const blocks with outer attributes was impacted because of it, and it's something that was overlooked.

The upside here is that const blocks now behave like other kinds of blocks when they're annotated with outer attributes. See https://github.com/rust-lang/rustfmt/issues/6106 for an example with unsafe blocks.

To prevent further churn, I don't think we can go back to the one line formatting without gating the change.

eric-seppanen commented 2 months ago

I don't have an opinion about matching the 1.80 behavior. Either format seems fine to me.

But formatting the block differently depending on whether there's an attribute present seems like a bug.

eric-seppanen commented 1 month ago

Rust 1.83 still has this problem, where the attribute causes different block formatting.

Example, with attribute:

impl Thing {
    pub fn set() {
        #[allow(clippy::assertions_on_constants)]
        const {
            assert!(COUNT == 5)
        };
    }
}

Example, without attribute:

impl Thing {
    pub fn set() {
        const { assert!(COUNT == 5) };
    }
}

nightly 2024-11-25 behaves the same.