rust-lang / rustfmt

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

Format fails if if expression is used on left side of `+` but not if used on right side #3203

Open yaahc opened 5 years ago

yaahc commented 5 years ago

the following string will successfully reformat with rusfmt

    let check = code.chars().rev().enumerate().filter(|(i, c)| c.is_digit(10)).try_fold(0u32, |sum, (i, c)| c.to_digit(10).map(|d| sum + if (i + 1) % 2 == 0 { if 2*d > 9 { 2*d - 9} else { 2*d }} else {d})).map_or(false, |sum| sum % 10 == 0);

and this one will not

    code.chars().rev().enumerate().filter(|(i, c)| c.is_digit(10)).try_fold(0u32, |sum, (i, c)| c.to_digit(10).map(|d| if (i + 1) % 2 == 0 { if 2*d > 9 { 2*d - 9} else { 2*d }} else {d} + sum)).map_or(false, |sum| sum % 10 == 0);

the only difference being that sum was moved from the back of the if expression to the front.

nrc commented 5 years ago

What does "string will successfully reformat with rustfmt" mean exactly? It crashes or formats poorly? Does it give a message

yaahc commented 5 years ago

No error message no output, it just doesn't change the format. Also im sorry but i pasted the wrong code originally and my failure example actually wasnt the one i intended to paste, so if you tried pasting it in some code and it got broken up into multiple lines then thats why.

The expected result is start with a file containing

/// Check a Luhn checksum.
pub fn is_valid(code: &str) -> bool {
    code.chars().rev().enumerate().filter(|(i, c)| c.is_digit(10)).try_fold(0u32, |sum, (i, c)| c.to_digit(10).map(|d| if (i + 1) % 2 == 0 { if 2*d > 9 { 2*d - 9} else { 2*d }} else {d} + sum)).map_or(false, |sum| sum % 10 == 0);
}

and end up with

/// Check a Luhn checksum.
pub fn is_valid(code: &str) -> bool {
    code.chars()
        .rev()
        .enumerate()
        .filter(|(i, c)| c.is_digit(10))
        .try_fold(0u32, |sum, (i, c)| {
            c.to_digit(10).map(|d| {
                if (i + 1) % 2 == 0 {
                    if 2 * d > 9 {
                        2 * d - 9
                    } else {
                        2 * d
                    }
                } else {
                    d
                }
            } + sum)
        }).map_or(false, |sum| sum % 10 == 0);
}

but instead it doesnt change the file.

tested with

master ✗ $ cargo +nightly fmt -- --version
rustfmt 0.99.6-nightly (750b252 2018-10-18)
yaahc commented 5 years ago
master ✗ $ rustfmt --verbose src/lib.rs
Formatting <redacted>/src/lib.rs
Spent 0.000 secs in the parsing phase, and 0.001 secs in the formatting phase

Also --check passes with exit code 0

scampi commented 5 years ago

if nobody's on this, I'd take a look.

nrc commented 5 years ago

That's be great, thanks!

scampi commented 5 years ago

With the code below that you can try on the playground, I found something unexpected while working on this issue: the 2nd line with b fails to compile with the error error: expected expression, found '+'.

@nrc Is this normal ?

fn main() {
    let a = if true { 1 } else { 2 } + 3;
    let b = { if true { 1 } else { 2 } + 3 };
}