rustfmt: error[internal]: left behind trailing whitespace on long lines in raw string

System

$ rustfmt --version
rustfmt 1.3.0-stable (d3345024 2019-06-09)

eric@Friendly_Name /cygdrive/c/Users/eric/Downloads/rustfmt_bug_lucidbrot/ex
$ cargo --version
cargo 1.37.0 (9edd08916 2019-08-02)

eric@Friendly_Name /cygdrive/c/Users/eric/Downloads/rustfmt_bug_lucidbrot/ex
$ uname -a
CYGWIN_NT-10.0 Friendly_Name 3.0.7(0.338/5/3) 2019-04-30 18:08 x86_64 Cygwin

Reproduction

rustfmt fails on this code sample.

const CONFIG_STRING: &str = 
    r###"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
"###;
fn main() {
    println!("Hello, world: {}", CONFIG_STRING);
}

The error it prints is this:

eric@Friendly_Name /cygdrive/c/Users/eric/Downloads/rustfmt_bug_lucidbrot/ex
$ cargo fmt
error[internal]: left behind trailing whitespace
 --> \\?\C:\Users\eric\Downloads\rustfmt_bug_lucidbrot\ex\src\main.rs:1:1:27
  |
1 | const CONFIG_STRING: &str =
  |                            ^
  |

warning: rustfmt has failed to format. See previous 1 errors.

This code sample, which has one a less, is successfully formatted:

const CONFIG_STRING: &str = 
    r###"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
"###;
fn main() {
    println!("Hello, world: {}", CONFIG_STRING);
}

The successfully formatted version looks like this:

const CONFIG_STRING: &str =
    r###"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
"###;
fn main() {
    println!("Hello, world: {}", CONFIG_STRING);
}

Another version of this snippet that can successfully be formatted is the following. It has the same number of as as the problematic example, but no trailing space after the equal sign on line 1:

const CONFIG_STRING: &str =
    r###"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
"###;
fn main() {
    println!("Hello, world: {}", CONFIG_STRING);
}

Possibly Related

I don’t know enough to say for sure. That’s why I created a new issue. But these may or may not be related:
https://github.com/rust-lang/rustfmt/issues/2896 (open) https://github.com/rust-lang/rustfmt/issues/3295 (nightly) (closed) https://github.com/rust-lang/rustfmt/issues/2896 (open) (collection thread)

More Examples

Good (Can be formatted):

const CONFIG_STRING: &str =     r###"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
"###;
fn main() {
    println!("Hello, world: {}", CONFIG_STRING);
}

Bad (Can not successfully be formatted):

const CONFIG_STRING: &str = 
r#"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"#;
fn main() {
    println!("Hello, world: {}", CONFIG_STRING);
}

Good:

const CONFIG_STRING: &str = 
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
fn main() {
    println!("Hello, world: {}", CONFIG_STRING);
}

Bad: Has no whitespace after the equal sign, but a long raw string

const CONFIG_STRING: &str = 
r#"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"#;
fn main() {
    println!("Hello, world: {}", CONFIG_STRING);
}

Good: Just like the sample right above this one, except it has one a less:

const CONFIG_STRING: &str = 
r#"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"#;
fn main() {
    println!("Hello, world: {}", CONFIG_STRING);
}

Bad: no longer a raw string

const CONFIG_STRING: &str = 
    "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
fn main() {
    println!("Hello, world: {}", CONFIG_STRING);
}

Splitting into multiple lines makes the bug disappear. Good:

const CONFIG_STRING: &str = "aaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaa";
fn main() {
    println!("Hello, world: {}", CONFIG_STRING);
}

Conclusion

It seems like this bug has to do with all of these in some way:

  • the space after the equal sign.
  • the difference between 90 as vs 89 as (I think the counts are correct?) - or rather, the length of the line as a whole.

When there is no whitespace after the equal sign, the number of as is irrelevant and formatting works.
When there are few enough as, the formatting works even with the whitespace.

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Comments: 15 (8 by maintainers)

Most upvoted comments

@lucidBrot - one admittedly confusing thing here is that the released 1.4.11 version of rustfmt that you are getting from rustup is a hotfix version of rustfmt that’s actually older than the current rustfmt on master branch (master is targeting a planned 2.0 release of rustfmt, but the version in Cargo.toml is still at 1.4.10 at the moment)

After re-checking that I had the latest rustfmt version (on master) on my Windows machine, I can’t reproduce this one either (Seems I was using a slightly older rustfmt version on Windows before when I was able to reproduce).

As such I believe this bug has already been fixed in the most recent version of rustfmt on master, but that fix hasn’t been released yet.

If you wanted to test the latest version of rustfmt on your machine against this snippet, you could try installing rustfmt directly from source. To do so, clone this repo and then run the below command in the root directory:

cargo +nightly install --path . --force --locked

If you happen to know whether that is intentional, let me know. Otherwise I won’t bother with it.

Assuming you’d prefer to switch back to the bundled/released version of rustfmt, the below commands should get you reset

cargo +nightly uninstall
rustup update

👀 yikes.

I’ll take a closer look into it later today. I’m using the latest version of rustfmt off the master branch in my env where I cannot reproduce, so either there’s something else going on, or perhaps a very recent fix has resolved this one already 🤞

We’re primarily focused on rustfmt 2.x right now so there’s quite a few changes on the master branch that weren’t in rustfmt 1.4.11 (which was released relatively recently with an urgent bug fix) so I’m hopeful that’s what’s happening

Easiest way would be to use rustup to upgrade to the latest stable version of rust and friends

rustup update stable (and/or nightly chanel if you prefer)

which will update you to rustfmt 1.4.8 or newer IIRC

It also does not seem to be a cygwin-related bug, as it also happens in windows cmd

Yeah these failed to format whitespace errors are internal rustfmt programming bugs that pop up from time to time