🧊

`rustfmt`が`match`アームをうまくフォーマットしてくれないとき

忘れた頃にハマるので今度こそ書いておく。

どういうことか

rustfmtでもcargo fmtでもいいけど、とにかく実行してもうまくフォーマットされない!なんでや!ってなることがある。

たとえばこういうコード。

match doc {
    Doc::BreakParent => true, Doc::Group(group) => {
        // ...
    }
    Doc::Array(arr)
    // TODO: | Doc::Align(arr)
    | Doc::LineSuffix(arr) => apply_vec(arr),
    _ => false,
}

内容はさておき、matchアームに注目してほしい。

最初のDoc::BreakParent => true,のところ、改行されないのおかしくない?

こうなるべきじゃない?

match doc {
    Doc::BreakParent => true,
    Doc::Group(group) => {
        // ...
    }
    Doc::Array(arr)
    // TODO: | Doc::Align(arr)
    | Doc::LineSuffix(arr) => apply_vec(arr),
    _ => false,
}

ただ、何回フォーマットしてもうんともすんとも言わない。

他の箇所はちゃんとフォーマットされるようなので、rustfmtが設定できてないとかではなさそう。

原因は

あれこれ試してみてわかったけど、どうやら後から付け足したであろうTODOコメントが原因だった。

silently fails to format match expression if arm pat contains comment · Issue #4119 · rust-lang/rustfmt https://github.com/rust-lang/rustfmt/issues/4119

最小構成はこれで再現できる。

match i {
    0|1
    // Comment!
    |2|3 => {println!("<4");}
    _=>unreachable!(),
}

コメントがあるとうまくフォーマットされず、コメントを消すかアームの頭に動かすとフォーマットされるようになる。

ちなみに、使ってるRustのバージョンがnightlyなら、error_on_unformatted = trueを指定することで気付けるものもあるらしい。

それにしても、コメントの扱いはどこへ行っても厄介なのだなあ・・・。