rust-lang / rustfmt

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

Flickering line break #6240

Open boozook opened 2 months ago

boozook commented 2 months ago

version: rustfmt 1.7.1-nightly (ba1d7f4a 2024-06-29) config: rustfmt.toml

Formatting is flickering for looooong chain like this:

from this

let removed = roots.extract_if(|root| {  /* long block */ }).count();

to this and back:

let removed = 
    roots.extract_if(|root| {  /* long block */ }).count();

Flickering in this case means following:

  1. run rustfmt cargo/src/build/mod.rs => we've got new line-break
  2. run rustfmt cargo/src/build/mod.rs => line-break is gone
  3. repeat...

example as pr-annotation: https://github.com/boozook/playdate/pull/399#discussion_r1676418639

ytmimi commented 2 months ago

@boozook Thanks for the report. Please try to reduce this to a minimal reproducible example.

boozook commented 2 months ago

@ytmimi, I honestly tried to get an isolated minimal reproducible example, but I can't, sorry. I suppose there is something complex 🤷🏻‍♂️

Also, just as little addition I've made neat video-demo in the IDE

https://github.com/user-attachments/assets/4e58df5f-9df6-4fa0-850e-6f30882fbe60

ytmimi commented 2 months ago

Thanks for the video. You might try to copy the entire let removed assignment into a snippet that's just as indented as the current code and take it from there. If you're able to post that it might help someone start looking into what's going on.

boozook commented 2 months ago

@ytmimi, done! example.zip

Seems to it depends on length of ling lines inside the block.

Important things in the config:

hard_tabs = true
tab_spaces = 3
mod foo {
    fn foo() {
        artifacts.extract_if(|(art, roots)| {
                     let removed = roots.extract_if(|root| {
                                       let ct =
                                           determine_crate_types(cfg, art, target, tk.clone(), ck).collect::<Vec<_>>();
                                   })
                                   .inspect(|r| {
                                       log::trace!("    excluded: {p}::{t} {:?}", match r.node().unit().platform {
                                           CompileKind::Host => "host",
                                          CompileKind::Target(ref kind) => kind.short_name(),
                                       })
                                   })
                                   .count();
                 });
    }
}

Also there is one more problem - cases of match has various indent:

  1. first has 5 tabs indent + 7*3 spaces align + 2 spaces in-block align
  2. second - 4 tabs indent + 8*3 spaces align + 2 spaces in-block align