Indentation in closures gets formatted twice and result is not nice™
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 7k
- Forks
- 1.1k
- Avg merge
- 2d 13h
- Merged PRs (30d)
- 24
Description
Describe the bug
On first invocation of rustfmt closure code gets formatted (nicely, arguably). On any subsequent iteration it gets formatted again (not so nicely, arguably).
To Reproduce
Throw the following in a test.rs file:
#[derive(Debug)]
struct Foo {
some: usize,
member: String,
}
impl Foo {
pub fn some_fn() {
let edb_file = fs::read_dir(&event_path)?.find_map(|p| {
let path = p.ok()?.path();
(path.is_file() && Self::as_regex().is_match(&get_file_name(&path).ok()?) && path.extension()? == "edb").as_some(path)
});
}
}
and put the following in a rustfmt.toml file in the same directory:
# "Block" | "Visual"
indent_style = "Visual"
Now invoke rustfmt on file test.rs once. The following should happen:
#[derive(Debug)]
struct Foo {
some: usize,
member: String,
}
impl Foo {
pub fn some_fn() {
let edb_file = fs::read_dir(&event_path)?.find_map(|p| {
let path = p.ok()?.path();
(path.is_file()
&& Self::as_regex().is_match(&get_file_name(&path).ok()?)
&& path.extension()? == "edb")
.as_some(path)
});
}
}
Now invoke rustfmt on file test.rs again, and the following should happen:
#[derive(Debug)]
struct Foo {
some: usize,
member: String,
}
impl Foo {
pub fn some_fn() {
let edb_file = fs::read_dir(&event_path)?.find_map(|p| {
let path = p.ok()?.path();
(path.is_file()
&& Self::as_regex().is_match(&get_file_name(&path).ok()?)
&& path.extension()? == "edb")
.as_some(path)
});
}
}
Subsequent invocations should not make a difference. Differing settings for max_width (we use 79 characters) produce similar output.
Expected behavior
rustfmt should certainly not take two invocations to format a section of code. Personally I think the output after the first invocation is the intended one.
Meta
- rustfmt version: rustfmt 1.4.30-nightly (acd9486 2020-12-20)
- From where did you install rustfmt?: rustup
- How do you run rustfmt: through vim but this is reproducible also on direct invocation
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Reproduce the issue using test.rs and the adjacent rustfmt.toml with indent_style set to Visual, first running rustfmt once and then again. Compare the two outputs and investigate the formatting path responsible for closure indentation and max_width handling. Done means repeated direct invocations produce identical output, with the first formatted result preserved.
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
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100