rust-lang / rust-lang/rustfmt

file-lines can't partially format trait bounds lists

Open
#6,894 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

C-bug needs-triage UO-file_lines
Dominant language
Rust
Stars
7k
Forks
1.1k
Avg merge
2d 13h
Merged PRs (30d)
24

Description

If I have a long list of trait bounds in a generic params list, I'd expect to be able to use the --file-lines option to format part of that list without affecting other parts of the function signature (or whatever the surrounding context is). But right now if any attempt to partially format the bounds list will cause the entire list to be reformatted, potentially pulling it all onto one line, modifying unselected lines in the process.

Summary

Consider the following code, where there's a long list of trait bounds and a couple of them are misaligned:

fn whatever<
    A: Clone
        + Copy
        + Debug
        + Display
    + PartialEq
    + Eq
        + PartialOrd
        + Ord
        + Hash,
>() {
}

I would like to use --file-lines to format just lines 6-7 to pull the two misaligned trait bounds in line with the rest, but not otherwise reformat the list.

Expected behavior
fn whatever<
    A: Clone
        + Copy
        + Debug
        + Display
        + PartialEq
        + Eq
        + PartialOrd
        + Ord
        + Hash,
>() {
}
Actual behavior
fn whatever<A: Clone + Copy + Debug + Display + PartialEq + Eq + PartialOrd + Ord + Hash>() {}

Note that because of https://github.com/rust-lang/rustfmt/issues/6868 the entire function signature is getting reformatted to one line. If that issue were fixed, the output here would look more like the following, where just the bounds list gets reformatted:

fn whatever<
    A: Clone + Copy + Debug + Display + PartialEq + Eq + PartialOrd + Ord + Hash,
>() {
}

That highlights the more fundamental issue here, that the logic for laying out the trait bounds list doesn't account for --file-lines and so can pull everything onto one line, modifying unselected lines in the process.

Configuration

rustfmt cli options used:

rustfmt --unstable-features --file-lines '[{"file":"test.rs","range":[6,7]}]' test.rs

Meta

The relevant code is in join_bounds_inner, which currently doesn't check the --file-lines configuration at all.

There's a few related issues here due to --file-lines not being fully implemented:

  • Right now any attempt to partially format a function signature will reformat the whole thing (tracked by https://github.com/rust-lang/rustfmt/issues/6868), so in the example above we see the entire function get rewritten to a single line.
  • Part of https://github.com/rust-lang/rustfmt/issues/6872, which tracks partial formatting of where clauses. Fixing this issue is a requirement for fixing that one, since a where clause is made up of a list of trait bounds lists, but I think this is worth splitting off into its own issue because trait bounds lists can show up outside of where clauses.
  • This might need to be added as a blocker for https://github.com/rust-lang/rustfmt/issues/3397, though I think there's some room to discuss what the actual desired behavior is here, and that may mean this doesn't need to block stabilization.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in src/types.rs at join_bounds_inner and inspect how trait-bound lists are laid out without checking --file-lines. Run the issue's rustfmt command against the provided example, then verify that formatting lines 6-7 changes only the selected bounds while leaving the surrounding signature and unselected lines unchanged.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
tooling
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
55/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.